2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2005 Aric Stewart for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 /* Msi top level apis directly related to installs */
37 #include "wine/heap.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
43 /***********************************************************************
44 * MsiDoActionA (MSI.@)
46 UINT WINAPI
MsiDoActionA( MSIHANDLE hInstall
, LPCSTR szAction
)
51 TRACE("%s\n", debugstr_a(szAction
));
53 szwAction
= strdupAtoW(szAction
);
54 if (szAction
&& !szwAction
)
55 return ERROR_FUNCTION_FAILED
;
57 ret
= MsiDoActionW( hInstall
, szwAction
);
58 msi_free( szwAction
);
62 /***********************************************************************
63 * MsiDoActionW (MSI.@)
65 UINT WINAPI
MsiDoActionW( MSIHANDLE hInstall
, LPCWSTR szAction
)
70 TRACE("%s\n",debugstr_w(szAction
));
73 return ERROR_INVALID_PARAMETER
;
75 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
80 if (!(remote
= msi_get_remote(hInstall
)))
81 return ERROR_INVALID_HANDLE
;
83 return remote_DoAction(remote
, szAction
);
86 ret
= ACTION_PerformAction( package
, szAction
, SCRIPT_NONE
);
87 msiobj_release( &package
->hdr
);
92 /***********************************************************************
93 * MsiSequenceA (MSI.@)
95 UINT WINAPI
MsiSequenceA( MSIHANDLE hInstall
, LPCSTR szTable
, INT iSequenceMode
)
100 TRACE("%s, %d\n", debugstr_a(szTable
), iSequenceMode
);
102 szwTable
= strdupAtoW(szTable
);
103 if (szTable
&& !szwTable
)
104 return ERROR_FUNCTION_FAILED
;
106 ret
= MsiSequenceW( hInstall
, szwTable
, iSequenceMode
);
107 msi_free( szwTable
);
111 /***********************************************************************
112 * MsiSequenceW (MSI.@)
114 UINT WINAPI
MsiSequenceW( MSIHANDLE hInstall
, LPCWSTR szTable
, INT iSequenceMode
)
119 TRACE("%s, %d\n", debugstr_w(szTable
), iSequenceMode
);
122 return ERROR_INVALID_PARAMETER
;
124 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
129 if (!(remote
= msi_get_remote(hInstall
)))
130 return ERROR_INVALID_HANDLE
;
132 return remote_Sequence(remote
, szTable
, iSequenceMode
);
134 ret
= MSI_Sequence( package
, szTable
);
135 msiobj_release( &package
->hdr
);
139 UINT
msi_strcpy_to_awstring( const WCHAR
*str
, int len
, awstring
*awbuf
, DWORD
*sz
)
141 UINT r
= ERROR_SUCCESS
;
143 if (awbuf
->str
.w
&& !sz
)
144 return ERROR_INVALID_PARAMETER
;
146 return ERROR_SUCCESS
;
148 if (len
< 0) len
= strlenW( str
);
150 if (awbuf
->unicode
&& awbuf
->str
.w
)
152 memcpy( awbuf
->str
.w
, str
, min(len
+ 1, *sz
) * sizeof(WCHAR
) );
153 if (*sz
&& len
>= *sz
)
154 awbuf
->str
.w
[*sz
- 1] = 0;
158 int lenA
= WideCharToMultiByte( CP_ACP
, 0, str
, len
+ 1, NULL
, 0, NULL
, NULL
);
160 WideCharToMultiByte( CP_ACP
, 0, str
, len
+ 1, awbuf
->str
.a
, *sz
, NULL
, NULL
);
161 if (awbuf
->str
.a
&& *sz
&& lenA
>= *sz
)
162 awbuf
->str
.a
[*sz
- 1] = 0;
165 if (awbuf
->str
.w
&& len
>= *sz
)
171 const WCHAR
*msi_get_target_folder( MSIPACKAGE
*package
, const WCHAR
*name
)
173 MSIFOLDER
*folder
= msi_get_loaded_folder( package
, name
);
175 if (!folder
) return NULL
;
176 if (!folder
->ResolvedTarget
)
178 MSIFOLDER
*parent
= folder
;
179 while (parent
->Parent
&& strcmpW( parent
->Parent
, parent
->Directory
))
181 parent
= msi_get_loaded_folder( package
, parent
->Parent
);
183 msi_resolve_target_folder( package
, parent
->Directory
, TRUE
);
185 return folder
->ResolvedTarget
;
188 /***********************************************************************
189 * MsiGetTargetPath (internal)
191 static UINT
MSI_GetTargetPath( MSIHANDLE hInstall
, LPCWSTR szFolder
,
192 awstring
*szPathBuf
, LPDWORD pcchPathBuf
)
196 UINT r
= ERROR_FUNCTION_FAILED
;
199 return ERROR_INVALID_PARAMETER
;
201 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
207 if (!(remote
= msi_get_remote(hInstall
)))
208 return ERROR_INVALID_HANDLE
;
210 r
= remote_GetTargetPath(remote
, szFolder
, &value
);
211 if (r
!= ERROR_SUCCESS
)
214 r
= msi_strcpy_to_awstring(value
, -1, szPathBuf
, pcchPathBuf
);
216 midl_user_free(value
);
220 path
= msi_get_target_folder( package
, szFolder
);
221 msiobj_release( &package
->hdr
);
224 return ERROR_DIRECTORY
;
226 return msi_strcpy_to_awstring( path
, -1, szPathBuf
, pcchPathBuf
);
229 /***********************************************************************
230 * MsiGetTargetPathA (MSI.@)
232 UINT WINAPI
MsiGetTargetPathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
233 LPSTR szPathBuf
, LPDWORD pcchPathBuf
)
239 TRACE("%s %p %p\n", debugstr_a(szFolder
), szPathBuf
, pcchPathBuf
);
241 szwFolder
= strdupAtoW(szFolder
);
242 if (szFolder
&& !szwFolder
)
243 return ERROR_FUNCTION_FAILED
;
245 path
.unicode
= FALSE
;
246 path
.str
.a
= szPathBuf
;
248 r
= MSI_GetTargetPath( hInstall
, szwFolder
, &path
, pcchPathBuf
);
250 msi_free( szwFolder
);
255 /***********************************************************************
256 * MsiGetTargetPathW (MSI.@)
258 UINT WINAPI
MsiGetTargetPathW( MSIHANDLE hInstall
, LPCWSTR szFolder
,
259 LPWSTR szPathBuf
, LPDWORD pcchPathBuf
)
263 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
266 path
.str
.w
= szPathBuf
;
268 return MSI_GetTargetPath( hInstall
, szFolder
, &path
, pcchPathBuf
);
271 static WCHAR
*get_source_root( MSIPACKAGE
*package
)
273 msi_set_sourcedir_props( package
, FALSE
);
274 return msi_dup_property( package
->db
, szSourceDir
);
277 WCHAR
*msi_resolve_source_folder( MSIPACKAGE
*package
, const WCHAR
*name
, MSIFOLDER
**folder
)
280 LPWSTR p
, path
= NULL
, parent
;
282 TRACE("working to resolve %s\n", debugstr_w(name
));
284 if (!strcmpW( name
, szSourceDir
)) name
= szTargetDir
;
285 if (!(f
= msi_get_loaded_folder( package
, name
))) return NULL
;
287 /* special resolving for root dir */
288 if (!strcmpW( name
, szTargetDir
) && !f
->ResolvedSource
)
290 f
->ResolvedSource
= get_source_root( package
);
292 if (folder
) *folder
= f
;
293 if (f
->ResolvedSource
)
295 path
= strdupW( f
->ResolvedSource
);
296 TRACE(" already resolved to %s\n", debugstr_w(path
));
299 if (!f
->Parent
) return path
;
301 TRACE(" ! parent is %s\n", debugstr_w(parent
));
303 p
= msi_resolve_source_folder( package
, parent
, NULL
);
305 if (package
->WordCount
& msidbSumInfoSourceTypeCompressed
)
306 path
= get_source_root( package
);
307 else if (package
->WordCount
& msidbSumInfoSourceTypeSFN
)
308 path
= msi_build_directory_name( 3, p
, f
->SourceShortPath
, NULL
);
310 path
= msi_build_directory_name( 3, p
, f
->SourceLongPath
, NULL
);
312 TRACE("-> %s\n", debugstr_w(path
));
313 f
->ResolvedSource
= strdupW( path
);
319 /***********************************************************************
320 * MSI_GetSourcePath (internal)
322 static UINT
MSI_GetSourcePath( MSIHANDLE hInstall
, LPCWSTR szFolder
,
323 awstring
*szPathBuf
, LPDWORD pcchPathBuf
)
327 UINT r
= ERROR_FUNCTION_FAILED
;
329 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
332 return ERROR_INVALID_PARAMETER
;
334 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
340 if (!(remote
= msi_get_remote(hInstall
)))
341 return ERROR_INVALID_HANDLE
;
343 r
= remote_GetSourcePath(remote
, szFolder
, &value
);
344 if (r
!= ERROR_SUCCESS
)
347 r
= msi_strcpy_to_awstring(value
, -1, szPathBuf
, pcchPathBuf
);
349 midl_user_free(value
);
353 if (szPathBuf
->str
.w
&& !pcchPathBuf
)
355 msiobj_release( &package
->hdr
);
356 return ERROR_INVALID_PARAMETER
;
359 path
= msi_resolve_source_folder( package
, szFolder
, NULL
);
360 msiobj_release( &package
->hdr
);
362 TRACE("path = %s\n", debugstr_w(path
));
364 return ERROR_DIRECTORY
;
366 r
= msi_strcpy_to_awstring( path
, -1, szPathBuf
, pcchPathBuf
);
371 /***********************************************************************
372 * MsiGetSourcePathA (MSI.@)
374 UINT WINAPI
MsiGetSourcePathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
375 LPSTR szPathBuf
, LPDWORD pcchPathBuf
)
381 TRACE("%s %p %p\n", debugstr_a(szFolder
), szPathBuf
, pcchPathBuf
);
384 str
.str
.a
= szPathBuf
;
386 folder
= strdupAtoW( szFolder
);
387 r
= MSI_GetSourcePath( hInstall
, folder
, &str
, pcchPathBuf
);
393 /***********************************************************************
394 * MsiGetSourcePathW (MSI.@)
396 UINT WINAPI
MsiGetSourcePathW( MSIHANDLE hInstall
, LPCWSTR szFolder
,
397 LPWSTR szPathBuf
, LPDWORD pcchPathBuf
)
401 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
404 str
.str
.w
= szPathBuf
;
406 return MSI_GetSourcePath( hInstall
, szFolder
, &str
, pcchPathBuf
);
409 /***********************************************************************
410 * MsiSetTargetPathA (MSI.@)
412 UINT WINAPI
MsiSetTargetPathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
413 LPCSTR szFolderPath
)
415 LPWSTR szwFolder
= NULL
, szwFolderPath
= NULL
;
416 UINT rc
= ERROR_OUTOFMEMORY
;
418 if ( !szFolder
|| !szFolderPath
)
419 return ERROR_INVALID_PARAMETER
;
421 szwFolder
= strdupAtoW(szFolder
);
422 szwFolderPath
= strdupAtoW(szFolderPath
);
423 if (!szwFolder
|| !szwFolderPath
)
426 rc
= MsiSetTargetPathW( hInstall
, szwFolder
, szwFolderPath
);
430 msi_free(szwFolderPath
);
435 static void set_target_path( MSIPACKAGE
*package
, MSIFOLDER
*folder
, const WCHAR
*path
)
441 if (!(target_path
= msi_normalize_path( path
))) return;
442 if (strcmpW( target_path
, folder
->ResolvedTarget
))
444 msi_free( folder
->ResolvedTarget
);
445 folder
->ResolvedTarget
= target_path
;
446 msi_set_property( package
->db
, folder
->Directory
, folder
->ResolvedTarget
, -1 );
448 LIST_FOR_EACH_ENTRY( fl
, &folder
->children
, FolderList
, entry
)
451 msi_resolve_target_folder( package
, child
->Directory
, FALSE
);
454 else msi_free( target_path
);
457 UINT
MSI_SetTargetPathW( MSIPACKAGE
*package
, LPCWSTR szFolder
, LPCWSTR szFolderPath
)
463 TRACE("%p %s %s\n", package
, debugstr_w(szFolder
), debugstr_w(szFolderPath
));
465 attrib
= GetFileAttributesW(szFolderPath
);
466 /* native MSI tests writeability by making temporary files at each drive */
467 if (attrib
!= INVALID_FILE_ATTRIBUTES
&&
468 (attrib
& FILE_ATTRIBUTE_OFFLINE
|| attrib
& FILE_ATTRIBUTE_READONLY
))
470 return ERROR_FUNCTION_FAILED
;
472 if (!(folder
= msi_get_loaded_folder( package
, szFolder
))) return ERROR_DIRECTORY
;
474 set_target_path( package
, folder
, szFolderPath
);
476 LIST_FOR_EACH_ENTRY( file
, &package
->files
, MSIFILE
, entry
)
479 MSICOMPONENT
*comp
= file
->Component
;
481 if (!comp
->Enabled
|| msi_is_global_assembly( comp
)) continue;
483 dir
= msi_get_target_folder( package
, comp
->Directory
);
484 msi_free( file
->TargetPath
);
485 file
->TargetPath
= msi_build_directory_name( 2, dir
, file
->FileName
);
487 return ERROR_SUCCESS
;
490 /***********************************************************************
491 * MsiSetTargetPathW (MSI.@)
493 UINT WINAPI
MsiSetTargetPathW(MSIHANDLE hInstall
, LPCWSTR szFolder
,
494 LPCWSTR szFolderPath
)
499 TRACE("%s %s\n",debugstr_w(szFolder
),debugstr_w(szFolderPath
));
501 if ( !szFolder
|| !szFolderPath
)
502 return ERROR_INVALID_PARAMETER
;
504 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
509 if (!(remote
= msi_get_remote(hInstall
)))
510 return ERROR_INVALID_HANDLE
;
512 return remote_SetTargetPath(remote
, szFolder
, szFolderPath
);
515 ret
= MSI_SetTargetPathW( package
, szFolder
, szFolderPath
);
516 msiobj_release( &package
->hdr
);
520 /***********************************************************************
523 * Returns an internal installer state (if it is running in a mode iRunMode)
526 * hInstall [I] Handle to the installation
527 * hRunMode [I] Checking run mode
528 * MSIRUNMODE_ADMIN Administrative mode
529 * MSIRUNMODE_ADVERTISE Advertisement mode
530 * MSIRUNMODE_MAINTENANCE Maintenance mode
531 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
532 * MSIRUNMODE_LOGENABLED Log file is writing
533 * MSIRUNMODE_OPERATIONS Operations in progress??
534 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
535 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
536 * MSIRUNMODE_CABINET Files from cabinet are installed
537 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed
538 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed
539 * MSIRUNMODE_RESERVED11 Reserved
540 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
541 * MSIRUNMODE_ZAWENABLED Demand installation is supported
542 * MSIRUNMODE_RESERVED14 Reserved
543 * MSIRUNMODE_RESERVED15 Reserved
544 * MSIRUNMODE_SCHEDULED called from install script
545 * MSIRUNMODE_ROLLBACK called from rollback script
546 * MSIRUNMODE_COMMIT called from commit script
550 * Not in the state: FALSE
553 BOOL WINAPI
MsiGetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
)
558 TRACE("%d %d\n", hInstall
, iRunMode
);
560 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
565 if (!(remote
= msi_get_remote(hInstall
)))
568 return remote_GetMode(remote
, iRunMode
);
573 case MSIRUNMODE_ADMIN
:
574 FIXME("no support for administrative installs\n");
577 case MSIRUNMODE_ADVERTISE
:
578 FIXME("no support for advertised installs\n");
581 case MSIRUNMODE_WINDOWS9X
:
582 if (GetVersion() & 0x80000000)
586 case MSIRUNMODE_OPERATIONS
:
587 case MSIRUNMODE_RESERVED11
:
588 case MSIRUNMODE_RESERVED14
:
589 case MSIRUNMODE_RESERVED15
:
592 case MSIRUNMODE_SCHEDULED
:
593 r
= package
->scheduled_action_running
;
596 case MSIRUNMODE_ROLLBACK
:
597 r
= package
->rollback_action_running
;
600 case MSIRUNMODE_COMMIT
:
601 r
= package
->commit_action_running
;
604 case MSIRUNMODE_MAINTENANCE
:
605 r
= msi_get_property_int( package
->db
, szInstalled
, 0 ) != 0;
608 case MSIRUNMODE_ROLLBACKENABLED
:
609 r
= msi_get_property_int( package
->db
, szRollbackDisabled
, 0 ) == 0;
612 case MSIRUNMODE_REBOOTATEND
:
613 r
= package
->need_reboot_at_end
;
616 case MSIRUNMODE_REBOOTNOW
:
617 r
= package
->need_reboot_now
;
620 case MSIRUNMODE_LOGENABLED
:
621 r
= (package
->log_file
!= INVALID_HANDLE_VALUE
);
625 FIXME("unimplemented run mode: %d\n", iRunMode
);
629 msiobj_release( &package
->hdr
);
633 /***********************************************************************
636 UINT WINAPI
MsiSetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
, BOOL fState
)
641 TRACE("%d %d %d\n", hInstall
, iRunMode
, fState
);
643 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
648 if (!(remote
= msi_get_remote(hInstall
)))
651 return remote_SetMode(remote
, iRunMode
, fState
);
656 case MSIRUNMODE_REBOOTATEND
:
657 package
->need_reboot_at_end
= (fState
!= 0);
661 case MSIRUNMODE_REBOOTNOW
:
662 package
->need_reboot_now
= (fState
!= 0);
667 r
= ERROR_ACCESS_DENIED
;
670 msiobj_release( &package
->hdr
);
674 /***********************************************************************
675 * MsiSetFeatureStateA (MSI.@)
677 * According to the docs, when this is called it immediately recalculates
678 * all the component states as well
680 UINT WINAPI
MsiSetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
683 LPWSTR szwFeature
= NULL
;
686 szwFeature
= strdupAtoW(szFeature
);
688 rc
= MsiSetFeatureStateW(hInstall
,szwFeature
, iState
);
690 msi_free(szwFeature
);
695 /* update component state based on a feature change */
696 void ACTION_UpdateComponentStates( MSIPACKAGE
*package
, MSIFEATURE
*feature
)
698 INSTALLSTATE newstate
;
701 newstate
= feature
->ActionRequest
;
702 if (newstate
== INSTALLSTATE_ABSENT
) newstate
= INSTALLSTATE_UNKNOWN
;
704 LIST_FOR_EACH_ENTRY(cl
, &feature
->Components
, ComponentList
, entry
)
706 MSICOMPONENT
*component
= cl
->component
;
708 if (!component
->Enabled
) continue;
710 TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
711 newstate
, debugstr_w(component
->Component
), component
->Installed
,
712 component
->Action
, component
->ActionRequest
);
714 if (newstate
== INSTALLSTATE_LOCAL
)
716 component
->Action
= INSTALLSTATE_LOCAL
;
717 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
721 ComponentList
*clist
;
724 component
->hasLocalFeature
= FALSE
;
726 component
->Action
= newstate
;
727 component
->ActionRequest
= newstate
;
728 /* if any other feature wants it local we need to set it local */
729 LIST_FOR_EACH_ENTRY(f
, &package
->features
, MSIFEATURE
, entry
)
731 if ( f
->ActionRequest
!= INSTALLSTATE_LOCAL
&&
732 f
->ActionRequest
!= INSTALLSTATE_SOURCE
)
736 LIST_FOR_EACH_ENTRY(clist
, &f
->Components
, ComponentList
, entry
)
738 if (clist
->component
== component
&&
739 (f
->ActionRequest
== INSTALLSTATE_LOCAL
||
740 f
->ActionRequest
== INSTALLSTATE_SOURCE
))
742 TRACE("Saved by %s\n", debugstr_w(f
->Feature
));
743 component
->hasLocalFeature
= TRUE
;
745 if (component
->Attributes
& msidbComponentAttributesOptional
)
747 if (f
->Attributes
& msidbFeatureAttributesFavorSource
)
749 component
->Action
= INSTALLSTATE_SOURCE
;
750 component
->ActionRequest
= INSTALLSTATE_SOURCE
;
754 component
->Action
= INSTALLSTATE_LOCAL
;
755 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
758 else if (component
->Attributes
& msidbComponentAttributesSourceOnly
)
760 component
->Action
= INSTALLSTATE_SOURCE
;
761 component
->ActionRequest
= INSTALLSTATE_SOURCE
;
765 component
->Action
= INSTALLSTATE_LOCAL
;
766 component
->ActionRequest
= INSTALLSTATE_LOCAL
;
772 TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
773 newstate
, debugstr_w(component
->Component
), component
->Installed
,
774 component
->Action
, component
->ActionRequest
);
778 UINT
MSI_SetFeatureStateW( MSIPACKAGE
*package
, LPCWSTR szFeature
, INSTALLSTATE iState
)
780 UINT rc
= ERROR_SUCCESS
;
781 MSIFEATURE
*feature
, *child
;
783 TRACE("%s %i\n", debugstr_w(szFeature
), iState
);
785 feature
= msi_get_loaded_feature( package
, szFeature
);
787 return ERROR_UNKNOWN_FEATURE
;
789 if (iState
== INSTALLSTATE_ADVERTISED
&&
790 feature
->Attributes
& msidbFeatureAttributesDisallowAdvertise
)
791 return ERROR_FUNCTION_FAILED
;
793 feature
->ActionRequest
= iState
;
795 ACTION_UpdateComponentStates( package
, feature
);
797 /* update all the features that are children of this feature */
798 LIST_FOR_EACH_ENTRY( child
, &package
->features
, MSIFEATURE
, entry
)
800 if (child
->Feature_Parent
&& !strcmpW( szFeature
, child
->Feature_Parent
))
801 MSI_SetFeatureStateW(package
, child
->Feature
, iState
);
807 /***********************************************************************
808 * MsiSetFeatureStateW (MSI.@)
810 UINT WINAPI
MsiSetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
814 UINT rc
= ERROR_SUCCESS
;
816 TRACE("%s %i\n",debugstr_w(szFeature
), iState
);
819 return ERROR_UNKNOWN_FEATURE
;
821 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
826 if (!(remote
= msi_get_remote(hInstall
)))
827 return ERROR_INVALID_HANDLE
;
829 return remote_SetFeatureState(remote
, szFeature
, iState
);
832 rc
= MSI_SetFeatureStateW(package
,szFeature
,iState
);
834 msiobj_release( &package
->hdr
);
838 /***********************************************************************
839 * MsiSetFeatureAttributesA (MSI.@)
841 UINT WINAPI
MsiSetFeatureAttributesA( MSIHANDLE handle
, LPCSTR feature
, DWORD attrs
)
844 WCHAR
*featureW
= NULL
;
846 TRACE("%u, %s, 0x%08x\n", handle
, debugstr_a(feature
), attrs
);
848 if (feature
&& !(featureW
= strdupAtoW( feature
))) return ERROR_OUTOFMEMORY
;
850 r
= MsiSetFeatureAttributesW( handle
, featureW
, attrs
);
851 msi_free( featureW
);
855 static DWORD
unmap_feature_attributes( DWORD attrs
)
859 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORLOCAL
) ret
= msidbFeatureAttributesFavorLocal
;
860 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORSOURCE
) ret
|= msidbFeatureAttributesFavorSource
;
861 if (attrs
& INSTALLFEATUREATTRIBUTE_FOLLOWPARENT
) ret
|= msidbFeatureAttributesFollowParent
;
862 if (attrs
& INSTALLFEATUREATTRIBUTE_FAVORADVERTISE
) ret
|= msidbFeatureAttributesFavorAdvertise
;
863 if (attrs
& INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE
) ret
|= msidbFeatureAttributesDisallowAdvertise
;
864 if (attrs
& INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE
) ret
|= msidbFeatureAttributesNoUnsupportedAdvertise
;
868 /***********************************************************************
869 * MsiSetFeatureAttributesW (MSI.@)
871 UINT WINAPI
MsiSetFeatureAttributesW( MSIHANDLE handle
, LPCWSTR name
, DWORD attrs
)
877 TRACE("%u, %s, 0x%08x\n", handle
, debugstr_w(name
), attrs
);
879 if (!name
|| !name
[0]) return ERROR_UNKNOWN_FEATURE
;
881 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
882 return ERROR_INVALID_HANDLE
;
884 costing
= msi_dup_property( package
->db
, szCostingComplete
);
885 if (!costing
|| !strcmpW( costing
, szOne
))
888 msiobj_release( &package
->hdr
);
889 return ERROR_FUNCTION_FAILED
;
892 if (!(feature
= msi_get_loaded_feature( package
, name
)))
894 msiobj_release( &package
->hdr
);
895 return ERROR_UNKNOWN_FEATURE
;
897 feature
->Attributes
= unmap_feature_attributes( attrs
);
898 msiobj_release( &package
->hdr
);
899 return ERROR_SUCCESS
;
902 /***********************************************************************
903 * MsiGetFeatureStateA (MSI.@)
905 UINT WINAPI
MsiGetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
906 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
908 LPWSTR szwFeature
= NULL
;
911 if (szFeature
&& !(szwFeature
= strdupAtoW(szFeature
))) return ERROR_OUTOFMEMORY
;
913 rc
= MsiGetFeatureStateW(hInstall
, szwFeature
, piInstalled
, piAction
);
914 msi_free( szwFeature
);
918 UINT
MSI_GetFeatureStateW(MSIPACKAGE
*package
, LPCWSTR szFeature
,
919 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
923 feature
= msi_get_loaded_feature(package
,szFeature
);
925 return ERROR_UNKNOWN_FEATURE
;
928 *piInstalled
= feature
->Installed
;
931 *piAction
= feature
->ActionRequest
;
933 TRACE("returning %i %i\n", feature
->Installed
, feature
->ActionRequest
);
935 return ERROR_SUCCESS
;
938 /***********************************************************************
939 * MsiGetFeatureStateW (MSI.@)
941 UINT WINAPI
MsiGetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
942 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
947 TRACE("%d %s %p %p\n", hInstall
, debugstr_w(szFeature
), piInstalled
, piAction
);
950 return ERROR_UNKNOWN_FEATURE
;
952 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
957 if (!(remote
= msi_get_remote(hInstall
)))
958 return ERROR_INVALID_HANDLE
;
960 /* FIXME: should use SEH */
961 if (!piInstalled
|| !piAction
)
962 return RPC_X_NULL_REF_POINTER
;
964 return remote_GetFeatureState(remote
, szFeature
, piInstalled
, piAction
);
967 ret
= MSI_GetFeatureStateW(package
, szFeature
, piInstalled
, piAction
);
968 msiobj_release( &package
->hdr
);
972 /***********************************************************************
973 * MsiGetFeatureCostA (MSI.@)
975 UINT WINAPI
MsiGetFeatureCostA(MSIHANDLE hInstall
, LPCSTR szFeature
,
976 MSICOSTTREE iCostTree
, INSTALLSTATE iState
, LPINT piCost
)
978 LPWSTR szwFeature
= NULL
;
981 szwFeature
= strdupAtoW(szFeature
);
983 rc
= MsiGetFeatureCostW(hInstall
, szwFeature
, iCostTree
, iState
, piCost
);
985 msi_free(szwFeature
);
990 static INT
feature_cost( MSIFEATURE
*feature
)
995 LIST_FOR_EACH_ENTRY( cl
, &feature
->Components
, ComponentList
, entry
)
997 cost
+= cl
->component
->Cost
;
1002 UINT
MSI_GetFeatureCost( MSIPACKAGE
*package
, MSIFEATURE
*feature
, MSICOSTTREE tree
,
1003 INSTALLSTATE state
, LPINT cost
)
1005 TRACE("%s, %u, %d, %p\n", debugstr_w(feature
->Feature
), tree
, state
, cost
);
1010 case MSICOSTTREE_CHILDREN
:
1014 LIST_FOR_EACH_ENTRY( child
, &feature
->Children
, MSIFEATURE
, entry
)
1016 if (child
->ActionRequest
== state
)
1017 *cost
+= feature_cost( child
);
1021 case MSICOSTTREE_PARENTS
:
1023 const WCHAR
*feature_parent
= feature
->Feature_Parent
;
1026 MSIFEATURE
*parent
= msi_get_loaded_feature( package
, feature_parent
);
1030 if (parent
->ActionRequest
== state
)
1031 *cost
+= feature_cost( parent
);
1033 feature_parent
= parent
->Feature_Parent
;
1037 case MSICOSTTREE_SELFONLY
:
1038 if (feature
->ActionRequest
== state
)
1039 *cost
= feature_cost( feature
);
1043 WARN("unhandled cost tree %u\n", tree
);
1048 return ERROR_SUCCESS
;
1051 /***********************************************************************
1052 * MsiGetFeatureCostW (MSI.@)
1054 UINT WINAPI
MsiGetFeatureCostW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
1055 MSICOSTTREE iCostTree
, INSTALLSTATE iState
, LPINT piCost
)
1057 MSIPACKAGE
*package
;
1058 MSIFEATURE
*feature
;
1061 TRACE("(%d %s %i %i %p)\n", hInstall
, debugstr_w(szFeature
),
1062 iCostTree
, iState
, piCost
);
1065 return ERROR_INVALID_PARAMETER
;
1067 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1072 if (!(remote
= msi_get_remote(hInstall
)))
1073 return ERROR_INVALID_HANDLE
;
1075 /* FIXME: should use SEH */
1077 return RPC_X_NULL_REF_POINTER
;
1079 return remote_GetFeatureCost(remote
, szFeature
, iCostTree
, iState
, piCost
);
1084 msiobj_release( &package
->hdr
);
1085 return ERROR_INVALID_PARAMETER
;
1088 feature
= msi_get_loaded_feature(package
, szFeature
);
1091 ret
= MSI_GetFeatureCost(package
, feature
, iCostTree
, iState
, piCost
);
1093 ret
= ERROR_UNKNOWN_FEATURE
;
1095 msiobj_release( &package
->hdr
);
1099 /***********************************************************************
1100 * MsiGetFeatureInfoA (MSI.@)
1102 UINT WINAPI
MsiGetFeatureInfoA( MSIHANDLE handle
, LPCSTR feature
, LPDWORD attrs
,
1103 LPSTR title
, LPDWORD title_len
, LPSTR help
, LPDWORD help_len
)
1106 WCHAR
*titleW
= NULL
, *helpW
= NULL
, *featureW
= NULL
;
1108 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle
, debugstr_a(feature
), attrs
, title
,
1109 title_len
, help
, help_len
);
1111 if (feature
&& !(featureW
= strdupAtoW( feature
))) return ERROR_OUTOFMEMORY
;
1113 if (title
&& title_len
&& !(titleW
= msi_alloc( *title_len
* sizeof(WCHAR
) )))
1115 msi_free( featureW
);
1116 return ERROR_OUTOFMEMORY
;
1118 if (help
&& help_len
&& !(helpW
= msi_alloc( *help_len
* sizeof(WCHAR
) )))
1120 msi_free( featureW
);
1122 return ERROR_OUTOFMEMORY
;
1124 r
= MsiGetFeatureInfoW( handle
, featureW
, attrs
, titleW
, title_len
, helpW
, help_len
);
1125 if (r
== ERROR_SUCCESS
)
1127 if (titleW
) WideCharToMultiByte( CP_ACP
, 0, titleW
, -1, title
, *title_len
+ 1, NULL
, NULL
);
1128 if (helpW
) WideCharToMultiByte( CP_ACP
, 0, helpW
, -1, help
, *help_len
+ 1, NULL
, NULL
);
1132 msi_free( featureW
);
1136 static DWORD
map_feature_attributes( DWORD attrs
)
1140 if (attrs
== msidbFeatureAttributesFavorLocal
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORLOCAL
;
1141 if (attrs
& msidbFeatureAttributesFavorSource
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORSOURCE
;
1142 if (attrs
& msidbFeatureAttributesFollowParent
) ret
|= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT
;
1143 if (attrs
& msidbFeatureAttributesFavorAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE
;
1144 if (attrs
& msidbFeatureAttributesDisallowAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE
;
1145 if (attrs
& msidbFeatureAttributesNoUnsupportedAdvertise
) ret
|= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE
;
1149 static UINT
MSI_GetFeatureInfo( MSIPACKAGE
*package
, LPCWSTR name
, LPDWORD attrs
,
1150 LPWSTR title
, LPDWORD title_len
, LPWSTR help
, LPDWORD help_len
)
1152 UINT r
= ERROR_SUCCESS
;
1153 MSIFEATURE
*feature
= msi_get_loaded_feature( package
, name
);
1156 if (!feature
) return ERROR_UNKNOWN_FEATURE
;
1157 if (attrs
) *attrs
= map_feature_attributes( feature
->Attributes
);
1160 if (feature
->Title
) len
= strlenW( feature
->Title
);
1162 if (*title_len
<= len
)
1165 if (title
) r
= ERROR_MORE_DATA
;
1169 if (feature
->Title
) strcpyW( title
, feature
->Title
);
1176 if (feature
->Description
) len
= strlenW( feature
->Description
);
1178 if (*help_len
<= len
)
1181 if (help
) r
= ERROR_MORE_DATA
;
1185 if (feature
->Description
) strcpyW( help
, feature
->Description
);
1193 /***********************************************************************
1194 * MsiGetFeatureInfoW (MSI.@)
1196 UINT WINAPI
MsiGetFeatureInfoW( MSIHANDLE handle
, LPCWSTR feature
, LPDWORD attrs
,
1197 LPWSTR title
, LPDWORD title_len
, LPWSTR help
, LPDWORD help_len
)
1200 MSIPACKAGE
*package
;
1202 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle
, debugstr_w(feature
), attrs
, title
,
1203 title_len
, help
, help_len
);
1205 if (!feature
) return ERROR_INVALID_PARAMETER
;
1207 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
1208 return ERROR_INVALID_HANDLE
;
1210 /* features may not have been loaded yet */
1211 msi_load_all_components( package
);
1212 msi_load_all_features( package
);
1214 r
= MSI_GetFeatureInfo( package
, feature
, attrs
, title
, title_len
, help
, help_len
);
1215 msiobj_release( &package
->hdr
);
1219 /***********************************************************************
1220 * MsiSetComponentStateA (MSI.@)
1222 UINT WINAPI
MsiSetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
1223 INSTALLSTATE iState
)
1226 LPWSTR szwComponent
= strdupAtoW(szComponent
);
1228 rc
= MsiSetComponentStateW(hInstall
, szwComponent
, iState
);
1230 msi_free(szwComponent
);
1235 /***********************************************************************
1236 * MsiGetComponentStateA (MSI.@)
1238 UINT WINAPI
MsiGetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
1239 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1241 LPWSTR szwComponent
= NULL
;
1244 szwComponent
= strdupAtoW(szComponent
);
1246 rc
= MsiGetComponentStateW(hInstall
,szwComponent
,piInstalled
, piAction
);
1248 msi_free( szwComponent
);
1253 static UINT
MSI_SetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
1254 INSTALLSTATE iState
)
1258 TRACE("%p %s %d\n", package
, debugstr_w(szComponent
), iState
);
1260 comp
= msi_get_loaded_component(package
, szComponent
);
1262 return ERROR_UNKNOWN_COMPONENT
;
1265 comp
->Action
= iState
;
1267 return ERROR_SUCCESS
;
1270 UINT
MSI_GetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
1271 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1275 TRACE("%p %s %p %p\n", package
, debugstr_w(szComponent
),
1276 piInstalled
, piAction
);
1278 comp
= msi_get_loaded_component(package
,szComponent
);
1280 return ERROR_UNKNOWN_COMPONENT
;
1285 *piInstalled
= comp
->Installed
;
1287 *piInstalled
= INSTALLSTATE_UNKNOWN
;
1293 *piAction
= comp
->Action
;
1295 *piAction
= INSTALLSTATE_UNKNOWN
;
1298 TRACE("states (%i, %i)\n", comp
->Installed
, comp
->Action
);
1299 return ERROR_SUCCESS
;
1302 /***********************************************************************
1303 * MsiSetComponentStateW (MSI.@)
1305 UINT WINAPI
MsiSetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
1306 INSTALLSTATE iState
)
1308 MSIPACKAGE
* package
;
1312 return ERROR_UNKNOWN_COMPONENT
;
1314 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1319 if (!(remote
= msi_get_remote(hInstall
)))
1320 return ERROR_INVALID_HANDLE
;
1322 return remote_SetComponentState(remote
, szComponent
, iState
);
1325 ret
= MSI_SetComponentStateW(package
, szComponent
, iState
);
1326 msiobj_release(&package
->hdr
);
1330 /***********************************************************************
1331 * MsiGetComponentStateW (MSI.@)
1333 UINT WINAPI
MsiGetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
1334 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
1336 MSIPACKAGE
* package
;
1339 TRACE("%d %s %p %p\n", hInstall
, debugstr_w(szComponent
),
1340 piInstalled
, piAction
);
1343 return ERROR_UNKNOWN_COMPONENT
;
1345 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1350 if (!(remote
= msi_get_remote(hInstall
)))
1351 return ERROR_INVALID_HANDLE
;
1353 /* FIXME: should use SEH */
1354 if (!piInstalled
|| !piAction
)
1355 return RPC_X_NULL_REF_POINTER
;
1357 return remote_GetComponentState(remote
, szComponent
, piInstalled
, piAction
);
1360 ret
= MSI_GetComponentStateW( package
, szComponent
, piInstalled
, piAction
);
1361 msiobj_release( &package
->hdr
);
1365 /***********************************************************************
1366 * MsiGetLanguage (MSI.@)
1368 LANGID WINAPI
MsiGetLanguage(MSIHANDLE hInstall
)
1370 MSIPACKAGE
* package
;
1373 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1378 if (!(remote
= msi_get_remote(hInstall
)))
1379 return ERROR_INVALID_HANDLE
;
1381 return remote_GetLanguage(remote
);
1384 langid
= msi_get_property_int( package
->db
, szProductLanguage
, 0 );
1385 msiobj_release( &package
->hdr
);
1389 UINT
MSI_SetInstallLevel( MSIPACKAGE
*package
, int iInstallLevel
)
1391 static const WCHAR fmt
[] = { '%','d',0 };
1396 TRACE("%p %i\n", package
, iInstallLevel
);
1398 if (iInstallLevel
> 32767)
1399 return ERROR_INVALID_PARAMETER
;
1401 if (iInstallLevel
< 1)
1402 return MSI_SetFeatureStates( package
);
1404 len
= sprintfW( level
, fmt
, iInstallLevel
);
1405 r
= msi_set_property( package
->db
, szInstallLevel
, level
, len
);
1406 if ( r
== ERROR_SUCCESS
)
1407 r
= MSI_SetFeatureStates( package
);
1412 /***********************************************************************
1413 * MsiSetInstallLevel (MSI.@)
1415 UINT WINAPI
MsiSetInstallLevel(MSIHANDLE hInstall
, int iInstallLevel
)
1417 MSIPACKAGE
* package
;
1420 TRACE("%d %i\n", hInstall
, iInstallLevel
);
1422 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
1427 if (!(remote
= msi_get_remote(hInstall
)))
1428 return ERROR_INVALID_HANDLE
;
1430 return remote_SetInstallLevel(remote
, iInstallLevel
);
1433 r
= MSI_SetInstallLevel( package
, iInstallLevel
);
1435 msiobj_release( &package
->hdr
);
1440 /***********************************************************************
1441 * MsiGetFeatureValidStatesW (MSI.@)
1443 UINT WINAPI
MsiGetFeatureValidStatesW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
1444 LPDWORD pInstallState
)
1446 if(pInstallState
) *pInstallState
= 1<<INSTALLSTATE_LOCAL
;
1447 FIXME("%d %s %p stub returning %d\n",
1448 hInstall
, debugstr_w(szFeature
), pInstallState
, pInstallState
? *pInstallState
: 0);
1450 return ERROR_SUCCESS
;
1453 /***********************************************************************
1454 * MsiGetFeatureValidStatesA (MSI.@)
1456 UINT WINAPI
MsiGetFeatureValidStatesA(MSIHANDLE hInstall
, LPCSTR szFeature
,
1457 LPDWORD pInstallState
)
1460 LPWSTR szwFeature
= strdupAtoW(szFeature
);
1462 ret
= MsiGetFeatureValidStatesW(hInstall
, szwFeature
, pInstallState
);
1464 msi_free(szwFeature
);