From 2cae30b6cf7a8672bc11ba001c4b82ddb539b5ba Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Wed, 19 Jan 2005 19:07:40 +0000 Subject: [PATCH] Quite a few fixes: - Allow for the queing of custom actions to trigger on the InstallExecute or InstallExecuteAgain actions. - allow for the queing of custom actions to trigger on InstallFinalize. - Properly set the CustomActionData property for said queued actions. - Implement RegisterProduct. - Beginning implementation of ForceReboot. - Don't kill install if an item to be duplicated does not exist. - Write out SourceList and LastUsedSource for resuming installs. - Use regsvr32 to register self reg dlls. --- dlls/msi/action.c | 421 ++++++++++++++++++++++++++++++++++++++++++--- dlls/msi/msipriv.h | 8 + 2 files changed, 402 insertions(+), 27 deletions(-) diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 6855604475b..0567104d2cd 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -150,7 +150,8 @@ static UINT ACTION_FileCost(MSIPACKAGE *package); static UINT ACTION_InstallFiles(MSIPACKAGE *package); static UINT ACTION_DuplicateFiles(MSIPACKAGE *package); static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package); -static UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action); +static UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action, + BOOL execute); static UINT ACTION_InstallInitialize(MSIPACKAGE *package); static UINT ACTION_InstallValidate(MSIPACKAGE *package); static UINT ACTION_ProcessComponents(MSIPACKAGE *package); @@ -162,6 +163,10 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package); static UINT ACTION_WriteIniValues(MSIPACKAGE *package); static UINT ACTION_SelfRegModules(MSIPACKAGE *package); static UINT ACTION_PublishFeatures(MSIPACKAGE *package); +static UINT ACTION_RegisterProduct(MSIPACKAGE *package); +static UINT ACTION_InstallExecute(MSIPACKAGE *package); +static UINT ACTION_InstallFinalize(MSIPACKAGE *package); +static UINT ACTION_ForceReboot(MSIPACKAGE *package); static UINT HANDLE_CustomType1(MSIPACKAGE *package, const LPWSTR source, const LPWSTR target, const INT type); @@ -233,6 +238,16 @@ const static WCHAR szSelfRegModules[] = {'S','e','l','f','R','e','g','M','o','d','u','l','e','s',0}; const static WCHAR szPublishFeatures[] = {'P','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0}; +const static WCHAR szRegisterProduct[] = +{'R','e','g','i','s','t','e','r','P','r','o','d','u','c','t',0}; +const static WCHAR szInstallExecute[] = +{'I','n','s','t','a','l','l','E','x','e','c','u','t','e',0}; +const static WCHAR szInstallExecuteAgain[] = +{'I','n','s','t','a','l','l','E','x','e','c','u','t','e','A','g','a','i','n',0}; +const static WCHAR szInstallFinalize[] = +{'I','n','s','t','a','l','l','F','i','n','a','l','i','z','e',0}; +const static WCHAR szForceReboot[] = +{'F','o','r','c','e','R','e','b','o','o','t',0}; /******************************************************** * helper functions to get around current HACKS and such @@ -474,6 +489,16 @@ extern void ACTION_free_package_structures( MSIPACKAGE* package) if (package->files && package->loaded_files > 0) HeapFree(GetProcessHeap(),0,package->files); + + for (i = 0; i < package->DeferredActionCount; i++) + HeapFree(GetProcessHeap(),0,package->DeferredAction[i]); + HeapFree(GetProcessHeap(),0,package->DeferredAction); + + for (i = 0; i < package->CommitActionCount; i++) + HeapFree(GetProcessHeap(),0,package->CommitAction[i]); + HeapFree(GetProcessHeap(),0,package->CommitAction); + + HeapFree(GetProcessHeap(),0,package->PackagePath); } static UINT ACTION_OpenQuery( MSIDATABASE *db, MSIQUERY **view, LPCWSTR fmt, ... ) @@ -783,6 +808,7 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath, { LPWSTR p, check, path; + package->PackagePath = dupstrW(szPackagePath); path = dupstrW(szPackagePath); p = strrchrW(path,'\\'); if (p) @@ -1240,15 +1266,23 @@ UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action) rc = ACTION_SelfRegModules(package); else if (strcmpW(action,szPublishFeatures)==0) rc = ACTION_PublishFeatures(package); + else if (strcmpW(action,szRegisterProduct)==0) + rc = ACTION_RegisterProduct(package); + else if (strcmpW(action,szInstallExecute)==0) + rc = ACTION_InstallExecute(package); + else if (strcmpW(action,szInstallExecuteAgain)==0) + rc = ACTION_InstallExecute(package); + else if (strcmpW(action,szInstallFinalize)==0) + rc = ACTION_InstallFinalize(package); + else if (strcmpW(action,szForceReboot)==0) + rc = ACTION_ForceReboot(package); /* Called during iTunes but unimplemented and seem important ResolveSource (sets SourceDir) - RegisterProduct - InstallFinalize */ - else if ((rc = ACTION_CustomAction(package,action)) != ERROR_SUCCESS) + else if ((rc = ACTION_CustomAction(package,action,FALSE)) != ERROR_SUCCESS) { FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action)); rc = ERROR_FUNCTION_NOT_CALLED; @@ -1259,7 +1293,8 @@ UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action) } -static UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action) +static UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action, + BOOL execute) { UINT rc = ERROR_SUCCESS; MSIQUERY * view; @@ -1301,6 +1336,73 @@ static UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action) TRACE("Handling custom action %s (%x %s %s)\n",debugstr_w(action),type, debugstr_w(source), debugstr_w(target)); + /* handle some of the deferred actions */ + if (type & 0x400) + { + if (type & 0x100) + { + FIXME("Rollback only action... rollbacks not supported yet\n"); + HeapFree(GetProcessHeap(),0,source); + HeapFree(GetProcessHeap(),0,target); + msiobj_release(&row->hdr); + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return ERROR_SUCCESS; + } + if (!execute) + { + LPWSTR *newbuf = NULL; + INT count; + if (type & 0x200) + { + TRACE("Deferring Commit Action!\n"); + count = package->CommitActionCount; + package->CommitActionCount++; + if (count != 0) + newbuf = HeapReAlloc(GetProcessHeap(),0, + package->CommitAction, + package->CommitActionCount * sizeof(LPWSTR)); + else + newbuf = HeapAlloc(GetProcessHeap(),0, sizeof(LPWSTR)); + + newbuf[count] = dupstrW(action); + package->CommitAction = newbuf; + } + else + { + TRACE("Deferring Action!\n"); + count = package->DeferredActionCount; + package->DeferredActionCount++; + if (count != 0) + newbuf = HeapReAlloc(GetProcessHeap(),0, + package->DeferredAction, + package->DeferredActionCount * sizeof(LPWSTR)); + else + newbuf = HeapAlloc(GetProcessHeap(),0, sizeof(LPWSTR)); + + newbuf[count] = dupstrW(action); + package->DeferredAction = newbuf; + } + + HeapFree(GetProcessHeap(),0,source); + HeapFree(GetProcessHeap(),0,target); + msiobj_release(&row->hdr); + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return ERROR_SUCCESS; + } + else + { + /*Set ActionData*/ + + static const WCHAR szActionData[] = { + 'C','u','s','t','o','m','A','c','t','i','o','n','D','a','t','a',0}; + LPWSTR actiondata = load_dynamic_property(package,action,NULL); + if (actiondata) + MSI_SetPropertyW(package,szActionData,actiondata); + } + } + /* we are ignoring ALOT of flags and important synchronization stuff */ switch (type & CUSTOM_ACTION_TYPE_MASK) { @@ -1426,7 +1528,6 @@ static UINT store_binary_to_temp(MSIPACKAGE *package, const LPWSTR source, } typedef UINT __stdcall CustomEntry(MSIHANDLE); -typedef UINT __stdcall DllRegisterServer(); typedef struct { @@ -3295,7 +3396,7 @@ inline static UINT get_file_target(MSIPACKAGE *package, LPCWSTR file_key, { if (strcmpW(file_key,package->files[index].File)==0) { - if (package->files[index].State >= 3) + if (package->files[index].State >= 2) { *file_source = dupstrW(package->files[index].TargetPath); return ERROR_SUCCESS; @@ -3385,7 +3486,7 @@ static UINT ACTION_DuplicateFiles(MSIPACKAGE *package) msiobj_release(&row->hdr); if (file_source) HeapFree(GetProcessHeap(),0,file_source); - break; + continue; } if (MSI_RecordIsNull(row,4)) @@ -4970,7 +5071,7 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) LPWSTR productcode; WCHAR squished_pc[0x100]; HKEY hkey=0,hkey2=0,hkey3=0; - HKEY hukey=0,hukey2=0,hukey3=0; + HKEY hukey=0,hukey2=0,hukey3=0,hukey4=0; static const WCHAR szProductCode[]= {'P','r','o','d','u','c','t','C','o','d','e',0}; static const WCHAR szInstaller[] = { @@ -4987,6 +5088,10 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) 'P','r','o','d','u','c','t','s',0}; static const WCHAR szProductName[] = { 'P','r','o','d','u','c','t','N','a','m','e',0}; + static const WCHAR szSourceList[] = { + 'S','o','u','r','c','e','L','i','s','t',0}; + static const WCHAR szLUS[] = { + 'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0}; LPWSTR buffer; DWORD size; @@ -4995,14 +5100,14 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) rc = MSI_DatabaseOpenViewW(package->db, Query, &view); if (rc != ERROR_SUCCESS) - return ERROR_SUCCESS; + goto next; rc = MSI_ViewExecute(view, 0); if (rc != ERROR_SUCCESS) { MSI_ViewClose(view); msiobj_release(&view->hdr); - return rc; + goto next; } while (1) @@ -5067,6 +5172,7 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) MSI_ViewClose(view); msiobj_release(&view->hdr); +next: /* ok there is alot more done here but i need to figure out what */ productcode = load_dynamic_property(package,szProductCode,&rc); if (!productcode) @@ -5102,7 +5208,16 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) size = strlenW(buffer)*sizeof(WCHAR); RegSetValueExW(hukey3,szProductName,0,REG_SZ, (LPSTR)buffer,size); HeapFree(GetProcessHeap(),0,buffer); - + FIXME("Need to write more keys to the user registry\n"); + + FIXME("This may not be in the right place. I dont know when todo this\n"); + RegCreateKeyW(hukey3, szSourceList, &hukey4); + buffer = load_dynamic_property(package,cszSourceDir,NULL); + size = strlenW(buffer)*sizeof(WCHAR); + RegSetValueExW(hukey4,szLUS,0,REG_SZ,(LPSTR)buffer,size); + HeapFree(GetProcessHeap(),0,buffer); + + RegCloseKey(hukey4); end: HeapFree(GetProcessHeap(),0,productcode); @@ -5114,7 +5229,6 @@ end: RegCloseKey(hukey); return rc; - } static UINT ACTION_WriteIniValues(MSIPACKAGE *package) @@ -5269,6 +5383,14 @@ static UINT ACTION_SelfRegModules(MSIPACKAGE *package) static const WCHAR ExecSeqQuery[] = {'S','e','l','e','c','t',' ','*',' ', 'f','r','o','m',' ','S','e','l','f','R','e','g',0}; + static const WCHAR ExeStr[] = { +'r','e','g','s','v','r','3','2','.','e','x','e',' ','/','s',' ',0}; + STARTUPINFOW si; + PROCESS_INFORMATION info; + BOOL brc; + + memset(&si,0,sizeof(STARTUPINFOW)); + rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view); if (rc != ERROR_SUCCESS) { @@ -5288,8 +5410,7 @@ static UINT ACTION_SelfRegModules(MSIPACKAGE *package) { LPWSTR filename; INT index; - HMODULE dll; - DllRegisterServer* regfunc; + DWORD len; rc = MSI_ViewFetch(view,&row); if (rc != ERROR_SUCCESS) @@ -5310,20 +5431,22 @@ static UINT ACTION_SelfRegModules(MSIPACKAGE *package) } HeapFree(GetProcessHeap(),0,filename); - dll = LoadLibraryW(package->files[index].TargetPath); - if (!dll) - { - ERR("Unable to load dll %s\n", - debugstr_w(package->files[index].TargetPath)); - msiobj_release(&row->hdr); - continue; - } + len = strlenW(ExeStr); + len += strlenW(package->files[index].TargetPath); + len +=2; - regfunc = (DllRegisterServer*)GetProcAddress(dll,"DllRegisterServer"); + filename = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR)); + strcpyW(filename,ExeStr); + strcatW(filename,package->files[index].TargetPath); - if (regfunc) - regfunc(); + TRACE("Registering %s\n",debugstr_w(filename)); + brc = CreateProcessW(NULL, filename, NULL, NULL, FALSE, 0, NULL, + c_collen, &si, &info); + if (brc) + WaitForSingleObject(info.hProcess,INFINITE); + + HeapFree(GetProcessHeap(),0,filename); msiobj_release(&row->hdr); } MSI_ViewClose(view); @@ -5422,7 +5545,7 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package) strcatW(data,package->features[i].Feature_Parent); } - size = (strlenW(data)+2)*sizeof(WCHAR); + size = (strlenW(data)+1)*sizeof(WCHAR); RegSetValueExW(hkey3,package->features[i].Feature,0,REG_SZ, (LPSTR)data,size); HeapFree(GetProcessHeap(),0,data); @@ -5443,6 +5566,250 @@ end: return rc; } +static UINT ACTION_RegisterProduct(MSIPACKAGE *package) +{ + static const WCHAR szKey[] = { + 'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'U','n','i','n','s','t','a','l','l',0 }; + static const WCHAR szProductCode[]= + {'P','r','o','d','u','c','t','C','o','d','e',0}; + HKEY hkey=0,hkey2=0; + LPWSTR buffer; + LPWSTR productcode; + UINT rc,i; + DWORD size; + static WCHAR szNONE[] = {0}; + static const WCHAR szWindowsInstaler[] = + {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0}; + static const WCHAR szPropKeys[][80] = + { +{'A','R','P','A','U','T','H','O','R','I','Z','E','D','C','D','F','P','R','E','F','I','X',0}, +{'A','R','P','C','O','N','T','A','C','T'}, +{'A','R','P','C','O','M','M','E','N','T','S',0}, +{'P','r','o','d','u','c','t','N','a','m','e',0}, +{'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0}, +{'A','R','P','H','E','L','P','L','I','N','K',0}, +{'A','R','P','H','E','L','P','T','E','L','E','P','H','O','N','E',0}, +{'A','R','P','I','N','S','T','A','L','L','L','O','C','A','T','I','O','N',0}, +{'S','O','U','R','C','E','D','I','R',0}, +{'M','a','n','u','f','a','c','t','u','r','e','r',0}, +{'A','R','P','R','E','A','D','M','E',0}, +{'A','R','P','S','I','Z','E',0}, +{'A','R','P','U','R','L','I','N','F','O','A','B','O','U','T',0}, +{'A','R','P','U','R','L','U','P','D','A','T','E','I','N','F','O',0}, +{0}, + }; + + static const WCHAR szRegKeys[][80] = + { +{'A','u','t','h','o','r','i','z','e','d','C','D','F','P','r','e','f','i','x',0}, +{'C','o','n','t','a','c','t',0}, +{'C','o','m','m','e','n','t','s',0}, +{'D','i','s','p','l','a','y','N','a','m','e',0}, +{'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0}, +{'H','e','l','p','L','i','n','k',0}, +{'H','e','l','p','T','e','l','e','p','h','o','n','e',0}, +{'I','n','s','t','a','l','l','L','o','c','a','t','i','o','n',0}, +{'I','n','s','t','a','l','l','S','o','u','r','c','e',0}, +{'P','u','b','l','i','s','h','e','r',0}, +{'R','e','a','d','m','e',0}, +{'S','i','z','e',0}, +{'U','R','L','I','n','f','o','A','b','o','u','t',0}, +{'U','R','L','U','p','d','a','t','e','I','n','f','o',0}, +{0}, + }; + + static const WCHAR path[] = { + 'C',':','\\','W','i','n','d','o','w','s','\\', + 'I','n','s','t','a','l','l','e','r','\\'}; + static const WCHAR fmt[] = { + 'C',':','\\','W','i','n','d','o','w','s','\\', + 'I','n','s','t','a','l','l','e','r','\\', + '%','x','.','m','s','i',0}; + static const WCHAR szLocalPackage[]= + {'L','o','c','a','l','P','a','c','k','a','g','e',0}; + WCHAR packagefile[MAX_PATH]; + INT num,start; + + if (!package) + return ERROR_INVALID_HANDLE; + + productcode = load_dynamic_property(package,szProductCode,&rc); + if (!productcode) + return rc; + + rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,szKey,&hkey); + if (rc != ERROR_SUCCESS) + goto end; + + rc = RegCreateKeyW(hkey,productcode,&hkey2); + if (rc != ERROR_SUCCESS) + goto end; + + /* dump all the info i can grab */ + FIXME("Flesh out more information \n"); + + i = 0; + while (szPropKeys[i][0]!=0) + { + buffer = load_dynamic_property(package,szPropKeys[i],&rc); + if (rc != ERROR_SUCCESS) + buffer = szNONE; + size = strlenW(buffer)*sizeof(WCHAR); + RegSetValueExW(hkey2,szRegKeys[i],0,REG_SZ,(LPSTR)buffer,size); + i++; + } + + rc = 0x1; + size = sizeof(rc); + RegSetValueExW(hkey2,szWindowsInstaler,0,REG_DWORD,(LPSTR)&rc,size); + + /* copy the package locally */ + num = GetTickCount() & 0xffff; + if (!num) + num = 1; + start = num; + sprintfW(packagefile,fmt,num); + do + { + HANDLE handle = CreateFileW(packagefile,GENERIC_WRITE, 0, NULL, + CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); + if (handle != INVALID_HANDLE_VALUE) + { + CloseHandle(handle); + break; + } + if (GetLastError() != ERROR_FILE_EXISTS && + GetLastError() != ERROR_SHARING_VIOLATION) + break; + if (!(++num & 0xffff)) num = 1; + sprintfW(packagefile,fmt,num); + } while (num != start); + + create_full_pathW(path); + CopyFileW(package->PackagePath,packagefile,FALSE); + size = strlenW(packagefile)/sizeof(WCHAR); + RegSetValueExW(hkey2,szLocalPackage,0,REG_SZ,(LPSTR)packagefile,size); + +end: + HeapFree(GetProcessHeap(),0,productcode); + RegCloseKey(hkey); + RegCloseKey(hkey2); + + return ERROR_SUCCESS; +} + +static UINT ACTION_InstallExecute(MSIPACKAGE *package) +{ + int i; + if (!package) + return ERROR_INVALID_HANDLE; + + for (i = 0; i < package->DeferredActionCount; i++) + { + LPWSTR action; + action = package->DeferredAction[i]; + ui_actionstart(package, action); + TRACE("Executing Action (%s)\n",debugstr_w(action)); + ACTION_CustomAction(package,action,TRUE); + HeapFree(GetProcessHeap(),0,package->DeferredAction[i]); + } + HeapFree(GetProcessHeap(),0,package->DeferredAction); + + package->DeferredActionCount = 0; + package->DeferredAction = NULL; + + return ERROR_SUCCESS; +} + +static UINT ACTION_InstallFinalize(MSIPACKAGE *package) +{ + int i; + if (!package) + return ERROR_INVALID_HANDLE; + + for (i = 0; i < package->CommitActionCount; i++) + { + LPWSTR action; + action = package->CommitAction[i]; + ui_actionstart(package, action); + TRACE("Executing Commit Action (%s)\n",debugstr_w(action)); + ACTION_CustomAction(package,action,TRUE); + HeapFree(GetProcessHeap(),0,package->CommitAction[i]); + } + HeapFree(GetProcessHeap(),0,package->CommitAction); + + package->CommitActionCount = 0; + package->CommitAction = NULL; + + return ERROR_SUCCESS; +} + +static UINT ACTION_ForceReboot(MSIPACKAGE *package) +{ + static const WCHAR RunOnce[] = { + 'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'R','u','n','O','n','c','e'}; + static const WCHAR InstallRunOnce[] = { + 'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'I','n','s','t','a','l','l','e','r','\\', + 'R','u','n','O','n','c','e','E','n','t','r','i','e','s'}; + + static const WCHAR msiexec_fmt[] = { + 'C',':','\\','W','i','n','d','o','w','s','\\','S','y','s','t','e','m', + '\\','M','s','i','E','x','e','c','.','e','x','e',' ','/','@',' ', + '\"','%','s','\"',0}; + static const WCHAR install_fmt[] = { + '/','I',' ','\"','%','s','\"',' ', + 'A','F','T','E','R','R','E','B','O','O','T','=','1',' ', + 'R','U','N','O','N','C','E','E','N','T','R','Y','=','\"','%','s','\"',0}; + WCHAR buffer[256]; + HKEY hkey; + LPWSTR productcode; + WCHAR squished_pc[100]; + INT rc; + DWORD size; + static const WCHAR szProductCode[]= + {'P','r','o','d','u','c','t','C','o','d','e',0}; + + if (!package) + return ERROR_INVALID_HANDLE; + + productcode = load_dynamic_property(package,szProductCode,&rc); + if (!productcode) + return rc; + + squash_guid(productcode,squished_pc); + + RegCreateKeyW(HKEY_LOCAL_MACHINE,RunOnce,&hkey); + sprintfW(buffer,msiexec_fmt,squished_pc); + + size = strlenW(buffer)*sizeof(WCHAR); + RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size); + RegCloseKey(hkey); + + TRACE("Reboot command %s\n",debugstr_w(buffer)); + + RegCreateKeyW(HKEY_LOCAL_MACHINE,InstallRunOnce,&hkey); + sprintfW(buffer,install_fmt,productcode,squished_pc); + RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size); + RegCloseKey(hkey); + + HeapFree(GetProcessHeap(),0,productcode); + + ExitWindowsEx(EWX_REBOOT,0); + return -1; +} + /* Msi functions that seem appropriate here */ UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction ) { diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 5475047d288..25bf0a913d0 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -196,6 +196,14 @@ typedef struct tagMSIPACKAGE UINT loaded_files; LPWSTR ActionFormat; LPWSTR LastAction; + + LPWSTR *DeferredAction; + UINT DeferredActionCount; + + LPWSTR *CommitAction; + UINT CommitActionCount; + + LPWSTR PackagePath; } MSIPACKAGE; #define MSIHANDLETYPE_ANY 0