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/exception.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
;
85 ret
= remote_DoAction(remote
, szAction
);
89 ret
= GetExceptionCode();
96 ret
= ACTION_PerformAction(package
, szAction
);
97 msiobj_release( &package
->hdr
);
102 /***********************************************************************
103 * MsiSequenceA (MSI.@)
105 UINT WINAPI
MsiSequenceA( MSIHANDLE hInstall
, LPCSTR szTable
, INT iSequenceMode
)
110 TRACE("%s, %d\n", debugstr_a(szTable
), iSequenceMode
);
112 szwTable
= strdupAtoW(szTable
);
113 if (szTable
&& !szwTable
)
114 return ERROR_FUNCTION_FAILED
;
116 ret
= MsiSequenceW( hInstall
, szwTable
, iSequenceMode
);
117 msi_free( szwTable
);
121 /***********************************************************************
122 * MsiSequenceW (MSI.@)
124 UINT WINAPI
MsiSequenceW( MSIHANDLE hInstall
, LPCWSTR szTable
, INT iSequenceMode
)
129 TRACE("%s, %d\n", debugstr_w(szTable
), iSequenceMode
);
132 return ERROR_INVALID_PARAMETER
;
134 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
139 if (!(remote
= msi_get_remote(hInstall
)))
140 return ERROR_INVALID_HANDLE
;
144 ret
= remote_Sequence(remote
, szTable
, iSequenceMode
);
148 ret
= GetExceptionCode();
154 ret
= MSI_Sequence( package
, szTable
);
155 msiobj_release( &package
->hdr
);
159 UINT
msi_strcpy_to_awstring( const WCHAR
*str
, int len
, awstring
*awbuf
, DWORD
*sz
)
161 UINT r
= ERROR_SUCCESS
;
163 if (awbuf
->str
.w
&& !sz
)
164 return ERROR_INVALID_PARAMETER
;
166 return ERROR_SUCCESS
;
168 if (len
< 0) len
= lstrlenW( str
);
170 if (awbuf
->unicode
&& awbuf
->str
.w
)
172 memcpy( awbuf
->str
.w
, str
, min(len
+ 1, *sz
) * sizeof(WCHAR
) );
173 if (*sz
&& len
>= *sz
)
174 awbuf
->str
.w
[*sz
- 1] = 0;
178 int lenA
= WideCharToMultiByte( CP_ACP
, 0, str
, len
+ 1, NULL
, 0, NULL
, NULL
);
180 WideCharToMultiByte( CP_ACP
, 0, str
, len
+ 1, awbuf
->str
.a
, *sz
, NULL
, NULL
);
181 if (awbuf
->str
.a
&& *sz
&& lenA
>= *sz
)
182 awbuf
->str
.a
[*sz
- 1] = 0;
185 if (awbuf
->str
.w
&& len
>= *sz
)
191 UINT
msi_strncpyWtoA(const WCHAR
*str
, int lenW
, char *buf
, DWORD
*sz
, BOOL remote
)
193 UINT r
= ERROR_SUCCESS
;
197 return buf
? ERROR_INVALID_PARAMETER
: ERROR_SUCCESS
;
199 if (lenW
< 0) lenW
= lstrlenW(str
);
200 lenA
= WideCharToMultiByte(CP_ACP
, 0, str
, lenW
+ 1, NULL
, 0, NULL
, NULL
);
201 WideCharToMultiByte(CP_ACP
, 0, str
, lenW
+ 1, buf
, *sz
, NULL
, NULL
);
203 if (buf
&& lenA
>= *sz
)
205 if (*sz
) buf
[*sz
- 1] = 0;
208 if (remote
&& lenA
>= *sz
)
214 UINT
msi_strncpyW(const WCHAR
*str
, int len
, WCHAR
*buf
, DWORD
*sz
)
216 UINT r
= ERROR_SUCCESS
;
219 return buf
? ERROR_INVALID_PARAMETER
: ERROR_SUCCESS
;
221 if (len
< 0) len
= lstrlenW(str
);
223 memcpy(buf
, str
, min(len
+ 1, *sz
) * sizeof(WCHAR
));
224 if (buf
&& len
>= *sz
)
226 if (*sz
) buf
[*sz
- 1] = 0;
233 const WCHAR
*msi_get_target_folder( MSIPACKAGE
*package
, const WCHAR
*name
)
235 MSIFOLDER
*folder
= msi_get_loaded_folder( package
, name
);
237 if (!folder
) return NULL
;
238 if (!folder
->ResolvedTarget
)
240 MSIFOLDER
*parent
= folder
;
241 while (parent
->Parent
&& wcscmp( parent
->Parent
, parent
->Directory
))
243 parent
= msi_get_loaded_folder( package
, parent
->Parent
);
245 msi_resolve_target_folder( package
, parent
->Directory
, TRUE
);
247 return folder
->ResolvedTarget
;
250 /***********************************************************************
251 * MsiGetTargetPathA (MSI.@)
253 UINT WINAPI
MsiGetTargetPathA(MSIHANDLE hinst
, const char *folder
, char *buf
, DWORD
*sz
)
260 TRACE("%s %p %p\n", debugstr_a(folder
), buf
, sz
);
263 return ERROR_INVALID_PARAMETER
;
265 if (!(folderW
= strdupAtoW(folder
)))
266 return ERROR_OUTOFMEMORY
;
268 package
= msihandle2msiinfo(hinst
, MSIHANDLETYPE_PACKAGE
);
274 if (!(remote
= msi_get_remote(hinst
)))
277 return ERROR_INVALID_HANDLE
;
282 r
= remote_GetTargetPath(remote
, folderW
, &path
);
286 r
= GetExceptionCode();
291 r
= msi_strncpyWtoA(path
, -1, buf
, sz
, TRUE
);
293 midl_user_free(path
);
298 path
= msi_get_target_folder(package
, folderW
);
300 r
= msi_strncpyWtoA(path
, -1, buf
, sz
, FALSE
);
305 msiobj_release(&package
->hdr
);
309 /***********************************************************************
310 * MsiGetTargetPathW (MSI.@)
312 UINT WINAPI
MsiGetTargetPathW(MSIHANDLE hinst
, const WCHAR
*folder
, WCHAR
*buf
, DWORD
*sz
)
318 TRACE("%s %p %p\n", debugstr_w(folder
), buf
, sz
);
321 return ERROR_INVALID_PARAMETER
;
323 package
= msihandle2msiinfo(hinst
, MSIHANDLETYPE_PACKAGE
);
329 if (!(remote
= msi_get_remote(hinst
)))
330 return ERROR_INVALID_HANDLE
;
334 r
= remote_GetTargetPath(remote
, folder
, &path
);
338 r
= GetExceptionCode();
343 r
= msi_strncpyW(path
, -1, buf
, sz
);
345 midl_user_free(path
);
349 path
= msi_get_target_folder(package
, folder
);
351 r
= msi_strncpyW(path
, -1, buf
, sz
);
355 msiobj_release(&package
->hdr
);
359 static WCHAR
*get_source_root( MSIPACKAGE
*package
)
361 msi_set_sourcedir_props( package
, FALSE
);
362 return msi_dup_property( package
->db
, L
"SourceDir" );
365 WCHAR
*msi_resolve_source_folder( MSIPACKAGE
*package
, const WCHAR
*name
, MSIFOLDER
**folder
)
368 LPWSTR p
, path
= NULL
, parent
;
370 TRACE("working to resolve %s\n", debugstr_w(name
));
372 if (!wcscmp( name
, L
"SourceDir" )) name
= L
"TARGETDIR";
373 if (!(f
= msi_get_loaded_folder( package
, name
))) return NULL
;
375 /* special resolving for root dir */
376 if (!wcscmp( name
, L
"TARGETDIR" ) && !f
->ResolvedSource
)
378 f
->ResolvedSource
= get_source_root( package
);
380 if (folder
) *folder
= f
;
381 if (f
->ResolvedSource
)
383 path
= strdupW( f
->ResolvedSource
);
384 TRACE(" already resolved to %s\n", debugstr_w(path
));
387 if (!f
->Parent
) return path
;
389 TRACE(" ! parent is %s\n", debugstr_w(parent
));
391 p
= msi_resolve_source_folder( package
, parent
, NULL
);
393 if (package
->WordCount
& msidbSumInfoSourceTypeCompressed
)
394 path
= get_source_root( package
);
395 else if (package
->WordCount
& msidbSumInfoSourceTypeSFN
)
396 path
= msi_build_directory_name( 3, p
, f
->SourceShortPath
, NULL
);
398 path
= msi_build_directory_name( 3, p
, f
->SourceLongPath
, NULL
);
400 TRACE("-> %s\n", debugstr_w(path
));
401 f
->ResolvedSource
= strdupW( path
);
407 /***********************************************************************
408 * MsiGetSourcePathA (MSI.@)
410 UINT WINAPI
MsiGetSourcePathA(MSIHANDLE hinst
, const char *folder
, char *buf
, DWORD
*sz
)
413 WCHAR
*path
, *folderW
;
416 TRACE("%s %p %p\n", debugstr_a(folder
), buf
, sz
);
419 return ERROR_INVALID_PARAMETER
;
421 if (!(folderW
= strdupAtoW(folder
)))
422 return ERROR_OUTOFMEMORY
;
424 package
= msihandle2msiinfo(hinst
, MSIHANDLETYPE_PACKAGE
);
430 if (!(remote
= msi_get_remote(hinst
)))
433 return ERROR_INVALID_HANDLE
;
438 r
= remote_GetSourcePath(remote
, folderW
, &path
);
442 r
= GetExceptionCode();
447 r
= msi_strncpyWtoA(path
, -1, buf
, sz
, TRUE
);
449 midl_user_free(path
);
454 path
= msi_resolve_source_folder(package
, folderW
, NULL
);
456 r
= msi_strncpyWtoA(path
, -1, buf
, sz
, FALSE
);
462 msiobj_release(&package
->hdr
);
466 /***********************************************************************
467 * MsiGetSourcePathW (MSI.@)
469 UINT WINAPI
MsiGetSourcePathW(MSIHANDLE hinst
, const WCHAR
*folder
, WCHAR
*buf
, DWORD
*sz
)
475 TRACE("%s %p %p\n", debugstr_w(folder
), buf
, sz
);
478 return ERROR_INVALID_PARAMETER
;
480 package
= msihandle2msiinfo(hinst
, MSIHANDLETYPE_PACKAGE
);
486 if (!(remote
= msi_get_remote(hinst
)))
487 return ERROR_INVALID_HANDLE
;
491 r
= remote_GetSourcePath(remote
, folder
, &path
);
495 r
= GetExceptionCode();
500 r
= msi_strncpyW(path
, -1, buf
, sz
);
502 midl_user_free(path
);
506 path
= msi_resolve_source_folder(package
, folder
, NULL
);
508 r
= msi_strncpyW(path
, -1, buf
, sz
);
513 msiobj_release(&package
->hdr
);
517 /***********************************************************************
518 * MsiSetTargetPathA (MSI.@)
520 UINT WINAPI
MsiSetTargetPathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
521 LPCSTR szFolderPath
)
523 LPWSTR szwFolder
= NULL
, szwFolderPath
= NULL
;
524 UINT rc
= ERROR_OUTOFMEMORY
;
526 if ( !szFolder
|| !szFolderPath
)
527 return ERROR_INVALID_PARAMETER
;
529 szwFolder
= strdupAtoW(szFolder
);
530 szwFolderPath
= strdupAtoW(szFolderPath
);
531 if (!szwFolder
|| !szwFolderPath
)
534 rc
= MsiSetTargetPathW( hInstall
, szwFolder
, szwFolderPath
);
538 msi_free(szwFolderPath
);
543 static void set_target_path( MSIPACKAGE
*package
, MSIFOLDER
*folder
, const WCHAR
*path
)
549 if (!(target_path
= msi_normalize_path( path
))) return;
550 if (wcscmp( target_path
, folder
->ResolvedTarget
))
552 msi_free( folder
->ResolvedTarget
);
553 folder
->ResolvedTarget
= target_path
;
554 msi_set_property( package
->db
, folder
->Directory
, folder
->ResolvedTarget
, -1 );
556 LIST_FOR_EACH_ENTRY( fl
, &folder
->children
, FolderList
, entry
)
559 msi_resolve_target_folder( package
, child
->Directory
, FALSE
);
562 else msi_free( target_path
);
565 UINT
MSI_SetTargetPathW( MSIPACKAGE
*package
, LPCWSTR szFolder
, LPCWSTR szFolderPath
)
571 TRACE("%p %s %s\n", package
, debugstr_w(szFolder
), debugstr_w(szFolderPath
));
573 attrib
= msi_get_file_attributes( package
, szFolderPath
);
574 /* native MSI tests writeability by making temporary files at each drive */
575 if (attrib
!= INVALID_FILE_ATTRIBUTES
&&
576 (attrib
& FILE_ATTRIBUTE_OFFLINE
|| attrib
& FILE_ATTRIBUTE_READONLY
))
578 return ERROR_FUNCTION_FAILED
;
580 if (!(folder
= msi_get_loaded_folder( package
, szFolder
))) return ERROR_DIRECTORY
;
582 set_target_path( package
, folder
, szFolderPath
);
584 LIST_FOR_EACH_ENTRY( file
, &package
->files
, MSIFILE
, entry
)
587 MSICOMPONENT
*comp
= file
->Component
;
589 if (!comp
->Enabled
|| msi_is_global_assembly( comp
)) continue;
591 dir
= msi_get_target_folder( package
, comp
->Directory
);
592 msi_free( file
->TargetPath
);
593 file
->TargetPath
= msi_build_directory_name( 2, dir
, file
->FileName
);
595 return ERROR_SUCCESS
;
598 /***********************************************************************
599 * MsiSetTargetPathW (MSI.@)
601 UINT WINAPI
MsiSetTargetPathW(MSIHANDLE hInstall
, LPCWSTR szFolder
,
602 LPCWSTR szFolderPath
)
607 TRACE("%s %s\n",debugstr_w(szFolder
),debugstr_w(szFolderPath
));
609 if ( !szFolder
|| !szFolderPath
)
610 return ERROR_INVALID_PARAMETER
;
612 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
617 if (!(remote
= msi_get_remote(hInstall
)))
618 return ERROR_INVALID_HANDLE
;
622 ret
= remote_SetTargetPath(remote
, szFolder
, szFolderPath
);
626 ret
= GetExceptionCode();
633 ret
= MSI_SetTargetPathW( package
, szFolder
, szFolderPath
);
634 msiobj_release( &package
->hdr
);
638 /***********************************************************************
641 * Returns an internal installer state (if it is running in a mode iRunMode)
644 * hInstall [I] Handle to the installation
645 * hRunMode [I] Checking run mode
646 * MSIRUNMODE_ADMIN Administrative mode
647 * MSIRUNMODE_ADVERTISE Advertisement mode
648 * MSIRUNMODE_MAINTENANCE Maintenance mode
649 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
650 * MSIRUNMODE_LOGENABLED Log file is writing
651 * MSIRUNMODE_OPERATIONS Operations in progress??
652 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
653 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
654 * MSIRUNMODE_CABINET Files from cabinet are installed
655 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed
656 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed
657 * MSIRUNMODE_RESERVED11 Reserved
658 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
659 * MSIRUNMODE_ZAWENABLED Demand installation is supported
660 * MSIRUNMODE_RESERVED14 Reserved
661 * MSIRUNMODE_RESERVED15 Reserved
662 * MSIRUNMODE_SCHEDULED called from install script
663 * MSIRUNMODE_ROLLBACK called from rollback script
664 * MSIRUNMODE_COMMIT called from commit script
668 * Not in the state: FALSE
671 BOOL WINAPI
MsiGetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
)
676 TRACE("%d %d\n", hInstall
, iRunMode
);
678 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
683 if (!(remote
= msi_get_remote(hInstall
)))
688 r
= remote_GetMode(remote
, iRunMode
);
701 case MSIRUNMODE_ADMIN
:
702 FIXME("no support for administrative installs\n");
705 case MSIRUNMODE_ADVERTISE
:
706 FIXME("no support for advertised installs\n");
709 case MSIRUNMODE_WINDOWS9X
:
710 if (GetVersion() & 0x80000000)
714 case MSIRUNMODE_OPERATIONS
:
715 case MSIRUNMODE_RESERVED11
:
716 case MSIRUNMODE_RESERVED14
:
717 case MSIRUNMODE_RESERVED15
:
720 case MSIRUNMODE_SCHEDULED
:
721 r
= package
->scheduled_action_running
;
724 case MSIRUNMODE_ROLLBACK
:
725 r
= package
->rollback_action_running
;
728 case MSIRUNMODE_COMMIT
:
729 r
= package
->commit_action_running
;
732 case MSIRUNMODE_MAINTENANCE
:
733 r
= msi_get_property_int( package
->db
, L
"Installed", 0 ) != 0;
736 case MSIRUNMODE_ROLLBACKENABLED
:
737 r
= msi_get_property_int( package
->db
, L
"RollbackDisabled", 0 ) == 0;
740 case MSIRUNMODE_REBOOTATEND
:
741 r
= package
->need_reboot_at_end
;
744 case MSIRUNMODE_REBOOTNOW
:
745 r
= package
->need_reboot_now
;
748 case MSIRUNMODE_LOGENABLED
:
749 r
= (package
->log_file
!= INVALID_HANDLE_VALUE
);
753 FIXME("unimplemented run mode: %d\n", iRunMode
);
757 msiobj_release( &package
->hdr
);
761 /***********************************************************************
764 UINT WINAPI
MsiSetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
, BOOL fState
)
769 TRACE("%d %d %d\n", hInstall
, iRunMode
, fState
);
771 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
776 if (!(remote
= msi_get_remote(hInstall
)))
781 r
= remote_SetMode(remote
, iRunMode
, fState
);
785 r
= GetExceptionCode();
794 case MSIRUNMODE_REBOOTATEND
:
795 package
->need_reboot_at_end
= (fState
!= 0);
799 case MSIRUNMODE_REBOOTNOW
:
800 package
->need_reboot_now
= (fState
!= 0);
805 r
= ERROR_ACCESS_DENIED
;
808 msiobj_release( &package
->hdr
);
812 /***********************************************************************
813 * MsiSetFeatureStateA (MSI.@)
815 * According to the docs, when this is called it immediately recalculates
816 * all the component states as well
818 UINT WINAPI
MsiSetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
821 LPWSTR szwFeature
= NULL
;
824 szwFeature
= strdupAtoW(szFeature
);
826 rc
= MsiSetFeatureStateW(hInstall
,szwFeature
, iState
);
828 msi_free(szwFeature
);
833 /* update component state based on a feature change */
834 void ACTION_UpdateComponentStates( MSIPACKAGE
*package
, MSIFEATURE
*feature
)
836 INSTALLSTATE newstate
;
839 newstate
= feature
->ActionRequest
;
840 if (newstate
== INSTALLSTATE_ABSENT
) newstate
= INSTALLSTATE_UNKNOWN
;
842 LIST_FOR_EACH_ENTRY(cl
, &feature
->Components
, ComponentList
, entry
)
844 MSICOMPONENT
*component
= cl
->component
;
846 if (!component
->Enabled
) continue;
848 TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
849 newstate
, debugstr_w(component
->Component
), component
->Installed
,
850 component
->Action
, component
->ActionRequest
);
852 if (newstate
== INSTALLSTATE_LOCAL
)
854 component
->Action
= INSTALLSTATE_LOCAL
;
855 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
859 ComponentList
*clist
;
862 component
->hasLocalFeature
= FALSE
;
864 component
->Action
= newstate
;
865 component
->ActionRequest
= newstate
;
866 /* if any other feature wants it local we need to set it local */
867 LIST_FOR_EACH_ENTRY(f
, &package
->features
, MSIFEATURE
, entry
)
869 if ( f
->ActionRequest
!= INSTALLSTATE_LOCAL
&&
870 f
->ActionRequest
!= INSTALLSTATE_SOURCE
)
874 LIST_FOR_EACH_ENTRY(clist
, &f
->Components
, ComponentList
, entry
)
876 if (clist
->component
== component
&&
877 (f
->ActionRequest
== INSTALLSTATE_LOCAL
||
878 f
->ActionRequest
== INSTALLSTATE_SOURCE
))
880 TRACE("Saved by %s\n", debugstr_w(f
->Feature
));
881 component
->hasLocalFeature
= TRUE
;
883 if (component
->Attributes
& msidbComponentAttributesOptional
)
885 if (f
->Attributes
& msidbFeatureAttributesFavorSource
)
887 component
->Action
= INSTALLSTATE_SOURCE
;
888 component
->ActionRequest
= INSTALLSTATE_SOURCE
;
892 component
->Action
= INSTALLSTATE_LOCAL
;
893 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
896 else if (component
->Attributes
& msidbComponentAttributesSourceOnly
)
898 component
->Action
= INSTALLSTATE_SOURCE
;
899 component
->ActionRequest
= INSTALLSTATE_SOURCE
;
903 component
->Action
= INSTALLSTATE_LOCAL
;
904 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
910 TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
911 newstate
, debugstr_w(component
->Component
), component
->Installed
,
912 component
->Action
, component
->ActionRequest
);
916 UINT
MSI_SetFeatureStateW( MSIPACKAGE
*package
, LPCWSTR szFeature
, INSTALLSTATE iState
)
918 UINT rc
= ERROR_SUCCESS
;
919 MSIFEATURE
*feature
, *child
;
921 TRACE("%s %i\n", debugstr_w(szFeature
), iState
);
923 feature
= msi_get_loaded_feature( package
, szFeature
);
925 return ERROR_UNKNOWN_FEATURE
;
927 if (iState
== INSTALLSTATE_ADVERTISED
&&
928 feature
->Attributes
& msidbFeatureAttributesDisallowAdvertise
)
929 return ERROR_FUNCTION_FAILED
;
931 feature
->ActionRequest
= iState
;
933 ACTION_UpdateComponentStates( package
, feature
);
935 /* update all the features that are children of this feature */
936 LIST_FOR_EACH_ENTRY( child
, &package
->features
, MSIFEATURE
, entry
)
938 if (child
->Feature_Parent
&& !wcscmp( szFeature
, child
->Feature_Parent
))
939 MSI_SetFeatureStateW(package
, child
->Feature
, iState
);
945 /***********************************************************************
946 * MsiSetFeatureStateW (MSI.@)
948 UINT WINAPI
MsiSetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
952 UINT rc
= ERROR_SUCCESS
;
954 TRACE("%s %i\n",debugstr_w(szFeature
), iState
);
957 return ERROR_UNKNOWN_FEATURE
;
959 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
964 if (!(remote
= msi_get_remote(hInstall
)))
965 return ERROR_INVALID_HANDLE
;
969 rc
= remote_SetFeatureState(remote
, szFeature
, iState
);
973 rc
= GetExceptionCode();
980 rc
= MSI_SetFeatureStateW(package
,szFeature
,iState
);
982 msiobj_release( &package
->hdr
);
986 /***********************************************************************
987 * MsiSetFeatureAttributesA (MSI.@)
989 UINT WINAPI
MsiSetFeatureAttributesA( MSIHANDLE handle
, LPCSTR feature
, DWORD attrs
)
992 WCHAR
*featureW
= NULL
;
994 TRACE("%u, %s, 0x%08x\n", handle
, debugstr_a(feature
), attrs
);
996 if (feature
&& !(featureW
= strdupAtoW( feature
))) return ERROR_OUTOFMEMORY
;
998 r
= MsiSetFeatureAttributesW( handle
, featureW
, attrs
);
999 msi_free( featureW
);
1003 static DWORD
unmap_feature_attributes( DWORD attrs
)
1007 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORLOCAL
) ret
= msidbFeatureAttributesFavorLocal
;
1008 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORSOURCE
) ret
|= msidbFeatureAttributesFavorSource
;
1009 if (attrs
& INSTALLFEATUREATTRIBUTE_FOLLOWPARENT
) ret
|= msidbFeatureAttributesFollowParent
;
1010 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORADVERTISE
) ret
|= msidbFeatureAttributesFavorAdvertise
;
1011 if (attrs
& INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE
) ret
|= msidbFeatureAttributesDisallowAdvertise
;
1012 if (attrs
& INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE
) ret
|= msidbFeatureAttributesNoUnsupportedAdvertise
;
1016 /***********************************************************************
1017 * MsiSetFeatureAttributesW (MSI.@)
1019 UINT WINAPI
MsiSetFeatureAttributesW( MSIHANDLE handle
, LPCWSTR name
, DWORD attrs
)
1021 MSIPACKAGE
*package
;
1022 MSIFEATURE
*feature
;
1025 TRACE("%u, %s, 0x%08x\n", handle
, debugstr_w(name
), attrs
);
1027 if (!name
|| !name
[0]) return ERROR_UNKNOWN_FEATURE
;
1029 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
1030 return ERROR_INVALID_HANDLE
;
1032 costing
= msi_dup_property( package
->db
, L
"CostingComplete" );
1033 if (!costing
|| !wcscmp( costing
, L
"1" ))
1035 msi_free( costing
);
1036 msiobj_release( &package
->hdr
);
1037 return ERROR_FUNCTION_FAILED
;
1039 msi_free( costing
);
1040 if (!(feature
= msi_get_loaded_feature( package
, name
)))
1042 msiobj_release( &package
->hdr
);
1043 return ERROR_UNKNOWN_FEATURE
;
1045 feature
->Attributes
= unmap_feature_attributes( attrs
);
1046 msiobj_release( &package
->hdr
);
1047 return ERROR_SUCCESS
;
1050 /***********************************************************************
1051 * MsiGetFeatureStateA (MSI.@)
1053 UINT WINAPI
MsiGetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
1054 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1056 LPWSTR szwFeature
= NULL
;
1059 if (szFeature
&& !(szwFeature
= strdupAtoW(szFeature
))) return ERROR_OUTOFMEMORY
;
1061 rc
= MsiGetFeatureStateW(hInstall
, szwFeature
, piInstalled
, piAction
);
1062 msi_free( szwFeature
);
1066 UINT
MSI_GetFeatureStateW(MSIPACKAGE
*package
, LPCWSTR szFeature
,
1067 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1069 MSIFEATURE
*feature
;
1071 feature
= msi_get_loaded_feature(package
,szFeature
);
1073 return ERROR_UNKNOWN_FEATURE
;
1076 *piInstalled
= feature
->Installed
;
1079 *piAction
= feature
->ActionRequest
;
1081 TRACE("returning %i %i\n", feature
->Installed
, feature
->ActionRequest
);
1083 return ERROR_SUCCESS
;
1086 /***********************************************************************
1087 * MsiGetFeatureStateW (MSI.@)
1089 UINT WINAPI
MsiGetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
1090 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1092 MSIPACKAGE
* package
;
1095 TRACE("%d %s %p %p\n", hInstall
, debugstr_w(szFeature
), piInstalled
, piAction
);
1098 return ERROR_UNKNOWN_FEATURE
;
1100 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1105 if (!(remote
= msi_get_remote(hInstall
)))
1106 return ERROR_INVALID_HANDLE
;
1110 ret
= remote_GetFeatureState(remote
, szFeature
, piInstalled
, piAction
);
1112 __EXCEPT(rpc_filter
)
1114 ret
= GetExceptionCode();
1121 ret
= MSI_GetFeatureStateW(package
, szFeature
, piInstalled
, piAction
);
1122 msiobj_release( &package
->hdr
);
1126 /***********************************************************************
1127 * MsiGetFeatureCostA (MSI.@)
1129 UINT WINAPI
MsiGetFeatureCostA(MSIHANDLE hInstall
, LPCSTR szFeature
,
1130 MSICOSTTREE iCostTree
, INSTALLSTATE iState
, LPINT piCost
)
1132 LPWSTR szwFeature
= NULL
;
1135 szwFeature
= strdupAtoW(szFeature
);
1137 rc
= MsiGetFeatureCostW(hInstall
, szwFeature
, iCostTree
, iState
, piCost
);
1139 msi_free(szwFeature
);
1144 static INT
feature_cost( MSIFEATURE
*feature
)
1149 LIST_FOR_EACH_ENTRY( cl
, &feature
->Components
, ComponentList
, entry
)
1151 cost
+= cl
->component
->Cost
;
1156 UINT
MSI_GetFeatureCost( MSIPACKAGE
*package
, MSIFEATURE
*feature
, MSICOSTTREE tree
,
1157 INSTALLSTATE state
, LPINT cost
)
1159 TRACE("%s, %u, %d, %p\n", debugstr_w(feature
->Feature
), tree
, state
, cost
);
1164 case MSICOSTTREE_CHILDREN
:
1168 LIST_FOR_EACH_ENTRY( child
, &feature
->Children
, MSIFEATURE
, entry
)
1170 if (child
->ActionRequest
== state
)
1171 *cost
+= feature_cost( child
);
1175 case MSICOSTTREE_PARENTS
:
1177 const WCHAR
*feature_parent
= feature
->Feature_Parent
;
1180 MSIFEATURE
*parent
= msi_get_loaded_feature( package
, feature_parent
);
1184 if (parent
->ActionRequest
== state
)
1185 *cost
+= feature_cost( parent
);
1187 feature_parent
= parent
->Feature_Parent
;
1191 case MSICOSTTREE_SELFONLY
:
1192 if (feature
->ActionRequest
== state
)
1193 *cost
= feature_cost( feature
);
1197 WARN("unhandled cost tree %u\n", tree
);
1202 return ERROR_SUCCESS
;
1205 /***********************************************************************
1206 * MsiGetFeatureCostW (MSI.@)
1208 UINT WINAPI
MsiGetFeatureCostW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
1209 MSICOSTTREE iCostTree
, INSTALLSTATE iState
, LPINT piCost
)
1211 MSIPACKAGE
*package
;
1212 MSIFEATURE
*feature
;
1215 TRACE("(%d %s %i %i %p)\n", hInstall
, debugstr_w(szFeature
),
1216 iCostTree
, iState
, piCost
);
1219 return ERROR_INVALID_PARAMETER
;
1221 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1226 if (!(remote
= msi_get_remote(hInstall
)))
1227 return ERROR_INVALID_HANDLE
;
1231 ret
= remote_GetFeatureCost(remote
, szFeature
, iCostTree
, iState
, piCost
);
1233 __EXCEPT(rpc_filter
)
1235 ret
= GetExceptionCode();
1244 msiobj_release( &package
->hdr
);
1245 return ERROR_INVALID_PARAMETER
;
1248 feature
= msi_get_loaded_feature(package
, szFeature
);
1251 ret
= MSI_GetFeatureCost(package
, feature
, iCostTree
, iState
, piCost
);
1253 ret
= ERROR_UNKNOWN_FEATURE
;
1255 msiobj_release( &package
->hdr
);
1259 /***********************************************************************
1260 * MsiGetFeatureInfoA (MSI.@)
1262 UINT WINAPI
MsiGetFeatureInfoA( MSIHANDLE handle
, LPCSTR feature
, LPDWORD attrs
,
1263 LPSTR title
, LPDWORD title_len
, LPSTR help
, LPDWORD help_len
)
1266 WCHAR
*titleW
= NULL
, *helpW
= NULL
, *featureW
= NULL
;
1268 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle
, debugstr_a(feature
), attrs
, title
,
1269 title_len
, help
, help_len
);
1271 if (feature
&& !(featureW
= strdupAtoW( feature
))) return ERROR_OUTOFMEMORY
;
1273 if (title
&& title_len
&& !(titleW
= msi_alloc( *title_len
* sizeof(WCHAR
) )))
1275 msi_free( featureW
);
1276 return ERROR_OUTOFMEMORY
;
1278 if (help
&& help_len
&& !(helpW
= msi_alloc( *help_len
* sizeof(WCHAR
) )))
1280 msi_free( featureW
);
1282 return ERROR_OUTOFMEMORY
;
1284 r
= MsiGetFeatureInfoW( handle
, featureW
, attrs
, titleW
, title_len
, helpW
, help_len
);
1285 if (r
== ERROR_SUCCESS
)
1287 if (titleW
) WideCharToMultiByte( CP_ACP
, 0, titleW
, -1, title
, *title_len
+ 1, NULL
, NULL
);
1288 if (helpW
) WideCharToMultiByte( CP_ACP
, 0, helpW
, -1, help
, *help_len
+ 1, NULL
, NULL
);
1292 msi_free( featureW
);
1296 static DWORD
map_feature_attributes( DWORD attrs
)
1300 if (attrs
== msidbFeatureAttributesFavorLocal
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORLOCAL
;
1301 if (attrs
& msidbFeatureAttributesFavorSource
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORSOURCE
;
1302 if (attrs
& msidbFeatureAttributesFollowParent
) ret
|= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT
;
1303 if (attrs
& msidbFeatureAttributesFavorAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE
;
1304 if (attrs
& msidbFeatureAttributesDisallowAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE
;
1305 if (attrs
& msidbFeatureAttributesNoUnsupportedAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE
;
1309 static UINT
MSI_GetFeatureInfo( MSIPACKAGE
*package
, LPCWSTR name
, LPDWORD attrs
,
1310 LPWSTR title
, LPDWORD title_len
, LPWSTR help
, LPDWORD help_len
)
1312 UINT r
= ERROR_SUCCESS
;
1313 MSIFEATURE
*feature
= msi_get_loaded_feature( package
, name
);
1316 if (!feature
) return ERROR_UNKNOWN_FEATURE
;
1317 if (attrs
) *attrs
= map_feature_attributes( feature
->Attributes
);
1320 if (feature
->Title
) len
= lstrlenW( feature
->Title
);
1322 if (*title_len
<= len
)
1325 if (title
) r
= ERROR_MORE_DATA
;
1329 if (feature
->Title
) lstrcpyW( title
, feature
->Title
);
1336 if (feature
->Description
) len
= lstrlenW( feature
->Description
);
1338 if (*help_len
<= len
)
1341 if (help
) r
= ERROR_MORE_DATA
;
1345 if (feature
->Description
) lstrcpyW( help
, feature
->Description
);
1353 /***********************************************************************
1354 * MsiGetFeatureInfoW (MSI.@)
1356 UINT WINAPI
MsiGetFeatureInfoW( MSIHANDLE handle
, LPCWSTR feature
, LPDWORD attrs
,
1357 LPWSTR title
, LPDWORD title_len
, LPWSTR help
, LPDWORD help_len
)
1360 MSIPACKAGE
*package
;
1362 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle
, debugstr_w(feature
), attrs
, title
,
1363 title_len
, help
, help_len
);
1365 if (!feature
) return ERROR_INVALID_PARAMETER
;
1367 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
1368 return ERROR_INVALID_HANDLE
;
1370 /* features may not have been loaded yet */
1371 msi_load_all_components( package
);
1372 msi_load_all_features( package
);
1374 r
= MSI_GetFeatureInfo( package
, feature
, attrs
, title
, title_len
, help
, help_len
);
1375 msiobj_release( &package
->hdr
);
1379 /***********************************************************************
1380 * MsiSetComponentStateA (MSI.@)
1382 UINT WINAPI
MsiSetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
1383 INSTALLSTATE iState
)
1386 LPWSTR szwComponent
= strdupAtoW(szComponent
);
1388 rc
= MsiSetComponentStateW(hInstall
, szwComponent
, iState
);
1390 msi_free(szwComponent
);
1395 /***********************************************************************
1396 * MsiGetComponentStateA (MSI.@)
1398 UINT WINAPI
MsiGetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
1399 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1401 LPWSTR szwComponent
= NULL
;
1404 szwComponent
= strdupAtoW(szComponent
);
1406 rc
= MsiGetComponentStateW(hInstall
,szwComponent
,piInstalled
, piAction
);
1408 msi_free( szwComponent
);
1413 static UINT
MSI_SetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
1414 INSTALLSTATE iState
)
1418 TRACE("%p %s %d\n", package
, debugstr_w(szComponent
), iState
);
1420 comp
= msi_get_loaded_component(package
, szComponent
);
1422 return ERROR_UNKNOWN_COMPONENT
;
1425 comp
->Action
= iState
;
1427 return ERROR_SUCCESS
;
1430 UINT
MSI_GetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
1431 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1435 TRACE("%p %s %p %p\n", package
, debugstr_w(szComponent
),
1436 piInstalled
, piAction
);
1438 comp
= msi_get_loaded_component(package
,szComponent
);
1440 return ERROR_UNKNOWN_COMPONENT
;
1445 *piInstalled
= comp
->Installed
;
1447 *piInstalled
= INSTALLSTATE_UNKNOWN
;
1453 *piAction
= comp
->Action
;
1455 *piAction
= INSTALLSTATE_UNKNOWN
;
1458 TRACE("states (%i, %i)\n", comp
->Installed
, comp
->Action
);
1459 return ERROR_SUCCESS
;
1462 /***********************************************************************
1463 * MsiSetComponentStateW (MSI.@)
1465 UINT WINAPI
MsiSetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
1466 INSTALLSTATE iState
)
1468 MSIPACKAGE
* package
;
1472 return ERROR_UNKNOWN_COMPONENT
;
1474 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1479 if (!(remote
= msi_get_remote(hInstall
)))
1480 return ERROR_INVALID_HANDLE
;
1484 ret
= remote_SetComponentState(remote
, szComponent
, iState
);
1486 __EXCEPT(rpc_filter
)
1488 ret
= GetExceptionCode();
1495 ret
= MSI_SetComponentStateW(package
, szComponent
, iState
);
1496 msiobj_release(&package
->hdr
);
1500 /***********************************************************************
1501 * MsiGetComponentStateW (MSI.@)
1503 UINT WINAPI
MsiGetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
1504 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1506 MSIPACKAGE
* package
;
1509 TRACE("%d %s %p %p\n", hInstall
, debugstr_w(szComponent
),
1510 piInstalled
, piAction
);
1513 return ERROR_UNKNOWN_COMPONENT
;
1515 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1520 if (!(remote
= msi_get_remote(hInstall
)))
1521 return ERROR_INVALID_HANDLE
;
1525 ret
= remote_GetComponentState(remote
, szComponent
, piInstalled
, piAction
);
1527 __EXCEPT(rpc_filter
)
1529 ret
= GetExceptionCode();
1536 ret
= MSI_GetComponentStateW( package
, szComponent
, piInstalled
, piAction
);
1537 msiobj_release( &package
->hdr
);
1541 /***********************************************************************
1542 * MsiGetLanguage (MSI.@)
1544 LANGID WINAPI
MsiGetLanguage(MSIHANDLE hInstall
)
1546 MSIPACKAGE
* package
;
1549 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1554 if (!(remote
= msi_get_remote(hInstall
)))
1555 return ERROR_INVALID_HANDLE
;
1559 langid
= remote_GetLanguage(remote
);
1561 __EXCEPT(rpc_filter
)
1570 langid
= msi_get_property_int( package
->db
, L
"ProductLanguage", 0 );
1571 msiobj_release( &package
->hdr
);
1575 UINT
MSI_SetInstallLevel( MSIPACKAGE
*package
, int iInstallLevel
)
1581 TRACE("%p %i\n", package
, iInstallLevel
);
1583 if (iInstallLevel
> 32767)
1584 return ERROR_INVALID_PARAMETER
;
1586 if (iInstallLevel
< 1)
1587 return MSI_SetFeatureStates( package
);
1589 len
= swprintf( level
, ARRAY_SIZE(level
), L
"%d", iInstallLevel
);
1590 r
= msi_set_property( package
->db
, L
"INSTALLLEVEL", level
, len
);
1591 if ( r
== ERROR_SUCCESS
)
1592 r
= MSI_SetFeatureStates( package
);
1597 /***********************************************************************
1598 * MsiSetInstallLevel (MSI.@)
1600 UINT WINAPI
MsiSetInstallLevel(MSIHANDLE hInstall
, int iInstallLevel
)
1602 MSIPACKAGE
* package
;
1605 TRACE("%d %i\n", hInstall
, iInstallLevel
);
1607 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1612 if (!(remote
= msi_get_remote(hInstall
)))
1613 return ERROR_INVALID_HANDLE
;
1617 r
= remote_SetInstallLevel(remote
, iInstallLevel
);
1619 __EXCEPT(rpc_filter
)
1621 r
= GetExceptionCode();
1628 r
= MSI_SetInstallLevel( package
, iInstallLevel
);
1630 msiobj_release( &package
->hdr
);
1635 /***********************************************************************
1636 * MsiGetFeatureValidStatesW (MSI.@)
1638 UINT WINAPI
MsiGetFeatureValidStatesW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
1639 LPDWORD pInstallState
)
1641 if(pInstallState
) *pInstallState
= 1<<INSTALLSTATE_LOCAL
;
1642 FIXME("%d %s %p stub returning %d\n",
1643 hInstall
, debugstr_w(szFeature
), pInstallState
, pInstallState
? *pInstallState
: 0);
1645 return ERROR_SUCCESS
;
1648 /***********************************************************************
1649 * MsiGetFeatureValidStatesA (MSI.@)
1651 UINT WINAPI
MsiGetFeatureValidStatesA(MSIHANDLE hInstall
, LPCSTR szFeature
,
1652 LPDWORD pInstallState
)
1655 LPWSTR szwFeature
= strdupAtoW(szFeature
);
1657 ret
= MsiGetFeatureValidStatesW(hInstall
, szwFeature
, pInstallState
);
1659 msi_free(szwFeature
);