Implementations for SelfRegModules and PublishFeatures.

Set default ACTION property for Install.
Deformat more than JUST properties properly. Allows for Files and
Component paths in deformat.
Properly deformat a LaunchCondition failure dialog box.
Resolve and save registry Keypaths.
Write the Features published keys more correctly. Still some
problems.
This commit is contained in:
Aric Stewart 2005-01-17 13:40:39 +00:00 committed by Alexandre Julliard
parent 82a6a3b826
commit 6269f00c33
1 changed files with 439 additions and 68 deletions

View File

@ -160,6 +160,8 @@ static UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package);
static UINT ACTION_CreateShortcuts(MSIPACKAGE *package);
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 HANDLE_CustomType1(MSIPACKAGE *package, const LPWSTR source,
const LPWSTR target, const INT type);
@ -175,7 +177,8 @@ static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source,
static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data);
static LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name,
BOOL source, BOOL set_prop, MSIFOLDER **folder);
static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name,
LPWSTR *FilePath);
static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path);
/*
@ -226,6 +229,10 @@ const static WCHAR szPublishProduct[] =
{'P','u','b','l','i','s','h','P','r','o','d','u','c','t',0};
const static WCHAR szWriteIniValues[] =
{'W','r','i','t','e','I','n','i','V','a','l','u','e','s',0};
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};
/********************************************************
* helper functions to get around current HACKS and such
@ -767,6 +774,10 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
WCHAR buffer[10];
UINT rc;
static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0};
static const WCHAR szAction[] = {'A','C','T','I','O','N',0};
static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
MSI_SetPropertyW(package, szAction, szInstall);
if (szPackagePath)
{
@ -1225,6 +1236,10 @@ UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action)
rc = ACTION_PublishProduct(package);
else if (strcmpW(action,szWriteIniValues)==0)
rc = ACTION_WriteIniValues(package);
else if (strcmpW(action,szSelfRegModules)==0)
rc = ACTION_SelfRegModules(package);
else if (strcmpW(action,szPublishFeatures)==0)
rc = ACTION_PublishFeatures(package);
/*
Called during iTunes but unimplemented and seem important
@ -1411,6 +1426,8 @@ static UINT store_binary_to_temp(MSIPACKAGE *package, const LPWSTR source,
}
typedef UINT __stdcall CustomEntry(MSIHANDLE);
typedef UINT __stdcall DllRegisterServer();
typedef struct
{
MSIPACKAGE *package;
@ -2684,7 +2701,7 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
WCHAR filever[0x100];
VS_FIXEDFILEINFO *lpVer;
FIXME("Version comparison.. \n");
TRACE("Version comparison.. \n");
versize = GetFileVersionInfoSizeW(file->TargetPath,&handle);
version = HeapAlloc(GetProcessHeap(),0,versize);
GetFileVersionInfoW(file->TargetPath, 0, versize, version);
@ -3694,9 +3711,10 @@ static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data)
DWORD size=0;
DWORD chunk=0;
WCHAR key[0x100];
LPWSTR value;
LPWSTR value = NULL;
DWORD sz;
UINT rc;
INT index;
if (ptr==NULL)
{
@ -3741,15 +3759,60 @@ static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data)
mark++;
TRACE("Current %s .. %s\n",debugstr_w(*data),debugstr_w(mark));
sz = 0;
rc = MSI_GetPropertyW(package, key, NULL, &sz);
if ((rc == ERROR_SUCCESS) || (rc == ERROR_MORE_DATA))
/* expand what we can deformat... Again, this should become a bison file */
switch (key[0])
{
case '~':
ERR("UNHANDLED DEFORMAT.. [~] should be NULL\n");
rc = ERROR_FUNCTION_FAILED;
break;
case '$':
ERR("POORLY HANDLED DEFORMAT.. [$componentkey] \n");
index = get_loaded_component(package,&key[1]);
if (index >= 0)
{
value = resolve_folder(package,
package->components[index].Directory,
FALSE, FALSE, NULL);
rc = 0;
}
else
rc = ERROR_FUNCTION_FAILED;
break;
case '#':
index = get_loaded_file(package,&key[1]);
if (index >=0)
{
sz = strlenW(package->files[index].TargetPath);
value = dupstrW(package->files[index].TargetPath);
rc= ERROR_SUCCESS;
}
else
rc = ERROR_FUNCTION_FAILED;
break;
case '\\':
value = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*2);
value[0] = key[1];
rc = ERROR_SUCCESS;
break;
case '%':
sz = GetEnvironmentVariableW(&key[1],NULL,0);
sz++;
value = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
GetEnvironmentVariableW(&key[1],value,sz);
rc = ERROR_SUCCESS;
break;
default:
rc = MSI_GetPropertyW(package, key, NULL, &sz);
sz++;
value = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
MSI_GetPropertyW(package, key, value, &sz);
break;
}
if (((rc == ERROR_SUCCESS) || (rc == ERROR_MORE_DATA))&& value!=NULL)
{
LPWSTR newdata;
sz++;
value = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
MSI_GetPropertyW(package, key, value, &sz);
chunk = (strlenW(value)+1) * sizeof(WCHAR);
size+=chunk;
newdata = HeapReAlloc(GetProcessHeap(),0,*data,size);
@ -3875,9 +3938,12 @@ static UINT ACTION_LaunchConditions(MSIPACKAGE *package)
if (MSI_EvaluateConditionW(package,cond) != MSICONDITION_TRUE)
{
LPWSTR deformated;
message = load_dynamic_stringW(row,2);
MessageBoxW(NULL,message,title,MB_OK);
deformat_string(package,message,&deformated);
MessageBoxW(NULL,deformated,title,MB_OK);
HeapFree(GetProcessHeap(),0,message);
HeapFree(GetProcessHeap(),0,deformated);
rc = ERROR_FUNCTION_FAILED;
}
HeapFree(GetProcessHeap(),0,cond);
@ -3898,9 +3964,71 @@ static LPWSTR resolve_keypath( MSIPACKAGE* package, INT
LPWSTR p = resolve_folder(package,cmp->Directory,FALSE,FALSE,NULL);
return p;
}
if ((cmp->Attributes & 0x4) || (cmp->Attributes & 0x20))
if (cmp->Attributes & 0x4)
{
FIXME("UNIMPLEMENTED keypath as Registry or ODBC Source\n");
MSIQUERY * view;
MSIRECORD * row = 0;
UINT rc,root,len;
LPWSTR key,deformated,buffer,name,deformated_name;
static const WCHAR ExecSeqQuery[] = {
's','e','l','e','c','t',' ','*',' ',
'f','r','o','m',' ','R','e','g','i','s','t','r','y',' ',
'w','h','e','r','e',' ','R','e','g','i','s','t','r','y',' ','=',' '
,'`','%','s','`',0 };
static const WCHAR fmt[]={'%','0','2','i',':','%','s',0};
static const WCHAR fmt2[]={'%','0','2','i',':','%','s','\\','%','s',0};
rc = ACTION_OpenQuery(package->db,&view,ExecSeqQuery,cmp->KeyPath);
if (rc!=ERROR_SUCCESS)
return NULL;
rc = MSI_ViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return NULL;
}
rc = MSI_ViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
{
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return NULL;
}
root = MSI_RecordGetInteger(row,2);
key = load_dynamic_stringW(row, 3);
name = load_dynamic_stringW(row, 4);
deformat_string(package, key , &deformated);
deformat_string(package, name, &deformated_name);
len = strlenW(deformated) + 5;
if (deformated_name)
len+=strlenW(deformated_name);
buffer = HeapAlloc(GetProcessHeap(),0, len *sizeof(WCHAR));
if (deformated_name)
sprintfW(buffer,fmt2,root,deformated,deformated_name);
else
sprintfW(buffer,fmt,root,deformated);
HeapFree(GetProcessHeap(),0,key);
HeapFree(GetProcessHeap(),0,deformated);
HeapFree(GetProcessHeap(),0,name);
HeapFree(GetProcessHeap(),0,deformated_name);
msiobj_release(&row->hdr);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return buffer;
}
else if (cmp->Attributes & 0x20)
{
FIXME("UNIMPLEMENTED keypath as ODBC Source\n");
return NULL;
}
else
@ -3940,8 +4068,6 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
'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',0 };
static const WCHAR szFeatures[] = {
'F','e','a','t','u','r','e','s',0 };
static const WCHAR szComponents[] = {
'C','o','m','p','o','n','e','n','t','s',0 };
@ -3958,48 +4084,6 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
if (rc != ERROR_SUCCESS)
goto end;
rc = RegCreateKeyW(hkey,szFeatures,&hkey2);
if (rc != ERROR_SUCCESS)
goto end;
rc = RegCreateKeyW(hkey2,squished_pc,&hkey3);
if (rc != ERROR_SUCCESS)
goto end;
/* here the guids are base 85 encoded */
for (i = 0; i < package->loaded_features; i++)
{
LPWSTR data = NULL;
GUID clsid;
int j;
INT size;
size = package->features[i].ComponentCount*21*sizeof(WCHAR);
data = HeapAlloc(GetProcessHeap(), 0, size);
data[0] = 0;
for (j = 0; j < package->features[i].ComponentCount; j++)
{
WCHAR buf[21];
TRACE("From %s\n",debugstr_w(package->components
[package->features[i].Components[j]].ComponentId));
CLSIDFromString(package->components
[package->features[i].Components[j]].ComponentId,
&clsid);
encode_base85_guid(&clsid,buf);
TRACE("to %s\n",debugstr_w(buf));
strcatW(data,buf);
}
size = strlenW(data)*sizeof(WCHAR);
RegSetValueExW(hkey3,package->features[i].Feature,0,REG_SZ,
(LPSTR)data,size);
HeapFree(GetProcessHeap(),0,data);
}
RegCloseKey(hkey3);
RegCloseKey(hkey2);
rc = RegCreateKeyW(hkey,szComponents,&hkey2);
if (rc != ERROR_SUCCESS)
goto end;
@ -4418,9 +4502,12 @@ end:
return rc;
}
static UINT register_progid_base(MSIRECORD * row, LPWSTR clsid)
static UINT register_progid_base(MSIPACKAGE* package, MSIRECORD * row,
LPWSTR clsid)
{
static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
static const WCHAR szDefaultIcon[] = {
'D','e','f','a','u','l','t','I','c','o','n',0};
HKEY hkey,hkey2;
WCHAR buffer[0x100];
DWORD sz;
@ -4458,7 +4545,25 @@ static UINT register_progid_base(MSIRECORD * row, LPWSTR clsid)
return ERROR_FUNCTION_FAILED;
}
if (!MSI_RecordIsNull(row,5))
FIXME ("UNHANDLED icon in Progid\n");
{
INT index = MSI_RecordGetInteger(row,6);
LPWSTR FileName = load_dynamic_stringW(row,5);
LPWSTR FilePath,IconPath;
static const WCHAR fmt[] = {'%','s',',','%','i',0};
RegCreateKeyW(hkey,szDefaultIcon,&hkey2);
build_icon_path(package,FileName,&FilePath);
IconPath = HeapAlloc(GetProcessHeap(),0,(strlenW(FilePath)+5)*
sizeof(WCHAR));
sprintfW(IconPath,fmt,FilePath,index);
RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)IconPath,
(strlenW(IconPath)+1) * sizeof(WCHAR));
HeapFree(GetProcessHeap(),0,FilePath);
HeapFree(GetProcessHeap(),0,FileName);
RegCloseKey(hkey2);
}
return ERROR_SUCCESS;
}
@ -4511,13 +4616,15 @@ static UINT register_progid(MSIPACKAGE *package, MSIRECORD * row, LPWSTR clsid)
UINT rc = ERROR_SUCCESS;
if (MSI_RecordIsNull(row,2))
rc = register_progid_base(row,clsid);
rc = register_progid_base(package,row,clsid);
else
{
WCHAR buffer[0x1000];
DWORD sz, disp;
HKEY hkey,hkey2;
static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
static const WCHAR szDefaultIcon[] = {
'D','e','f','a','u','l','t','I','c','o','n',0};
/* check if already registered */
sz = 0x100;
@ -4530,6 +4637,11 @@ static UINT register_progid(MSIPACKAGE *package, MSIRECORD * row, LPWSTR clsid)
RegCloseKey(hkey);
return rc;
}
sz = 0x100;
MSI_RecordGetStringW(row,2,buffer,&sz);
rc = register_parent_progid(package,buffer,clsid);
/* clsid is same as parent */
RegCreateKeyW(hkey,szCLSID,&hkey2);
RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)clsid, (strlenW(clsid)+1) *
@ -4537,9 +4649,6 @@ static UINT register_progid(MSIPACKAGE *package, MSIRECORD * row, LPWSTR clsid)
RegCloseKey(hkey2);
sz = 0x100;
MSI_RecordGetStringW(row,2,buffer,&sz);
rc = register_parent_progid(package,buffer,clsid);
if (!MSI_RecordIsNull(row,4))
{
@ -4550,7 +4659,17 @@ static UINT register_progid(MSIPACKAGE *package, MSIRECORD * row, LPWSTR clsid)
}
if (!MSI_RecordIsNull(row,5))
FIXME ("UNHANDLED icon in Progid\n");
{
LPWSTR FileName = load_dynamic_stringW(row,5);
LPWSTR FilePath;
RegCreateKeyW(hkey,szDefaultIcon,&hkey2);
build_icon_path(package,FileName,&FilePath);
RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)FilePath,
(strlenW(FilePath)+1) * sizeof(WCHAR));
HeapFree(GetProcessHeap(),0,FilePath);
HeapFree(GetProcessHeap(),0,FileName);
RegCloseKey(hkey2);
}
RegCloseKey(hkey);
}
@ -4847,6 +4966,29 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
'S','E','L','E','C','T',' ','*',' ',
'f','r','o','m',' ','I','c','o','n',0};
DWORD sz;
/* for registry stuff */
LPWSTR productcode;
WCHAR squished_pc[0x100];
HKEY hkey=0,hkey2=0,hkey3=0;
HKEY hukey=0,hukey2=0,hukey3=0;
static const WCHAR szProductCode[]=
{'P','r','o','d','u','c','t','C','o','d','e',0};
static const WCHAR szInstaller[] = {
'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',0 };
static const WCHAR szUserInstaller[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'I','n','s','t','a','l','l','e','r',0 };
static const WCHAR szProducts[] = {
'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};
LPWSTR buffer;
DWORD size;
if (!package)
return ERROR_INVALID_HANDLE;
@ -4924,6 +5066,53 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
}
MSI_ViewClose(view);
msiobj_release(&view->hdr);
/* ok there is alot more done here but i need to figure out what */
productcode = load_dynamic_property(package,szProductCode,&rc);
if (!productcode)
return rc;
squash_guid(productcode,squished_pc);
rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller,&hkey);
if (rc != ERROR_SUCCESS)
goto end;
rc = RegCreateKeyW(HKEY_CURRENT_USER,szUserInstaller,&hukey);
if (rc != ERROR_SUCCESS)
goto end;
rc = RegCreateKeyW(hkey,szProducts,&hkey2);
if (rc != ERROR_SUCCESS)
goto end;
rc = RegCreateKeyW(hukey,szProducts,&hukey2);
if (rc != ERROR_SUCCESS)
goto end;
rc = RegCreateKeyW(hkey2,squished_pc,&hkey3);
if (rc != ERROR_SUCCESS)
goto end;
rc = RegCreateKeyW(hukey2,squished_pc,&hukey3);
if (rc != ERROR_SUCCESS)
goto end;
buffer = load_dynamic_property(package,szProductName,NULL);
size = strlenW(buffer)*sizeof(WCHAR);
RegSetValueExW(hukey3,szProductName,0,REG_SZ, (LPSTR)buffer,size);
HeapFree(GetProcessHeap(),0,buffer);
end:
HeapFree(GetProcessHeap(),0,productcode);
RegCloseKey(hkey3);
RegCloseKey(hkey2);
RegCloseKey(hkey);
RegCloseKey(hukey3);
RegCloseKey(hukey2);
RegCloseKey(hukey);
return rc;
}
@ -5072,6 +5261,188 @@ cleanup:
return rc;
}
static UINT ACTION_SelfRegModules(MSIPACKAGE *package)
{
UINT rc;
MSIQUERY * view;
MSIRECORD * row = 0;
static const WCHAR ExecSeqQuery[] = {'S','e','l','e','c','t',' ','*',' ',
'f','r','o','m',' ','S','e','l','f','R','e','g',0};
rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
if (rc != ERROR_SUCCESS)
{
TRACE("no SelfReg table\n");
return ERROR_SUCCESS;
}
rc = MSI_ViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return rc;
}
while (1)
{
LPWSTR filename;
INT index;
HMODULE dll;
DllRegisterServer* regfunc;
rc = MSI_ViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
{
rc = ERROR_SUCCESS;
break;
}
filename = load_dynamic_stringW(row,1);
index = get_loaded_file(package,filename);
if (index < 0)
{
ERR("Unable to find file id %s\n",debugstr_w(filename));
HeapFree(GetProcessHeap(),0,filename);
msiobj_release(&row->hdr);
continue;
}
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;
}
regfunc = (DllRegisterServer*)GetProcAddress(dll,"DllRegisterServer");
if (regfunc)
regfunc();
msiobj_release(&row->hdr);
}
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return rc;
}
static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
{
LPWSTR productcode;
WCHAR squished_pc[0x100];
UINT rc;
DWORD i;
HKEY hkey=0,hkey2=0,hkey3=0;
HKEY hukey=0,hukey2=0,hukey3=0;
static const WCHAR szProductCode[]=
{'P','r','o','d','u','c','t','C','o','d','e',0};
static const WCHAR szInstaller[] = {
'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',0 };
static const WCHAR szUserInstaller[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'I','n','s','t','a','l','l','e','r',0 };
static const WCHAR szFeatures[] = {
'F','e','a','t','u','r','e','s',0 };
if (!package)
return ERROR_INVALID_HANDLE;
productcode = load_dynamic_property(package,szProductCode,&rc);
if (!productcode)
return rc;
squash_guid(productcode,squished_pc);
rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller,&hkey);
if (rc != ERROR_SUCCESS)
goto end;
rc = RegCreateKeyW(HKEY_CURRENT_USER,szUserInstaller,&hukey);
if (rc != ERROR_SUCCESS)
goto end;
rc = RegCreateKeyW(hkey,szFeatures,&hkey2);
if (rc != ERROR_SUCCESS)
goto end;
rc = RegCreateKeyW(hukey,szFeatures,&hukey2);
if (rc != ERROR_SUCCESS)
goto end;
rc = RegCreateKeyW(hkey2,squished_pc,&hkey3);
if (rc != ERROR_SUCCESS)
goto end;
rc = RegCreateKeyW(hukey2,squished_pc,&hukey3);
if (rc != ERROR_SUCCESS)
goto end;
/* here the guids are base 85 encoded */
for (i = 0; i < package->loaded_features; i++)
{
LPWSTR data = NULL;
GUID clsid;
int j;
INT size;
size = package->features[i].ComponentCount*21;
size +=1;
if (package->features[i].Feature_Parent[0])
size += strlenW(package->features[i].Feature_Parent)+2;
data = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
data[0] = 0;
for (j = 0; j < package->features[i].ComponentCount; j++)
{
WCHAR buf[21];
memset(buf,0,sizeof(buf));
TRACE("From %s\n",debugstr_w(package->components
[package->features[i].Components[j]].ComponentId));
CLSIDFromString(package->components
[package->features[i].Components[j]].ComponentId,
&clsid);
encode_base85_guid(&clsid,buf);
TRACE("to %s\n",debugstr_w(buf));
strcatW(data,buf);
}
if (package->features[i].Feature_Parent[0])
{
static const WCHAR sep[] = {'\2',0};
strcatW(data,sep);
strcatW(data,package->features[i].Feature_Parent);
}
size = (strlenW(data)+2)*sizeof(WCHAR);
RegSetValueExW(hkey3,package->features[i].Feature,0,REG_SZ,
(LPSTR)data,size);
HeapFree(GetProcessHeap(),0,data);
size = strlenW(package->features[i].Feature_Parent)*sizeof(WCHAR);
RegSetValueExW(hukey3,package->features[i].Feature,0,REG_SZ,
(LPSTR)package->features[i].Feature_Parent,size);
}
RegCloseKey(hkey3);
RegCloseKey(hukey3);
end:
HeapFree(GetProcessHeap(), 0, productcode);
RegCloseKey(hkey2);
RegCloseKey(hukey2);
RegCloseKey(hkey);
RegCloseKey(hukey);
return rc;
}
/* Msi functions that seem appropriate here */
UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
{
@ -5554,21 +5925,21 @@ static UINT ACTION_Template(MSIPACKAGE *package)
MSIRECORD * row = 0;
static const WCHAR ExecSeqQuery[] = {0};
rc = MsiDatabaseOpenViewW(package->db, ExecSeqQuery, &view);
rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
if (rc != ERROR_SUCCESS)
return rc;
rc = MsiViewExecute(view, 0);
rc = MSI_ViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
MsiViewClose(view);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return rc;
}
while (1)
{
rc = MsiViewFetch(view,&row);
rc = MSI_ViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
{
rc = ERROR_SUCCESS;
@ -5577,7 +5948,7 @@ static UINT ACTION_Template(MSIPACKAGE *package)
msiobj_release(&row->hdr);
}
MsiViewClose(view);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return rc;
}