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 */
30 #include "wine/debug.h"
38 #include "wine/unicode.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
);
81 if (!(remote
= msi_get_remote(hInstall
)))
82 return ERROR_INVALID_HANDLE
;
84 action
= SysAllocString( szAction
);
86 return ERROR_OUTOFMEMORY
;
88 hr
= remote_DoAction(remote
, action
);
90 SysFreeString( action
);
94 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
95 return HRESULT_CODE(hr
);
97 return ERROR_FUNCTION_FAILED
;
100 return ERROR_SUCCESS
;
103 ret
= ACTION_PerformAction( package
, szAction
, SCRIPT_NONE
);
104 msiobj_release( &package
->hdr
);
109 /***********************************************************************
110 * MsiSequenceA (MSI.@)
112 UINT WINAPI
MsiSequenceA( MSIHANDLE hInstall
, LPCSTR szTable
, INT iSequenceMode
)
117 TRACE("%s, %d\n", debugstr_a(szTable
), iSequenceMode
);
119 szwTable
= strdupAtoW(szTable
);
120 if (szTable
&& !szwTable
)
121 return ERROR_FUNCTION_FAILED
;
123 ret
= MsiSequenceW( hInstall
, szwTable
, iSequenceMode
);
124 msi_free( szwTable
);
128 /***********************************************************************
129 * MsiSequenceW (MSI.@)
131 UINT WINAPI
MsiSequenceW( MSIHANDLE hInstall
, LPCWSTR szTable
, INT iSequenceMode
)
136 TRACE("%s, %d\n", debugstr_w(szTable
), iSequenceMode
);
138 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
145 if (!(remote
= msi_get_remote(hInstall
)))
146 return ERROR_INVALID_HANDLE
;
148 table
= SysAllocString( szTable
);
150 return ERROR_OUTOFMEMORY
;
152 hr
= remote_Sequence(remote
, table
, iSequenceMode
);
154 SysFreeString( table
);
158 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
159 return HRESULT_CODE(hr
);
161 return ERROR_FUNCTION_FAILED
;
164 return ERROR_SUCCESS
;
166 ret
= MSI_Sequence( package
, szTable
);
167 msiobj_release( &package
->hdr
);
171 UINT
msi_strcpy_to_awstring( const WCHAR
*str
, int len
, awstring
*awbuf
, DWORD
*sz
)
173 UINT r
= ERROR_SUCCESS
;
175 if (awbuf
->str
.w
&& !sz
)
176 return ERROR_INVALID_PARAMETER
;
178 return ERROR_SUCCESS
;
180 if (len
< 0) len
= strlenW( str
);
182 if (awbuf
->unicode
&& awbuf
->str
.w
)
184 memcpy( awbuf
->str
.w
, str
, min(len
+ 1, *sz
) * sizeof(WCHAR
) );
185 if (*sz
&& len
>= *sz
)
186 awbuf
->str
.w
[*sz
- 1] = 0;
190 int lenA
= WideCharToMultiByte( CP_ACP
, 0, str
, len
+ 1, NULL
, 0, NULL
, NULL
);
192 WideCharToMultiByte( CP_ACP
, 0, str
, len
+ 1, awbuf
->str
.a
, *sz
, NULL
, NULL
);
193 if (awbuf
->str
.a
&& *sz
&& lenA
>= *sz
)
194 awbuf
->str
.a
[*sz
- 1] = 0;
197 if (awbuf
->str
.w
&& len
>= *sz
)
203 const WCHAR
*msi_get_target_folder( MSIPACKAGE
*package
, const WCHAR
*name
)
205 MSIFOLDER
*folder
= msi_get_loaded_folder( package
, name
);
207 if (!folder
) return NULL
;
208 if (!folder
->ResolvedTarget
)
210 MSIFOLDER
*parent
= folder
;
211 while (parent
->Parent
&& strcmpW( parent
->Parent
, parent
->Directory
))
213 parent
= msi_get_loaded_folder( package
, parent
->Parent
);
215 msi_resolve_target_folder( package
, parent
->Directory
, TRUE
);
217 return folder
->ResolvedTarget
;
220 /***********************************************************************
221 * MsiGetTargetPath (internal)
223 static UINT
MSI_GetTargetPath( MSIHANDLE hInstall
, LPCWSTR szFolder
,
224 awstring
*szPathBuf
, LPDWORD pcchPathBuf
)
228 UINT r
= ERROR_FUNCTION_FAILED
;
231 return ERROR_INVALID_PARAMETER
;
233 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
242 if (!(remote
= msi_get_remote(hInstall
)))
243 return ERROR_INVALID_HANDLE
;
245 folder
= SysAllocString( szFolder
);
247 return ERROR_OUTOFMEMORY
;
250 hr
= remote_GetTargetPath(remote
, folder
, NULL
, &len
);
255 value
= msi_alloc(len
* sizeof(WCHAR
));
258 r
= ERROR_OUTOFMEMORY
;
262 hr
= remote_GetTargetPath(remote
, folder
, value
, &len
);
266 r
= msi_strcpy_to_awstring( value
, len
, szPathBuf
, pcchPathBuf
);
269 SysFreeString( folder
);
274 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
275 return HRESULT_CODE(hr
);
277 return ERROR_FUNCTION_FAILED
;
283 path
= msi_get_target_folder( package
, szFolder
);
284 msiobj_release( &package
->hdr
);
287 return ERROR_DIRECTORY
;
289 return msi_strcpy_to_awstring( path
, -1, szPathBuf
, pcchPathBuf
);
292 /***********************************************************************
293 * MsiGetTargetPathA (MSI.@)
295 UINT WINAPI
MsiGetTargetPathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
296 LPSTR szPathBuf
, LPDWORD pcchPathBuf
)
302 TRACE("%s %p %p\n", debugstr_a(szFolder
), szPathBuf
, pcchPathBuf
);
304 szwFolder
= strdupAtoW(szFolder
);
305 if (szFolder
&& !szwFolder
)
306 return ERROR_FUNCTION_FAILED
;
308 path
.unicode
= FALSE
;
309 path
.str
.a
= szPathBuf
;
311 r
= MSI_GetTargetPath( hInstall
, szwFolder
, &path
, pcchPathBuf
);
313 msi_free( szwFolder
);
318 /***********************************************************************
319 * MsiGetTargetPathW (MSI.@)
321 UINT WINAPI
MsiGetTargetPathW( MSIHANDLE hInstall
, LPCWSTR szFolder
,
322 LPWSTR szPathBuf
, LPDWORD pcchPathBuf
)
326 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
329 path
.str
.w
= szPathBuf
;
331 return MSI_GetTargetPath( hInstall
, szFolder
, &path
, pcchPathBuf
);
334 static WCHAR
*get_source_root( MSIPACKAGE
*package
)
336 msi_set_sourcedir_props( package
, FALSE
);
337 return msi_dup_property( package
->db
, szSourceDir
);
340 WCHAR
*msi_resolve_source_folder( MSIPACKAGE
*package
, const WCHAR
*name
, MSIFOLDER
**folder
)
343 LPWSTR p
, path
= NULL
, parent
;
345 TRACE("working to resolve %s\n", debugstr_w(name
));
347 if (!strcmpW( name
, szSourceDir
)) name
= szTargetDir
;
348 if (!(f
= msi_get_loaded_folder( package
, name
))) return NULL
;
350 /* special resolving for root dir */
351 if (!strcmpW( name
, szTargetDir
) && !f
->ResolvedSource
)
353 f
->ResolvedSource
= get_source_root( package
);
355 if (folder
) *folder
= f
;
356 if (f
->ResolvedSource
)
358 path
= strdupW( f
->ResolvedSource
);
359 TRACE(" already resolved to %s\n", debugstr_w(path
));
362 if (!f
->Parent
) return path
;
364 TRACE(" ! parent is %s\n", debugstr_w(parent
));
366 p
= msi_resolve_source_folder( package
, parent
, NULL
);
368 if (package
->WordCount
& msidbSumInfoSourceTypeCompressed
)
369 path
= get_source_root( package
);
370 else if (package
->WordCount
& msidbSumInfoSourceTypeSFN
)
371 path
= msi_build_directory_name( 3, p
, f
->SourceShortPath
, NULL
);
373 path
= msi_build_directory_name( 3, p
, f
->SourceLongPath
, NULL
);
375 TRACE("-> %s\n", debugstr_w(path
));
376 f
->ResolvedSource
= strdupW( path
);
382 /***********************************************************************
383 * MSI_GetSourcePath (internal)
385 static UINT
MSI_GetSourcePath( MSIHANDLE hInstall
, LPCWSTR szFolder
,
386 awstring
*szPathBuf
, LPDWORD pcchPathBuf
)
390 UINT r
= ERROR_FUNCTION_FAILED
;
392 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
395 return ERROR_INVALID_PARAMETER
;
397 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
406 if (!(remote
= msi_get_remote(hInstall
)))
407 return ERROR_INVALID_HANDLE
;
409 folder
= SysAllocString( szFolder
);
411 return ERROR_OUTOFMEMORY
;
414 hr
= remote_GetSourcePath(remote
, folder
, NULL
, &len
);
419 value
= msi_alloc(len
* sizeof(WCHAR
));
422 r
= ERROR_OUTOFMEMORY
;
426 hr
= remote_GetSourcePath(remote
, folder
, value
, &len
);
430 r
= msi_strcpy_to_awstring( value
, len
, szPathBuf
, pcchPathBuf
);
433 SysFreeString( folder
);
438 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
439 return HRESULT_CODE(hr
);
441 return ERROR_FUNCTION_FAILED
;
447 if (szPathBuf
->str
.w
&& !pcchPathBuf
)
449 msiobj_release( &package
->hdr
);
450 return ERROR_INVALID_PARAMETER
;
453 path
= msi_resolve_source_folder( package
, szFolder
, NULL
);
454 msiobj_release( &package
->hdr
);
456 TRACE("path = %s\n", debugstr_w(path
));
458 return ERROR_DIRECTORY
;
460 r
= msi_strcpy_to_awstring( path
, -1, szPathBuf
, pcchPathBuf
);
465 /***********************************************************************
466 * MsiGetSourcePathA (MSI.@)
468 UINT WINAPI
MsiGetSourcePathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
469 LPSTR szPathBuf
, LPDWORD pcchPathBuf
)
475 TRACE("%s %p %p\n", debugstr_a(szFolder
), szPathBuf
, pcchPathBuf
);
478 str
.str
.a
= szPathBuf
;
480 folder
= strdupAtoW( szFolder
);
481 r
= MSI_GetSourcePath( hInstall
, folder
, &str
, pcchPathBuf
);
487 /***********************************************************************
488 * MsiGetSourcePathW (MSI.@)
490 UINT WINAPI
MsiGetSourcePathW( MSIHANDLE hInstall
, LPCWSTR szFolder
,
491 LPWSTR szPathBuf
, LPDWORD pcchPathBuf
)
495 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
498 str
.str
.w
= szPathBuf
;
500 return MSI_GetSourcePath( hInstall
, szFolder
, &str
, pcchPathBuf
);
503 /***********************************************************************
504 * MsiSetTargetPathA (MSI.@)
506 UINT WINAPI
MsiSetTargetPathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
507 LPCSTR szFolderPath
)
509 LPWSTR szwFolder
= NULL
, szwFolderPath
= NULL
;
510 UINT rc
= ERROR_OUTOFMEMORY
;
512 if ( !szFolder
|| !szFolderPath
)
513 return ERROR_INVALID_PARAMETER
;
515 szwFolder
= strdupAtoW(szFolder
);
516 szwFolderPath
= strdupAtoW(szFolderPath
);
517 if (!szwFolder
|| !szwFolderPath
)
520 rc
= MsiSetTargetPathW( hInstall
, szwFolder
, szwFolderPath
);
524 msi_free(szwFolderPath
);
529 static void set_target_path( MSIPACKAGE
*package
, MSIFOLDER
*folder
, const WCHAR
*path
)
535 if (!(target_path
= msi_normalize_path( path
))) return;
536 if (strcmpW( target_path
, folder
->ResolvedTarget
))
538 msi_free( folder
->ResolvedTarget
);
539 folder
->ResolvedTarget
= target_path
;
540 msi_set_property( package
->db
, folder
->Directory
, folder
->ResolvedTarget
, -1 );
542 LIST_FOR_EACH_ENTRY( fl
, &folder
->children
, FolderList
, entry
)
545 msi_resolve_target_folder( package
, child
->Directory
, FALSE
);
548 else msi_free( target_path
);
551 UINT
MSI_SetTargetPathW( MSIPACKAGE
*package
, LPCWSTR szFolder
, LPCWSTR szFolderPath
)
557 TRACE("%p %s %s\n", package
, debugstr_w(szFolder
), debugstr_w(szFolderPath
));
559 attrib
= GetFileAttributesW(szFolderPath
);
560 /* native MSI tests writeability by making temporary files at each drive */
561 if (attrib
!= INVALID_FILE_ATTRIBUTES
&&
562 (attrib
& FILE_ATTRIBUTE_OFFLINE
|| attrib
& FILE_ATTRIBUTE_READONLY
))
564 return ERROR_FUNCTION_FAILED
;
566 if (!(folder
= msi_get_loaded_folder( package
, szFolder
))) return ERROR_DIRECTORY
;
568 set_target_path( package
, folder
, szFolderPath
);
570 LIST_FOR_EACH_ENTRY( file
, &package
->files
, MSIFILE
, entry
)
573 MSICOMPONENT
*comp
= file
->Component
;
575 if (!comp
->Enabled
|| msi_is_global_assembly( comp
)) continue;
577 dir
= msi_get_target_folder( package
, comp
->Directory
);
578 msi_free( file
->TargetPath
);
579 file
->TargetPath
= msi_build_directory_name( 2, dir
, file
->FileName
);
581 return ERROR_SUCCESS
;
584 /***********************************************************************
585 * MsiSetTargetPathW (MSI.@)
587 UINT WINAPI
MsiSetTargetPathW(MSIHANDLE hInstall
, LPCWSTR szFolder
,
588 LPCWSTR szFolderPath
)
593 TRACE("%s %s\n",debugstr_w(szFolder
),debugstr_w(szFolderPath
));
595 if ( !szFolder
|| !szFolderPath
)
596 return ERROR_INVALID_PARAMETER
;
598 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
605 if (!(remote
= msi_get_remote(hInstall
)))
606 return ERROR_INVALID_HANDLE
;
608 folder
= SysAllocString( szFolder
);
609 path
= SysAllocString( szFolderPath
);
610 if (!folder
|| !path
)
612 SysFreeString(folder
);
614 return ERROR_OUTOFMEMORY
;
617 hr
= remote_SetTargetPath(remote
, folder
, path
);
619 SysFreeString(folder
);
624 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
625 return HRESULT_CODE(hr
);
627 return ERROR_FUNCTION_FAILED
;
630 return ERROR_SUCCESS
;
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
);
685 if (!(remote
= msi_get_remote(hInstall
)))
688 hr
= remote_GetMode(remote
, iRunMode
, &ret
);
698 case MSIRUNMODE_ADMIN
:
699 FIXME("no support for administrative installs\n");
702 case MSIRUNMODE_ADVERTISE
:
703 FIXME("no support for advertised installs\n");
706 case MSIRUNMODE_WINDOWS9X
:
707 if (GetVersion() & 0x80000000)
711 case MSIRUNMODE_OPERATIONS
:
712 case MSIRUNMODE_RESERVED11
:
713 case MSIRUNMODE_RESERVED14
:
714 case MSIRUNMODE_RESERVED15
:
717 case MSIRUNMODE_SCHEDULED
:
718 r
= package
->scheduled_action_running
;
721 case MSIRUNMODE_ROLLBACK
:
722 r
= package
->rollback_action_running
;
725 case MSIRUNMODE_COMMIT
:
726 r
= package
->commit_action_running
;
729 case MSIRUNMODE_MAINTENANCE
:
730 r
= msi_get_property_int( package
->db
, szInstalled
, 0 ) != 0;
733 case MSIRUNMODE_ROLLBACKENABLED
:
734 r
= msi_get_property_int( package
->db
, szRollbackDisabled
, 0 ) == 0;
737 case MSIRUNMODE_REBOOTATEND
:
738 r
= package
->need_reboot_at_end
;
741 case MSIRUNMODE_REBOOTNOW
:
742 r
= package
->need_reboot_now
;
745 case MSIRUNMODE_LOGENABLED
:
746 r
= (package
->log_file
!= INVALID_HANDLE_VALUE
);
750 FIXME("unimplemented run mode: %d\n", iRunMode
);
754 msiobj_release( &package
->hdr
);
758 /***********************************************************************
761 UINT WINAPI
MsiSetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
, BOOL fState
)
766 TRACE("%d %d %d\n", hInstall
, iRunMode
, fState
);
768 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
774 if (!(remote
= msi_get_remote(hInstall
)))
777 hr
= remote_SetMode(remote
, iRunMode
, fState
);
781 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
782 return HRESULT_CODE(hr
);
784 return ERROR_FUNCTION_FAILED
;
787 return ERROR_SUCCESS
;
792 case MSIRUNMODE_REBOOTATEND
:
793 package
->need_reboot_at_end
= (fState
!= 0);
797 case MSIRUNMODE_REBOOTNOW
:
798 package
->need_reboot_now
= (fState
!= 0);
803 r
= ERROR_ACCESS_DENIED
;
806 msiobj_release( &package
->hdr
);
810 /***********************************************************************
811 * MsiSetFeatureStateA (MSI.@)
813 * According to the docs, when this is called it immediately recalculates
814 * all the component states as well
816 UINT WINAPI
MsiSetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
819 LPWSTR szwFeature
= NULL
;
822 szwFeature
= strdupAtoW(szFeature
);
825 return ERROR_FUNCTION_FAILED
;
827 rc
= MsiSetFeatureStateW(hInstall
,szwFeature
, iState
);
829 msi_free(szwFeature
);
834 /* update component state based on a feature change */
835 void ACTION_UpdateComponentStates( MSIPACKAGE
*package
, MSIFEATURE
*feature
)
837 INSTALLSTATE newstate
;
840 newstate
= feature
->ActionRequest
;
841 if (newstate
== INSTALLSTATE_ABSENT
) newstate
= INSTALLSTATE_UNKNOWN
;
843 LIST_FOR_EACH_ENTRY(cl
, &feature
->Components
, ComponentList
, entry
)
845 MSICOMPONENT
*component
= cl
->component
;
847 if (!component
->Enabled
) continue;
849 TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
850 newstate
, debugstr_w(component
->Component
), component
->Installed
,
851 component
->Action
, component
->ActionRequest
);
853 if (newstate
== INSTALLSTATE_LOCAL
)
855 component
->Action
= INSTALLSTATE_LOCAL
;
856 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
860 ComponentList
*clist
;
863 component
->hasLocalFeature
= FALSE
;
865 component
->Action
= newstate
;
866 component
->ActionRequest
= newstate
;
867 /* if any other feature wants it local we need to set it local */
868 LIST_FOR_EACH_ENTRY(f
, &package
->features
, MSIFEATURE
, entry
)
870 if ( f
->ActionRequest
!= INSTALLSTATE_LOCAL
&&
871 f
->ActionRequest
!= INSTALLSTATE_SOURCE
)
875 LIST_FOR_EACH_ENTRY(clist
, &f
->Components
, ComponentList
, entry
)
877 if (clist
->component
== component
&&
878 (f
->ActionRequest
== INSTALLSTATE_LOCAL
||
879 f
->ActionRequest
== INSTALLSTATE_SOURCE
))
881 TRACE("Saved by %s\n", debugstr_w(f
->Feature
));
882 component
->hasLocalFeature
= TRUE
;
884 if (component
->Attributes
& msidbComponentAttributesOptional
)
886 if (f
->Attributes
& msidbFeatureAttributesFavorSource
)
888 component
->Action
= INSTALLSTATE_SOURCE
;
889 component
->ActionRequest
= INSTALLSTATE_SOURCE
;
893 component
->Action
= INSTALLSTATE_LOCAL
;
894 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
897 else if (component
->Attributes
& msidbComponentAttributesSourceOnly
)
899 component
->Action
= INSTALLSTATE_SOURCE
;
900 component
->ActionRequest
= INSTALLSTATE_SOURCE
;
904 component
->Action
= INSTALLSTATE_LOCAL
;
905 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
911 TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
912 newstate
, debugstr_w(component
->Component
), component
->Installed
,
913 component
->Action
, component
->ActionRequest
);
917 UINT
MSI_SetFeatureStateW( MSIPACKAGE
*package
, LPCWSTR szFeature
, INSTALLSTATE iState
)
919 UINT rc
= ERROR_SUCCESS
;
920 MSIFEATURE
*feature
, *child
;
922 TRACE("%s %i\n", debugstr_w(szFeature
), iState
);
924 feature
= msi_get_loaded_feature( package
, szFeature
);
926 return ERROR_UNKNOWN_FEATURE
;
928 if (iState
== INSTALLSTATE_ADVERTISED
&&
929 feature
->Attributes
& msidbFeatureAttributesDisallowAdvertise
)
930 return ERROR_FUNCTION_FAILED
;
932 feature
->ActionRequest
= iState
;
934 ACTION_UpdateComponentStates( package
, feature
);
936 /* update all the features that are children of this feature */
937 LIST_FOR_EACH_ENTRY( child
, &package
->features
, MSIFEATURE
, entry
)
939 if (child
->Feature_Parent
&& !strcmpW( szFeature
, child
->Feature_Parent
))
940 MSI_SetFeatureStateW(package
, child
->Feature
, iState
);
946 /***********************************************************************
947 * MsiSetFeatureStateW (MSI.@)
949 UINT WINAPI
MsiSetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
953 UINT rc
= ERROR_SUCCESS
;
955 TRACE("%s %i\n",debugstr_w(szFeature
), iState
);
957 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
964 if (!(remote
= msi_get_remote(hInstall
)))
965 return ERROR_INVALID_HANDLE
;
967 feature
= SysAllocString(szFeature
);
969 return ERROR_OUTOFMEMORY
;
971 hr
= remote_SetFeatureState(remote
, feature
, iState
);
973 SysFreeString(feature
);
977 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
978 return HRESULT_CODE(hr
);
980 return ERROR_FUNCTION_FAILED
;
983 return ERROR_SUCCESS
;
986 rc
= MSI_SetFeatureStateW(package
,szFeature
,iState
);
988 msiobj_release( &package
->hdr
);
992 /***********************************************************************
993 * MsiSetFeatureAttributesA (MSI.@)
995 UINT WINAPI
MsiSetFeatureAttributesA( MSIHANDLE handle
, LPCSTR feature
, DWORD attrs
)
998 WCHAR
*featureW
= NULL
;
1000 TRACE("%u, %s, 0x%08x\n", handle
, debugstr_a(feature
), attrs
);
1002 if (feature
&& !(featureW
= strdupAtoW( feature
))) return ERROR_OUTOFMEMORY
;
1004 r
= MsiSetFeatureAttributesW( handle
, featureW
, attrs
);
1005 msi_free( featureW
);
1009 static DWORD
unmap_feature_attributes( DWORD attrs
)
1013 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORLOCAL
) ret
= msidbFeatureAttributesFavorLocal
;
1014 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORSOURCE
) ret
|= msidbFeatureAttributesFavorSource
;
1015 if (attrs
& INSTALLFEATUREATTRIBUTE_FOLLOWPARENT
) ret
|= msidbFeatureAttributesFollowParent
;
1016 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORADVERTISE
) ret
|= msidbFeatureAttributesFavorAdvertise
;
1017 if (attrs
& INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE
) ret
|= msidbFeatureAttributesDisallowAdvertise
;
1018 if (attrs
& INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE
) ret
|= msidbFeatureAttributesNoUnsupportedAdvertise
;
1022 /***********************************************************************
1023 * MsiSetFeatureAttributesW (MSI.@)
1025 UINT WINAPI
MsiSetFeatureAttributesW( MSIHANDLE handle
, LPCWSTR name
, DWORD attrs
)
1027 MSIPACKAGE
*package
;
1028 MSIFEATURE
*feature
;
1031 TRACE("%u, %s, 0x%08x\n", handle
, debugstr_w(name
), attrs
);
1033 if (!name
|| !name
[0]) return ERROR_UNKNOWN_FEATURE
;
1035 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
1036 return ERROR_INVALID_HANDLE
;
1038 costing
= msi_dup_property( package
->db
, szCostingComplete
);
1039 if (!costing
|| !strcmpW( costing
, szOne
))
1041 msi_free( costing
);
1042 msiobj_release( &package
->hdr
);
1043 return ERROR_FUNCTION_FAILED
;
1045 msi_free( costing
);
1046 if (!(feature
= msi_get_loaded_feature( package
, name
)))
1048 msiobj_release( &package
->hdr
);
1049 return ERROR_UNKNOWN_FEATURE
;
1051 feature
->Attributes
= unmap_feature_attributes( attrs
);
1052 msiobj_release( &package
->hdr
);
1053 return ERROR_SUCCESS
;
1056 /***********************************************************************
1057 * MsiGetFeatureStateA (MSI.@)
1059 UINT WINAPI
MsiGetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
1060 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1062 LPWSTR szwFeature
= NULL
;
1065 if (szFeature
&& !(szwFeature
= strdupAtoW(szFeature
))) return ERROR_OUTOFMEMORY
;
1067 rc
= MsiGetFeatureStateW(hInstall
, szwFeature
, piInstalled
, piAction
);
1068 msi_free( szwFeature
);
1072 UINT
MSI_GetFeatureStateW(MSIPACKAGE
*package
, LPCWSTR szFeature
,
1073 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1075 MSIFEATURE
*feature
;
1077 feature
= msi_get_loaded_feature(package
,szFeature
);
1079 return ERROR_UNKNOWN_FEATURE
;
1082 *piInstalled
= feature
->Installed
;
1085 *piAction
= feature
->ActionRequest
;
1087 TRACE("returning %i %i\n", feature
->Installed
, feature
->ActionRequest
);
1089 return ERROR_SUCCESS
;
1092 /***********************************************************************
1093 * MsiGetFeatureStateW (MSI.@)
1095 UINT WINAPI
MsiGetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
1096 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1098 MSIPACKAGE
* package
;
1101 TRACE("%d %s %p %p\n", hInstall
, debugstr_w(szFeature
), piInstalled
, piAction
);
1103 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1110 if (!(remote
= msi_get_remote(hInstall
)))
1111 return ERROR_INVALID_HANDLE
;
1113 feature
= SysAllocString(szFeature
);
1115 return ERROR_OUTOFMEMORY
;
1117 hr
= remote_GetFeatureState(remote
, feature
, piInstalled
, piAction
);
1119 SysFreeString(feature
);
1123 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1124 return HRESULT_CODE(hr
);
1126 return ERROR_FUNCTION_FAILED
;
1129 return ERROR_SUCCESS
;
1132 ret
= MSI_GetFeatureStateW(package
, szFeature
, piInstalled
, piAction
);
1133 msiobj_release( &package
->hdr
);
1137 /***********************************************************************
1138 * MsiGetFeatureCostA (MSI.@)
1140 UINT WINAPI
MsiGetFeatureCostA(MSIHANDLE hInstall
, LPCSTR szFeature
,
1141 MSICOSTTREE iCostTree
, INSTALLSTATE iState
, LPINT piCost
)
1143 LPWSTR szwFeature
= NULL
;
1146 szwFeature
= strdupAtoW(szFeature
);
1148 rc
= MsiGetFeatureCostW(hInstall
, szwFeature
, iCostTree
, iState
, piCost
);
1150 msi_free(szwFeature
);
1155 static INT
feature_cost( MSIFEATURE
*feature
)
1160 LIST_FOR_EACH_ENTRY( cl
, &feature
->Components
, ComponentList
, entry
)
1162 cost
+= cl
->component
->Cost
;
1167 UINT
MSI_GetFeatureCost( MSIPACKAGE
*package
, MSIFEATURE
*feature
, MSICOSTTREE tree
,
1168 INSTALLSTATE state
, LPINT cost
)
1170 TRACE("%s, %u, %d, %p\n", debugstr_w(feature
->Feature
), tree
, state
, cost
);
1175 case MSICOSTTREE_CHILDREN
:
1179 LIST_FOR_EACH_ENTRY( child
, &feature
->Children
, MSIFEATURE
, entry
)
1181 if (child
->ActionRequest
== state
)
1182 *cost
+= feature_cost( child
);
1186 case MSICOSTTREE_PARENTS
:
1188 const WCHAR
*feature_parent
= feature
->Feature_Parent
;
1191 MSIFEATURE
*parent
= msi_get_loaded_feature( package
, feature_parent
);
1195 if (parent
->ActionRequest
== state
)
1196 *cost
+= feature_cost( parent
);
1198 feature_parent
= parent
->Feature_Parent
;
1202 case MSICOSTTREE_SELFONLY
:
1203 if (feature
->ActionRequest
== state
)
1204 *cost
= feature_cost( feature
);
1208 WARN("unhandled cost tree %u\n", tree
);
1213 return ERROR_SUCCESS
;
1216 /***********************************************************************
1217 * MsiGetFeatureCostW (MSI.@)
1219 UINT WINAPI
MsiGetFeatureCostW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
1220 MSICOSTTREE iCostTree
, INSTALLSTATE iState
, LPINT piCost
)
1222 MSIPACKAGE
*package
;
1223 MSIFEATURE
*feature
;
1226 TRACE("(%d %s %i %i %p)\n", hInstall
, debugstr_w(szFeature
),
1227 iCostTree
, iState
, piCost
);
1229 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1236 if (!(remote
= msi_get_remote(hInstall
)))
1237 return ERROR_INVALID_HANDLE
;
1239 feature
= SysAllocString(szFeature
);
1241 return ERROR_OUTOFMEMORY
;
1243 hr
= remote_GetFeatureCost(remote
, feature
, iCostTree
, iState
, piCost
);
1245 SysFreeString(feature
);
1249 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1250 return HRESULT_CODE(hr
);
1252 return ERROR_FUNCTION_FAILED
;
1255 return ERROR_SUCCESS
;
1258 feature
= msi_get_loaded_feature(package
, szFeature
);
1261 ret
= MSI_GetFeatureCost(package
, feature
, iCostTree
, iState
, piCost
);
1263 ret
= ERROR_UNKNOWN_FEATURE
;
1265 msiobj_release( &package
->hdr
);
1269 /***********************************************************************
1270 * MsiGetFeatureInfoA (MSI.@)
1272 UINT WINAPI
MsiGetFeatureInfoA( MSIHANDLE handle
, LPCSTR feature
, LPDWORD attrs
,
1273 LPSTR title
, LPDWORD title_len
, LPSTR help
, LPDWORD help_len
)
1276 WCHAR
*titleW
= NULL
, *helpW
= NULL
, *featureW
= NULL
;
1278 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle
, debugstr_a(feature
), attrs
, title
,
1279 title_len
, help
, help_len
);
1281 if (feature
&& !(featureW
= strdupAtoW( feature
))) return ERROR_OUTOFMEMORY
;
1283 if (title
&& title_len
&& !(titleW
= msi_alloc( *title_len
* sizeof(WCHAR
) )))
1285 msi_free( featureW
);
1286 return ERROR_OUTOFMEMORY
;
1288 if (help
&& help_len
&& !(helpW
= msi_alloc( *help_len
* sizeof(WCHAR
) )))
1290 msi_free( featureW
);
1292 return ERROR_OUTOFMEMORY
;
1294 r
= MsiGetFeatureInfoW( handle
, featureW
, attrs
, titleW
, title_len
, helpW
, help_len
);
1295 if (r
== ERROR_SUCCESS
)
1297 if (titleW
) WideCharToMultiByte( CP_ACP
, 0, titleW
, -1, title
, *title_len
+ 1, NULL
, NULL
);
1298 if (helpW
) WideCharToMultiByte( CP_ACP
, 0, helpW
, -1, help
, *help_len
+ 1, NULL
, NULL
);
1302 msi_free( featureW
);
1306 static DWORD
map_feature_attributes( DWORD attrs
)
1310 if (attrs
== msidbFeatureAttributesFavorLocal
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORLOCAL
;
1311 if (attrs
& msidbFeatureAttributesFavorSource
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORSOURCE
;
1312 if (attrs
& msidbFeatureAttributesFollowParent
) ret
|= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT
;
1313 if (attrs
& msidbFeatureAttributesFavorAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE
;
1314 if (attrs
& msidbFeatureAttributesDisallowAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE
;
1315 if (attrs
& msidbFeatureAttributesNoUnsupportedAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE
;
1319 static UINT
MSI_GetFeatureInfo( MSIPACKAGE
*package
, LPCWSTR name
, LPDWORD attrs
,
1320 LPWSTR title
, LPDWORD title_len
, LPWSTR help
, LPDWORD help_len
)
1322 UINT r
= ERROR_SUCCESS
;
1323 MSIFEATURE
*feature
= msi_get_loaded_feature( package
, name
);
1326 if (!feature
) return ERROR_UNKNOWN_FEATURE
;
1327 if (attrs
) *attrs
= map_feature_attributes( feature
->Attributes
);
1330 if (feature
->Title
) len
= strlenW( feature
->Title
);
1332 if (*title_len
<= len
)
1335 if (title
) r
= ERROR_MORE_DATA
;
1339 if (feature
->Title
) strcpyW( title
, feature
->Title
);
1346 if (feature
->Description
) len
= strlenW( feature
->Description
);
1348 if (*help_len
<= len
)
1351 if (help
) r
= ERROR_MORE_DATA
;
1355 if (feature
->Description
) strcpyW( help
, feature
->Description
);
1363 /***********************************************************************
1364 * MsiGetFeatureInfoW (MSI.@)
1366 UINT WINAPI
MsiGetFeatureInfoW( MSIHANDLE handle
, LPCWSTR feature
, LPDWORD attrs
,
1367 LPWSTR title
, LPDWORD title_len
, LPWSTR help
, LPDWORD help_len
)
1370 MSIPACKAGE
*package
;
1372 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle
, debugstr_w(feature
), attrs
, title
,
1373 title_len
, help
, help_len
);
1375 if (!feature
) return ERROR_INVALID_PARAMETER
;
1377 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
1378 return ERROR_INVALID_HANDLE
;
1380 /* features may not have been loaded yet */
1381 msi_load_all_components( package
);
1382 msi_load_all_features( package
);
1384 r
= MSI_GetFeatureInfo( package
, feature
, attrs
, title
, title_len
, help
, help_len
);
1385 msiobj_release( &package
->hdr
);
1389 /***********************************************************************
1390 * MsiSetComponentStateA (MSI.@)
1392 UINT WINAPI
MsiSetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
1393 INSTALLSTATE iState
)
1396 LPWSTR szwComponent
= strdupAtoW(szComponent
);
1398 rc
= MsiSetComponentStateW(hInstall
, szwComponent
, iState
);
1400 msi_free(szwComponent
);
1405 /***********************************************************************
1406 * MsiGetComponentStateA (MSI.@)
1408 UINT WINAPI
MsiGetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
1409 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1411 LPWSTR szwComponent
= NULL
;
1414 szwComponent
= strdupAtoW(szComponent
);
1416 rc
= MsiGetComponentStateW(hInstall
,szwComponent
,piInstalled
, piAction
);
1418 msi_free( szwComponent
);
1423 static UINT
MSI_SetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
1424 INSTALLSTATE iState
)
1428 TRACE("%p %s %d\n", package
, debugstr_w(szComponent
), iState
);
1430 comp
= msi_get_loaded_component(package
, szComponent
);
1432 return ERROR_UNKNOWN_COMPONENT
;
1435 comp
->Action
= iState
;
1437 return ERROR_SUCCESS
;
1440 UINT
MSI_GetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
1441 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1445 TRACE("%p %s %p %p\n", package
, debugstr_w(szComponent
),
1446 piInstalled
, piAction
);
1448 comp
= msi_get_loaded_component(package
,szComponent
);
1450 return ERROR_UNKNOWN_COMPONENT
;
1455 *piInstalled
= comp
->Installed
;
1457 *piInstalled
= INSTALLSTATE_UNKNOWN
;
1463 *piAction
= comp
->Action
;
1465 *piAction
= INSTALLSTATE_UNKNOWN
;
1468 TRACE("states (%i, %i)\n", comp
->Installed
, comp
->Action
);
1469 return ERROR_SUCCESS
;
1472 /***********************************************************************
1473 * MsiSetComponentStateW (MSI.@)
1475 UINT WINAPI
MsiSetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
1476 INSTALLSTATE iState
)
1478 MSIPACKAGE
* package
;
1481 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1488 if (!(remote
= msi_get_remote(hInstall
)))
1489 return ERROR_INVALID_HANDLE
;
1491 component
= SysAllocString(szComponent
);
1493 return ERROR_OUTOFMEMORY
;
1495 hr
= remote_SetComponentState(remote
, component
, iState
);
1497 SysFreeString(component
);
1501 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1502 return HRESULT_CODE(hr
);
1504 return ERROR_FUNCTION_FAILED
;
1507 return ERROR_SUCCESS
;
1510 ret
= MSI_SetComponentStateW(package
, szComponent
, iState
);
1511 msiobj_release(&package
->hdr
);
1515 /***********************************************************************
1516 * MsiGetComponentStateW (MSI.@)
1518 UINT WINAPI
MsiGetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
1519 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1521 MSIPACKAGE
* package
;
1524 TRACE("%d %s %p %p\n", hInstall
, debugstr_w(szComponent
),
1525 piInstalled
, piAction
);
1527 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1534 if (!(remote
= msi_get_remote(hInstall
)))
1535 return ERROR_INVALID_HANDLE
;
1537 component
= SysAllocString(szComponent
);
1539 return ERROR_OUTOFMEMORY
;
1541 hr
= remote_GetComponentState(remote
, component
, piInstalled
, piAction
);
1543 SysFreeString(component
);
1547 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1548 return HRESULT_CODE(hr
);
1550 return ERROR_FUNCTION_FAILED
;
1553 return ERROR_SUCCESS
;
1556 ret
= MSI_GetComponentStateW( package
, szComponent
, piInstalled
, piAction
);
1557 msiobj_release( &package
->hdr
);
1561 /***********************************************************************
1562 * MsiGetLanguage (MSI.@)
1564 LANGID WINAPI
MsiGetLanguage(MSIHANDLE hInstall
)
1566 MSIPACKAGE
* package
;
1569 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1576 if (!(remote
= msi_get_remote(hInstall
)))
1577 return ERROR_INVALID_HANDLE
;
1579 hr
= remote_GetLanguage(remote
, &lang
);
1587 langid
= msi_get_property_int( package
->db
, szProductLanguage
, 0 );
1588 msiobj_release( &package
->hdr
);
1592 UINT
MSI_SetInstallLevel( MSIPACKAGE
*package
, int iInstallLevel
)
1594 static const WCHAR fmt
[] = { '%','d',0 };
1599 TRACE("%p %i\n", package
, iInstallLevel
);
1601 if (iInstallLevel
> 32767)
1602 return ERROR_INVALID_PARAMETER
;
1604 if (iInstallLevel
< 1)
1605 return MSI_SetFeatureStates( package
);
1607 len
= sprintfW( level
, fmt
, iInstallLevel
);
1608 r
= msi_set_property( package
->db
, szInstallLevel
, level
, len
);
1609 if ( r
== ERROR_SUCCESS
)
1610 r
= MSI_SetFeatureStates( package
);
1615 /***********************************************************************
1616 * MsiSetInstallLevel (MSI.@)
1618 UINT WINAPI
MsiSetInstallLevel(MSIHANDLE hInstall
, int iInstallLevel
)
1620 MSIPACKAGE
* package
;
1623 TRACE("%d %i\n", hInstall
, iInstallLevel
);
1625 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1631 if (!(remote
= msi_get_remote(hInstall
)))
1632 return ERROR_INVALID_HANDLE
;
1634 hr
= remote_SetInstallLevel(remote
, iInstallLevel
);
1638 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
)
1639 return HRESULT_CODE(hr
);
1641 return ERROR_FUNCTION_FAILED
;
1644 return ERROR_SUCCESS
;
1647 r
= MSI_SetInstallLevel( package
, iInstallLevel
);
1649 msiobj_release( &package
->hdr
);
1654 /***********************************************************************
1655 * MsiGetFeatureValidStatesW (MSI.@)
1657 UINT WINAPI
MsiGetFeatureValidStatesW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
1658 LPDWORD pInstallState
)
1660 if(pInstallState
) *pInstallState
= 1<<INSTALLSTATE_LOCAL
;
1661 FIXME("%d %s %p stub returning %d\n",
1662 hInstall
, debugstr_w(szFeature
), pInstallState
, pInstallState
? *pInstallState
: 0);
1664 return ERROR_SUCCESS
;
1667 /***********************************************************************
1668 * MsiGetFeatureValidStatesA (MSI.@)
1670 UINT WINAPI
MsiGetFeatureValidStatesA(MSIHANDLE hInstall
, LPCSTR szFeature
,
1671 LPDWORD pInstallState
)
1674 LPWSTR szwFeature
= strdupAtoW(szFeature
);
1676 ret
= MsiGetFeatureValidStatesW(hInstall
, szwFeature
, pInstallState
);
1678 msi_free(szwFeature
);