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.
This commit is contained in:
parent
dee736764f
commit
2cae30b6cf
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue