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/debug.h"
38 #include "wine/exception.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
42 /***********************************************************************
43 * MsiDoActionA (MSI.@)
45 UINT WINAPI
MsiDoActionA( MSIHANDLE hInstall
, LPCSTR szAction
)
50 TRACE("%s\n", debugstr_a(szAction
));
52 szwAction
= strdupAtoW(szAction
);
53 if (szAction
&& !szwAction
)
54 return ERROR_FUNCTION_FAILED
;
56 ret
= MsiDoActionW( hInstall
, szwAction
);
57 msi_free( szwAction
);
61 /***********************************************************************
62 * MsiDoActionW (MSI.@)
64 UINT WINAPI
MsiDoActionW( MSIHANDLE hInstall
, LPCWSTR szAction
)
69 TRACE("%s\n",debugstr_w(szAction
));
72 return ERROR_INVALID_PARAMETER
;
74 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
79 if (!(remote
= msi_get_remote(hInstall
)))
80 return ERROR_INVALID_HANDLE
;
84 ret
= remote_DoAction(remote
, szAction
);
88 ret
= GetExceptionCode();
95 ret
= ACTION_PerformAction(package
, szAction
);
96 msiobj_release( &package
->hdr
);
101 /***********************************************************************
102 * MsiSequenceA (MSI.@)
104 UINT WINAPI
MsiSequenceA( MSIHANDLE hInstall
, LPCSTR szTable
, INT iSequenceMode
)
109 TRACE("%s, %d\n", debugstr_a(szTable
), iSequenceMode
);
111 szwTable
= strdupAtoW(szTable
);
112 if (szTable
&& !szwTable
)
113 return ERROR_FUNCTION_FAILED
;
115 ret
= MsiSequenceW( hInstall
, szwTable
, iSequenceMode
);
116 msi_free( szwTable
);
120 /***********************************************************************
121 * MsiSequenceW (MSI.@)
123 UINT WINAPI
MsiSequenceW( MSIHANDLE hInstall
, LPCWSTR szTable
, INT iSequenceMode
)
128 TRACE("%s, %d\n", debugstr_w(szTable
), iSequenceMode
);
131 return ERROR_INVALID_PARAMETER
;
133 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
138 if (!(remote
= msi_get_remote(hInstall
)))
139 return ERROR_INVALID_HANDLE
;
143 ret
= remote_Sequence(remote
, szTable
, iSequenceMode
);
147 ret
= GetExceptionCode();
153 ret
= MSI_Sequence( package
, szTable
);
154 msiobj_release( &package
->hdr
);
158 UINT
msi_strcpy_to_awstring( const WCHAR
*str
, int len
, awstring
*awbuf
, DWORD
*sz
)
160 UINT r
= ERROR_SUCCESS
;
162 if (awbuf
->str
.w
&& !sz
)
163 return ERROR_INVALID_PARAMETER
;
165 return ERROR_SUCCESS
;
167 if (len
< 0) len
= lstrlenW( str
);
169 if (awbuf
->unicode
&& awbuf
->str
.w
)
171 memcpy( awbuf
->str
.w
, str
, min(len
+ 1, *sz
) * sizeof(WCHAR
) );
172 if (*sz
&& len
>= *sz
)
173 awbuf
->str
.w
[*sz
- 1] = 0;
177 int lenA
= WideCharToMultiByte( CP_ACP
, 0, str
, len
+ 1, NULL
, 0, NULL
, NULL
);
179 WideCharToMultiByte( CP_ACP
, 0, str
, len
+ 1, awbuf
->str
.a
, *sz
, NULL
, NULL
);
180 if (awbuf
->str
.a
&& *sz
&& lenA
>= *sz
)
181 awbuf
->str
.a
[*sz
- 1] = 0;
184 if (awbuf
->str
.w
&& len
>= *sz
)
190 UINT
msi_strncpyWtoA(const WCHAR
*str
, int lenW
, char *buf
, DWORD
*sz
, BOOL remote
)
192 UINT r
= ERROR_SUCCESS
;
196 return buf
? ERROR_INVALID_PARAMETER
: ERROR_SUCCESS
;
198 if (lenW
< 0) lenW
= lstrlenW(str
);
199 lenA
= WideCharToMultiByte(CP_ACP
, 0, str
, lenW
+ 1, NULL
, 0, NULL
, NULL
);
200 WideCharToMultiByte(CP_ACP
, 0, str
, lenW
+ 1, buf
, *sz
, NULL
, NULL
);
202 if (buf
&& lenA
>= *sz
)
204 if (*sz
) buf
[*sz
- 1] = 0;
207 if (remote
&& lenA
>= *sz
)
213 UINT
msi_strncpyW(const WCHAR
*str
, int len
, WCHAR
*buf
, DWORD
*sz
)
215 UINT r
= ERROR_SUCCESS
;
218 return buf
? ERROR_INVALID_PARAMETER
: ERROR_SUCCESS
;
220 if (len
< 0) len
= lstrlenW(str
);
222 memcpy(buf
, str
, min(len
+ 1, *sz
) * sizeof(WCHAR
));
223 if (buf
&& len
>= *sz
)
225 if (*sz
) buf
[*sz
- 1] = 0;
232 const WCHAR
*msi_get_target_folder( MSIPACKAGE
*package
, const WCHAR
*name
)
234 MSIFOLDER
*folder
= msi_get_loaded_folder( package
, name
);
236 if (!folder
) return NULL
;
237 if (!folder
->ResolvedTarget
)
239 MSIFOLDER
*parent
= folder
;
240 while (parent
->Parent
&& wcscmp( parent
->Parent
, parent
->Directory
))
242 parent
= msi_get_loaded_folder( package
, parent
->Parent
);
244 msi_resolve_target_folder( package
, parent
->Directory
, TRUE
);
246 return folder
->ResolvedTarget
;
249 /***********************************************************************
250 * MsiGetTargetPathA (MSI.@)
252 UINT WINAPI
MsiGetTargetPathA(MSIHANDLE hinst
, const char *folder
, char *buf
, DWORD
*sz
)
259 TRACE("%s %p %p\n", debugstr_a(folder
), buf
, sz
);
262 return ERROR_INVALID_PARAMETER
;
264 if (!(folderW
= strdupAtoW(folder
)))
265 return ERROR_OUTOFMEMORY
;
267 package
= msihandle2msiinfo(hinst
, MSIHANDLETYPE_PACKAGE
);
273 if (!(remote
= msi_get_remote(hinst
)))
276 return ERROR_INVALID_HANDLE
;
281 r
= remote_GetTargetPath(remote
, folderW
, &path
);
285 r
= GetExceptionCode();
290 r
= msi_strncpyWtoA(path
, -1, buf
, sz
, TRUE
);
292 midl_user_free(path
);
297 path
= msi_get_target_folder(package
, folderW
);
299 r
= msi_strncpyWtoA(path
, -1, buf
, sz
, FALSE
);
304 msiobj_release(&package
->hdr
);
308 /***********************************************************************
309 * MsiGetTargetPathW (MSI.@)
311 UINT WINAPI
MsiGetTargetPathW(MSIHANDLE hinst
, const WCHAR
*folder
, WCHAR
*buf
, DWORD
*sz
)
317 TRACE("%s %p %p\n", debugstr_w(folder
), buf
, sz
);
320 return ERROR_INVALID_PARAMETER
;
322 package
= msihandle2msiinfo(hinst
, MSIHANDLETYPE_PACKAGE
);
328 if (!(remote
= msi_get_remote(hinst
)))
329 return ERROR_INVALID_HANDLE
;
333 r
= remote_GetTargetPath(remote
, folder
, &path
);
337 r
= GetExceptionCode();
342 r
= msi_strncpyW(path
, -1, buf
, sz
);
344 midl_user_free(path
);
348 path
= msi_get_target_folder(package
, folder
);
350 r
= msi_strncpyW(path
, -1, buf
, sz
);
354 msiobj_release(&package
->hdr
);
358 static WCHAR
*get_source_root( MSIPACKAGE
*package
)
360 msi_set_sourcedir_props( package
, FALSE
);
361 return msi_dup_property( package
->db
, L
"SourceDir" );
364 WCHAR
*msi_resolve_source_folder( MSIPACKAGE
*package
, const WCHAR
*name
, MSIFOLDER
**folder
)
367 LPWSTR p
, path
= NULL
, parent
;
369 TRACE("working to resolve %s\n", debugstr_w(name
));
371 if (!wcscmp( name
, L
"SourceDir" )) name
= L
"TARGETDIR";
372 if (!(f
= msi_get_loaded_folder( package
, name
))) return NULL
;
374 /* special resolving for root dir */
375 if (!wcscmp( name
, L
"TARGETDIR" ) && !f
->ResolvedSource
)
377 f
->ResolvedSource
= get_source_root( package
);
379 if (folder
) *folder
= f
;
380 if (f
->ResolvedSource
)
382 path
= strdupW( f
->ResolvedSource
);
383 TRACE(" already resolved to %s\n", debugstr_w(path
));
386 if (!f
->Parent
) return path
;
388 TRACE(" ! parent is %s\n", debugstr_w(parent
));
390 p
= msi_resolve_source_folder( package
, parent
, NULL
);
392 if (package
->WordCount
& msidbSumInfoSourceTypeCompressed
)
393 path
= get_source_root( package
);
394 else if (package
->WordCount
& msidbSumInfoSourceTypeSFN
)
395 path
= msi_build_directory_name( 3, p
, f
->SourceShortPath
, NULL
);
397 path
= msi_build_directory_name( 3, p
, f
->SourceLongPath
, NULL
);
399 TRACE("-> %s\n", debugstr_w(path
));
400 f
->ResolvedSource
= strdupW( path
);
406 /***********************************************************************
407 * MsiGetSourcePathA (MSI.@)
409 UINT WINAPI
MsiGetSourcePathA(MSIHANDLE hinst
, const char *folder
, char *buf
, DWORD
*sz
)
412 WCHAR
*path
, *folderW
;
415 TRACE("%s %p %p\n", debugstr_a(folder
), buf
, sz
);
418 return ERROR_INVALID_PARAMETER
;
420 if (!(folderW
= strdupAtoW(folder
)))
421 return ERROR_OUTOFMEMORY
;
423 package
= msihandle2msiinfo(hinst
, MSIHANDLETYPE_PACKAGE
);
429 if (!(remote
= msi_get_remote(hinst
)))
432 return ERROR_INVALID_HANDLE
;
437 r
= remote_GetSourcePath(remote
, folderW
, &path
);
441 r
= GetExceptionCode();
446 r
= msi_strncpyWtoA(path
, -1, buf
, sz
, TRUE
);
448 midl_user_free(path
);
453 path
= msi_resolve_source_folder(package
, folderW
, NULL
);
455 r
= msi_strncpyWtoA(path
, -1, buf
, sz
, FALSE
);
461 msiobj_release(&package
->hdr
);
465 /***********************************************************************
466 * MsiGetSourcePathW (MSI.@)
468 UINT WINAPI
MsiGetSourcePathW(MSIHANDLE hinst
, const WCHAR
*folder
, WCHAR
*buf
, DWORD
*sz
)
474 TRACE("%s %p %p\n", debugstr_w(folder
), buf
, sz
);
477 return ERROR_INVALID_PARAMETER
;
479 package
= msihandle2msiinfo(hinst
, MSIHANDLETYPE_PACKAGE
);
485 if (!(remote
= msi_get_remote(hinst
)))
486 return ERROR_INVALID_HANDLE
;
490 r
= remote_GetSourcePath(remote
, folder
, &path
);
494 r
= GetExceptionCode();
499 r
= msi_strncpyW(path
, -1, buf
, sz
);
501 midl_user_free(path
);
505 path
= msi_resolve_source_folder(package
, folder
, NULL
);
507 r
= msi_strncpyW(path
, -1, buf
, sz
);
512 msiobj_release(&package
->hdr
);
516 /***********************************************************************
517 * MsiSetTargetPathA (MSI.@)
519 UINT WINAPI
MsiSetTargetPathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
520 LPCSTR szFolderPath
)
522 LPWSTR szwFolder
= NULL
, szwFolderPath
= NULL
;
523 UINT rc
= ERROR_OUTOFMEMORY
;
525 if ( !szFolder
|| !szFolderPath
)
526 return ERROR_INVALID_PARAMETER
;
528 szwFolder
= strdupAtoW(szFolder
);
529 szwFolderPath
= strdupAtoW(szFolderPath
);
530 if (!szwFolder
|| !szwFolderPath
)
533 rc
= MsiSetTargetPathW( hInstall
, szwFolder
, szwFolderPath
);
537 msi_free(szwFolderPath
);
542 static void set_target_path( MSIPACKAGE
*package
, MSIFOLDER
*folder
, const WCHAR
*path
)
548 if (!(target_path
= msi_normalize_path( path
))) return;
549 if (wcscmp( target_path
, folder
->ResolvedTarget
))
551 msi_free( folder
->ResolvedTarget
);
552 folder
->ResolvedTarget
= target_path
;
553 msi_set_property( package
->db
, folder
->Directory
, folder
->ResolvedTarget
, -1 );
555 LIST_FOR_EACH_ENTRY( fl
, &folder
->children
, FolderList
, entry
)
558 msi_resolve_target_folder( package
, child
->Directory
, FALSE
);
561 else msi_free( target_path
);
564 UINT
MSI_SetTargetPathW( MSIPACKAGE
*package
, LPCWSTR szFolder
, LPCWSTR szFolderPath
)
570 TRACE("%p %s %s\n", package
, debugstr_w(szFolder
), debugstr_w(szFolderPath
));
572 attrib
= msi_get_file_attributes( package
, szFolderPath
);
573 /* native MSI tests writeability by making temporary files at each drive */
574 if (attrib
!= INVALID_FILE_ATTRIBUTES
&&
575 (attrib
& FILE_ATTRIBUTE_OFFLINE
|| attrib
& FILE_ATTRIBUTE_READONLY
))
577 return ERROR_FUNCTION_FAILED
;
579 if (!(folder
= msi_get_loaded_folder( package
, szFolder
))) return ERROR_DIRECTORY
;
581 set_target_path( package
, folder
, szFolderPath
);
583 LIST_FOR_EACH_ENTRY( file
, &package
->files
, MSIFILE
, entry
)
586 MSICOMPONENT
*comp
= file
->Component
;
588 if (!comp
->Enabled
|| msi_is_global_assembly( comp
)) continue;
590 dir
= msi_get_target_folder( package
, comp
->Directory
);
591 msi_free( file
->TargetPath
);
592 file
->TargetPath
= msi_build_directory_name( 2, dir
, file
->FileName
);
594 return ERROR_SUCCESS
;
597 /***********************************************************************
598 * MsiSetTargetPathW (MSI.@)
600 UINT WINAPI
MsiSetTargetPathW(MSIHANDLE hInstall
, LPCWSTR szFolder
,
601 LPCWSTR szFolderPath
)
606 TRACE("%s %s\n",debugstr_w(szFolder
),debugstr_w(szFolderPath
));
608 if ( !szFolder
|| !szFolderPath
)
609 return ERROR_INVALID_PARAMETER
;
611 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
616 if (!(remote
= msi_get_remote(hInstall
)))
617 return ERROR_INVALID_HANDLE
;
621 ret
= remote_SetTargetPath(remote
, szFolder
, szFolderPath
);
625 ret
= GetExceptionCode();
632 ret
= MSI_SetTargetPathW( package
, szFolder
, szFolderPath
);
633 msiobj_release( &package
->hdr
);
637 /***********************************************************************
640 * Returns an internal installer state (if it is running in a mode iRunMode)
643 * hInstall [I] Handle to the installation
644 * hRunMode [I] Checking run mode
645 * MSIRUNMODE_ADMIN Administrative mode
646 * MSIRUNMODE_ADVERTISE Advertisement mode
647 * MSIRUNMODE_MAINTENANCE Maintenance mode
648 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
649 * MSIRUNMODE_LOGENABLED Log file is writing
650 * MSIRUNMODE_OPERATIONS Operations in progress??
651 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
652 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
653 * MSIRUNMODE_CABINET Files from cabinet are installed
654 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed
655 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed
656 * MSIRUNMODE_RESERVED11 Reserved
657 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
658 * MSIRUNMODE_ZAWENABLED Demand installation is supported
659 * MSIRUNMODE_RESERVED14 Reserved
660 * MSIRUNMODE_RESERVED15 Reserved
661 * MSIRUNMODE_SCHEDULED called from install script
662 * MSIRUNMODE_ROLLBACK called from rollback script
663 * MSIRUNMODE_COMMIT called from commit script
667 * Not in the state: FALSE
670 BOOL WINAPI
MsiGetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
)
675 TRACE( "%lu, %d\n", hInstall
, iRunMode
);
677 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
682 if (!(remote
= msi_get_remote(hInstall
)))
687 r
= remote_GetMode(remote
, iRunMode
);
700 case MSIRUNMODE_ADMIN
:
701 FIXME("no support for administrative installs\n");
704 case MSIRUNMODE_ADVERTISE
:
705 FIXME("no support for advertised installs\n");
708 case MSIRUNMODE_WINDOWS9X
:
709 if (GetVersion() & 0x80000000)
713 case MSIRUNMODE_OPERATIONS
:
714 case MSIRUNMODE_RESERVED11
:
715 case MSIRUNMODE_RESERVED14
:
716 case MSIRUNMODE_RESERVED15
:
719 case MSIRUNMODE_SCHEDULED
:
720 r
= package
->scheduled_action_running
;
723 case MSIRUNMODE_ROLLBACK
:
724 r
= package
->rollback_action_running
;
727 case MSIRUNMODE_COMMIT
:
728 r
= package
->commit_action_running
;
731 case MSIRUNMODE_MAINTENANCE
:
732 r
= msi_get_property_int( package
->db
, L
"Installed", 0 ) != 0;
735 case MSIRUNMODE_ROLLBACKENABLED
:
736 r
= msi_get_property_int( package
->db
, L
"RollbackDisabled", 0 ) == 0;
739 case MSIRUNMODE_REBOOTATEND
:
740 r
= package
->need_reboot_at_end
;
743 case MSIRUNMODE_REBOOTNOW
:
744 r
= package
->need_reboot_now
;
747 case MSIRUNMODE_LOGENABLED
:
748 r
= (package
->log_file
!= INVALID_HANDLE_VALUE
);
752 FIXME("unimplemented run mode: %d\n", iRunMode
);
756 msiobj_release( &package
->hdr
);
760 /***********************************************************************
763 UINT WINAPI
MsiSetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
, BOOL fState
)
768 TRACE( "%lu, %d, %d\n", hInstall
, iRunMode
, fState
);
770 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
775 if (!(remote
= msi_get_remote(hInstall
)))
780 r
= remote_SetMode(remote
, iRunMode
, fState
);
784 r
= GetExceptionCode();
793 case MSIRUNMODE_REBOOTATEND
:
794 package
->need_reboot_at_end
= (fState
!= 0);
798 case MSIRUNMODE_REBOOTNOW
:
799 package
->need_reboot_now
= (fState
!= 0);
804 r
= ERROR_ACCESS_DENIED
;
807 msiobj_release( &package
->hdr
);
811 /***********************************************************************
812 * MsiSetFeatureStateA (MSI.@)
814 * According to the docs, when this is called it immediately recalculates
815 * all the component states as well
817 UINT WINAPI
MsiSetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
820 LPWSTR szwFeature
= NULL
;
823 szwFeature
= strdupAtoW(szFeature
);
825 rc
= MsiSetFeatureStateW(hInstall
,szwFeature
, iState
);
827 msi_free(szwFeature
);
832 /* update component state based on a feature change */
833 void ACTION_UpdateComponentStates( MSIPACKAGE
*package
, MSIFEATURE
*feature
)
835 INSTALLSTATE newstate
;
838 newstate
= feature
->ActionRequest
;
839 if (newstate
== INSTALLSTATE_ABSENT
) newstate
= INSTALLSTATE_UNKNOWN
;
841 LIST_FOR_EACH_ENTRY(cl
, &feature
->Components
, ComponentList
, entry
)
843 MSICOMPONENT
*component
= cl
->component
;
845 if (!component
->Enabled
) continue;
847 TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
848 newstate
, debugstr_w(component
->Component
), component
->Installed
,
849 component
->Action
, component
->ActionRequest
);
851 if (newstate
== INSTALLSTATE_LOCAL
)
853 component
->Action
= INSTALLSTATE_LOCAL
;
854 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
858 ComponentList
*clist
;
861 component
->hasLocalFeature
= FALSE
;
863 component
->Action
= newstate
;
864 component
->ActionRequest
= newstate
;
865 /* if any other feature wants it local we need to set it local */
866 LIST_FOR_EACH_ENTRY(f
, &package
->features
, MSIFEATURE
, entry
)
868 if ( f
->ActionRequest
!= INSTALLSTATE_LOCAL
&&
869 f
->ActionRequest
!= INSTALLSTATE_SOURCE
)
873 LIST_FOR_EACH_ENTRY(clist
, &f
->Components
, ComponentList
, entry
)
875 if (clist
->component
== component
&&
876 (f
->ActionRequest
== INSTALLSTATE_LOCAL
||
877 f
->ActionRequest
== INSTALLSTATE_SOURCE
))
879 TRACE("Saved by %s\n", debugstr_w(f
->Feature
));
880 component
->hasLocalFeature
= TRUE
;
882 if (component
->Attributes
& msidbComponentAttributesOptional
)
884 if (f
->Attributes
& msidbFeatureAttributesFavorSource
)
886 component
->Action
= INSTALLSTATE_SOURCE
;
887 component
->ActionRequest
= INSTALLSTATE_SOURCE
;
891 component
->Action
= INSTALLSTATE_LOCAL
;
892 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
895 else if (component
->Attributes
& msidbComponentAttributesSourceOnly
)
897 component
->Action
= INSTALLSTATE_SOURCE
;
898 component
->ActionRequest
= INSTALLSTATE_SOURCE
;
902 component
->Action
= INSTALLSTATE_LOCAL
;
903 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
909 TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
910 newstate
, debugstr_w(component
->Component
), component
->Installed
,
911 component
->Action
, component
->ActionRequest
);
915 UINT
MSI_SetFeatureStateW( MSIPACKAGE
*package
, LPCWSTR szFeature
, INSTALLSTATE iState
)
917 UINT rc
= ERROR_SUCCESS
;
918 MSIFEATURE
*feature
, *child
;
920 TRACE("%s %i\n", debugstr_w(szFeature
), iState
);
922 feature
= msi_get_loaded_feature( package
, szFeature
);
924 return ERROR_UNKNOWN_FEATURE
;
926 if (iState
== INSTALLSTATE_ADVERTISED
&&
927 feature
->Attributes
& msidbFeatureAttributesDisallowAdvertise
)
928 return ERROR_FUNCTION_FAILED
;
930 feature
->ActionRequest
= iState
;
932 ACTION_UpdateComponentStates( package
, feature
);
934 /* update all the features that are children of this feature */
935 LIST_FOR_EACH_ENTRY( child
, &package
->features
, MSIFEATURE
, entry
)
937 if (child
->Feature_Parent
&& !wcscmp( szFeature
, child
->Feature_Parent
))
938 MSI_SetFeatureStateW(package
, child
->Feature
, iState
);
944 /***********************************************************************
945 * MsiSetFeatureStateW (MSI.@)
947 UINT WINAPI
MsiSetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
951 UINT rc
= ERROR_SUCCESS
;
953 TRACE("%s %i\n",debugstr_w(szFeature
), iState
);
956 return ERROR_UNKNOWN_FEATURE
;
958 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
963 if (!(remote
= msi_get_remote(hInstall
)))
964 return ERROR_INVALID_HANDLE
;
968 rc
= remote_SetFeatureState(remote
, szFeature
, iState
);
972 rc
= GetExceptionCode();
979 rc
= MSI_SetFeatureStateW(package
,szFeature
,iState
);
981 msiobj_release( &package
->hdr
);
985 /***********************************************************************
986 * MsiSetFeatureAttributesA (MSI.@)
988 UINT WINAPI
MsiSetFeatureAttributesA( MSIHANDLE handle
, LPCSTR feature
, DWORD attrs
)
991 WCHAR
*featureW
= NULL
;
993 TRACE( "%lu, %s, %#lx\n", handle
, debugstr_a(feature
), attrs
);
995 if (feature
&& !(featureW
= strdupAtoW( feature
))) return ERROR_OUTOFMEMORY
;
997 r
= MsiSetFeatureAttributesW( handle
, featureW
, attrs
);
998 msi_free( featureW
);
1002 static DWORD
unmap_feature_attributes( DWORD attrs
)
1006 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORLOCAL
) ret
= msidbFeatureAttributesFavorLocal
;
1007 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORSOURCE
) ret
|= msidbFeatureAttributesFavorSource
;
1008 if (attrs
& INSTALLFEATUREATTRIBUTE_FOLLOWPARENT
) ret
|= msidbFeatureAttributesFollowParent
;
1009 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORADVERTISE
) ret
|= msidbFeatureAttributesFavorAdvertise
;
1010 if (attrs
& INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE
) ret
|= msidbFeatureAttributesDisallowAdvertise
;
1011 if (attrs
& INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE
) ret
|= msidbFeatureAttributesNoUnsupportedAdvertise
;
1015 /***********************************************************************
1016 * MsiSetFeatureAttributesW (MSI.@)
1018 UINT WINAPI
MsiSetFeatureAttributesW( MSIHANDLE handle
, LPCWSTR name
, DWORD attrs
)
1020 MSIPACKAGE
*package
;
1021 MSIFEATURE
*feature
;
1024 TRACE( "%lu, %s, %#lx\n", handle
, debugstr_w(name
), attrs
);
1026 if (!name
|| !name
[0]) return ERROR_UNKNOWN_FEATURE
;
1028 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
1029 return ERROR_INVALID_HANDLE
;
1031 costing
= msi_dup_property( package
->db
, L
"CostingComplete" );
1032 if (!costing
|| !wcscmp( costing
, L
"1" ))
1034 msi_free( costing
);
1035 msiobj_release( &package
->hdr
);
1036 return ERROR_FUNCTION_FAILED
;
1038 msi_free( costing
);
1039 if (!(feature
= msi_get_loaded_feature( package
, name
)))
1041 msiobj_release( &package
->hdr
);
1042 return ERROR_UNKNOWN_FEATURE
;
1044 feature
->Attributes
= unmap_feature_attributes( attrs
);
1045 msiobj_release( &package
->hdr
);
1046 return ERROR_SUCCESS
;
1049 /***********************************************************************
1050 * MsiGetFeatureStateA (MSI.@)
1052 UINT WINAPI
MsiGetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
1053 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1055 LPWSTR szwFeature
= NULL
;
1058 if (szFeature
&& !(szwFeature
= strdupAtoW(szFeature
))) return ERROR_OUTOFMEMORY
;
1060 rc
= MsiGetFeatureStateW(hInstall
, szwFeature
, piInstalled
, piAction
);
1061 msi_free( szwFeature
);
1065 UINT
MSI_GetFeatureStateW(MSIPACKAGE
*package
, LPCWSTR szFeature
,
1066 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1068 MSIFEATURE
*feature
;
1070 feature
= msi_get_loaded_feature(package
,szFeature
);
1072 return ERROR_UNKNOWN_FEATURE
;
1075 *piInstalled
= feature
->Installed
;
1078 *piAction
= feature
->ActionRequest
;
1080 TRACE("returning %i %i\n", feature
->Installed
, feature
->ActionRequest
);
1082 return ERROR_SUCCESS
;
1085 /***********************************************************************
1086 * MsiGetFeatureStateW (MSI.@)
1088 UINT WINAPI
MsiGetFeatureStateW( MSIHANDLE hInstall
, const WCHAR
*szFeature
, INSTALLSTATE
*piInstalled
,
1089 INSTALLSTATE
*piAction
)
1091 MSIPACKAGE
* package
;
1094 TRACE( "%lu, %s, %p, %p\n", hInstall
, debugstr_w(szFeature
), piInstalled
, piAction
);
1097 return ERROR_UNKNOWN_FEATURE
;
1099 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1104 if (!(remote
= msi_get_remote(hInstall
)))
1105 return ERROR_INVALID_HANDLE
;
1109 ret
= remote_GetFeatureState(remote
, szFeature
, piInstalled
, piAction
);
1111 __EXCEPT(rpc_filter
)
1113 ret
= GetExceptionCode();
1120 ret
= MSI_GetFeatureStateW(package
, szFeature
, piInstalled
, piAction
);
1121 msiobj_release( &package
->hdr
);
1125 /***********************************************************************
1126 * MsiGetFeatureCostA (MSI.@)
1128 UINT WINAPI
MsiGetFeatureCostA(MSIHANDLE hInstall
, LPCSTR szFeature
,
1129 MSICOSTTREE iCostTree
, INSTALLSTATE iState
, LPINT piCost
)
1131 LPWSTR szwFeature
= NULL
;
1134 szwFeature
= strdupAtoW(szFeature
);
1136 rc
= MsiGetFeatureCostW(hInstall
, szwFeature
, iCostTree
, iState
, piCost
);
1138 msi_free(szwFeature
);
1143 static INT
feature_cost( MSIFEATURE
*feature
)
1148 LIST_FOR_EACH_ENTRY( cl
, &feature
->Components
, ComponentList
, entry
)
1150 cost
+= cl
->component
->Cost
;
1155 UINT
MSI_GetFeatureCost( MSIPACKAGE
*package
, MSIFEATURE
*feature
, MSICOSTTREE tree
,
1156 INSTALLSTATE state
, LPINT cost
)
1158 TRACE("%s, %u, %d, %p\n", debugstr_w(feature
->Feature
), tree
, state
, cost
);
1163 case MSICOSTTREE_CHILDREN
:
1167 LIST_FOR_EACH_ENTRY( child
, &feature
->Children
, MSIFEATURE
, entry
)
1169 if (child
->ActionRequest
== state
)
1170 *cost
+= feature_cost( child
);
1174 case MSICOSTTREE_PARENTS
:
1176 const WCHAR
*feature_parent
= feature
->Feature_Parent
;
1179 MSIFEATURE
*parent
= msi_get_loaded_feature( package
, feature_parent
);
1183 if (parent
->ActionRequest
== state
)
1184 *cost
+= feature_cost( parent
);
1186 feature_parent
= parent
->Feature_Parent
;
1190 case MSICOSTTREE_SELFONLY
:
1191 if (feature
->ActionRequest
== state
)
1192 *cost
= feature_cost( feature
);
1196 WARN("unhandled cost tree %u\n", tree
);
1201 return ERROR_SUCCESS
;
1204 /***********************************************************************
1205 * MsiGetFeatureCostW (MSI.@)
1207 UINT WINAPI
MsiGetFeatureCostW( MSIHANDLE hInstall
, const WCHAR
*szFeature
, MSICOSTTREE iCostTree
,
1208 INSTALLSTATE iState
, INT
*piCost
)
1210 MSIPACKAGE
*package
;
1211 MSIFEATURE
*feature
;
1214 TRACE( "%lu, %s, %d, %d, %p\n", hInstall
, debugstr_w(szFeature
), iCostTree
, iState
, piCost
);
1217 return ERROR_INVALID_PARAMETER
;
1219 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1224 if (!(remote
= msi_get_remote(hInstall
)))
1225 return ERROR_INVALID_HANDLE
;
1229 ret
= remote_GetFeatureCost(remote
, szFeature
, iCostTree
, iState
, piCost
);
1231 __EXCEPT(rpc_filter
)
1233 ret
= GetExceptionCode();
1242 msiobj_release( &package
->hdr
);
1243 return ERROR_INVALID_PARAMETER
;
1246 feature
= msi_get_loaded_feature(package
, szFeature
);
1249 ret
= MSI_GetFeatureCost(package
, feature
, iCostTree
, iState
, piCost
);
1251 ret
= ERROR_UNKNOWN_FEATURE
;
1253 msiobj_release( &package
->hdr
);
1257 /***********************************************************************
1258 * MsiGetFeatureInfoA (MSI.@)
1260 UINT WINAPI
MsiGetFeatureInfoA( MSIHANDLE handle
, const char *feature
, DWORD
*attrs
,
1261 char *title
, DWORD
*title_len
, char *help
, DWORD
*help_len
)
1264 WCHAR
*titleW
= NULL
, *helpW
= NULL
, *featureW
= NULL
;
1266 TRACE( "%lu, %s, %p, %p, %p, %p, %p\n", handle
, debugstr_a(feature
), attrs
, title
,
1267 title_len
, help
, help_len
);
1269 if (feature
&& !(featureW
= strdupAtoW( feature
))) return ERROR_OUTOFMEMORY
;
1271 if (title
&& title_len
&& !(titleW
= msi_alloc( *title_len
* sizeof(WCHAR
) )))
1273 msi_free( featureW
);
1274 return ERROR_OUTOFMEMORY
;
1276 if (help
&& help_len
&& !(helpW
= msi_alloc( *help_len
* sizeof(WCHAR
) )))
1278 msi_free( featureW
);
1280 return ERROR_OUTOFMEMORY
;
1282 r
= MsiGetFeatureInfoW( handle
, featureW
, attrs
, titleW
, title_len
, helpW
, help_len
);
1283 if (r
== ERROR_SUCCESS
)
1285 if (titleW
) WideCharToMultiByte( CP_ACP
, 0, titleW
, -1, title
, *title_len
+ 1, NULL
, NULL
);
1286 if (helpW
) WideCharToMultiByte( CP_ACP
, 0, helpW
, -1, help
, *help_len
+ 1, NULL
, NULL
);
1290 msi_free( featureW
);
1294 static DWORD
map_feature_attributes( DWORD attrs
)
1298 if (attrs
== msidbFeatureAttributesFavorLocal
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORLOCAL
;
1299 if (attrs
& msidbFeatureAttributesFavorSource
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORSOURCE
;
1300 if (attrs
& msidbFeatureAttributesFollowParent
) ret
|= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT
;
1301 if (attrs
& msidbFeatureAttributesFavorAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE
;
1302 if (attrs
& msidbFeatureAttributesDisallowAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE
;
1303 if (attrs
& msidbFeatureAttributesNoUnsupportedAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE
;
1307 static UINT
MSI_GetFeatureInfo( MSIPACKAGE
*package
, LPCWSTR name
, LPDWORD attrs
,
1308 LPWSTR title
, LPDWORD title_len
, LPWSTR help
, LPDWORD help_len
)
1310 UINT r
= ERROR_SUCCESS
;
1311 MSIFEATURE
*feature
= msi_get_loaded_feature( package
, name
);
1314 if (!feature
) return ERROR_UNKNOWN_FEATURE
;
1315 if (attrs
) *attrs
= map_feature_attributes( feature
->Attributes
);
1318 if (feature
->Title
) len
= lstrlenW( feature
->Title
);
1320 if (*title_len
<= len
)
1323 if (title
) r
= ERROR_MORE_DATA
;
1327 if (feature
->Title
) lstrcpyW( title
, feature
->Title
);
1334 if (feature
->Description
) len
= lstrlenW( feature
->Description
);
1336 if (*help_len
<= len
)
1339 if (help
) r
= ERROR_MORE_DATA
;
1343 if (feature
->Description
) lstrcpyW( help
, feature
->Description
);
1351 /***********************************************************************
1352 * MsiGetFeatureInfoW (MSI.@)
1354 UINT WINAPI
MsiGetFeatureInfoW( MSIHANDLE handle
, const WCHAR
*feature
, DWORD
*attrs
,
1355 WCHAR
*title
, DWORD
*title_len
, WCHAR
*help
, DWORD
*help_len
)
1358 MSIPACKAGE
*package
;
1360 TRACE( "%lu, %s, %p, %p, %p, %p, %p\n", handle
, debugstr_w(feature
), attrs
, title
,
1361 title_len
, help
, help_len
);
1363 if (!feature
) return ERROR_INVALID_PARAMETER
;
1365 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
1366 return ERROR_INVALID_HANDLE
;
1368 /* features may not have been loaded yet */
1369 msi_load_all_components( package
);
1370 msi_load_all_features( package
);
1372 r
= MSI_GetFeatureInfo( package
, feature
, attrs
, title
, title_len
, help
, help_len
);
1373 msiobj_release( &package
->hdr
);
1377 /***********************************************************************
1378 * MsiSetComponentStateA (MSI.@)
1380 UINT WINAPI
MsiSetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
1381 INSTALLSTATE iState
)
1384 LPWSTR szwComponent
= strdupAtoW(szComponent
);
1386 rc
= MsiSetComponentStateW(hInstall
, szwComponent
, iState
);
1388 msi_free(szwComponent
);
1393 /***********************************************************************
1394 * MsiGetComponentStateA (MSI.@)
1396 UINT WINAPI
MsiGetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
1397 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1399 LPWSTR szwComponent
= NULL
;
1402 szwComponent
= strdupAtoW(szComponent
);
1404 rc
= MsiGetComponentStateW(hInstall
,szwComponent
,piInstalled
, piAction
);
1406 msi_free( szwComponent
);
1411 static UINT
MSI_SetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
1412 INSTALLSTATE iState
)
1416 TRACE("%p %s %d\n", package
, debugstr_w(szComponent
), iState
);
1418 comp
= msi_get_loaded_component(package
, szComponent
);
1420 return ERROR_UNKNOWN_COMPONENT
;
1423 comp
->Action
= iState
;
1425 return ERROR_SUCCESS
;
1428 UINT
MSI_GetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
1429 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1433 TRACE("%p %s %p %p\n", package
, debugstr_w(szComponent
),
1434 piInstalled
, piAction
);
1436 comp
= msi_get_loaded_component(package
,szComponent
);
1438 return ERROR_UNKNOWN_COMPONENT
;
1443 *piInstalled
= comp
->Installed
;
1445 *piInstalled
= INSTALLSTATE_UNKNOWN
;
1451 *piAction
= comp
->Action
;
1453 *piAction
= INSTALLSTATE_UNKNOWN
;
1456 TRACE("states (%i, %i)\n", comp
->Installed
, comp
->Action
);
1457 return ERROR_SUCCESS
;
1460 /***********************************************************************
1461 * MsiSetComponentStateW (MSI.@)
1463 UINT WINAPI
MsiSetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
1464 INSTALLSTATE iState
)
1466 MSIPACKAGE
* package
;
1470 return ERROR_UNKNOWN_COMPONENT
;
1472 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1477 if (!(remote
= msi_get_remote(hInstall
)))
1478 return ERROR_INVALID_HANDLE
;
1482 ret
= remote_SetComponentState(remote
, szComponent
, iState
);
1484 __EXCEPT(rpc_filter
)
1486 ret
= GetExceptionCode();
1493 ret
= MSI_SetComponentStateW(package
, szComponent
, iState
);
1494 msiobj_release(&package
->hdr
);
1498 /***********************************************************************
1499 * MsiGetComponentStateW (MSI.@)
1501 UINT WINAPI
MsiGetComponentStateW( MSIHANDLE hInstall
, const WCHAR
*szComponent
, INSTALLSTATE
*piInstalled
,
1502 INSTALLSTATE
*piAction
)
1504 MSIPACKAGE
* package
;
1507 TRACE( "%lu, %s, %p, %p\n", hInstall
, debugstr_w(szComponent
), piInstalled
, piAction
);
1510 return ERROR_UNKNOWN_COMPONENT
;
1512 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1517 if (!(remote
= msi_get_remote(hInstall
)))
1518 return ERROR_INVALID_HANDLE
;
1522 ret
= remote_GetComponentState(remote
, szComponent
, piInstalled
, piAction
);
1524 __EXCEPT(rpc_filter
)
1526 ret
= GetExceptionCode();
1533 ret
= MSI_GetComponentStateW( package
, szComponent
, piInstalled
, piAction
);
1534 msiobj_release( &package
->hdr
);
1538 /***********************************************************************
1539 * MsiGetLanguage (MSI.@)
1541 LANGID WINAPI
MsiGetLanguage(MSIHANDLE hInstall
)
1543 MSIPACKAGE
* package
;
1546 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1551 if (!(remote
= msi_get_remote(hInstall
)))
1552 return ERROR_INVALID_HANDLE
;
1556 langid
= remote_GetLanguage(remote
);
1558 __EXCEPT(rpc_filter
)
1567 langid
= msi_get_property_int( package
->db
, L
"ProductLanguage", 0 );
1568 msiobj_release( &package
->hdr
);
1572 UINT
MSI_SetInstallLevel( MSIPACKAGE
*package
, int iInstallLevel
)
1578 TRACE("%p %i\n", package
, iInstallLevel
);
1580 if (iInstallLevel
> 32767)
1581 return ERROR_INVALID_PARAMETER
;
1583 if (iInstallLevel
< 1)
1584 return MSI_SetFeatureStates( package
);
1586 len
= swprintf( level
, ARRAY_SIZE(level
), L
"%d", iInstallLevel
);
1587 r
= msi_set_property( package
->db
, L
"INSTALLLEVEL", level
, len
);
1588 if ( r
== ERROR_SUCCESS
)
1589 r
= MSI_SetFeatureStates( package
);
1594 /***********************************************************************
1595 * MsiSetInstallLevel (MSI.@)
1597 UINT WINAPI
MsiSetInstallLevel(MSIHANDLE hInstall
, int iInstallLevel
)
1599 MSIPACKAGE
* package
;
1602 TRACE( "%lu %d\n", hInstall
, iInstallLevel
);
1604 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1609 if (!(remote
= msi_get_remote(hInstall
)))
1610 return ERROR_INVALID_HANDLE
;
1614 r
= remote_SetInstallLevel(remote
, iInstallLevel
);
1616 __EXCEPT(rpc_filter
)
1618 r
= GetExceptionCode();
1625 r
= MSI_SetInstallLevel( package
, iInstallLevel
);
1627 msiobj_release( &package
->hdr
);
1632 /***********************************************************************
1633 * MsiGetFeatureValidStatesW (MSI.@)
1635 UINT WINAPI
MsiGetFeatureValidStatesW( MSIHANDLE hInstall
, const WCHAR
*szFeature
, DWORD
*pInstallState
)
1637 if (pInstallState
) *pInstallState
= 1 << INSTALLSTATE_LOCAL
;
1638 FIXME( "%lu, %s, %p stub returning %lu\n", hInstall
, debugstr_w(szFeature
), pInstallState
,
1639 pInstallState
? *pInstallState
: 0 );
1640 return ERROR_SUCCESS
;
1643 /***********************************************************************
1644 * MsiGetFeatureValidStatesA (MSI.@)
1646 UINT WINAPI
MsiGetFeatureValidStatesA( MSIHANDLE hInstall
, const char *szFeature
, DWORD
*pInstallState
)
1649 WCHAR
*szwFeature
= strdupAtoW(szFeature
);
1650 ret
= MsiGetFeatureValidStatesW(hInstall
, szwFeature
, pInstallState
);
1651 msi_free(szwFeature
);