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 */
28 #include "wine/debug.h"
32 #include "wine/unicode.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
36 /***********************************************************************
37 * MsiDoActionA (MSI.@)
39 UINT WINAPI
MsiDoActionA( MSIHANDLE hInstall
, LPCSTR szAction
)
44 TRACE("%s\n", debugstr_a(szAction
));
46 szwAction
= strdupAtoW(szAction
);
47 if (szAction
&& !szwAction
)
48 return ERROR_FUNCTION_FAILED
;
50 ret
= MsiDoActionW( hInstall
, szwAction
);
51 msi_free( szwAction
);
55 /***********************************************************************
56 * MsiDoActionW (MSI.@)
58 UINT WINAPI
MsiDoActionW( MSIHANDLE hInstall
, LPCWSTR szAction
)
63 TRACE("%s\n",debugstr_w(szAction
));
66 return ERROR_INVALID_PARAMETER
;
68 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
70 return ERROR_INVALID_HANDLE
;
72 ret
= ACTION_PerformUIAction( package
, szAction
);
73 msiobj_release( &package
->hdr
);
78 /***********************************************************************
79 * MsiSequenceA (MSI.@)
81 UINT WINAPI
MsiSequenceA( MSIHANDLE hInstall
, LPCSTR szTable
, INT iSequenceMode
)
86 TRACE("%s\n", debugstr_a(szTable
));
88 szwTable
= strdupAtoW(szTable
);
89 if (szTable
&& !szwTable
)
90 return ERROR_FUNCTION_FAILED
;
92 ret
= MsiSequenceW( hInstall
, szwTable
, iSequenceMode
);
97 /***********************************************************************
98 * MsiSequenceW (MSI.@)
100 UINT WINAPI
MsiSequenceW( MSIHANDLE hInstall
, LPCWSTR szTable
, INT iSequenceMode
)
105 TRACE("%s\n", debugstr_w(szTable
));
107 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
109 return ERROR_INVALID_HANDLE
;
111 ret
= MSI_Sequence( package
, szTable
, iSequenceMode
);
112 msiobj_release( &package
->hdr
);
117 UINT
msi_strcpy_to_awstring( LPCWSTR str
, awstring
*awbuf
, DWORD
*sz
)
119 UINT len
, r
= ERROR_SUCCESS
;
121 if (awbuf
->str
.w
&& !sz
)
122 return ERROR_INVALID_PARAMETER
;
129 len
= lstrlenW( str
);
131 lstrcpynW( awbuf
->str
.w
, str
, *sz
);
135 len
= WideCharToMultiByte( CP_ACP
, 0, str
, -1, NULL
, 0, NULL
, NULL
);
138 WideCharToMultiByte( CP_ACP
, 0, str
, -1, awbuf
->str
.a
, *sz
, NULL
, NULL
);
139 if ( awbuf
->str
.a
&& *sz
&& (len
>= *sz
) )
140 awbuf
->str
.a
[*sz
- 1] = 0;
143 if (awbuf
->str
.w
&& len
>= *sz
)
149 /***********************************************************************
150 * MsiGetTargetPath (internal)
152 static UINT WINAPI
MSI_GetTargetPath( MSIHANDLE hInstall
, LPCWSTR szFolder
,
153 awstring
*szPathBuf
, DWORD
* pcchPathBuf
)
160 return ERROR_INVALID_PARAMETER
;
162 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
164 return ERROR_INVALID_HANDLE
;
166 path
= resolve_folder( package
, szFolder
, FALSE
, FALSE
, TRUE
, NULL
);
167 msiobj_release( &package
->hdr
);
170 return ERROR_DIRECTORY
;
172 r
= msi_strcpy_to_awstring( path
, szPathBuf
, pcchPathBuf
);
177 /***********************************************************************
178 * MsiGetTargetPathA (MSI.@)
180 UINT WINAPI
MsiGetTargetPathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
181 LPSTR szPathBuf
, DWORD
* pcchPathBuf
)
187 TRACE("%s %p %p\n", debugstr_a(szFolder
), szPathBuf
, pcchPathBuf
);
189 szwFolder
= strdupAtoW(szFolder
);
190 if (szFolder
&& !szwFolder
)
191 return ERROR_FUNCTION_FAILED
;
193 path
.unicode
= FALSE
;
194 path
.str
.a
= szPathBuf
;
196 r
= MSI_GetTargetPath( hInstall
, szwFolder
, &path
, pcchPathBuf
);
198 msi_free( szwFolder
);
203 /***********************************************************************
204 * MsiGetTargetPathW (MSI.@)
206 UINT WINAPI
MsiGetTargetPathW( MSIHANDLE hInstall
, LPCWSTR szFolder
,
207 LPWSTR szPathBuf
, DWORD
* pcchPathBuf
)
211 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
214 path
.str
.w
= szPathBuf
;
216 return MSI_GetTargetPath( hInstall
, szFolder
, &path
, pcchPathBuf
);
219 /***********************************************************************
220 * MsiGetSourcePath (internal)
222 static UINT
MSI_GetSourcePath( MSIHANDLE hInstall
, LPCWSTR szFolder
,
223 awstring
*szPathBuf
, DWORD
* pcchPathBuf
)
229 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
232 return ERROR_INVALID_PARAMETER
;
234 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
236 return ERROR_INVALID_HANDLE
;
238 if (szPathBuf
->str
.w
&& !pcchPathBuf
)
240 msiobj_release( &package
->hdr
);
241 return ERROR_INVALID_PARAMETER
;
244 path
= resolve_folder(package
, szFolder
, TRUE
, FALSE
, TRUE
, NULL
);
245 msiobj_release( &package
->hdr
);
247 TRACE("path = %s\n",debugstr_w(path
));
249 return ERROR_DIRECTORY
;
251 r
= msi_strcpy_to_awstring( path
, szPathBuf
, pcchPathBuf
);
256 /***********************************************************************
257 * MsiGetSourcePathA (MSI.@)
259 UINT WINAPI
MsiGetSourcePathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
260 LPSTR szPathBuf
, DWORD
* pcchPathBuf
)
266 TRACE("%s %p %p\n", szFolder
, debugstr_a(szPathBuf
), pcchPathBuf
);
269 str
.str
.a
= szPathBuf
;
271 folder
= strdupAtoW( szFolder
);
272 r
= MSI_GetSourcePath( hInstall
, folder
, &str
, pcchPathBuf
);
278 /***********************************************************************
279 * MsiGetSourcePathW (MSI.@)
281 UINT WINAPI
MsiGetSourcePathW( MSIHANDLE hInstall
, LPCWSTR szFolder
,
282 LPWSTR szPathBuf
, DWORD
* pcchPathBuf
)
286 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
289 str
.str
.w
= szPathBuf
;
291 return MSI_GetSourcePath( hInstall
, szFolder
, &str
, pcchPathBuf
);
294 /***********************************************************************
295 * MsiSetTargetPathA (MSI.@)
297 UINT WINAPI
MsiSetTargetPathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
298 LPCSTR szFolderPath
)
300 LPWSTR szwFolder
= NULL
, szwFolderPath
= NULL
;
301 UINT rc
= ERROR_OUTOFMEMORY
;
303 if ( !szFolder
|| !szFolderPath
)
304 return ERROR_INVALID_PARAMETER
;
306 szwFolder
= strdupAtoW(szFolder
);
307 szwFolderPath
= strdupAtoW(szFolderPath
);
308 if (!szwFolder
|| !szwFolderPath
)
311 rc
= MsiSetTargetPathW( hInstall
, szwFolder
, szwFolderPath
);
315 msi_free(szwFolderPath
);
321 * Ok my original interpretation of this was wrong. And it looks like msdn has
322 * changed a bit also. The given folder path does not have to actually already
323 * exist, it just cannot be read only and must be a legal folder path.
325 UINT
MSI_SetTargetPathW(MSIPACKAGE
*package
, LPCWSTR szFolder
,
326 LPCWSTR szFolderPath
)
334 TRACE("%p %s %s\n",package
, debugstr_w(szFolder
),debugstr_w(szFolderPath
));
336 attrib
= GetFileAttributesW(szFolderPath
);
337 /* native MSI tests writeability by making temporary files at each drive */
338 if ( attrib
!= INVALID_FILE_ATTRIBUTES
&&
339 (attrib
& FILE_ATTRIBUTE_OFFLINE
||
340 attrib
& FILE_ATTRIBUTE_READONLY
))
341 return ERROR_FUNCTION_FAILED
;
343 path
= resolve_folder(package
,szFolder
,FALSE
,FALSE
,FALSE
,&folder
);
345 return ERROR_DIRECTORY
;
347 msi_free(folder
->Property
);
348 folder
->Property
= build_directory_name(2, szFolderPath
, NULL
);
350 if (lstrcmpiW(path
, folder
->Property
) == 0)
353 * Resolved Target has not really changed, so just
354 * set this folder and do not recalculate everything.
356 msi_free(folder
->ResolvedTarget
);
357 folder
->ResolvedTarget
= NULL
;
358 path2
= resolve_folder(package
,szFolder
,FALSE
,TRUE
,FALSE
,NULL
);
365 LIST_FOR_EACH_ENTRY( f
, &package
->folders
, MSIFOLDER
, entry
)
367 msi_free(f
->ResolvedTarget
);
368 f
->ResolvedTarget
=NULL
;
371 LIST_FOR_EACH_ENTRY( f
, &package
->folders
, MSIFOLDER
, entry
)
373 path2
= resolve_folder(package
, f
->Directory
, FALSE
, TRUE
, FALSE
, NULL
);
377 LIST_FOR_EACH_ENTRY( file
, &package
->files
, MSIFILE
, entry
)
379 MSICOMPONENT
*comp
= file
->Component
;
385 p
= resolve_folder(package
, comp
->Directory
, FALSE
, FALSE
, FALSE
, NULL
);
386 msi_free(file
->TargetPath
);
388 file
->TargetPath
= build_directory_name(2, p
, file
->FileName
);
394 return ERROR_SUCCESS
;
397 /***********************************************************************
398 * MsiSetTargetPathW (MSI.@)
400 UINT WINAPI
MsiSetTargetPathW(MSIHANDLE hInstall
, LPCWSTR szFolder
,
401 LPCWSTR szFolderPath
)
406 TRACE("%s %s\n",debugstr_w(szFolder
),debugstr_w(szFolderPath
));
408 if ( !szFolder
|| !szFolderPath
)
409 return ERROR_INVALID_PARAMETER
;
411 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
413 return ERROR_INVALID_HANDLE
;
415 ret
= MSI_SetTargetPathW( package
, szFolder
, szFolderPath
);
416 msiobj_release( &package
->hdr
);
420 /***********************************************************************
423 * Returns an internal installer state (if it is running in a mode iRunMode)
426 * hInstall [I] Handle to the installation
427 * hRunMode [I] Checking run mode
428 * MSIRUNMODE_ADMIN Administrative mode
429 * MSIRUNMODE_ADVERTISE Advertisement mode
430 * MSIRUNMODE_MAINTENANCE Maintenance mode
431 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
432 * MSIRUNMODE_LOGENABLED Log file is writing
433 * MSIRUNMODE_OPERATIONS Operations in progress??
434 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
435 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
436 * MSIRUNMODE_CABINET Files from cabinet are installed
437 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed
438 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed
439 * MSIRUNMODE_RESERVED11 Reserved
440 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
441 * MSIRUNMODE_ZAWENABLED Demand installation is supported
442 * MSIRUNMODE_RESERVED14 Reserved
443 * MSIRUNMODE_RESERVED15 Reserved
444 * MSIRUNMODE_SCHEDULED called from install script
445 * MSIRUNMODE_ROLLBACK called from rollback script
446 * MSIRUNMODE_COMMIT called from commit script
450 * Not in the state: FALSE
453 extern int global_deferred
;
454 BOOL WINAPI
MsiGetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
)
460 case MSIRUNMODE_WINDOWS9X
:
461 if (GetVersion() & 0x80000000)
465 case MSIRUNMODE_RESERVED11
:
466 case MSIRUNMODE_RESERVED14
:
467 case MSIRUNMODE_RESERVED15
:
470 case MSIRUNMODE_SCHEDULED
:
471 case MSIRUNMODE_COMMIT
:
472 if (global_deferred
) r
= TRUE
;
474 case MSIRUNMODE_ROLLBACK
:
478 FIXME("%ld %d\n", hInstall
, iRunMode
);
482 TRACE("%d -> %d\n", iRunMode
, r
);
486 /***********************************************************************
489 BOOL WINAPI
MsiSetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
, BOOL fState
)
493 case MSIRUNMODE_RESERVED11
:
494 case MSIRUNMODE_WINDOWS9X
:
495 case MSIRUNMODE_RESERVED14
:
496 case MSIRUNMODE_RESERVED15
:
499 FIXME("%ld %d %d\n", hInstall
, iRunMode
, fState
);
504 /***********************************************************************
505 * MsiSetFeatureStateA (MSI.@)
507 * According to the docs, when this is called it immediately recalculates
508 * all the component states as well
510 UINT WINAPI
MsiSetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
513 LPWSTR szwFeature
= NULL
;
516 szwFeature
= strdupAtoW(szFeature
);
519 return ERROR_FUNCTION_FAILED
;
521 rc
= MsiSetFeatureStateW(hInstall
,szwFeature
, iState
);
523 msi_free(szwFeature
);
530 UINT WINAPI
MSI_SetFeatureStateW(MSIPACKAGE
* package
, LPCWSTR szFeature
,
533 UINT rc
= ERROR_SUCCESS
;
534 MSIFEATURE
*feature
, *child
;
536 TRACE("%s %i\n", debugstr_w(szFeature
), iState
);
538 feature
= get_loaded_feature(package
,szFeature
);
540 return ERROR_UNKNOWN_FEATURE
;
542 if (iState
== INSTALLSTATE_ADVERTISED
&&
543 feature
->Attributes
& msidbFeatureAttributesDisallowAdvertise
)
544 return ERROR_FUNCTION_FAILED
;
546 msi_feature_set_state( feature
, iState
);
548 ACTION_UpdateComponentStates(package
,szFeature
);
550 /* update all the features that are children of this feature */
551 LIST_FOR_EACH_ENTRY( child
, &package
->features
, MSIFEATURE
, entry
)
553 if (lstrcmpW(szFeature
, child
->Feature_Parent
) == 0)
554 MSI_SetFeatureStateW(package
, child
->Feature
, iState
);
560 /***********************************************************************
561 * MsiSetFeatureStateW (MSI.@)
563 UINT WINAPI
MsiSetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
567 UINT rc
= ERROR_SUCCESS
;
569 TRACE("%s %i\n",debugstr_w(szFeature
), iState
);
571 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
573 return ERROR_INVALID_HANDLE
;
575 rc
= MSI_SetFeatureStateW(package
,szFeature
,iState
);
577 msiobj_release( &package
->hdr
);
581 /***********************************************************************
582 * MsiGetFeatureStateA (MSI.@)
584 UINT WINAPI
MsiGetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
585 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
587 LPWSTR szwFeature
= NULL
;
590 szwFeature
= strdupAtoW(szFeature
);
592 rc
= MsiGetFeatureStateW(hInstall
,szwFeature
,piInstalled
, piAction
);
594 msi_free( szwFeature
);
599 UINT
MSI_GetFeatureStateW(MSIPACKAGE
*package
, LPCWSTR szFeature
,
600 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
604 feature
= get_loaded_feature(package
,szFeature
);
606 return ERROR_UNKNOWN_FEATURE
;
609 *piInstalled
= feature
->Installed
;
612 *piAction
= feature
->Action
;
614 TRACE("returning %i %i\n", feature
->Installed
, feature
->Action
);
616 return ERROR_SUCCESS
;
619 /***********************************************************************
620 * MsiGetFeatureStateW (MSI.@)
622 UINT WINAPI
MsiGetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
623 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
628 TRACE("%ld %s %p %p\n", hInstall
, debugstr_w(szFeature
), piInstalled
, piAction
);
630 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
632 return ERROR_INVALID_HANDLE
;
633 ret
= MSI_GetFeatureStateW(package
, szFeature
, piInstalled
, piAction
);
634 msiobj_release( &package
->hdr
);
638 /***********************************************************************
639 * MsiGetFeatureCostA (MSI.@)
641 UINT WINAPI
MsiGetFeatureCostA(MSIHANDLE hInstall
, LPCSTR szFeature
,
642 MSICOSTTREE iCostTree
, INSTALLSTATE iState
, INT
*piCost
)
644 FIXME("(%ld %s %i %i %p): stub\n", hInstall
, debugstr_a(szFeature
),
645 iCostTree
, iState
, piCost
);
646 if (piCost
) *piCost
= 0;
647 return ERROR_SUCCESS
;
650 /***********************************************************************
651 * MsiGetFeatureCostW (MSI.@)
653 UINT WINAPI
MsiGetFeatureCostW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
654 MSICOSTTREE iCostTree
, INSTALLSTATE iState
, INT
*piCost
)
656 FIXME("(%ld %s %i %i %p): stub\n", hInstall
, debugstr_w(szFeature
),
657 iCostTree
, iState
, piCost
);
658 if (piCost
) *piCost
= 0;
659 return ERROR_SUCCESS
;
662 /***********************************************************************
663 * MsiSetComponentStateA (MSI.@)
665 UINT WINAPI
MsiSetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
669 LPWSTR szwComponent
= strdupAtoW(szComponent
);
671 rc
= MsiSetComponentStateW(hInstall
, szwComponent
, iState
);
673 msi_free(szwComponent
);
678 /***********************************************************************
679 * MsiGetComponentStateA (MSI.@)
681 UINT WINAPI
MsiGetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
682 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
684 LPWSTR szwComponent
= NULL
;
687 szwComponent
= strdupAtoW(szComponent
);
689 rc
= MsiGetComponentStateW(hInstall
,szwComponent
,piInstalled
, piAction
);
691 msi_free( szwComponent
);
696 static UINT
MSI_SetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
701 TRACE("%p %s %d\n", package
, debugstr_w(szComponent
), iState
);
703 comp
= get_loaded_component(package
, szComponent
);
705 return ERROR_UNKNOWN_COMPONENT
;
707 comp
->Installed
= iState
;
709 return ERROR_SUCCESS
;
712 UINT
MSI_GetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
713 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
717 TRACE("%p %s %p %p\n", package
, debugstr_w(szComponent
),
718 piInstalled
, piAction
);
720 comp
= get_loaded_component(package
,szComponent
);
722 return ERROR_UNKNOWN_COMPONENT
;
725 *piInstalled
= comp
->Installed
;
728 *piAction
= comp
->Action
;
730 TRACE("states (%i, %i)\n", comp
->Installed
, comp
->Action
);
732 return ERROR_SUCCESS
;
735 /***********************************************************************
736 * MsiSetComponentStateW (MSI.@)
738 UINT WINAPI
MsiSetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
744 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
746 return ERROR_INVALID_HANDLE
;
747 ret
= MSI_SetComponentStateW(package
, szComponent
, iState
);
748 msiobj_release(&package
->hdr
);
752 /***********************************************************************
753 * MsiGetComponentStateW (MSI.@)
755 UINT WINAPI
MsiGetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
756 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
761 TRACE("%ld %s %p %p\n", hInstall
, debugstr_w(szComponent
),
762 piInstalled
, piAction
);
764 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
766 return ERROR_INVALID_HANDLE
;
767 ret
= MSI_GetComponentStateW( package
, szComponent
, piInstalled
, piAction
);
768 msiobj_release( &package
->hdr
);
772 /***********************************************************************
773 * MsiGetLanguage (MSI.@)
775 LANGID WINAPI
MsiGetLanguage(MSIHANDLE hInstall
)
779 static const WCHAR szProductLanguage
[] =
780 {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
782 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
784 return ERROR_INVALID_HANDLE
;
786 langid
= msi_get_property_int( package
, szProductLanguage
, 0 );
787 msiobj_release( &package
->hdr
);
791 UINT
MSI_SetInstallLevel( MSIPACKAGE
*package
, int iInstallLevel
)
793 static const WCHAR szInstallLevel
[] = {
794 'I','N','S','T','A','L','L','L','E','V','E','L',0 };
795 static const WCHAR fmt
[] = { '%','d',0 };
799 TRACE("%p %i\n", package
, iInstallLevel
);
801 if (iInstallLevel
<1 || iInstallLevel
>32767)
802 return ERROR_INVALID_PARAMETER
;
804 sprintfW( level
, fmt
, iInstallLevel
);
805 r
= MSI_SetPropertyW( package
, szInstallLevel
, level
);
806 if ( r
== ERROR_SUCCESS
)
808 r
= MSI_SetFeatureStates( package
);
814 /***********************************************************************
815 * MsiSetInstallLevel (MSI.@)
817 UINT WINAPI
MsiSetInstallLevel(MSIHANDLE hInstall
, int iInstallLevel
)
822 TRACE("%ld %i\n", hInstall
, iInstallLevel
);
824 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
826 return ERROR_INVALID_HANDLE
;
828 r
= MSI_SetInstallLevel( package
, iInstallLevel
);
830 msiobj_release( &package
->hdr
);
835 /***********************************************************************
836 * MsiGetFeatureValidStatesW (MSI.@)
838 UINT WINAPI
MsiGetFeatureValidStatesW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
839 DWORD
* pInstallState
)
841 if(pInstallState
) *pInstallState
= 1<<INSTALLSTATE_LOCAL
;
842 FIXME("%ld %s %p stub returning %d\n",
843 hInstall
, debugstr_w(szFeature
), pInstallState
, pInstallState
? *pInstallState
: 0);
845 return ERROR_SUCCESS
;
848 /***********************************************************************
849 * MsiGetFeatureValidStatesA (MSI.@)
851 UINT WINAPI
MsiGetFeatureValidStatesA(MSIHANDLE hInstall
, LPCSTR szFeature
,
852 DWORD
* pInstallState
)
855 LPWSTR szwFeature
= strdupAtoW(szFeature
);
857 ret
= MsiGetFeatureValidStatesW(hInstall
, szwFeature
, pInstallState
);
859 msi_free(szwFeature
);