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"
37 #include "msiserver.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 );
79 IWineMsiRemotePackage *remote_package;
81 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
83 return ERROR_INVALID_HANDLE;
85 action = SysAllocString( szAction );
88 IWineMsiRemotePackage_Release( remote_package );
89 return ERROR_OUTOFMEMORY;
92 hr = IWineMsiRemotePackage_DoAction( remote_package, action );
94 SysFreeString( action );
95 IWineMsiRemotePackage_Release( remote_package );
99 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
100 return HRESULT_CODE(hr);
102 return ERROR_FUNCTION_FAILED;
105 return ERROR_SUCCESS;
108 ret = ACTION_PerformUIAction( package, szAction, -1 );
109 msiobj_release( &package->hdr );
114 /***********************************************************************
115 * MsiSequenceA (MSI.@)
117 UINT WINAPI MsiSequenceA( MSIHANDLE hInstall, LPCSTR szTable, INT iSequenceMode )
122 TRACE("%s, %d\n", debugstr_a(szTable), iSequenceMode);
124 szwTable = strdupAtoW(szTable);
125 if (szTable && !szwTable)
126 return ERROR_FUNCTION_FAILED;
128 ret = MsiSequenceW( hInstall, szwTable, iSequenceMode );
129 msi_free( szwTable );
133 /***********************************************************************
134 * MsiSequenceW (MSI.@)
136 UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode )
141 TRACE("%s, %d\n", debugstr_w(szTable), iSequenceMode);
143 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
148 IWineMsiRemotePackage *remote_package;
150 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
152 return ERROR_INVALID_HANDLE;
154 table = SysAllocString( szTable );
157 IWineMsiRemotePackage_Release( remote_package );
158 return ERROR_OUTOFMEMORY;
161 hr = IWineMsiRemotePackage_Sequence( remote_package, table, iSequenceMode );
163 SysFreeString( table );
164 IWineMsiRemotePackage_Release( remote_package );
168 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
169 return HRESULT_CODE(hr);
171 return ERROR_FUNCTION_FAILED;
174 return ERROR_SUCCESS;
176 ret = MSI_Sequence( package, szTable );
177 msiobj_release( &package->hdr );
181 UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
183 UINT len, r = ERROR_SUCCESS;
185 if (awbuf->str.w && !sz )
186 return ERROR_INVALID_PARAMETER;
193 len = lstrlenW( str );
195 lstrcpynW( awbuf->str.w, str, *sz );
199 len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
202 WideCharToMultiByte( CP_ACP, 0, str, -1, awbuf->str.a, *sz, NULL, NULL );
203 if ( awbuf->str.a && *sz && (len >= *sz) )
204 awbuf->str.a[*sz - 1] = 0;
207 if (awbuf->str.w && len >= *sz)
213 const WCHAR *msi_get_target_folder( MSIPACKAGE *package, const WCHAR *name )
215 MSIFOLDER *folder = msi_get_loaded_folder( package, name );
216 if (folder) 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 );
237 IWineMsiRemotePackage *remote_package;
242 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
244 return ERROR_INVALID_HANDLE;
246 folder = SysAllocString( szFolder );
249 IWineMsiRemotePackage_Release( remote_package );
250 return ERROR_OUTOFMEMORY;
254 hr = IWineMsiRemotePackage_GetTargetPath( remote_package, folder, NULL, &len );
259 value = msi_alloc(len * sizeof(WCHAR));
262 r = ERROR_OUTOFMEMORY;
266 hr = IWineMsiRemotePackage_GetTargetPath( remote_package, folder, value, &len );
270 r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf );
273 IWineMsiRemotePackage_Release( remote_package );
274 SysFreeString( folder );
279 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
280 return HRESULT_CODE(hr);
282 return ERROR_FUNCTION_FAILED;
288 path = msi_get_target_folder( package, szFolder );
289 msiobj_release( &package->hdr );
292 return ERROR_DIRECTORY;
294 r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
298 /***********************************************************************
299 * MsiGetTargetPathA (MSI.@)
301 UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
302 LPSTR szPathBuf, LPDWORD pcchPathBuf )
308 TRACE("%s %p %p\n", debugstr_a(szFolder), szPathBuf, pcchPathBuf);
310 szwFolder = strdupAtoW(szFolder);
311 if (szFolder && !szwFolder)
312 return ERROR_FUNCTION_FAILED;
314 path.unicode = FALSE;
315 path.str.a = szPathBuf;
317 r = MSI_GetTargetPath( hInstall, szwFolder, &path, pcchPathBuf );
319 msi_free( szwFolder );
324 /***********************************************************************
325 * MsiGetTargetPathW (MSI.@)
327 UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
328 LPWSTR szPathBuf, LPDWORD pcchPathBuf )
332 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf);
335 path.str.w = szPathBuf;
337 return MSI_GetTargetPath( hInstall, szFolder, &path, pcchPathBuf );
340 static WCHAR *get_source_root( MSIDATABASE *db )
344 if ((path = msi_dup_property( db, szSourceDir ))) return path;
345 if ((path = msi_dup_property( db, szDatabase )))
347 if ((p = strrchrW( path, '\\' ))) p[1] = 0;
352 WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder )
355 LPWSTR p, path = NULL, parent;
357 TRACE("working to resolve %s\n", debugstr_w(name));
359 if (!strcmpW( name, szSourceDir )) name = szTargetDir;
360 if (!(f = msi_get_loaded_folder( package, name ))) return NULL;
362 /* special resolving for root dir */
363 if (!strcmpW( name, szTargetDir ) && !f->ResolvedSource)
365 f->ResolvedSource = get_source_root( package->db );
367 if (folder) *folder = f;
368 if (f->ResolvedSource)
370 path = strdupW( f->ResolvedSource );
371 TRACE(" already resolved to %s\n", debugstr_w(path));
374 if (!f->Parent) return path;
376 TRACE(" ! parent is %s\n", debugstr_w(parent));
378 p = msi_resolve_source_folder( package, parent, NULL );
380 if (package->WordCount & msidbSumInfoSourceTypeCompressed)
381 path = get_source_root( package->db );
382 else if (package->WordCount & msidbSumInfoSourceTypeSFN)
383 path = msi_build_directory_name( 3, p, f->SourceShortPath, NULL );
385 path = msi_build_directory_name( 3, p, f->SourceLongPath, NULL );
387 TRACE("-> %s\n", debugstr_w(path));
388 f->ResolvedSource = strdupW( path );
394 /***********************************************************************
395 * MSI_GetSourcePath (internal)
397 static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
398 awstring *szPathBuf, LPDWORD pcchPathBuf )
402 UINT r = ERROR_FUNCTION_FAILED;
404 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
407 return ERROR_INVALID_PARAMETER;
409 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
413 IWineMsiRemotePackage *remote_package;
418 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
420 return ERROR_INVALID_HANDLE;
422 folder = SysAllocString( szFolder );
425 IWineMsiRemotePackage_Release( remote_package );
426 return ERROR_OUTOFMEMORY;
430 hr = IWineMsiRemotePackage_GetSourcePath( remote_package, folder, NULL, &len );
435 value = msi_alloc(len * sizeof(WCHAR));
438 r = ERROR_OUTOFMEMORY;
442 hr = IWineMsiRemotePackage_GetSourcePath( remote_package, folder, value, &len );
446 r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf );
449 IWineMsiRemotePackage_Release( remote_package );
450 SysFreeString( folder );
455 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
456 return HRESULT_CODE(hr);
458 return ERROR_FUNCTION_FAILED;
464 if (szPathBuf->str.w && !pcchPathBuf )
466 msiobj_release( &package->hdr );
467 return ERROR_INVALID_PARAMETER;
470 path = msi_resolve_source_folder( package, szFolder, NULL );
471 msiobj_release( &package->hdr );
473 TRACE("path = %s\n", debugstr_w(path));
475 return ERROR_DIRECTORY;
477 r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
482 /***********************************************************************
483 * MsiGetSourcePathA (MSI.@)
485 UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder,
486 LPSTR szPathBuf, LPDWORD pcchPathBuf )
492 TRACE("%s %p %p\n", debugstr_a(szFolder), debugstr_a(szPathBuf), pcchPathBuf);
495 str.str.a = szPathBuf;
497 folder = strdupAtoW( szFolder );
498 r = MSI_GetSourcePath( hInstall, folder, &str, pcchPathBuf );
504 /***********************************************************************
505 * MsiGetSourcePathW (MSI.@)
507 UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder,
508 LPWSTR szPathBuf, LPDWORD pcchPathBuf )
512 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
515 str.str.w = szPathBuf;
517 return MSI_GetSourcePath( hInstall, szFolder, &str, pcchPathBuf );
520 /***********************************************************************
521 * MsiSetTargetPathA (MSI.@)
523 UINT WINAPI MsiSetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
524 LPCSTR szFolderPath )
526 LPWSTR szwFolder = NULL, szwFolderPath = NULL;
527 UINT rc = ERROR_OUTOFMEMORY;
529 if ( !szFolder || !szFolderPath )
530 return ERROR_INVALID_PARAMETER;
532 szwFolder = strdupAtoW(szFolder);
533 szwFolderPath = strdupAtoW(szFolderPath);
534 if (!szwFolder || !szwFolderPath)
537 rc = MsiSetTargetPathW( hInstall, szwFolder, szwFolderPath );
541 msi_free(szwFolderPath);
546 static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR *path )
552 if (!(target_path = strdupW( path ))) return;
553 msi_clean_path( target_path );
554 if (strcmpW( target_path, folder->ResolvedTarget ))
556 msi_free( folder->ResolvedTarget );
557 folder->ResolvedTarget = target_path;
558 msi_set_property( package->db, folder->Directory, folder->ResolvedTarget );
560 LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
563 msi_resolve_target_folder( package, child->Directory, FALSE );
566 else msi_free( target_path );
569 UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath )
575 TRACE("%p %s %s\n", package, debugstr_w(szFolder), debugstr_w(szFolderPath));
577 attrib = GetFileAttributesW(szFolderPath);
578 /* native MSI tests writeability by making temporary files at each drive */
579 if (attrib != INVALID_FILE_ATTRIBUTES &&
580 (attrib & FILE_ATTRIBUTE_OFFLINE || attrib & FILE_ATTRIBUTE_READONLY))
582 return ERROR_FUNCTION_FAILED;
584 if (!(folder = msi_get_loaded_folder( package, szFolder ))) return ERROR_DIRECTORY;
586 len = strlenW( szFolderPath );
587 if (len && szFolderPath[len - 1] != '\\')
589 WCHAR *path = msi_alloc( (len + 2) * sizeof(WCHAR) );
590 memcpy( path, szFolderPath, len * sizeof(WCHAR) );
593 set_target_path( package, folder, path );
596 else set_target_path( package, folder, szFolderPath );
598 LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
601 MSICOMPONENT *comp = file->Component;
603 if (!comp->Enabled || (comp->assembly && !comp->assembly->application)) continue;
605 dir = msi_get_target_folder( package, comp->Directory );
606 msi_free( file->TargetPath );
607 file->TargetPath = msi_build_directory_name( 2, dir, file->FileName );
609 return ERROR_SUCCESS;
612 /***********************************************************************
613 * MsiSetTargetPathW (MSI.@)
615 UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
616 LPCWSTR szFolderPath)
621 TRACE("%s %s\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
623 if ( !szFolder || !szFolderPath )
624 return ERROR_INVALID_PARAMETER;
626 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
631 IWineMsiRemotePackage *remote_package;
633 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
635 return ERROR_INVALID_HANDLE;
637 folder = SysAllocString( szFolder );
638 path = SysAllocString( szFolderPath );
639 if (!folder || !path)
641 SysFreeString(folder);
643 IWineMsiRemotePackage_Release( remote_package );
644 return ERROR_OUTOFMEMORY;
647 hr = IWineMsiRemotePackage_SetTargetPath( remote_package, folder, path );
649 SysFreeString(folder);
651 IWineMsiRemotePackage_Release( remote_package );
655 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
656 return HRESULT_CODE(hr);
658 return ERROR_FUNCTION_FAILED;
661 return ERROR_SUCCESS;
664 ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
665 msiobj_release( &package->hdr );
669 /***********************************************************************
672 * Returns an internal installer state (if it is running in a mode iRunMode)
675 * hInstall [I] Handle to the installation
676 * hRunMode [I] Checking run mode
677 * MSIRUNMODE_ADMIN Administrative mode
678 * MSIRUNMODE_ADVERTISE Advertisement mode
679 * MSIRUNMODE_MAINTENANCE Maintenance mode
680 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
681 * MSIRUNMODE_LOGENABLED Log file is writing
682 * MSIRUNMODE_OPERATIONS Operations in progress??
683 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
684 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
685 * MSIRUNMODE_CABINET Files from cabinet are installed
686 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed
687 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed
688 * MSIRUNMODE_RESERVED11 Reserved
689 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
690 * MSIRUNMODE_ZAWENABLED Demand installation is supported
691 * MSIRUNMODE_RESERVED14 Reserved
692 * MSIRUNMODE_RESERVED15 Reserved
693 * MSIRUNMODE_SCHEDULED called from install script
694 * MSIRUNMODE_ROLLBACK called from rollback script
695 * MSIRUNMODE_COMMIT called from commit script
699 * Not in the state: FALSE
702 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
707 TRACE("%d %d\n", hInstall, iRunMode);
709 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
714 IWineMsiRemotePackage *remote_package;
716 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
720 hr = IWineMsiRemotePackage_GetMode(remote_package, iRunMode, &ret);
721 IWineMsiRemotePackage_Release(remote_package);
731 case MSIRUNMODE_ADMIN:
732 FIXME("no support for administrative installs\n");
735 case MSIRUNMODE_ADVERTISE:
736 FIXME("no support for advertised installs\n");
739 case MSIRUNMODE_WINDOWS9X:
740 if (GetVersion() & 0x80000000)
744 case MSIRUNMODE_OPERATIONS:
745 case MSIRUNMODE_RESERVED11:
746 case MSIRUNMODE_RESERVED14:
747 case MSIRUNMODE_RESERVED15:
750 case MSIRUNMODE_SCHEDULED:
751 r = package->scheduled_action_running;
754 case MSIRUNMODE_ROLLBACK:
755 r = package->rollback_action_running;
758 case MSIRUNMODE_COMMIT:
759 r = package->commit_action_running;
762 case MSIRUNMODE_MAINTENANCE:
763 r = msi_get_property_int( package->db, szInstalled, 0 ) != 0;
766 case MSIRUNMODE_ROLLBACKENABLED:
767 r = msi_get_property_int( package->db, szRollbackDisabled, 0 ) == 0;
770 case MSIRUNMODE_REBOOTATEND:
771 r = package->need_reboot;
774 case MSIRUNMODE_LOGENABLED:
775 r = (package->log_file != INVALID_HANDLE_VALUE);
779 FIXME("unimplemented run mode: %d\n", iRunMode);
783 msiobj_release( &package->hdr );
787 /***********************************************************************
790 UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
795 TRACE("%d %d %d\n", hInstall, iRunMode, fState);
797 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
801 IWineMsiRemotePackage *remote_package;
803 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
807 hr = IWineMsiRemotePackage_SetMode( remote_package, iRunMode, fState );
808 IWineMsiRemotePackage_Release( remote_package );
812 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
813 return HRESULT_CODE(hr);
815 return ERROR_FUNCTION_FAILED;
818 return ERROR_SUCCESS;
823 case MSIRUNMODE_REBOOTATEND:
824 package->need_reboot = 1;
828 case MSIRUNMODE_REBOOTNOW:
829 FIXME("unimplemented run mode: %d\n", iRunMode);
830 r = ERROR_FUNCTION_FAILED;
834 r = ERROR_ACCESS_DENIED;
837 msiobj_release( &package->hdr );
841 /***********************************************************************
842 * MsiSetFeatureStateA (MSI.@)
844 * According to the docs, when this is called it immediately recalculates
845 * all the component states as well
847 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
850 LPWSTR szwFeature = NULL;
853 szwFeature = strdupAtoW(szFeature);
856 return ERROR_FUNCTION_FAILED;
858 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
860 msi_free(szwFeature);
865 /* update component state based on a feature change */
866 void ACTION_UpdateComponentStates( MSIPACKAGE *package, MSIFEATURE *feature )
868 INSTALLSTATE newstate;
871 newstate = feature->ActionRequest;
872 if (newstate == INSTALLSTATE_ABSENT) newstate = INSTALLSTATE_UNKNOWN;
874 LIST_FOR_EACH_ENTRY(cl, &feature->Components, ComponentList, entry)
876 MSICOMPONENT *component = cl->component;
878 if (!component->Enabled) continue;
880 TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
881 newstate, debugstr_w(component->Component), component->Installed,
882 component->Action, component->ActionRequest);
884 if (newstate == INSTALLSTATE_LOCAL)
886 component->Action = INSTALLSTATE_LOCAL;
887 component->ActionRequest = INSTALLSTATE_LOCAL;
891 ComponentList *clist;
894 component->hasLocalFeature = FALSE;
896 component->Action = newstate;
897 component->ActionRequest = newstate;
898 /* if any other feature wants it local we need to set it local */
899 LIST_FOR_EACH_ENTRY(f, &package->features, MSIFEATURE, entry)
901 if ( f->ActionRequest != INSTALLSTATE_LOCAL &&
902 f->ActionRequest != INSTALLSTATE_SOURCE )
906 LIST_FOR_EACH_ENTRY(clist, &f->Components, ComponentList, entry)
908 if (clist->component == component &&
909 (f->ActionRequest == INSTALLSTATE_LOCAL ||
910 f->ActionRequest == INSTALLSTATE_SOURCE))
912 TRACE("Saved by %s\n", debugstr_w(f->Feature));
913 component->hasLocalFeature = TRUE;
915 if (component->Attributes & msidbComponentAttributesOptional)
917 if (f->Attributes & msidbFeatureAttributesFavorSource)
919 component->Action = INSTALLSTATE_SOURCE;
920 component->ActionRequest = INSTALLSTATE_SOURCE;
924 component->Action = INSTALLSTATE_LOCAL;
925 component->ActionRequest = INSTALLSTATE_LOCAL;
928 else if (component->Attributes & msidbComponentAttributesSourceOnly)
930 component->Action = INSTALLSTATE_SOURCE;
931 component->ActionRequest = INSTALLSTATE_SOURCE;
935 component->Action = INSTALLSTATE_LOCAL;
936 component->ActionRequest = INSTALLSTATE_LOCAL;
942 TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
943 newstate, debugstr_w(component->Component), component->Installed,
944 component->Action, component->ActionRequest);
948 UINT WINAPI MSI_SetFeatureStateW( MSIPACKAGE *package, LPCWSTR szFeature, INSTALLSTATE iState )
950 UINT rc = ERROR_SUCCESS;
951 MSIFEATURE *feature, *child;
953 TRACE("%s %i\n", debugstr_w(szFeature), iState);
955 feature = msi_get_loaded_feature( package, szFeature );
957 return ERROR_UNKNOWN_FEATURE;
959 if (iState == INSTALLSTATE_ADVERTISED &&
960 feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
961 return ERROR_FUNCTION_FAILED;
963 feature->ActionRequest = iState;
965 ACTION_UpdateComponentStates( package, feature );
967 /* update all the features that are children of this feature */
968 LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
970 if (child->Feature_Parent && !strcmpW( szFeature, child->Feature_Parent ))
971 MSI_SetFeatureStateW(package, child->Feature, iState);
977 /***********************************************************************
978 * MsiSetFeatureStateW (MSI.@)
980 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
984 UINT rc = ERROR_SUCCESS;
986 TRACE("%s %i\n",debugstr_w(szFeature), iState);
988 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
993 IWineMsiRemotePackage *remote_package;
995 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
997 return ERROR_INVALID_HANDLE;
999 feature = SysAllocString(szFeature);
1002 IWineMsiRemotePackage_Release(remote_package);
1003 return ERROR_OUTOFMEMORY;
1006 hr = IWineMsiRemotePackage_SetFeatureState(remote_package, feature, iState);
1008 SysFreeString(feature);
1009 IWineMsiRemotePackage_Release(remote_package);
1013 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1014 return HRESULT_CODE(hr);
1016 return ERROR_FUNCTION_FAILED;
1019 return ERROR_SUCCESS;
1022 rc = MSI_SetFeatureStateW(package,szFeature,iState);
1024 msiobj_release( &package->hdr );
1028 /***********************************************************************
1029 * MsiSetFeatureAttributesA (MSI.@)
1031 UINT WINAPI MsiSetFeatureAttributesA( MSIHANDLE handle, LPCSTR feature, DWORD attrs )
1034 WCHAR *featureW = NULL;
1036 TRACE("%u, %s, 0x%08x\n", handle, debugstr_a(feature), attrs);
1038 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
1040 r = MsiSetFeatureAttributesW( handle, featureW, attrs );
1041 msi_free( featureW );
1045 static DWORD unmap_feature_attributes( DWORD attrs )
1049 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORLOCAL) ret = msidbFeatureAttributesFavorLocal;
1050 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORSOURCE) ret |= msidbFeatureAttributesFavorSource;
1051 if (attrs & INSTALLFEATUREATTRIBUTE_FOLLOWPARENT) ret |= msidbFeatureAttributesFollowParent;
1052 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORADVERTISE) ret |= msidbFeatureAttributesFavorAdvertise;
1053 if (attrs & INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE) ret |= msidbFeatureAttributesDisallowAdvertise;
1054 if (attrs & INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE) ret |= msidbFeatureAttributesNoUnsupportedAdvertise;
1058 /***********************************************************************
1059 * MsiSetFeatureAttributesW (MSI.@)
1061 UINT WINAPI MsiSetFeatureAttributesW( MSIHANDLE handle, LPCWSTR name, DWORD attrs )
1063 MSIPACKAGE *package;
1064 MSIFEATURE *feature;
1067 TRACE("%u, %s, 0x%08x\n", handle, debugstr_w(name), attrs);
1069 if (!name || !name[0]) return ERROR_UNKNOWN_FEATURE;
1071 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1072 return ERROR_INVALID_HANDLE;
1074 costing = msi_dup_property( package->db, szCostingComplete );
1075 if (!costing || !strcmpW( costing, szOne ))
1077 msi_free( costing );
1078 msiobj_release( &package->hdr );
1079 return ERROR_FUNCTION_FAILED;
1081 msi_free( costing );
1082 if (!(feature = msi_get_loaded_feature( package, name )))
1084 msiobj_release( &package->hdr );
1085 return ERROR_UNKNOWN_FEATURE;
1087 feature->Attributes = unmap_feature_attributes( attrs );
1088 msiobj_release( &package->hdr );
1089 return ERROR_SUCCESS;
1092 /***********************************************************************
1093 * MsiGetFeatureStateA (MSI.@)
1095 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
1096 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1098 LPWSTR szwFeature = NULL;
1101 if (szFeature && !(szwFeature = strdupAtoW(szFeature))) return ERROR_OUTOFMEMORY;
1103 rc = MsiGetFeatureStateW(hInstall, szwFeature, piInstalled, piAction);
1104 msi_free( szwFeature);
1108 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
1109 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1111 MSIFEATURE *feature;
1113 feature = msi_get_loaded_feature(package,szFeature);
1115 return ERROR_UNKNOWN_FEATURE;
1118 *piInstalled = feature->Installed;
1121 *piAction = feature->ActionRequest;
1123 TRACE("returning %i %i\n", feature->Installed, feature->ActionRequest);
1125 return ERROR_SUCCESS;
1128 /***********************************************************************
1129 * MsiGetFeatureStateW (MSI.@)
1131 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
1132 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1134 MSIPACKAGE* package;
1137 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
1139 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1144 IWineMsiRemotePackage *remote_package;
1146 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1147 if (!remote_package)
1148 return ERROR_INVALID_HANDLE;
1150 feature = SysAllocString(szFeature);
1153 IWineMsiRemotePackage_Release(remote_package);
1154 return ERROR_OUTOFMEMORY;
1157 hr = IWineMsiRemotePackage_GetFeatureState(remote_package, feature,
1158 piInstalled, piAction);
1160 SysFreeString(feature);
1161 IWineMsiRemotePackage_Release(remote_package);
1165 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1166 return HRESULT_CODE(hr);
1168 return ERROR_FUNCTION_FAILED;
1171 return ERROR_SUCCESS;
1174 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
1175 msiobj_release( &package->hdr );
1179 /***********************************************************************
1180 * MsiGetFeatureCostA (MSI.@)
1182 UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
1183 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1185 LPWSTR szwFeature = NULL;
1188 szwFeature = strdupAtoW(szFeature);
1190 rc = MsiGetFeatureCostW(hInstall, szwFeature, iCostTree, iState, piCost);
1192 msi_free(szwFeature);
1197 static INT feature_cost( MSIFEATURE *feature )
1202 LIST_FOR_EACH_ENTRY( comp, &feature->Components, MSICOMPONENT, entry )
1209 UINT MSI_GetFeatureCost( MSIPACKAGE *package, MSIFEATURE *feature, MSICOSTTREE tree,
1210 INSTALLSTATE state, LPINT cost )
1212 TRACE("%s, %u, %d, %p\n", debugstr_w(feature->Feature), tree, state, cost);
1217 case MSICOSTTREE_CHILDREN:
1221 LIST_FOR_EACH_ENTRY( child, &feature->Children, MSIFEATURE, entry )
1223 if (child->ActionRequest == state)
1224 *cost += feature_cost( child );
1228 case MSICOSTTREE_PARENTS:
1230 const WCHAR *feature_parent = feature->Feature_Parent;
1233 MSIFEATURE *parent = msi_get_loaded_feature( package, feature_parent );
1237 if (parent->ActionRequest == state)
1238 *cost += feature_cost( parent );
1240 feature_parent = parent->Feature_Parent;
1244 case MSICOSTTREE_SELFONLY:
1245 if (feature->ActionRequest == state)
1246 *cost = feature_cost( feature );
1250 WARN("unhandled cost tree %u\n", tree);
1255 return ERROR_SUCCESS;
1258 /***********************************************************************
1259 * MsiGetFeatureCostW (MSI.@)
1261 UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
1262 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1264 MSIPACKAGE *package;
1265 MSIFEATURE *feature;
1268 TRACE("(%d %s %i %i %p)\n", hInstall, debugstr_w(szFeature),
1269 iCostTree, iState, piCost);
1271 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1276 IWineMsiRemotePackage *remote_package;
1278 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1279 if (!remote_package)
1280 return ERROR_INVALID_HANDLE;
1282 feature = SysAllocString(szFeature);
1285 IWineMsiRemotePackage_Release(remote_package);
1286 return ERROR_OUTOFMEMORY;
1289 hr = IWineMsiRemotePackage_GetFeatureCost(remote_package, feature,
1290 iCostTree, iState, piCost);
1292 SysFreeString(feature);
1293 IWineMsiRemotePackage_Release(remote_package);
1297 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1298 return HRESULT_CODE(hr);
1300 return ERROR_FUNCTION_FAILED;
1303 return ERROR_SUCCESS;
1306 feature = msi_get_loaded_feature(package, szFeature);
1309 ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost);
1311 ret = ERROR_UNKNOWN_FEATURE;
1313 msiobj_release( &package->hdr );
1317 /***********************************************************************
1318 * MsiGetFeatureInfoA (MSI.@)
1320 UINT WINAPI MsiGetFeatureInfoA( MSIHANDLE handle, LPCSTR feature, LPDWORD attrs,
1321 LPSTR title, LPDWORD title_len, LPSTR help, LPDWORD help_len )
1324 WCHAR *titleW = NULL, *helpW = NULL, *featureW = NULL;
1326 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_a(feature), attrs, title,
1327 title_len, help, help_len);
1329 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
1331 if (title && title_len && !(titleW = msi_alloc( *title_len * sizeof(WCHAR) )))
1333 msi_free( featureW );
1334 return ERROR_OUTOFMEMORY;
1336 if (help && help_len && !(helpW = msi_alloc( *help_len * sizeof(WCHAR) )))
1338 msi_free( featureW );
1340 return ERROR_OUTOFMEMORY;
1342 r = MsiGetFeatureInfoW( handle, featureW, attrs, titleW, title_len, helpW, help_len );
1343 if (r == ERROR_SUCCESS)
1345 if (titleW) WideCharToMultiByte( CP_ACP, 0, titleW, -1, title, *title_len + 1, NULL, NULL );
1346 if (helpW) WideCharToMultiByte( CP_ACP, 0, helpW, -1, help, *help_len + 1, NULL, NULL );
1350 msi_free( featureW );
1354 static DWORD map_feature_attributes( DWORD attrs )
1358 if (attrs == msidbFeatureAttributesFavorLocal) ret |= INSTALLFEATUREATTRIBUTE_FAVORLOCAL;
1359 if (attrs & msidbFeatureAttributesFavorSource) ret |= INSTALLFEATUREATTRIBUTE_FAVORSOURCE;
1360 if (attrs & msidbFeatureAttributesFollowParent) ret |= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT;
1361 if (attrs & msidbFeatureAttributesFavorAdvertise) ret |= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE;
1362 if (attrs & msidbFeatureAttributesDisallowAdvertise) ret |= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE;
1363 if (attrs & msidbFeatureAttributesNoUnsupportedAdvertise) ret |= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE;
1367 static UINT MSI_GetFeatureInfo( MSIPACKAGE *package, LPCWSTR name, LPDWORD attrs,
1368 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1370 UINT r = ERROR_SUCCESS;
1371 MSIFEATURE *feature = msi_get_loaded_feature( package, name );
1374 if (!feature) return ERROR_UNKNOWN_FEATURE;
1375 if (attrs) *attrs = map_feature_attributes( feature->Attributes );
1378 if (feature->Title) len = strlenW( feature->Title );
1380 if (*title_len <= len)
1383 if (title) r = ERROR_MORE_DATA;
1387 if (feature->Title) strcpyW( title, feature->Title );
1394 if (feature->Description) len = strlenW( feature->Description );
1396 if (*help_len <= len)
1399 if (help) r = ERROR_MORE_DATA;
1403 if (feature->Description) strcpyW( help, feature->Description );
1411 /***********************************************************************
1412 * MsiGetFeatureInfoW (MSI.@)
1414 UINT WINAPI MsiGetFeatureInfoW( MSIHANDLE handle, LPCWSTR feature, LPDWORD attrs,
1415 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1418 MSIPACKAGE *package;
1420 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_w(feature), attrs, title,
1421 title_len, help, help_len);
1423 if (!feature) return ERROR_INVALID_PARAMETER;
1425 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1426 return ERROR_INVALID_HANDLE;
1428 /* features may not have been loaded yet */
1429 msi_load_all_components( package );
1430 msi_load_all_features( package );
1432 r = MSI_GetFeatureInfo( package, feature, attrs, title, title_len, help, help_len );
1433 msiobj_release( &package->hdr );
1437 /***********************************************************************
1438 * MsiSetComponentStateA (MSI.@)
1440 UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1441 INSTALLSTATE iState)
1444 LPWSTR szwComponent = strdupAtoW(szComponent);
1446 rc = MsiSetComponentStateW(hInstall, szwComponent, iState);
1448 msi_free(szwComponent);
1453 /***********************************************************************
1454 * MsiGetComponentStateA (MSI.@)
1456 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1457 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1459 LPWSTR szwComponent= NULL;
1462 szwComponent= strdupAtoW(szComponent);
1464 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
1466 msi_free( szwComponent);
1471 static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1472 INSTALLSTATE iState)
1476 TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);
1478 comp = msi_get_loaded_component(package, szComponent);
1480 return ERROR_UNKNOWN_COMPONENT;
1483 comp->Action = iState;
1485 return ERROR_SUCCESS;
1488 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1489 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1493 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
1494 piInstalled, piAction);
1496 comp = msi_get_loaded_component(package,szComponent);
1498 return ERROR_UNKNOWN_COMPONENT;
1503 *piInstalled = comp->Installed;
1505 *piInstalled = INSTALLSTATE_UNKNOWN;
1511 *piAction = comp->Action;
1513 *piAction = INSTALLSTATE_UNKNOWN;
1516 TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
1517 return ERROR_SUCCESS;
1520 /***********************************************************************
1521 * MsiSetComponentStateW (MSI.@)
1523 UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1524 INSTALLSTATE iState)
1526 MSIPACKAGE* package;
1529 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1534 IWineMsiRemotePackage *remote_package;
1536 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1537 if (!remote_package)
1538 return ERROR_INVALID_HANDLE;
1540 component = SysAllocString(szComponent);
1543 IWineMsiRemotePackage_Release(remote_package);
1544 return ERROR_OUTOFMEMORY;
1547 hr = IWineMsiRemotePackage_SetComponentState(remote_package, component, iState);
1549 SysFreeString(component);
1550 IWineMsiRemotePackage_Release(remote_package);
1554 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1555 return HRESULT_CODE(hr);
1557 return ERROR_FUNCTION_FAILED;
1560 return ERROR_SUCCESS;
1563 ret = MSI_SetComponentStateW(package, szComponent, iState);
1564 msiobj_release(&package->hdr);
1568 /***********************************************************************
1569 * MsiGetComponentStateW (MSI.@)
1571 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1572 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1574 MSIPACKAGE* package;
1577 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szComponent),
1578 piInstalled, piAction);
1580 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1585 IWineMsiRemotePackage *remote_package;
1587 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1588 if (!remote_package)
1589 return ERROR_INVALID_HANDLE;
1591 component = SysAllocString(szComponent);
1594 IWineMsiRemotePackage_Release(remote_package);
1595 return ERROR_OUTOFMEMORY;
1598 hr = IWineMsiRemotePackage_GetComponentState(remote_package, component,
1599 piInstalled, piAction);
1601 SysFreeString(component);
1602 IWineMsiRemotePackage_Release(remote_package);
1606 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1607 return HRESULT_CODE(hr);
1609 return ERROR_FUNCTION_FAILED;
1612 return ERROR_SUCCESS;
1615 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
1616 msiobj_release( &package->hdr );
1620 /***********************************************************************
1621 * MsiGetLanguage (MSI.@)
1623 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
1625 MSIPACKAGE* package;
1628 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1633 IWineMsiRemotePackage *remote_package;
1635 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1636 if (!remote_package)
1637 return ERROR_INVALID_HANDLE;
1639 hr = IWineMsiRemotePackage_GetLanguage(remote_package, &lang);
1647 langid = msi_get_property_int( package->db, szProductLanguage, 0 );
1648 msiobj_release( &package->hdr );
1652 UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
1654 static const WCHAR fmt[] = { '%','d',0 };
1658 TRACE("%p %i\n", package, iInstallLevel);
1660 if (iInstallLevel > 32767)
1661 return ERROR_INVALID_PARAMETER;
1663 if (iInstallLevel < 1)
1664 return MSI_SetFeatureStates( package );
1666 sprintfW( level, fmt, iInstallLevel );
1667 r = msi_set_property( package->db, szInstallLevel, level );
1668 if ( r == ERROR_SUCCESS )
1669 r = MSI_SetFeatureStates( package );
1674 /***********************************************************************
1675 * MsiSetInstallLevel (MSI.@)
1677 UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
1679 MSIPACKAGE* package;
1682 TRACE("%d %i\n", hInstall, iInstallLevel);
1684 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1688 IWineMsiRemotePackage *remote_package;
1690 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1691 if (!remote_package)
1692 return ERROR_INVALID_HANDLE;
1694 hr = IWineMsiRemotePackage_SetInstallLevel(remote_package, iInstallLevel);
1696 IWineMsiRemotePackage_Release(remote_package);
1700 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1701 return HRESULT_CODE(hr);
1703 return ERROR_FUNCTION_FAILED;
1706 return ERROR_SUCCESS;
1709 r = MSI_SetInstallLevel( package, iInstallLevel );
1711 msiobj_release( &package->hdr );
1716 /***********************************************************************
1717 * MsiGetFeatureValidStatesW (MSI.@)
1719 UINT WINAPI MsiGetFeatureValidStatesW(MSIHANDLE hInstall, LPCWSTR szFeature,
1720 LPDWORD pInstallState)
1722 if(pInstallState) *pInstallState = 1<<INSTALLSTATE_LOCAL;
1723 FIXME("%d %s %p stub returning %d\n",
1724 hInstall, debugstr_w(szFeature), pInstallState, pInstallState ? *pInstallState : 0);
1726 return ERROR_SUCCESS;
1729 /***********************************************************************
1730 * MsiGetFeatureValidStatesA (MSI.@)
1732 UINT WINAPI MsiGetFeatureValidStatesA(MSIHANDLE hInstall, LPCSTR szFeature,
1733 LPDWORD pInstallState)
1736 LPWSTR szwFeature = strdupAtoW(szFeature);
1738 ret = MsiGetFeatureValidStatesW(hInstall, szwFeature, pInstallState);
1740 msi_free(szwFeature);