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
);
565 if (!(remote
= msi_get_remote(hInstall
)))
568 return remote_GetMode(remote
, iRunMode
);
573 case MSIRUNMODE_ADMIN
:
574 FIXME("no support for administrative installs\n");
577 case MSIRUNMODE_ADVERTISE
:
578 FIXME("no support for advertised installs\n");
581 case MSIRUNMODE_WINDOWS9X
:
582 if (GetVersion() & 0x80000000)
586 case MSIRUNMODE_OPERATIONS
:
587 case MSIRUNMODE_RESERVED11
:
588 case MSIRUNMODE_RESERVED14
:
589 case MSIRUNMODE_RESERVED15
:
592 case MSIRUNMODE_SCHEDULED
:
593 r
= package
->scheduled_action_running
;
596 case MSIRUNMODE_ROLLBACK
:
597 r
= package
->rollback_action_running
;
600 case MSIRUNMODE_COMMIT
:
601 r
= package
->commit_action_running
;
604 case MSIRUNMODE_MAINTENANCE
:
605 r
= msi_get_property_int( package
->db
, szInstalled
, 0 ) != 0;
608 case MSIRUNMODE_ROLLBACKENABLED
:
609 r
= msi_get_property_int( package
->db
, szRollbackDisabled
, 0 ) == 0;
612 case MSIRUNMODE_REBOOTATEND
:
613 r
= package
->need_reboot_at_end
;
616 case MSIRUNMODE_REBOOTNOW
:
617 r
= package
->need_reboot_now
;
620 case MSIRUNMODE_LOGENABLED
:
621 r
= (package
->log_file
!= INVALID_HANDLE_VALUE
);
625 FIXME("unimplemented run mode: %d\n", iRunMode
);
629 msiobj_release( &package
->hdr
);
633 /***********************************************************************
636 UINT WINAPI
MsiSetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
, BOOL fState
)
641 TRACE("%d %d %d\n", hInstall
, iRunMode
, fState
);
643 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
649 if (!(remote
= msi_get_remote(hInstall
)))
652 hr
= remote_SetMode(remote
, iRunMode
, fState
);
656 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
657 return HRESULT_CODE(hr
);
659 return ERROR_FUNCTION_FAILED
;
662 return ERROR_SUCCESS
;
667 case MSIRUNMODE_REBOOTATEND
:
668 package
->need_reboot_at_end
= (fState
!= 0);
672 case MSIRUNMODE_REBOOTNOW
:
673 package
->need_reboot_now
= (fState
!= 0);
678 r
= ERROR_ACCESS_DENIED
;
681 msiobj_release( &package
->hdr
);
685 /***********************************************************************
686 * MsiSetFeatureStateA (MSI.@)
688 * According to the docs, when this is called it immediately recalculates
689 * all the component states as well
691 UINT WINAPI
MsiSetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
694 LPWSTR szwFeature
= NULL
;
697 szwFeature
= strdupAtoW(szFeature
);
700 return ERROR_FUNCTION_FAILED
;
702 rc
= MsiSetFeatureStateW(hInstall
,szwFeature
, iState
);
704 msi_free(szwFeature
);
709 /* update component state based on a feature change */
710 void ACTION_UpdateComponentStates( MSIPACKAGE
*package
, MSIFEATURE
*feature
)
712 INSTALLSTATE newstate
;
715 newstate
= feature
->ActionRequest
;
716 if (newstate
== INSTALLSTATE_ABSENT
) newstate
= INSTALLSTATE_UNKNOWN
;
718 LIST_FOR_EACH_ENTRY(cl
, &feature
->Components
, ComponentList
, entry
)
720 MSICOMPONENT
*component
= cl
->component
;
722 if (!component
->Enabled
) continue;
724 TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
725 newstate
, debugstr_w(component
->Component
), component
->Installed
,
726 component
->Action
, component
->ActionRequest
);
728 if (newstate
== INSTALLSTATE_LOCAL
)
730 component
->Action
= INSTALLSTATE_LOCAL
;
731 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
735 ComponentList
*clist
;
738 component
->hasLocalFeature
= FALSE
;
740 component
->Action
= newstate
;
741 component
->ActionRequest
= newstate
;
742 /* if any other feature wants it local we need to set it local */
743 LIST_FOR_EACH_ENTRY(f
, &package
->features
, MSIFEATURE
, entry
)
745 if ( f
->ActionRequest
!= INSTALLSTATE_LOCAL
&&
746 f
->ActionRequest
!= INSTALLSTATE_SOURCE
)
750 LIST_FOR_EACH_ENTRY(clist
, &f
->Components
, ComponentList
, entry
)
752 if (clist
->component
== component
&&
753 (f
->ActionRequest
== INSTALLSTATE_LOCAL
||
754 f
->ActionRequest
== INSTALLSTATE_SOURCE
))
756 TRACE("Saved by %s\n", debugstr_w(f
->Feature
));
757 component
->hasLocalFeature
= TRUE
;
759 if (component
->Attributes
& msidbComponentAttributesOptional
)
761 if (f
->Attributes
& msidbFeatureAttributesFavorSource
)
763 component
->Action
= INSTALLSTATE_SOURCE
;
764 component
->ActionRequest
= INSTALLSTATE_SOURCE
;
768 component
->Action
= INSTALLSTATE_LOCAL
;
769 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
772 else if (component
->Attributes
& msidbComponentAttributesSourceOnly
)
774 component
->Action
= INSTALLSTATE_SOURCE
;
775 component
->ActionRequest
= INSTALLSTATE_SOURCE
;
779 component
->Action
= INSTALLSTATE_LOCAL
;
780 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
786 TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
787 newstate
, debugstr_w(component
->Component
), component
->Installed
,
788 component
->Action
, component
->ActionRequest
);
792 UINT
MSI_SetFeatureStateW( MSIPACKAGE
*package
, LPCWSTR szFeature
, INSTALLSTATE iState
)
794 UINT rc
= ERROR_SUCCESS
;
795 MSIFEATURE
*feature
, *child
;
797 TRACE("%s %i\n", debugstr_w(szFeature
), iState
);
799 feature
= msi_get_loaded_feature( package
, szFeature
);
801 return ERROR_UNKNOWN_FEATURE
;
803 if (iState
== INSTALLSTATE_ADVERTISED
&&
804 feature
->Attributes
& msidbFeatureAttributesDisallowAdvertise
)
805 return ERROR_FUNCTION_FAILED
;
807 feature
->ActionRequest
= iState
;
809 ACTION_UpdateComponentStates( package
, feature
);
811 /* update all the features that are children of this feature */
812 LIST_FOR_EACH_ENTRY( child
, &package
->features
, MSIFEATURE
, entry
)
814 if (child
->Feature_Parent
&& !strcmpW( szFeature
, child
->Feature_Parent
))
815 MSI_SetFeatureStateW(package
, child
->Feature
, iState
);
821 /***********************************************************************
822 * MsiSetFeatureStateW (MSI.@)
824 UINT WINAPI
MsiSetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
828 UINT rc
= ERROR_SUCCESS
;
830 TRACE("%s %i\n",debugstr_w(szFeature
), iState
);
832 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
839 if (!(remote
= msi_get_remote(hInstall
)))
840 return ERROR_INVALID_HANDLE
;
842 feature
= SysAllocString(szFeature
);
844 return ERROR_OUTOFMEMORY
;
846 hr
= remote_SetFeatureState(remote
, feature
, iState
);
848 SysFreeString(feature
);
852 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
853 return HRESULT_CODE(hr
);
855 return ERROR_FUNCTION_FAILED
;
858 return ERROR_SUCCESS
;
861 rc
= MSI_SetFeatureStateW(package
,szFeature
,iState
);
863 msiobj_release( &package
->hdr
);
867 /***********************************************************************
868 * MsiSetFeatureAttributesA (MSI.@)
870 UINT WINAPI
MsiSetFeatureAttributesA( MSIHANDLE handle
, LPCSTR feature
, DWORD attrs
)
873 WCHAR
*featureW
= NULL
;
875 TRACE("%u, %s, 0x%08x\n", handle
, debugstr_a(feature
), attrs
);
877 if (feature
&& !(featureW
= strdupAtoW( feature
))) return ERROR_OUTOFMEMORY
;
879 r
= MsiSetFeatureAttributesW( handle
, featureW
, attrs
);
880 msi_free( featureW
);
884 static DWORD
unmap_feature_attributes( DWORD attrs
)
888 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORLOCAL
) ret
= msidbFeatureAttributesFavorLocal
;
889 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORSOURCE
) ret
|= msidbFeatureAttributesFavorSource
;
890 if (attrs
& INSTALLFEATUREATTRIBUTE_FOLLOWPARENT
) ret
|= msidbFeatureAttributesFollowParent
;
891 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORADVERTISE
) ret
|= msidbFeatureAttributesFavorAdvertise
;
892 if (attrs
& INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE
) ret
|= msidbFeatureAttributesDisallowAdvertise
;
893 if (attrs
& INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE
) ret
|= msidbFeatureAttributesNoUnsupportedAdvertise
;
897 /***********************************************************************
898 * MsiSetFeatureAttributesW (MSI.@)
900 UINT WINAPI
MsiSetFeatureAttributesW( MSIHANDLE handle
, LPCWSTR name
, DWORD attrs
)
906 TRACE("%u, %s, 0x%08x\n", handle
, debugstr_w(name
), attrs
);
908 if (!name
|| !name
[0]) return ERROR_UNKNOWN_FEATURE
;
910 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
911 return ERROR_INVALID_HANDLE
;
913 costing
= msi_dup_property( package
->db
, szCostingComplete
);
914 if (!costing
|| !strcmpW( costing
, szOne
))
917 msiobj_release( &package
->hdr
);
918 return ERROR_FUNCTION_FAILED
;
921 if (!(feature
= msi_get_loaded_feature( package
, name
)))
923 msiobj_release( &package
->hdr
);
924 return ERROR_UNKNOWN_FEATURE
;
926 feature
->Attributes
= unmap_feature_attributes( attrs
);
927 msiobj_release( &package
->hdr
);
928 return ERROR_SUCCESS
;
931 /***********************************************************************
932 * MsiGetFeatureStateA (MSI.@)
934 UINT WINAPI
MsiGetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
935 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
937 LPWSTR szwFeature
= NULL
;
940 if (szFeature
&& !(szwFeature
= strdupAtoW(szFeature
))) return ERROR_OUTOFMEMORY
;
942 rc
= MsiGetFeatureStateW(hInstall
, szwFeature
, piInstalled
, piAction
);
943 msi_free( szwFeature
);
947 UINT
MSI_GetFeatureStateW(MSIPACKAGE
*package
, LPCWSTR szFeature
,
948 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
952 feature
= msi_get_loaded_feature(package
,szFeature
);
954 return ERROR_UNKNOWN_FEATURE
;
957 *piInstalled
= feature
->Installed
;
960 *piAction
= feature
->ActionRequest
;
962 TRACE("returning %i %i\n", feature
->Installed
, feature
->ActionRequest
);
964 return ERROR_SUCCESS
;
967 /***********************************************************************
968 * MsiGetFeatureStateW (MSI.@)
970 UINT WINAPI
MsiGetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
971 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
976 TRACE("%d %s %p %p\n", hInstall
, debugstr_w(szFeature
), piInstalled
, piAction
);
978 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
985 if (!(remote
= msi_get_remote(hInstall
)))
986 return ERROR_INVALID_HANDLE
;
988 feature
= SysAllocString(szFeature
);
990 return ERROR_OUTOFMEMORY
;
992 hr
= remote_GetFeatureState(remote
, feature
, piInstalled
, piAction
);
994 SysFreeString(feature
);
998 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
999 return HRESULT_CODE(hr
);
1001 return ERROR_FUNCTION_FAILED
;
1004 return ERROR_SUCCESS
;
1007 ret
= MSI_GetFeatureStateW(package
, szFeature
, piInstalled
, piAction
);
1008 msiobj_release( &package
->hdr
);
1012 /***********************************************************************
1013 * MsiGetFeatureCostA (MSI.@)
1015 UINT WINAPI
MsiGetFeatureCostA(MSIHANDLE hInstall
, LPCSTR szFeature
,
1016 MSICOSTTREE iCostTree
, INSTALLSTATE iState
, LPINT piCost
)
1018 LPWSTR szwFeature
= NULL
;
1021 szwFeature
= strdupAtoW(szFeature
);
1023 rc
= MsiGetFeatureCostW(hInstall
, szwFeature
, iCostTree
, iState
, piCost
);
1025 msi_free(szwFeature
);
1030 static INT
feature_cost( MSIFEATURE
*feature
)
1035 LIST_FOR_EACH_ENTRY( cl
, &feature
->Components
, ComponentList
, entry
)
1037 cost
+= cl
->component
->Cost
;
1042 UINT
MSI_GetFeatureCost( MSIPACKAGE
*package
, MSIFEATURE
*feature
, MSICOSTTREE tree
,
1043 INSTALLSTATE state
, LPINT cost
)
1045 TRACE("%s, %u, %d, %p\n", debugstr_w(feature
->Feature
), tree
, state
, cost
);
1050 case MSICOSTTREE_CHILDREN
:
1054 LIST_FOR_EACH_ENTRY( child
, &feature
->Children
, MSIFEATURE
, entry
)
1056 if (child
->ActionRequest
== state
)
1057 *cost
+= feature_cost( child
);
1061 case MSICOSTTREE_PARENTS
:
1063 const WCHAR
*feature_parent
= feature
->Feature_Parent
;
1066 MSIFEATURE
*parent
= msi_get_loaded_feature( package
, feature_parent
);
1070 if (parent
->ActionRequest
== state
)
1071 *cost
+= feature_cost( parent
);
1073 feature_parent
= parent
->Feature_Parent
;
1077 case MSICOSTTREE_SELFONLY
:
1078 if (feature
->ActionRequest
== state
)
1079 *cost
= feature_cost( feature
);
1083 WARN("unhandled cost tree %u\n", tree
);
1088 return ERROR_SUCCESS
;
1091 /***********************************************************************
1092 * MsiGetFeatureCostW (MSI.@)
1094 UINT WINAPI
MsiGetFeatureCostW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
1095 MSICOSTTREE iCostTree
, INSTALLSTATE iState
, LPINT piCost
)
1097 MSIPACKAGE
*package
;
1098 MSIFEATURE
*feature
;
1101 TRACE("(%d %s %i %i %p)\n", hInstall
, debugstr_w(szFeature
),
1102 iCostTree
, iState
, piCost
);
1104 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1111 if (!(remote
= msi_get_remote(hInstall
)))
1112 return ERROR_INVALID_HANDLE
;
1114 feature
= SysAllocString(szFeature
);
1116 return ERROR_OUTOFMEMORY
;
1118 hr
= remote_GetFeatureCost(remote
, feature
, iCostTree
, iState
, piCost
);
1120 SysFreeString(feature
);
1124 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1125 return HRESULT_CODE(hr
);
1127 return ERROR_FUNCTION_FAILED
;
1130 return ERROR_SUCCESS
;
1133 feature
= msi_get_loaded_feature(package
, szFeature
);
1136 ret
= MSI_GetFeatureCost(package
, feature
, iCostTree
, iState
, piCost
);
1138 ret
= ERROR_UNKNOWN_FEATURE
;
1140 msiobj_release( &package
->hdr
);
1144 /***********************************************************************
1145 * MsiGetFeatureInfoA (MSI.@)
1147 UINT WINAPI
MsiGetFeatureInfoA( MSIHANDLE handle
, LPCSTR feature
, LPDWORD attrs
,
1148 LPSTR title
, LPDWORD title_len
, LPSTR help
, LPDWORD help_len
)
1151 WCHAR
*titleW
= NULL
, *helpW
= NULL
, *featureW
= NULL
;
1153 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle
, debugstr_a(feature
), attrs
, title
,
1154 title_len
, help
, help_len
);
1156 if (feature
&& !(featureW
= strdupAtoW( feature
))) return ERROR_OUTOFMEMORY
;
1158 if (title
&& title_len
&& !(titleW
= msi_alloc( *title_len
* sizeof(WCHAR
) )))
1160 msi_free( featureW
);
1161 return ERROR_OUTOFMEMORY
;
1163 if (help
&& help_len
&& !(helpW
= msi_alloc( *help_len
* sizeof(WCHAR
) )))
1165 msi_free( featureW
);
1167 return ERROR_OUTOFMEMORY
;
1169 r
= MsiGetFeatureInfoW( handle
, featureW
, attrs
, titleW
, title_len
, helpW
, help_len
);
1170 if (r
== ERROR_SUCCESS
)
1172 if (titleW
) WideCharToMultiByte( CP_ACP
, 0, titleW
, -1, title
, *title_len
+ 1, NULL
, NULL
);
1173 if (helpW
) WideCharToMultiByte( CP_ACP
, 0, helpW
, -1, help
, *help_len
+ 1, NULL
, NULL
);
1177 msi_free( featureW
);
1181 static DWORD
map_feature_attributes( DWORD attrs
)
1185 if (attrs
== msidbFeatureAttributesFavorLocal
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORLOCAL
;
1186 if (attrs
& msidbFeatureAttributesFavorSource
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORSOURCE
;
1187 if (attrs
& msidbFeatureAttributesFollowParent
) ret
|= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT
;
1188 if (attrs
& msidbFeatureAttributesFavorAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE
;
1189 if (attrs
& msidbFeatureAttributesDisallowAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE
;
1190 if (attrs
& msidbFeatureAttributesNoUnsupportedAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE
;
1194 static UINT
MSI_GetFeatureInfo( MSIPACKAGE
*package
, LPCWSTR name
, LPDWORD attrs
,
1195 LPWSTR title
, LPDWORD title_len
, LPWSTR help
, LPDWORD help_len
)
1197 UINT r
= ERROR_SUCCESS
;
1198 MSIFEATURE
*feature
= msi_get_loaded_feature( package
, name
);
1201 if (!feature
) return ERROR_UNKNOWN_FEATURE
;
1202 if (attrs
) *attrs
= map_feature_attributes( feature
->Attributes
);
1205 if (feature
->Title
) len
= strlenW( feature
->Title
);
1207 if (*title_len
<= len
)
1210 if (title
) r
= ERROR_MORE_DATA
;
1214 if (feature
->Title
) strcpyW( title
, feature
->Title
);
1221 if (feature
->Description
) len
= strlenW( feature
->Description
);
1223 if (*help_len
<= len
)
1226 if (help
) r
= ERROR_MORE_DATA
;
1230 if (feature
->Description
) strcpyW( help
, feature
->Description
);
1238 /***********************************************************************
1239 * MsiGetFeatureInfoW (MSI.@)
1241 UINT WINAPI
MsiGetFeatureInfoW( MSIHANDLE handle
, LPCWSTR feature
, LPDWORD attrs
,
1242 LPWSTR title
, LPDWORD title_len
, LPWSTR help
, LPDWORD help_len
)
1245 MSIPACKAGE
*package
;
1247 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle
, debugstr_w(feature
), attrs
, title
,
1248 title_len
, help
, help_len
);
1250 if (!feature
) return ERROR_INVALID_PARAMETER
;
1252 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
1253 return ERROR_INVALID_HANDLE
;
1255 /* features may not have been loaded yet */
1256 msi_load_all_components( package
);
1257 msi_load_all_features( package
);
1259 r
= MSI_GetFeatureInfo( package
, feature
, attrs
, title
, title_len
, help
, help_len
);
1260 msiobj_release( &package
->hdr
);
1264 /***********************************************************************
1265 * MsiSetComponentStateA (MSI.@)
1267 UINT WINAPI
MsiSetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
1268 INSTALLSTATE iState
)
1271 LPWSTR szwComponent
= strdupAtoW(szComponent
);
1273 rc
= MsiSetComponentStateW(hInstall
, szwComponent
, iState
);
1275 msi_free(szwComponent
);
1280 /***********************************************************************
1281 * MsiGetComponentStateA (MSI.@)
1283 UINT WINAPI
MsiGetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
1284 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1286 LPWSTR szwComponent
= NULL
;
1289 szwComponent
= strdupAtoW(szComponent
);
1291 rc
= MsiGetComponentStateW(hInstall
,szwComponent
,piInstalled
, piAction
);
1293 msi_free( szwComponent
);
1298 static UINT
MSI_SetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
1299 INSTALLSTATE iState
)
1303 TRACE("%p %s %d\n", package
, debugstr_w(szComponent
), iState
);
1305 comp
= msi_get_loaded_component(package
, szComponent
);
1307 return ERROR_UNKNOWN_COMPONENT
;
1310 comp
->Action
= iState
;
1312 return ERROR_SUCCESS
;
1315 UINT
MSI_GetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
1316 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1320 TRACE("%p %s %p %p\n", package
, debugstr_w(szComponent
),
1321 piInstalled
, piAction
);
1323 comp
= msi_get_loaded_component(package
,szComponent
);
1325 return ERROR_UNKNOWN_COMPONENT
;
1330 *piInstalled
= comp
->Installed
;
1332 *piInstalled
= INSTALLSTATE_UNKNOWN
;
1338 *piAction
= comp
->Action
;
1340 *piAction
= INSTALLSTATE_UNKNOWN
;
1343 TRACE("states (%i, %i)\n", comp
->Installed
, comp
->Action
);
1344 return ERROR_SUCCESS
;
1347 /***********************************************************************
1348 * MsiSetComponentStateW (MSI.@)
1350 UINT WINAPI
MsiSetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
1351 INSTALLSTATE iState
)
1353 MSIPACKAGE
* package
;
1356 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1363 if (!(remote
= msi_get_remote(hInstall
)))
1364 return ERROR_INVALID_HANDLE
;
1366 component
= SysAllocString(szComponent
);
1368 return ERROR_OUTOFMEMORY
;
1370 hr
= remote_SetComponentState(remote
, component
, iState
);
1372 SysFreeString(component
);
1376 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1377 return HRESULT_CODE(hr
);
1379 return ERROR_FUNCTION_FAILED
;
1382 return ERROR_SUCCESS
;
1385 ret
= MSI_SetComponentStateW(package
, szComponent
, iState
);
1386 msiobj_release(&package
->hdr
);
1390 /***********************************************************************
1391 * MsiGetComponentStateW (MSI.@)
1393 UINT WINAPI
MsiGetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
1394 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1396 MSIPACKAGE
* package
;
1399 TRACE("%d %s %p %p\n", hInstall
, debugstr_w(szComponent
),
1400 piInstalled
, piAction
);
1402 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1409 if (!(remote
= msi_get_remote(hInstall
)))
1410 return ERROR_INVALID_HANDLE
;
1412 component
= SysAllocString(szComponent
);
1414 return ERROR_OUTOFMEMORY
;
1416 hr
= remote_GetComponentState(remote
, component
, piInstalled
, piAction
);
1418 SysFreeString(component
);
1422 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1423 return HRESULT_CODE(hr
);
1425 return ERROR_FUNCTION_FAILED
;
1428 return ERROR_SUCCESS
;
1431 ret
= MSI_GetComponentStateW( package
, szComponent
, piInstalled
, piAction
);
1432 msiobj_release( &package
->hdr
);
1436 /***********************************************************************
1437 * MsiGetLanguage (MSI.@)
1439 LANGID WINAPI
MsiGetLanguage(MSIHANDLE hInstall
)
1441 MSIPACKAGE
* package
;
1444 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1451 if (!(remote
= msi_get_remote(hInstall
)))
1452 return ERROR_INVALID_HANDLE
;
1454 hr
= remote_GetLanguage(remote
, &lang
);
1462 langid
= msi_get_property_int( package
->db
, szProductLanguage
, 0 );
1463 msiobj_release( &package
->hdr
);
1467 UINT
MSI_SetInstallLevel( MSIPACKAGE
*package
, int iInstallLevel
)
1469 static const WCHAR fmt
[] = { '%','d',0 };
1474 TRACE("%p %i\n", package
, iInstallLevel
);
1476 if (iInstallLevel
> 32767)
1477 return ERROR_INVALID_PARAMETER
;
1479 if (iInstallLevel
< 1)
1480 return MSI_SetFeatureStates( package
);
1482 len
= sprintfW( level
, fmt
, iInstallLevel
);
1483 r
= msi_set_property( package
->db
, szInstallLevel
, level
, len
);
1484 if ( r
== ERROR_SUCCESS
)
1485 r
= MSI_SetFeatureStates( package
);
1490 /***********************************************************************
1491 * MsiSetInstallLevel (MSI.@)
1493 UINT WINAPI
MsiSetInstallLevel(MSIHANDLE hInstall
, int iInstallLevel
)
1495 MSIPACKAGE
* package
;
1498 TRACE("%d %i\n", hInstall
, iInstallLevel
);
1500 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1506 if (!(remote
= msi_get_remote(hInstall
)))
1507 return ERROR_INVALID_HANDLE
;
1509 hr
= remote_SetInstallLevel(remote
, iInstallLevel
);
1513 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1514 return HRESULT_CODE(hr
);
1516 return ERROR_FUNCTION_FAILED
;
1519 return ERROR_SUCCESS
;
1522 r
= MSI_SetInstallLevel( package
, iInstallLevel
);
1524 msiobj_release( &package
->hdr
);
1529 /***********************************************************************
1530 * MsiGetFeatureValidStatesW (MSI.@)
1532 UINT WINAPI
MsiGetFeatureValidStatesW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
1533 LPDWORD pInstallState
)
1535 if(pInstallState
) *pInstallState
= 1<<INSTALLSTATE_LOCAL
;
1536 FIXME("%d %s %p stub returning %d\n",
1537 hInstall
, debugstr_w(szFeature
), pInstallState
, pInstallState
? *pInstallState
: 0);
1539 return ERROR_SUCCESS
;
1542 /***********************************************************************
1543 * MsiGetFeatureValidStatesA (MSI.@)
1545 UINT WINAPI
MsiGetFeatureValidStatesA(MSIHANDLE hInstall
, LPCSTR szFeature
,
1546 LPDWORD pInstallState
)
1549 LPWSTR szwFeature
= strdupAtoW(szFeature
);
1551 ret
= MsiGetFeatureValidStatesW(hInstall
, szwFeature
, pInstallState
);
1553 msi_free(szwFeature
);