/* * Implementation of the Microsoft Installer (msi.dll) * * Copyright 2005 Aric Stewart for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Msi top level apis directly related to installs */ #include #include "windef.h" #include "winbase.h" #include "winerror.h" #include "wine/debug.h" #include "msi.h" #include "msidefs.h" #include "msipriv.h" #include "winuser.h" #include "wine/unicode.h" #include "action.h" WINE_DEFAULT_DEBUG_CHANNEL(msi); /*********************************************************************** * MsiDoActionA (MSI.@) */ UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction ) { LPWSTR szwAction; UINT rc; TRACE(" exteral attempt at action %s\n",szAction); if (!szAction) return ERROR_FUNCTION_FAILED; if (hInstall == 0) return ERROR_FUNCTION_FAILED; szwAction = strdupAtoW(szAction); if (!szwAction) return ERROR_FUNCTION_FAILED; rc = MsiDoActionW(hInstall, szwAction); HeapFree(GetProcessHeap(),0,szwAction); return rc; } /*********************************************************************** * MsiDoActionW (MSI.@) */ UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction ) { MSIPACKAGE *package; UINT ret = ERROR_INVALID_HANDLE; TRACE(" external attempt at action %s \n",debugstr_w(szAction)); package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); if( package ) { ret = ACTION_PerformUIAction(package,szAction); msiobj_release( &package->hdr ); } return ret; } /*********************************************************************** * MsiGetTargetPathA (MSI.@) */ UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder, LPSTR szPathBuf, DWORD* pcchPathBuf) { LPWSTR szwFolder; LPWSTR szwPathBuf; UINT rc; TRACE("getting folder %s %p %li\n",szFolder,szPathBuf, *pcchPathBuf); if (!szFolder) return ERROR_FUNCTION_FAILED; if (hInstall == 0) return ERROR_FUNCTION_FAILED; szwFolder = strdupAtoW(szFolder); if (!szwFolder) return ERROR_FUNCTION_FAILED; szwPathBuf = HeapAlloc( GetProcessHeap(), 0 , *pcchPathBuf * sizeof(WCHAR)); rc = MsiGetTargetPathW(hInstall, szwFolder, szwPathBuf,pcchPathBuf); WideCharToMultiByte( CP_ACP, 0, szwPathBuf, *pcchPathBuf, szPathBuf, *pcchPathBuf, NULL, NULL ); HeapFree(GetProcessHeap(),0,szwFolder); HeapFree(GetProcessHeap(),0,szwPathBuf); return rc; } /*********************************************************************** * MsiGetTargetPathW (MSI.@) */ UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR szPathBuf, DWORD* pcchPathBuf) { LPWSTR path; UINT rc = ERROR_FUNCTION_FAILED; MSIPACKAGE *package; TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf); package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); if (!package) return ERROR_INVALID_HANDLE; path = resolve_folder(package, szFolder, FALSE, FALSE, NULL); msiobj_release( &package->hdr ); if (path && (strlenW(path) > *pcchPathBuf)) { *pcchPathBuf = strlenW(path)+1; rc = ERROR_MORE_DATA; } else if (path) { *pcchPathBuf = strlenW(path)+1; strcpyW(szPathBuf,path); TRACE("Returning Path %s\n",debugstr_w(path)); rc = ERROR_SUCCESS; } HeapFree(GetProcessHeap(),0,path); return rc; } /*********************************************************************** * MsiGetSourcePathA (MSI.@) */ UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder, LPSTR szPathBuf, DWORD* pcchPathBuf) { LPWSTR szwFolder; LPWSTR szwPathBuf; UINT rc; TRACE("getting source %s %p %li\n",szFolder,szPathBuf, *pcchPathBuf); if (!szFolder) return ERROR_FUNCTION_FAILED; if (hInstall == 0) return ERROR_FUNCTION_FAILED; szwFolder = strdupAtoW(szFolder); if (!szwFolder) return ERROR_FUNCTION_FAILED; szwPathBuf = HeapAlloc( GetProcessHeap(), 0 , *pcchPathBuf * sizeof(WCHAR)); rc = MsiGetSourcePathW(hInstall, szwFolder, szwPathBuf,pcchPathBuf); WideCharToMultiByte( CP_ACP, 0, szwPathBuf, *pcchPathBuf, szPathBuf, *pcchPathBuf, NULL, NULL ); HeapFree(GetProcessHeap(),0,szwFolder); HeapFree(GetProcessHeap(),0,szwPathBuf); return rc; } /*********************************************************************** * MsiGetSourcePathW (MSI.@) */ UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR szPathBuf, DWORD* pcchPathBuf) { LPWSTR path; UINT rc = ERROR_FUNCTION_FAILED; MSIPACKAGE *package; TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf); package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); if( !package ) return ERROR_INVALID_HANDLE; path = resolve_folder(package, szFolder, TRUE, FALSE, NULL); msiobj_release( &package->hdr ); if (path && strlenW(path) > *pcchPathBuf) { *pcchPathBuf = strlenW(path)+1; rc = ERROR_MORE_DATA; } else if (path) { *pcchPathBuf = strlenW(path)+1; strcpyW(szPathBuf,path); TRACE("Returning Path %s\n",debugstr_w(path)); rc = ERROR_SUCCESS; } HeapFree(GetProcessHeap(),0,path); return rc; } /*********************************************************************** * MsiSetTargetPathA (MSI.@) */ UINT WINAPI MsiSetTargetPathA(MSIHANDLE hInstall, LPCSTR szFolder, LPCSTR szFolderPath) { LPWSTR szwFolder; LPWSTR szwFolderPath; UINT rc; if (!szFolder) return ERROR_FUNCTION_FAILED; if (hInstall == 0) return ERROR_FUNCTION_FAILED; szwFolder = strdupAtoW(szFolder); if (!szwFolder) return ERROR_FUNCTION_FAILED; szwFolderPath = strdupAtoW(szFolderPath); if (!szwFolderPath) { HeapFree(GetProcessHeap(),0,szwFolder); return ERROR_FUNCTION_FAILED; } rc = MsiSetTargetPathW(hInstall, szwFolder, szwFolderPath); HeapFree(GetProcessHeap(),0,szwFolder); HeapFree(GetProcessHeap(),0,szwFolderPath); return rc; } /* * Ok my original interpretation of this was wrong. And it looks like msdn has * changed a bit also. The given folder path does not have to actually already * exist, it just cannot be read only and must be a legal folder path. */ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath) { DWORD i; DWORD attrib; LPWSTR path = NULL; LPWSTR path2 = NULL; MSIFOLDER *folder; TRACE("(%p %s %s)\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath)); if (package==NULL) return ERROR_INVALID_HANDLE; if (szFolderPath[0]==0) return ERROR_FUNCTION_FAILED; attrib = GetFileAttributesW(szFolderPath); if ( attrib != INVALID_FILE_ATTRIBUTES && (!(attrib & FILE_ATTRIBUTE_DIRECTORY) || attrib & FILE_ATTRIBUTE_OFFLINE || attrib & FILE_ATTRIBUTE_READONLY)) return ERROR_FUNCTION_FAILED; path = resolve_folder(package,szFolder,FALSE,FALSE,&folder); if (!path) return ERROR_INVALID_PARAMETER; if (attrib == INVALID_FILE_ATTRIBUTES) { if (!CreateDirectoryW(szFolderPath,NULL)) return ERROR_FUNCTION_FAILED; RemoveDirectoryW(szFolderPath); } HeapFree(GetProcessHeap(),0,folder->Property); folder->Property = build_directory_name(2, szFolderPath, NULL); if (lstrcmpiW(path, folder->Property) == 0) { /* * Resolved Target has not really changed, so just * set this folder and do not recalculate everything. */ HeapFree(GetProcessHeap(),0,folder->ResolvedTarget); folder->ResolvedTarget = NULL; path2 = resolve_folder(package,szFolder,FALSE,TRUE,NULL); HeapFree(GetProcessHeap(),0,path2); } else { for (i = 0; i < package->loaded_folders; i++) { HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget); package->folders[i].ResolvedTarget=NULL; } for (i = 0; i < package->loaded_folders; i++) { path2=resolve_folder(package, package->folders[i].Directory, FALSE, TRUE, NULL); HeapFree(GetProcessHeap(),0,path2); } } HeapFree(GetProcessHeap(),0,path); return ERROR_SUCCESS; } /*********************************************************************** * MsiSetTargetPathW (MSI.@) */ UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder, LPCWSTR szFolderPath) { MSIPACKAGE *package; UINT ret; TRACE("(%s %s)\n",debugstr_w(szFolder),debugstr_w(szFolderPath)); package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); ret = MSI_SetTargetPathW( package, szFolder, szFolderPath ); msiobj_release( &package->hdr ); return ret; } /*********************************************************************** * MsiGetMode (MSI.@) * * Returns an internal installer state (if it is running in a mode iRunMode) * * PARAMS * hInstall [I] Handle to the installation * hRunMode [I] Checking run mode * MSIRUNMODE_ADMIN Administrative mode * MSIRUNMODE_ADVERTISE Advertisement mode * MSIRUNMODE_MAINTENANCE Maintenance mode * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled * MSIRUNMODE_LOGENABLED Log file is writing * MSIRUNMODE_OPERATIONS Operations in progress?? * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation * MSIRUNMODE_CABINET Files from cabinet are installed * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed * MSIRUNMODE_RESERVED11 Reserved * MSIRUNMODE_WINDOWS9X Running under Windows95/98 * MSIRUNMODE_ZAWENABLED Demand installation is supported * MSIRUNMODE_RESERVED14 Reserved * MSIRUNMODE_RESERVED15 Reserved * MSIRUNMODE_SCHEDULED called from install script * MSIRUNMODE_ROLLBACK called from rollback script * MSIRUNMODE_COMMIT called from commit script * * RETURNS * In the state: TRUE * Not in the state: FALSE * */ BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode) { FIXME("STUB (iRunMode=%i)\n",iRunMode); return TRUE; } /*********************************************************************** * MsiSetFeatureStateA (MSI.@) * * According to the docs, when this is called it immediately recalculates * all the component states as well */ UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature, INSTALLSTATE iState) { LPWSTR szwFeature = NULL; UINT rc; szwFeature = strdupAtoW(szFeature); if (!szwFeature) return ERROR_FUNCTION_FAILED; rc = MsiSetFeatureStateW(hInstall,szwFeature, iState); HeapFree(GetProcessHeap(),0,szwFeature); return rc; } UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature, INSTALLSTATE iState) { INT index, i; UINT rc = ERROR_SUCCESS; TRACE(" %s to %i\n",debugstr_w(szFeature), iState); index = get_loaded_feature(package,szFeature); if (index < 0) return ERROR_UNKNOWN_FEATURE; if (iState == INSTALLSTATE_ADVERTISED && package->features[index].Attributes & msidbFeatureAttributesDisallowAdvertise) return ERROR_FUNCTION_FAILED; package->features[index].ActionRequest= iState; package->features[index].Action= iState; ACTION_UpdateComponentStates(package,szFeature); /* update all the features that are children of this feature */ for (i = 0; i < package->loaded_features; i++) { if (strcmpW(szFeature, package->features[i].Feature_Parent) == 0) MSI_SetFeatureStateW(package, package->features[i].Feature, iState); } return rc; } /*********************************************************************** * MsiSetFeatureStateW (MSI.@) */ UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature, INSTALLSTATE iState) { MSIPACKAGE* package; UINT rc = ERROR_SUCCESS; TRACE(" %s to %i\n",debugstr_w(szFeature), iState); package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); if (!package) return ERROR_INVALID_HANDLE; rc = MSI_SetFeatureStateW(package,szFeature,iState); msiobj_release( &package->hdr ); return rc; } /*********************************************************************** * MsiGetFeatureStateA (MSI.@) */ UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature, INSTALLSTATE *piInstalled, INSTALLSTATE *piAction) { LPWSTR szwFeature = NULL; UINT rc; szwFeature = strdupAtoW(szFeature); rc = MsiGetFeatureStateW(hInstall,szwFeature,piInstalled, piAction); HeapFree( GetProcessHeap(), 0 , szwFeature); return rc; } UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature, INSTALLSTATE *piInstalled, INSTALLSTATE *piAction) { INT index; index = get_loaded_feature(package,szFeature); if (index < 0) return ERROR_UNKNOWN_FEATURE; if (piInstalled) *piInstalled = package->features[index].Installed; if (piAction) *piAction = package->features[index].Action; TRACE("returning %i %i\n",*piInstalled,*piAction); return ERROR_SUCCESS; } /*********************************************************************** * MsiGetFeatureStateW (MSI.@) */ UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPWSTR szFeature, INSTALLSTATE *piInstalled, INSTALLSTATE *piAction) { MSIPACKAGE* package; UINT ret; TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction); package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); if (!package) return ERROR_INVALID_HANDLE; ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction); msiobj_release( &package->hdr ); return ret; } /*********************************************************************** * MsiGetComponentStateA (MSI.@) */ UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPSTR szComponent, INSTALLSTATE *piInstalled, INSTALLSTATE *piAction) { LPWSTR szwComponent= NULL; UINT rc; szwComponent= strdupAtoW(szComponent); rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction); HeapFree( GetProcessHeap(), 0 , szwComponent); return rc; } UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPWSTR szComponent, INSTALLSTATE *piInstalled, INSTALLSTATE *piAction) { INT index; TRACE("%p %s %p %p\n", package, debugstr_w(szComponent), piInstalled, piAction); index = get_loaded_component(package,szComponent); if (index < 0) return ERROR_UNKNOWN_COMPONENT; if (piInstalled) *piInstalled = package->components[index].Installed; if (piAction) *piAction = package->components[index].Action; TRACE("states (%i, %i)\n", (piInstalled)?*piInstalled:-1,(piAction)?*piAction:-1); return ERROR_SUCCESS; } /*********************************************************************** * MsiGetComponentStateW (MSI.@) */ UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPWSTR szComponent, INSTALLSTATE *piInstalled, INSTALLSTATE *piAction) { MSIPACKAGE* package; UINT ret; TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szComponent), piInstalled, piAction); package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); if (!package) return ERROR_INVALID_HANDLE; ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction); msiobj_release( &package->hdr ); return ret; } /*********************************************************************** * MsiGetLanguage (MSI.@) */ LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall) { MSIPACKAGE* package; LANGID langid; LPWSTR buffer; static const WCHAR szProductLanguage[] = {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0}; package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); if (!package) return ERROR_INVALID_HANDLE; buffer = load_dynamic_property(package,szProductLanguage,NULL); langid = atoiW(buffer); HeapFree(GetProcessHeap(),0,buffer); msiobj_release (&package->hdr); return langid; }