2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2005 Aric Stewart for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 /* Msi top level apis directly related to installs */
37 #include "wine/heap.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
43 /***********************************************************************
44 * MsiDoActionA (MSI.@)
46 UINT WINAPI
MsiDoActionA( MSIHANDLE hInstall
, LPCSTR szAction
)
51 TRACE("%s\n", debugstr_a(szAction
));
53 szwAction
= strdupAtoW(szAction
);
54 if (szAction
&& !szwAction
)
55 return ERROR_FUNCTION_FAILED
;
57 ret
= MsiDoActionW( hInstall
, szwAction
);
58 msi_free( szwAction
);
62 /***********************************************************************
63 * MsiDoActionW (MSI.@)
65 UINT WINAPI
MsiDoActionW( MSIHANDLE hInstall
, LPCWSTR szAction
)
70 TRACE("%s\n",debugstr_w(szAction
));
73 return ERROR_INVALID_PARAMETER
;
75 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
80 if (!(remote
= msi_get_remote(hInstall
)))
81 return ERROR_INVALID_HANDLE
;
83 return remote_DoAction(remote
, szAction
);
86 ret
= ACTION_PerformAction( package
, szAction
, SCRIPT_NONE
);
87 msiobj_release( &package
->hdr
);
92 /***********************************************************************
93 * MsiSequenceA (MSI.@)
95 UINT WINAPI
MsiSequenceA( MSIHANDLE hInstall
, LPCSTR szTable
, INT iSequenceMode
)
100 TRACE("%s, %d\n", debugstr_a(szTable
), iSequenceMode
);
102 szwTable
= strdupAtoW(szTable
);
103 if (szTable
&& !szwTable
)
104 return ERROR_FUNCTION_FAILED
;
106 ret
= MsiSequenceW( hInstall
, szwTable
, iSequenceMode
);
107 msi_free( szwTable
);
111 /***********************************************************************
112 * MsiSequenceW (MSI.@)
114 UINT WINAPI
MsiSequenceW( MSIHANDLE hInstall
, LPCWSTR szTable
, INT iSequenceMode
)
119 TRACE("%s, %d\n", debugstr_w(szTable
), iSequenceMode
);
122 return ERROR_INVALID_PARAMETER
;
124 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
129 if (!(remote
= msi_get_remote(hInstall
)))
130 return ERROR_INVALID_HANDLE
;
132 return remote_Sequence(remote
, szTable
, iSequenceMode
);
134 ret
= MSI_Sequence( package
, szTable
);
135 msiobj_release( &package
->hdr
);
139 UINT
msi_strcpy_to_awstring( const WCHAR
*str
, int len
, awstring
*awbuf
, DWORD
*sz
)
141 UINT r
= ERROR_SUCCESS
;
143 if (awbuf
->str
.w
&& !sz
)
144 return ERROR_INVALID_PARAMETER
;
146 return ERROR_SUCCESS
;
148 if (len
< 0) len
= strlenW( str
);
150 if (awbuf
->unicode
&& awbuf
->str
.w
)
152 memcpy( awbuf
->str
.w
, str
, min(len
+ 1, *sz
) * sizeof(WCHAR
) );
153 if (*sz
&& len
>= *sz
)
154 awbuf
->str
.w
[*sz
- 1] = 0;
158 int lenA
= WideCharToMultiByte( CP_ACP
, 0, str
, len
+ 1, NULL
, 0, NULL
, NULL
);
160 WideCharToMultiByte( CP_ACP
, 0, str
, len
+ 1, awbuf
->str
.a
, *sz
, NULL
, NULL
);
161 if (awbuf
->str
.a
&& *sz
&& lenA
>= *sz
)
162 awbuf
->str
.a
[*sz
- 1] = 0;
165 if (awbuf
->str
.w
&& len
>= *sz
)
171 const WCHAR
*msi_get_target_folder( MSIPACKAGE
*package
, const WCHAR
*name
)
173 MSIFOLDER
*folder
= msi_get_loaded_folder( package
, name
);
175 if (!folder
) return NULL
;
176 if (!folder
->ResolvedTarget
)
178 MSIFOLDER
*parent
= folder
;
179 while (parent
->Parent
&& strcmpW( parent
->Parent
, parent
->Directory
))
181 parent
= msi_get_loaded_folder( package
, parent
->Parent
);
183 msi_resolve_target_folder( package
, parent
->Directory
, TRUE
);
185 return folder
->ResolvedTarget
;
188 /***********************************************************************
189 * MsiGetTargetPath (internal)
191 static UINT
MSI_GetTargetPath( MSIHANDLE hInstall
, LPCWSTR szFolder
,
192 awstring
*szPathBuf
, LPDWORD pcchPathBuf
)
196 UINT r
= ERROR_FUNCTION_FAILED
;
199 return ERROR_INVALID_PARAMETER
;
201 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
207 if (!(remote
= msi_get_remote(hInstall
)))
208 return ERROR_INVALID_HANDLE
;
210 r
= remote_GetTargetPath(remote
, szFolder
, &value
);
211 if (r
!= ERROR_SUCCESS
)
214 r
= msi_strcpy_to_awstring(value
, -1, szPathBuf
, pcchPathBuf
);
216 midl_user_free(value
);
220 path
= msi_get_target_folder( package
, szFolder
);
221 msiobj_release( &package
->hdr
);
224 return ERROR_DIRECTORY
;
226 return msi_strcpy_to_awstring( path
, -1, szPathBuf
, pcchPathBuf
);
229 /***********************************************************************
230 * MsiGetTargetPathA (MSI.@)
232 UINT WINAPI
MsiGetTargetPathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
233 LPSTR szPathBuf
, LPDWORD pcchPathBuf
)
239 TRACE("%s %p %p\n", debugstr_a(szFolder
), szPathBuf
, pcchPathBuf
);
241 szwFolder
= strdupAtoW(szFolder
);
242 if (szFolder
&& !szwFolder
)
243 return ERROR_FUNCTION_FAILED
;
245 path
.unicode
= FALSE
;
246 path
.str
.a
= szPathBuf
;
248 r
= MSI_GetTargetPath( hInstall
, szwFolder
, &path
, pcchPathBuf
);
250 msi_free( szwFolder
);
255 /***********************************************************************
256 * MsiGetTargetPathW (MSI.@)
258 UINT WINAPI
MsiGetTargetPathW( MSIHANDLE hInstall
, LPCWSTR szFolder
,
259 LPWSTR szPathBuf
, LPDWORD pcchPathBuf
)
263 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
266 path
.str
.w
= szPathBuf
;
268 return MSI_GetTargetPath( hInstall
, szFolder
, &path
, pcchPathBuf
);
271 static WCHAR
*get_source_root( MSIPACKAGE
*package
)
273 msi_set_sourcedir_props( package
, FALSE
);
274 return msi_dup_property( package
->db
, szSourceDir
);
277 WCHAR
*msi_resolve_source_folder( MSIPACKAGE
*package
, const WCHAR
*name
, MSIFOLDER
**folder
)
280 LPWSTR p
, path
= NULL
, parent
;
282 TRACE("working to resolve %s\n", debugstr_w(name
));
284 if (!strcmpW( name
, szSourceDir
)) name
= szTargetDir
;
285 if (!(f
= msi_get_loaded_folder( package
, name
))) return NULL
;
287 /* special resolving for root dir */
288 if (!strcmpW( name
, szTargetDir
) && !f
->ResolvedSource
)
290 f
->ResolvedSource
= get_source_root( package
);
292 if (folder
) *folder
= f
;
293 if (f
->ResolvedSource
)
295 path
= strdupW( f
->ResolvedSource
);
296 TRACE(" already resolved to %s\n", debugstr_w(path
));
299 if (!f
->Parent
) return path
;
301 TRACE(" ! parent is %s\n", debugstr_w(parent
));
303 p
= msi_resolve_source_folder( package
, parent
, NULL
);
305 if (package
->WordCount
& msidbSumInfoSourceTypeCompressed
)
306 path
= get_source_root( package
);
307 else if (package
->WordCount
& msidbSumInfoSourceTypeSFN
)
308 path
= msi_build_directory_name( 3, p
, f
->SourceShortPath
, NULL
);
310 path
= msi_build_directory_name( 3, p
, f
->SourceLongPath
, NULL
);
312 TRACE("-> %s\n", debugstr_w(path
));
313 f
->ResolvedSource
= strdupW( path
);
319 /***********************************************************************
320 * MSI_GetSourcePath (internal)
322 static UINT
MSI_GetSourcePath( MSIHANDLE hInstall
, LPCWSTR szFolder
,
323 awstring
*szPathBuf
, LPDWORD pcchPathBuf
)
327 UINT r
= ERROR_FUNCTION_FAILED
;
329 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
332 return ERROR_INVALID_PARAMETER
;
334 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
340 if (!(remote
= msi_get_remote(hInstall
)))
341 return ERROR_INVALID_HANDLE
;
343 r
= remote_GetSourcePath(remote
, szFolder
, &value
);
344 if (r
!= ERROR_SUCCESS
)
347 r
= msi_strcpy_to_awstring(value
, -1, szPathBuf
, pcchPathBuf
);
349 midl_user_free(value
);
353 if (szPathBuf
->str
.w
&& !pcchPathBuf
)
355 msiobj_release( &package
->hdr
);
356 return ERROR_INVALID_PARAMETER
;
359 path
= msi_resolve_source_folder( package
, szFolder
, NULL
);
360 msiobj_release( &package
->hdr
);
362 TRACE("path = %s\n", debugstr_w(path
));
364 return ERROR_DIRECTORY
;
366 r
= msi_strcpy_to_awstring( path
, -1, szPathBuf
, pcchPathBuf
);
371 /***********************************************************************
372 * MsiGetSourcePathA (MSI.@)
374 UINT WINAPI
MsiGetSourcePathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
375 LPSTR szPathBuf
, LPDWORD pcchPathBuf
)
381 TRACE("%s %p %p\n", debugstr_a(szFolder
), szPathBuf
, pcchPathBuf
);
384 str
.str
.a
= szPathBuf
;
386 folder
= strdupAtoW( szFolder
);
387 r
= MSI_GetSourcePath( hInstall
, folder
, &str
, pcchPathBuf
);
393 /***********************************************************************
394 * MsiGetSourcePathW (MSI.@)
396 UINT WINAPI
MsiGetSourcePathW( MSIHANDLE hInstall
, LPCWSTR szFolder
,
397 LPWSTR szPathBuf
, LPDWORD pcchPathBuf
)
401 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
404 str
.str
.w
= szPathBuf
;
406 return MSI_GetSourcePath( hInstall
, szFolder
, &str
, pcchPathBuf
);
409 /***********************************************************************
410 * MsiSetTargetPathA (MSI.@)
412 UINT WINAPI
MsiSetTargetPathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
413 LPCSTR szFolderPath
)
415 LPWSTR szwFolder
= NULL
, szwFolderPath
= NULL
;
416 UINT rc
= ERROR_OUTOFMEMORY
;
418 if ( !szFolder
|| !szFolderPath
)
419 return ERROR_INVALID_PARAMETER
;
421 szwFolder
= strdupAtoW(szFolder
);
422 szwFolderPath
= strdupAtoW(szFolderPath
);
423 if (!szwFolder
|| !szwFolderPath
)
426 rc
= MsiSetTargetPathW( hInstall
, szwFolder
, szwFolderPath
);
430 msi_free(szwFolderPath
);
435 static void set_target_path( MSIPACKAGE
*package
, MSIFOLDER
*folder
, const WCHAR
*path
)
441 if (!(target_path
= msi_normalize_path( path
))) return;
442 if (strcmpW( target_path
, folder
->ResolvedTarget
))
444 msi_free( folder
->ResolvedTarget
);
445 folder
->ResolvedTarget
= target_path
;
446 msi_set_property( package
->db
, folder
->Directory
, folder
->ResolvedTarget
, -1 );
448 LIST_FOR_EACH_ENTRY( fl
, &folder
->children
, FolderList
, entry
)
451 msi_resolve_target_folder( package
, child
->Directory
, FALSE
);
454 else msi_free( target_path
);
457 UINT
MSI_SetTargetPathW( MSIPACKAGE
*package
, LPCWSTR szFolder
, LPCWSTR szFolderPath
)
463 TRACE("%p %s %s\n", package
, debugstr_w(szFolder
), debugstr_w(szFolderPath
));
465 attrib
= GetFileAttributesW(szFolderPath
);
466 /* native MSI tests writeability by making temporary files at each drive */
467 if (attrib
!= INVALID_FILE_ATTRIBUTES
&&
468 (attrib
& FILE_ATTRIBUTE_OFFLINE
|| attrib
& FILE_ATTRIBUTE_READONLY
))
470 return ERROR_FUNCTION_FAILED
;
472 if (!(folder
= msi_get_loaded_folder( package
, szFolder
))) return ERROR_DIRECTORY
;
474 set_target_path( package
, folder
, szFolderPath
);
476 LIST_FOR_EACH_ENTRY( file
, &package
->files
, MSIFILE
, entry
)
479 MSICOMPONENT
*comp
= file
->Component
;
481 if (!comp
->Enabled
|| msi_is_global_assembly( comp
)) continue;
483 dir
= msi_get_target_folder( package
, comp
->Directory
);
484 msi_free( file
->TargetPath
);
485 file
->TargetPath
= msi_build_directory_name( 2, dir
, file
->FileName
);
487 return ERROR_SUCCESS
;
490 /***********************************************************************
491 * MsiSetTargetPathW (MSI.@)
493 UINT WINAPI
MsiSetTargetPathW(MSIHANDLE hInstall
, LPCWSTR szFolder
,
494 LPCWSTR szFolderPath
)
499 TRACE("%s %s\n",debugstr_w(szFolder
),debugstr_w(szFolderPath
));
501 if ( !szFolder
|| !szFolderPath
)
502 return ERROR_INVALID_PARAMETER
;
504 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
509 if (!(remote
= msi_get_remote(hInstall
)))
510 return ERROR_INVALID_HANDLE
;
512 return remote_SetTargetPath(remote
, szFolder
, szFolderPath
);
515 ret
= MSI_SetTargetPathW( package
, szFolder
, szFolderPath
);
516 msiobj_release( &package
->hdr
);
520 /***********************************************************************
523 * Returns an internal installer state (if it is running in a mode iRunMode)
526 * hInstall [I] Handle to the installation
527 * hRunMode [I] Checking run mode
528 * MSIRUNMODE_ADMIN Administrative mode
529 * MSIRUNMODE_ADVERTISE Advertisement mode
530 * MSIRUNMODE_MAINTENANCE Maintenance mode
531 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
532 * MSIRUNMODE_LOGENABLED Log file is writing
533 * MSIRUNMODE_OPERATIONS Operations in progress??
534 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
535 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
536 * MSIRUNMODE_CABINET Files from cabinet are installed
537 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed
538 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed
539 * MSIRUNMODE_RESERVED11 Reserved
540 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
541 * MSIRUNMODE_ZAWENABLED Demand installation is supported
542 * MSIRUNMODE_RESERVED14 Reserved
543 * MSIRUNMODE_RESERVED15 Reserved
544 * MSIRUNMODE_SCHEDULED called from install script
545 * MSIRUNMODE_ROLLBACK called from rollback script
546 * MSIRUNMODE_COMMIT called from commit script
550 * Not in the state: FALSE
553 BOOL WINAPI
MsiGetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
)
558 TRACE("%d %d\n", hInstall
, iRunMode
);
560 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
567 if (!(remote
= msi_get_remote(hInstall
)))
570 hr
= remote_GetMode(remote
, iRunMode
, &ret
);
580 case MSIRUNMODE_ADMIN
:
581 FIXME("no support for administrative installs\n");
584 case MSIRUNMODE_ADVERTISE
:
585 FIXME("no support for advertised installs\n");
588 case MSIRUNMODE_WINDOWS9X
:
589 if (GetVersion() & 0x80000000)
593 case MSIRUNMODE_OPERATIONS
:
594 case MSIRUNMODE_RESERVED11
:
595 case MSIRUNMODE_RESERVED14
:
596 case MSIRUNMODE_RESERVED15
:
599 case MSIRUNMODE_SCHEDULED
:
600 r
= package
->scheduled_action_running
;
603 case MSIRUNMODE_ROLLBACK
:
604 r
= package
->rollback_action_running
;
607 case MSIRUNMODE_COMMIT
:
608 r
= package
->commit_action_running
;
611 case MSIRUNMODE_MAINTENANCE
:
612 r
= msi_get_property_int( package
->db
, szInstalled
, 0 ) != 0;
615 case MSIRUNMODE_ROLLBACKENABLED
:
616 r
= msi_get_property_int( package
->db
, szRollbackDisabled
, 0 ) == 0;
619 case MSIRUNMODE_REBOOTATEND
:
620 r
= package
->need_reboot_at_end
;
623 case MSIRUNMODE_REBOOTNOW
:
624 r
= package
->need_reboot_now
;
627 case MSIRUNMODE_LOGENABLED
:
628 r
= (package
->log_file
!= INVALID_HANDLE_VALUE
);
632 FIXME("unimplemented run mode: %d\n", iRunMode
);
636 msiobj_release( &package
->hdr
);
640 /***********************************************************************
643 UINT WINAPI
MsiSetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
, BOOL fState
)
648 TRACE("%d %d %d\n", hInstall
, iRunMode
, fState
);
650 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
656 if (!(remote
= msi_get_remote(hInstall
)))
659 hr
= remote_SetMode(remote
, iRunMode
, fState
);
663 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
664 return HRESULT_CODE(hr
);
666 return ERROR_FUNCTION_FAILED
;
669 return ERROR_SUCCESS
;
674 case MSIRUNMODE_REBOOTATEND
:
675 package
->need_reboot_at_end
= (fState
!= 0);
679 case MSIRUNMODE_REBOOTNOW
:
680 package
->need_reboot_now
= (fState
!= 0);
685 r
= ERROR_ACCESS_DENIED
;
688 msiobj_release( &package
->hdr
);
692 /***********************************************************************
693 * MsiSetFeatureStateA (MSI.@)
695 * According to the docs, when this is called it immediately recalculates
696 * all the component states as well
698 UINT WINAPI
MsiSetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
701 LPWSTR szwFeature
= NULL
;
704 szwFeature
= strdupAtoW(szFeature
);
707 return ERROR_FUNCTION_FAILED
;
709 rc
= MsiSetFeatureStateW(hInstall
,szwFeature
, iState
);
711 msi_free(szwFeature
);
716 /* update component state based on a feature change */
717 void ACTION_UpdateComponentStates( MSIPACKAGE
*package
, MSIFEATURE
*feature
)
719 INSTALLSTATE newstate
;
722 newstate
= feature
->ActionRequest
;
723 if (newstate
== INSTALLSTATE_ABSENT
) newstate
= INSTALLSTATE_UNKNOWN
;
725 LIST_FOR_EACH_ENTRY(cl
, &feature
->Components
, ComponentList
, entry
)
727 MSICOMPONENT
*component
= cl
->component
;
729 if (!component
->Enabled
) continue;
731 TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
732 newstate
, debugstr_w(component
->Component
), component
->Installed
,
733 component
->Action
, component
->ActionRequest
);
735 if (newstate
== INSTALLSTATE_LOCAL
)
737 component
->Action
= INSTALLSTATE_LOCAL
;
738 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
742 ComponentList
*clist
;
745 component
->hasLocalFeature
= FALSE
;
747 component
->Action
= newstate
;
748 component
->ActionRequest
= newstate
;
749 /* if any other feature wants it local we need to set it local */
750 LIST_FOR_EACH_ENTRY(f
, &package
->features
, MSIFEATURE
, entry
)
752 if ( f
->ActionRequest
!= INSTALLSTATE_LOCAL
&&
753 f
->ActionRequest
!= INSTALLSTATE_SOURCE
)
757 LIST_FOR_EACH_ENTRY(clist
, &f
->Components
, ComponentList
, entry
)
759 if (clist
->component
== component
&&
760 (f
->ActionRequest
== INSTALLSTATE_LOCAL
||
761 f
->ActionRequest
== INSTALLSTATE_SOURCE
))
763 TRACE("Saved by %s\n", debugstr_w(f
->Feature
));
764 component
->hasLocalFeature
= TRUE
;
766 if (component
->Attributes
& msidbComponentAttributesOptional
)
768 if (f
->Attributes
& msidbFeatureAttributesFavorSource
)
770 component
->Action
= INSTALLSTATE_SOURCE
;
771 component
->ActionRequest
= INSTALLSTATE_SOURCE
;
775 component
->Action
= INSTALLSTATE_LOCAL
;
776 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
779 else if (component
->Attributes
& msidbComponentAttributesSourceOnly
)
781 component
->Action
= INSTALLSTATE_SOURCE
;
782 component
->ActionRequest
= INSTALLSTATE_SOURCE
;
786 component
->Action
= INSTALLSTATE_LOCAL
;
787 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
793 TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
794 newstate
, debugstr_w(component
->Component
), component
->Installed
,
795 component
->Action
, component
->ActionRequest
);
799 UINT
MSI_SetFeatureStateW( MSIPACKAGE
*package
, LPCWSTR szFeature
, INSTALLSTATE iState
)
801 UINT rc
= ERROR_SUCCESS
;
802 MSIFEATURE
*feature
, *child
;
804 TRACE("%s %i\n", debugstr_w(szFeature
), iState
);
806 feature
= msi_get_loaded_feature( package
, szFeature
);
808 return ERROR_UNKNOWN_FEATURE
;
810 if (iState
== INSTALLSTATE_ADVERTISED
&&
811 feature
->Attributes
& msidbFeatureAttributesDisallowAdvertise
)
812 return ERROR_FUNCTION_FAILED
;
814 feature
->ActionRequest
= iState
;
816 ACTION_UpdateComponentStates( package
, feature
);
818 /* update all the features that are children of this feature */
819 LIST_FOR_EACH_ENTRY( child
, &package
->features
, MSIFEATURE
, entry
)
821 if (child
->Feature_Parent
&& !strcmpW( szFeature
, child
->Feature_Parent
))
822 MSI_SetFeatureStateW(package
, child
->Feature
, iState
);
828 /***********************************************************************
829 * MsiSetFeatureStateW (MSI.@)
831 UINT WINAPI
MsiSetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
835 UINT rc
= ERROR_SUCCESS
;
837 TRACE("%s %i\n",debugstr_w(szFeature
), iState
);
839 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
846 if (!(remote
= msi_get_remote(hInstall
)))
847 return ERROR_INVALID_HANDLE
;
849 feature
= SysAllocString(szFeature
);
851 return ERROR_OUTOFMEMORY
;
853 hr
= remote_SetFeatureState(remote
, feature
, iState
);
855 SysFreeString(feature
);
859 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
860 return HRESULT_CODE(hr
);
862 return ERROR_FUNCTION_FAILED
;
865 return ERROR_SUCCESS
;
868 rc
= MSI_SetFeatureStateW(package
,szFeature
,iState
);
870 msiobj_release( &package
->hdr
);
874 /***********************************************************************
875 * MsiSetFeatureAttributesA (MSI.@)
877 UINT WINAPI
MsiSetFeatureAttributesA( MSIHANDLE handle
, LPCSTR feature
, DWORD attrs
)
880 WCHAR
*featureW
= NULL
;
882 TRACE("%u, %s, 0x%08x\n", handle
, debugstr_a(feature
), attrs
);
884 if (feature
&& !(featureW
= strdupAtoW( feature
))) return ERROR_OUTOFMEMORY
;
886 r
= MsiSetFeatureAttributesW( handle
, featureW
, attrs
);
887 msi_free( featureW
);
891 static DWORD
unmap_feature_attributes( DWORD attrs
)
895 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORLOCAL
) ret
= msidbFeatureAttributesFavorLocal
;
896 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORSOURCE
) ret
|= msidbFeatureAttributesFavorSource
;
897 if (attrs
& INSTALLFEATUREATTRIBUTE_FOLLOWPARENT
) ret
|= msidbFeatureAttributesFollowParent
;
898 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORADVERTISE
) ret
|= msidbFeatureAttributesFavorAdvertise
;
899 if (attrs
& INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE
) ret
|= msidbFeatureAttributesDisallowAdvertise
;
900 if (attrs
& INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE
) ret
|= msidbFeatureAttributesNoUnsupportedAdvertise
;
904 /***********************************************************************
905 * MsiSetFeatureAttributesW (MSI.@)
907 UINT WINAPI
MsiSetFeatureAttributesW( MSIHANDLE handle
, LPCWSTR name
, DWORD attrs
)
913 TRACE("%u, %s, 0x%08x\n", handle
, debugstr_w(name
), attrs
);
915 if (!name
|| !name
[0]) return ERROR_UNKNOWN_FEATURE
;
917 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
918 return ERROR_INVALID_HANDLE
;
920 costing
= msi_dup_property( package
->db
, szCostingComplete
);
921 if (!costing
|| !strcmpW( costing
, szOne
))
924 msiobj_release( &package
->hdr
);
925 return ERROR_FUNCTION_FAILED
;
928 if (!(feature
= msi_get_loaded_feature( package
, name
)))
930 msiobj_release( &package
->hdr
);
931 return ERROR_UNKNOWN_FEATURE
;
933 feature
->Attributes
= unmap_feature_attributes( attrs
);
934 msiobj_release( &package
->hdr
);
935 return ERROR_SUCCESS
;
938 /***********************************************************************
939 * MsiGetFeatureStateA (MSI.@)
941 UINT WINAPI
MsiGetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
942 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
944 LPWSTR szwFeature
= NULL
;
947 if (szFeature
&& !(szwFeature
= strdupAtoW(szFeature
))) return ERROR_OUTOFMEMORY
;
949 rc
= MsiGetFeatureStateW(hInstall
, szwFeature
, piInstalled
, piAction
);
950 msi_free( szwFeature
);
954 UINT
MSI_GetFeatureStateW(MSIPACKAGE
*package
, LPCWSTR szFeature
,
955 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
959 feature
= msi_get_loaded_feature(package
,szFeature
);
961 return ERROR_UNKNOWN_FEATURE
;
964 *piInstalled
= feature
->Installed
;
967 *piAction
= feature
->ActionRequest
;
969 TRACE("returning %i %i\n", feature
->Installed
, feature
->ActionRequest
);
971 return ERROR_SUCCESS
;
974 /***********************************************************************
975 * MsiGetFeatureStateW (MSI.@)
977 UINT WINAPI
MsiGetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
978 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
983 TRACE("%d %s %p %p\n", hInstall
, debugstr_w(szFeature
), piInstalled
, piAction
);
985 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
992 if (!(remote
= msi_get_remote(hInstall
)))
993 return ERROR_INVALID_HANDLE
;
995 feature
= SysAllocString(szFeature
);
997 return ERROR_OUTOFMEMORY
;
999 hr
= remote_GetFeatureState(remote
, feature
, piInstalled
, piAction
);
1001 SysFreeString(feature
);
1005 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1006 return HRESULT_CODE(hr
);
1008 return ERROR_FUNCTION_FAILED
;
1011 return ERROR_SUCCESS
;
1014 ret
= MSI_GetFeatureStateW(package
, szFeature
, piInstalled
, piAction
);
1015 msiobj_release( &package
->hdr
);
1019 /***********************************************************************
1020 * MsiGetFeatureCostA (MSI.@)
1022 UINT WINAPI
MsiGetFeatureCostA(MSIHANDLE hInstall
, LPCSTR szFeature
,
1023 MSICOSTTREE iCostTree
, INSTALLSTATE iState
, LPINT piCost
)
1025 LPWSTR szwFeature
= NULL
;
1028 szwFeature
= strdupAtoW(szFeature
);
1030 rc
= MsiGetFeatureCostW(hInstall
, szwFeature
, iCostTree
, iState
, piCost
);
1032 msi_free(szwFeature
);
1037 static INT
feature_cost( MSIFEATURE
*feature
)
1042 LIST_FOR_EACH_ENTRY( cl
, &feature
->Components
, ComponentList
, entry
)
1044 cost
+= cl
->component
->Cost
;
1049 UINT
MSI_GetFeatureCost( MSIPACKAGE
*package
, MSIFEATURE
*feature
, MSICOSTTREE tree
,
1050 INSTALLSTATE state
, LPINT cost
)
1052 TRACE("%s, %u, %d, %p\n", debugstr_w(feature
->Feature
), tree
, state
, cost
);
1057 case MSICOSTTREE_CHILDREN
:
1061 LIST_FOR_EACH_ENTRY( child
, &feature
->Children
, MSIFEATURE
, entry
)
1063 if (child
->ActionRequest
== state
)
1064 *cost
+= feature_cost( child
);
1068 case MSICOSTTREE_PARENTS
:
1070 const WCHAR
*feature_parent
= feature
->Feature_Parent
;
1073 MSIFEATURE
*parent
= msi_get_loaded_feature( package
, feature_parent
);
1077 if (parent
->ActionRequest
== state
)
1078 *cost
+= feature_cost( parent
);
1080 feature_parent
= parent
->Feature_Parent
;
1084 case MSICOSTTREE_SELFONLY
:
1085 if (feature
->ActionRequest
== state
)
1086 *cost
= feature_cost( feature
);
1090 WARN("unhandled cost tree %u\n", tree
);
1095 return ERROR_SUCCESS
;
1098 /***********************************************************************
1099 * MsiGetFeatureCostW (MSI.@)
1101 UINT WINAPI
MsiGetFeatureCostW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
1102 MSICOSTTREE iCostTree
, INSTALLSTATE iState
, LPINT piCost
)
1104 MSIPACKAGE
*package
;
1105 MSIFEATURE
*feature
;
1108 TRACE("(%d %s %i %i %p)\n", hInstall
, debugstr_w(szFeature
),
1109 iCostTree
, iState
, piCost
);
1111 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1118 if (!(remote
= msi_get_remote(hInstall
)))
1119 return ERROR_INVALID_HANDLE
;
1121 feature
= SysAllocString(szFeature
);
1123 return ERROR_OUTOFMEMORY
;
1125 hr
= remote_GetFeatureCost(remote
, feature
, iCostTree
, iState
, piCost
);
1127 SysFreeString(feature
);
1131 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1132 return HRESULT_CODE(hr
);
1134 return ERROR_FUNCTION_FAILED
;
1137 return ERROR_SUCCESS
;
1140 feature
= msi_get_loaded_feature(package
, szFeature
);
1143 ret
= MSI_GetFeatureCost(package
, feature
, iCostTree
, iState
, piCost
);
1145 ret
= ERROR_UNKNOWN_FEATURE
;
1147 msiobj_release( &package
->hdr
);
1151 /***********************************************************************
1152 * MsiGetFeatureInfoA (MSI.@)
1154 UINT WINAPI
MsiGetFeatureInfoA( MSIHANDLE handle
, LPCSTR feature
, LPDWORD attrs
,
1155 LPSTR title
, LPDWORD title_len
, LPSTR help
, LPDWORD help_len
)
1158 WCHAR
*titleW
= NULL
, *helpW
= NULL
, *featureW
= NULL
;
1160 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle
, debugstr_a(feature
), attrs
, title
,
1161 title_len
, help
, help_len
);
1163 if (feature
&& !(featureW
= strdupAtoW( feature
))) return ERROR_OUTOFMEMORY
;
1165 if (title
&& title_len
&& !(titleW
= msi_alloc( *title_len
* sizeof(WCHAR
) )))
1167 msi_free( featureW
);
1168 return ERROR_OUTOFMEMORY
;
1170 if (help
&& help_len
&& !(helpW
= msi_alloc( *help_len
* sizeof(WCHAR
) )))
1172 msi_free( featureW
);
1174 return ERROR_OUTOFMEMORY
;
1176 r
= MsiGetFeatureInfoW( handle
, featureW
, attrs
, titleW
, title_len
, helpW
, help_len
);
1177 if (r
== ERROR_SUCCESS
)
1179 if (titleW
) WideCharToMultiByte( CP_ACP
, 0, titleW
, -1, title
, *title_len
+ 1, NULL
, NULL
);
1180 if (helpW
) WideCharToMultiByte( CP_ACP
, 0, helpW
, -1, help
, *help_len
+ 1, NULL
, NULL
);
1184 msi_free( featureW
);
1188 static DWORD
map_feature_attributes( DWORD attrs
)
1192 if (attrs
== msidbFeatureAttributesFavorLocal
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORLOCAL
;
1193 if (attrs
& msidbFeatureAttributesFavorSource
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORSOURCE
;
1194 if (attrs
& msidbFeatureAttributesFollowParent
) ret
|= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT
;
1195 if (attrs
& msidbFeatureAttributesFavorAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE
;
1196 if (attrs
& msidbFeatureAttributesDisallowAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE
;
1197 if (attrs
& msidbFeatureAttributesNoUnsupportedAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE
;
1201 static UINT
MSI_GetFeatureInfo( MSIPACKAGE
*package
, LPCWSTR name
, LPDWORD attrs
,
1202 LPWSTR title
, LPDWORD title_len
, LPWSTR help
, LPDWORD help_len
)
1204 UINT r
= ERROR_SUCCESS
;
1205 MSIFEATURE
*feature
= msi_get_loaded_feature( package
, name
);
1208 if (!feature
) return ERROR_UNKNOWN_FEATURE
;
1209 if (attrs
) *attrs
= map_feature_attributes( feature
->Attributes
);
1212 if (feature
->Title
) len
= strlenW( feature
->Title
);
1214 if (*title_len
<= len
)
1217 if (title
) r
= ERROR_MORE_DATA
;
1221 if (feature
->Title
) strcpyW( title
, feature
->Title
);
1228 if (feature
->Description
) len
= strlenW( feature
->Description
);
1230 if (*help_len
<= len
)
1233 if (help
) r
= ERROR_MORE_DATA
;
1237 if (feature
->Description
) strcpyW( help
, feature
->Description
);
1245 /***********************************************************************
1246 * MsiGetFeatureInfoW (MSI.@)
1248 UINT WINAPI
MsiGetFeatureInfoW( MSIHANDLE handle
, LPCWSTR feature
, LPDWORD attrs
,
1249 LPWSTR title
, LPDWORD title_len
, LPWSTR help
, LPDWORD help_len
)
1252 MSIPACKAGE
*package
;
1254 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle
, debugstr_w(feature
), attrs
, title
,
1255 title_len
, help
, help_len
);
1257 if (!feature
) return ERROR_INVALID_PARAMETER
;
1259 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
1260 return ERROR_INVALID_HANDLE
;
1262 /* features may not have been loaded yet */
1263 msi_load_all_components( package
);
1264 msi_load_all_features( package
);
1266 r
= MSI_GetFeatureInfo( package
, feature
, attrs
, title
, title_len
, help
, help_len
);
1267 msiobj_release( &package
->hdr
);
1271 /***********************************************************************
1272 * MsiSetComponentStateA (MSI.@)
1274 UINT WINAPI
MsiSetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
1275 INSTALLSTATE iState
)
1278 LPWSTR szwComponent
= strdupAtoW(szComponent
);
1280 rc
= MsiSetComponentStateW(hInstall
, szwComponent
, iState
);
1282 msi_free(szwComponent
);
1287 /***********************************************************************
1288 * MsiGetComponentStateA (MSI.@)
1290 UINT WINAPI
MsiGetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
1291 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1293 LPWSTR szwComponent
= NULL
;
1296 szwComponent
= strdupAtoW(szComponent
);
1298 rc
= MsiGetComponentStateW(hInstall
,szwComponent
,piInstalled
, piAction
);
1300 msi_free( szwComponent
);
1305 static UINT
MSI_SetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
1306 INSTALLSTATE iState
)
1310 TRACE("%p %s %d\n", package
, debugstr_w(szComponent
), iState
);
1312 comp
= msi_get_loaded_component(package
, szComponent
);
1314 return ERROR_UNKNOWN_COMPONENT
;
1317 comp
->Action
= iState
;
1319 return ERROR_SUCCESS
;
1322 UINT
MSI_GetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
1323 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1327 TRACE("%p %s %p %p\n", package
, debugstr_w(szComponent
),
1328 piInstalled
, piAction
);
1330 comp
= msi_get_loaded_component(package
,szComponent
);
1332 return ERROR_UNKNOWN_COMPONENT
;
1337 *piInstalled
= comp
->Installed
;
1339 *piInstalled
= INSTALLSTATE_UNKNOWN
;
1345 *piAction
= comp
->Action
;
1347 *piAction
= INSTALLSTATE_UNKNOWN
;
1350 TRACE("states (%i, %i)\n", comp
->Installed
, comp
->Action
);
1351 return ERROR_SUCCESS
;
1354 /***********************************************************************
1355 * MsiSetComponentStateW (MSI.@)
1357 UINT WINAPI
MsiSetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
1358 INSTALLSTATE iState
)
1360 MSIPACKAGE
* package
;
1363 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1370 if (!(remote
= msi_get_remote(hInstall
)))
1371 return ERROR_INVALID_HANDLE
;
1373 component
= SysAllocString(szComponent
);
1375 return ERROR_OUTOFMEMORY
;
1377 hr
= remote_SetComponentState(remote
, component
, iState
);
1379 SysFreeString(component
);
1383 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1384 return HRESULT_CODE(hr
);
1386 return ERROR_FUNCTION_FAILED
;
1389 return ERROR_SUCCESS
;
1392 ret
= MSI_SetComponentStateW(package
, szComponent
, iState
);
1393 msiobj_release(&package
->hdr
);
1397 /***********************************************************************
1398 * MsiGetComponentStateW (MSI.@)
1400 UINT WINAPI
MsiGetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
1401 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1403 MSIPACKAGE
* package
;
1406 TRACE("%d %s %p %p\n", hInstall
, debugstr_w(szComponent
),
1407 piInstalled
, piAction
);
1409 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1416 if (!(remote
= msi_get_remote(hInstall
)))
1417 return ERROR_INVALID_HANDLE
;
1419 component
= SysAllocString(szComponent
);
1421 return ERROR_OUTOFMEMORY
;
1423 hr
= remote_GetComponentState(remote
, component
, piInstalled
, piAction
);
1425 SysFreeString(component
);
1429 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1430 return HRESULT_CODE(hr
);
1432 return ERROR_FUNCTION_FAILED
;
1435 return ERROR_SUCCESS
;
1438 ret
= MSI_GetComponentStateW( package
, szComponent
, piInstalled
, piAction
);
1439 msiobj_release( &package
->hdr
);
1443 /***********************************************************************
1444 * MsiGetLanguage (MSI.@)
1446 LANGID WINAPI
MsiGetLanguage(MSIHANDLE hInstall
)
1448 MSIPACKAGE
* package
;
1451 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1458 if (!(remote
= msi_get_remote(hInstall
)))
1459 return ERROR_INVALID_HANDLE
;
1461 hr
= remote_GetLanguage(remote
, &lang
);
1469 langid
= msi_get_property_int( package
->db
, szProductLanguage
, 0 );
1470 msiobj_release( &package
->hdr
);
1474 UINT
MSI_SetInstallLevel( MSIPACKAGE
*package
, int iInstallLevel
)
1476 static const WCHAR fmt
[] = { '%','d',0 };
1481 TRACE("%p %i\n", package
, iInstallLevel
);
1483 if (iInstallLevel
> 32767)
1484 return ERROR_INVALID_PARAMETER
;
1486 if (iInstallLevel
< 1)
1487 return MSI_SetFeatureStates( package
);
1489 len
= sprintfW( level
, fmt
, iInstallLevel
);
1490 r
= msi_set_property( package
->db
, szInstallLevel
, level
, len
);
1491 if ( r
== ERROR_SUCCESS
)
1492 r
= MSI_SetFeatureStates( package
);
1497 /***********************************************************************
1498 * MsiSetInstallLevel (MSI.@)
1500 UINT WINAPI
MsiSetInstallLevel(MSIHANDLE hInstall
, int iInstallLevel
)
1502 MSIPACKAGE
* package
;
1505 TRACE("%d %i\n", hInstall
, iInstallLevel
);
1507 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1513 if (!(remote
= msi_get_remote(hInstall
)))
1514 return ERROR_INVALID_HANDLE
;
1516 hr
= remote_SetInstallLevel(remote
, iInstallLevel
);
1520 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1521 return HRESULT_CODE(hr
);
1523 return ERROR_FUNCTION_FAILED
;
1526 return ERROR_SUCCESS
;
1529 r
= MSI_SetInstallLevel( package
, iInstallLevel
);
1531 msiobj_release( &package
->hdr
);
1536 /***********************************************************************
1537 * MsiGetFeatureValidStatesW (MSI.@)
1539 UINT WINAPI
MsiGetFeatureValidStatesW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
1540 LPDWORD pInstallState
)
1542 if(pInstallState
) *pInstallState
= 1<<INSTALLSTATE_LOCAL
;
1543 FIXME("%d %s %p stub returning %d\n",
1544 hInstall
, debugstr_w(szFeature
), pInstallState
, pInstallState
? *pInstallState
: 0);
1546 return ERROR_SUCCESS
;
1549 /***********************************************************************
1550 * MsiGetFeatureValidStatesA (MSI.@)
1552 UINT WINAPI
MsiGetFeatureValidStatesA(MSIHANDLE hInstall
, LPCSTR szFeature
,
1553 LPDWORD pInstallState
)
1556 LPWSTR szwFeature
= strdupAtoW(szFeature
);
1558 ret
= MsiGetFeatureValidStatesW(hInstall
, szwFeature
, pInstallState
);
1560 msi_free(szwFeature
);