mirror of
https://github.com/reactos/reactos.git
synced 2024-07-01 02:10:07 +00:00
Autosyncing with Wine HEAD
svn path=/trunk/; revision=32849
This commit is contained in:
parent
5ef42dd10a
commit
e1e678b0f2
|
@ -18,14 +18,6 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Pages I need
|
|
||||||
*
|
|
||||||
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/installexecutesequence_table.asp
|
|
||||||
|
|
||||||
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/standard_actions_reference.asp
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
|
@ -55,6 +47,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||||
static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
|
static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
|
||||||
static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
|
static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
|
||||||
static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI);
|
static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI);
|
||||||
|
static BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action, UINT* rc, BOOL force);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* consts and values used
|
* consts and values used
|
||||||
|
@ -241,8 +234,6 @@ struct _actions {
|
||||||
STANDARDACTIONHANDLER handler;
|
STANDARDACTIONHANDLER handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct _actions StandardActions[];
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************
|
/********************************************************
|
||||||
* helper functions
|
* helper functions
|
||||||
|
@ -573,7 +564,7 @@ static UINT msi_apply_transforms( MSIPACKAGE *package )
|
||||||
for( i=0; xforms && xforms[i] && r == ERROR_SUCCESS; i++ )
|
for( i=0; xforms && xforms[i] && r == ERROR_SUCCESS; i++ )
|
||||||
{
|
{
|
||||||
if (xforms[i][0] == ':')
|
if (xforms[i][0] == ':')
|
||||||
r = msi_apply_substorage_transform( package, package->db, &xforms[i][1] );
|
r = msi_apply_substorage_transform( package, package->db, xforms[i] );
|
||||||
else
|
else
|
||||||
r = MSI_DatabaseApplyTransformW( package->db, xforms[i], 0 );
|
r = MSI_DatabaseApplyTransformW( package->db, xforms[i], 0 );
|
||||||
}
|
}
|
||||||
|
@ -584,7 +575,7 @@ static UINT msi_apply_transforms( MSIPACKAGE *package )
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL ui_sequence_exists( MSIPACKAGE *package )
|
static BOOL ui_sequence_exists( MSIPACKAGE *package )
|
||||||
{
|
{
|
||||||
MSIQUERY *view;
|
MSIQUERY *view;
|
||||||
UINT rc;
|
UINT rc;
|
||||||
|
@ -973,56 +964,6 @@ static UINT ACTION_ProcessUISequence(MSIPACKAGE *package)
|
||||||
/********************************************************
|
/********************************************************
|
||||||
* ACTION helper functions and functions that perform the actions
|
* ACTION helper functions and functions that perform the actions
|
||||||
*******************************************************/
|
*******************************************************/
|
||||||
static BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action,
|
|
||||||
UINT* rc, BOOL force )
|
|
||||||
{
|
|
||||||
BOOL ret = FALSE;
|
|
||||||
BOOL run = force;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!run && !package->script->CurrentlyScripting)
|
|
||||||
run = TRUE;
|
|
||||||
|
|
||||||
if (!run)
|
|
||||||
{
|
|
||||||
if (strcmpW(action,szInstallFinalize) == 0 ||
|
|
||||||
strcmpW(action,szInstallExecute) == 0 ||
|
|
||||||
strcmpW(action,szInstallExecuteAgain) == 0)
|
|
||||||
run = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while (StandardActions[i].action != NULL)
|
|
||||||
{
|
|
||||||
if (strcmpW(StandardActions[i].action, action)==0)
|
|
||||||
{
|
|
||||||
if (!run)
|
|
||||||
{
|
|
||||||
ui_actioninfo(package, action, TRUE, 0);
|
|
||||||
*rc = schedule_action(package,INSTALL_SCRIPT,action);
|
|
||||||
ui_actioninfo(package, action, FALSE, *rc);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ui_actionstart(package, action);
|
|
||||||
if (StandardActions[i].handler)
|
|
||||||
{
|
|
||||||
*rc = StandardActions[i].handler(package);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FIXME("unhandled standard action %s\n",debugstr_w(action));
|
|
||||||
*rc = ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL ACTION_HandleCustomAction( MSIPACKAGE* package, LPCWSTR action,
|
static BOOL ACTION_HandleCustomAction( MSIPACKAGE* package, LPCWSTR action,
|
||||||
UINT* rc, UINT script, BOOL force )
|
UINT* rc, UINT script, BOOL force )
|
||||||
{
|
{
|
||||||
|
@ -1061,7 +1002,7 @@ UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, UINT script,
|
||||||
|
|
||||||
if (!handled)
|
if (!handled)
|
||||||
{
|
{
|
||||||
FIXME("unhandled msi action %s\n",debugstr_w(action));
|
WARN("unhandled msi action %s\n",debugstr_w(action));
|
||||||
rc = ERROR_FUNCTION_NOT_CALLED;
|
rc = ERROR_FUNCTION_NOT_CALLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1085,7 +1026,7 @@ UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action, UINT scrip
|
||||||
|
|
||||||
if (!handled)
|
if (!handled)
|
||||||
{
|
{
|
||||||
FIXME("unhandled msi action %s\n",debugstr_w(action));
|
WARN("unhandled msi action %s\n",debugstr_w(action));
|
||||||
rc = ERROR_FUNCTION_NOT_CALLED;
|
rc = ERROR_FUNCTION_NOT_CALLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2322,7 +2263,6 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type,
|
||||||
{
|
{
|
||||||
static const WCHAR szMulti[] = {'[','~',']',0};
|
static const WCHAR szMulti[] = {'[','~',']',0};
|
||||||
LPCWSTR ptr;
|
LPCWSTR ptr;
|
||||||
LPWSTR newdata;
|
|
||||||
*type=REG_SZ;
|
*type=REG_SZ;
|
||||||
|
|
||||||
if (value[0]=='#')
|
if (value[0]=='#')
|
||||||
|
@ -2350,19 +2290,8 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type,
|
||||||
/* add double NULL terminator */
|
/* add double NULL terminator */
|
||||||
if (*type == REG_MULTI_SZ)
|
if (*type == REG_MULTI_SZ)
|
||||||
{
|
{
|
||||||
*size += sizeof(WCHAR);
|
*size += 2 * sizeof(WCHAR); /* two NULL terminators */
|
||||||
newdata = msi_alloc(*size);
|
data = msi_realloc_zero(data, *size);
|
||||||
if (!newdata)
|
|
||||||
{
|
|
||||||
msi_free(data);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(newdata, data, *size - 1);
|
|
||||||
newdata[*size] = '\0';
|
|
||||||
|
|
||||||
msi_free(data);
|
|
||||||
data = (LPSTR)newdata;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
|
@ -2503,10 +2432,6 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
|
||||||
|
|
||||||
deformat_string(package, name, &deformated);
|
deformat_string(package, name, &deformated);
|
||||||
|
|
||||||
/* get the double nulls to terminate SZ_MULTI */
|
|
||||||
if (type == REG_MULTI_SZ)
|
|
||||||
size +=sizeof(WCHAR);
|
|
||||||
|
|
||||||
if (!check_first)
|
if (!check_first)
|
||||||
{
|
{
|
||||||
TRACE("Setting value %s of %s\n",debugstr_w(deformated),
|
TRACE("Setting value %s of %s\n",debugstr_w(deformated),
|
||||||
|
@ -3379,6 +3304,7 @@ static BOOL msi_check_publish(MSIPACKAGE *package)
|
||||||
static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
||||||
{
|
{
|
||||||
UINT rc;
|
UINT rc;
|
||||||
|
LPWSTR packname;
|
||||||
MSIQUERY * view;
|
MSIQUERY * view;
|
||||||
MSISOURCELISTINFO *info;
|
MSISOURCELISTINFO *info;
|
||||||
MSIMEDIADISK *disk;
|
MSIMEDIADISK *disk;
|
||||||
|
@ -3389,12 +3315,16 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
||||||
HKEY hkey=0;
|
HKEY hkey=0;
|
||||||
HKEY hukey=0;
|
HKEY hukey=0;
|
||||||
HKEY hudkey=0, props=0;
|
HKEY hudkey=0, props=0;
|
||||||
|
HKEY source;
|
||||||
static const WCHAR szProductLanguage[] =
|
static const WCHAR szProductLanguage[] =
|
||||||
{'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
|
{'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
|
||||||
static const WCHAR szARPProductIcon[] =
|
static const WCHAR szARPProductIcon[] =
|
||||||
{'A','R','P','P','R','O','D','U','C','T','I','C','O','N',0};
|
{'A','R','P','P','R','O','D','U','C','T','I','C','O','N',0};
|
||||||
static const WCHAR szProductVersion[] =
|
static const WCHAR szProductVersion[] =
|
||||||
{'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
|
{'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
|
||||||
|
static const WCHAR szSourceList[] =
|
||||||
|
{'S','o','u','r','c','e','L','i','s','t',0};
|
||||||
|
static const WCHAR szEmpty[] = {0};
|
||||||
DWORD langid;
|
DWORD langid;
|
||||||
LPWSTR buffer;
|
LPWSTR buffer;
|
||||||
DWORD size;
|
DWORD size;
|
||||||
|
@ -3423,6 +3353,12 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
rc = RegCreateKeyW(hukey, szSourceList, &source);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
RegCloseKey(source);
|
||||||
|
|
||||||
rc = MSIREG_OpenUserDataProductKey(package->ProductCode,&hudkey,TRUE);
|
rc = MSIREG_OpenUserDataProductKey(package->ProductCode,&hudkey,TRUE);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -3436,7 +3372,14 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
||||||
msi_free(buffer);
|
msi_free(buffer);
|
||||||
|
|
||||||
langid = msi_get_property_int( package, szProductLanguage, 0 );
|
langid = msi_get_property_int( package, szProductLanguage, 0 );
|
||||||
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_LANGUAGEW, langid );
|
msi_reg_set_val_dword( hukey, INSTALLPROPERTY_LANGUAGEW, langid );
|
||||||
|
|
||||||
|
packname = strrchrW( package->PackagePath, '\\' ) + 1;
|
||||||
|
msi_reg_set_val_str( hukey, INSTALLPROPERTY_PACKAGENAMEW, packname );
|
||||||
|
|
||||||
|
/* FIXME */
|
||||||
|
msi_reg_set_val_dword( hukey, INSTALLPROPERTY_AUTHORIZED_LUA_APPW, 0 );
|
||||||
|
msi_reg_set_val_dword( props, INSTALLPROPERTY_INSTANCETYPEW, 0 );
|
||||||
|
|
||||||
buffer = msi_dup_property( package, szARPProductIcon );
|
buffer = msi_dup_property( package, szARPProductIcon );
|
||||||
if (buffer)
|
if (buffer)
|
||||||
|
@ -3451,10 +3394,29 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
||||||
if (buffer)
|
if (buffer)
|
||||||
{
|
{
|
||||||
DWORD verdword = msi_version_str_to_dword(buffer);
|
DWORD verdword = msi_version_str_to_dword(buffer);
|
||||||
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONW, verdword );
|
msi_reg_set_val_dword( hukey, INSTALLPROPERTY_VERSIONW, verdword );
|
||||||
}
|
}
|
||||||
msi_free(buffer);
|
msi_free(buffer);
|
||||||
|
|
||||||
|
buffer = strrchrW( package->PackagePath, '\\') + 1;
|
||||||
|
rc = MsiSourceListSetInfoW( package->ProductCode, NULL,
|
||||||
|
MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
|
||||||
|
INSTALLPROPERTY_PACKAGENAMEW, buffer );
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
rc = MsiSourceListSetInfoW( package->ProductCode, NULL,
|
||||||
|
MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
|
||||||
|
INSTALLPROPERTY_MEDIAPACKAGEPATHW, szEmpty );
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
rc = MsiSourceListSetInfoW( package->ProductCode, NULL,
|
||||||
|
MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
|
||||||
|
INSTALLPROPERTY_DISKPROMPTW, szEmpty );
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
goto end;
|
||||||
|
|
||||||
/* FIXME: Need to write more keys to the user registry */
|
/* FIXME: Need to write more keys to the user registry */
|
||||||
|
|
||||||
hDb= alloc_msihandle( &package->db->hdr );
|
hDb= alloc_msihandle( &package->db->hdr );
|
||||||
|
@ -3472,12 +3434,10 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
||||||
guidbuffer, &size);
|
guidbuffer, &size);
|
||||||
if (rc == ERROR_SUCCESS)
|
if (rc == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
WCHAR squashed[GUID_SIZE];
|
|
||||||
/* for now we only care about the first guid */
|
/* for now we only care about the first guid */
|
||||||
LPWSTR ptr = strchrW(guidbuffer,';');
|
LPWSTR ptr = strchrW(guidbuffer,';');
|
||||||
if (ptr) *ptr = 0;
|
if (ptr) *ptr = 0;
|
||||||
squash_guid(guidbuffer,squashed);
|
msi_reg_set_val_str( hukey, INSTALLPROPERTY_PACKAGECODEW, guidbuffer );
|
||||||
msi_reg_set_val_str( hukey, INSTALLPROPERTY_PACKAGECODEW, squashed );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3495,9 +3455,13 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
||||||
/* publish the SourceList info */
|
/* publish the SourceList info */
|
||||||
LIST_FOR_EACH_ENTRY(info, &package->sourcelist_info, MSISOURCELISTINFO, entry)
|
LIST_FOR_EACH_ENTRY(info, &package->sourcelist_info, MSISOURCELISTINFO, entry)
|
||||||
{
|
{
|
||||||
MsiSourceListSetInfoW(package->ProductCode, NULL,
|
if (!lstrcmpW(info->property, INSTALLPROPERTY_LASTUSEDSOURCEW))
|
||||||
info->context, info->options,
|
msi_set_last_used_source(package->ProductCode, NULL, info->context,
|
||||||
info->property, info->value);
|
info->options, info->value);
|
||||||
|
else
|
||||||
|
MsiSourceListSetInfoW(package->ProductCode, NULL,
|
||||||
|
info->context, info->options,
|
||||||
|
info->property, info->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY(disk, &package->sourcelist_media, MSIMEDIADISK, entry)
|
LIST_FOR_EACH_ENTRY(disk, &package->sourcelist_media, MSIMEDIADISK, entry)
|
||||||
|
@ -4000,6 +3964,14 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
|
||||||
{'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
|
{'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
|
||||||
static const WCHAR szProductVersion[] =
|
static const WCHAR szProductVersion[] =
|
||||||
{'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
|
{'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
|
||||||
|
static const WCHAR szProductName[] =
|
||||||
|
{'P','r','o','d','u','c','t','N','a','m','e',0};
|
||||||
|
static const WCHAR szDisplayName[] =
|
||||||
|
{'D','i','s','p','l','a','y','N','a','m','e',0};
|
||||||
|
static const WCHAR szDisplayVersion[] =
|
||||||
|
{'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
|
||||||
|
static const WCHAR szManufacturer[] =
|
||||||
|
{'M','a','n','u','f','a','c','t','u','r','e','r',0};
|
||||||
|
|
||||||
SYSTEMTIME systime;
|
SYSTEMTIME systime;
|
||||||
static const WCHAR date_fmt[] = {'%','i','%','0','2','i','%','0','2','i',0};
|
static const WCHAR date_fmt[] = {'%','i','%','0','2','i','%','0','2','i',0};
|
||||||
|
@ -4014,6 +3986,10 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
rc = MSIREG_OpenInstallPropertiesKey(package->ProductCode, &props, TRUE);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
return rc;
|
||||||
|
|
||||||
/* dump all the info i can grab */
|
/* dump all the info i can grab */
|
||||||
/* FIXME: Flesh out more information */
|
/* FIXME: Flesh out more information */
|
||||||
|
|
||||||
|
@ -4031,22 +4007,39 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
|
||||||
|
|
||||||
/* FIXME: Write real Estimated Size when we have it */
|
/* FIXME: Write real Estimated Size when we have it */
|
||||||
msi_reg_set_val_dword( hkey, szEstimatedSize, 0 );
|
msi_reg_set_val_dword( hkey, szEstimatedSize, 0 );
|
||||||
|
|
||||||
|
buffer = msi_dup_property( package, szProductName );
|
||||||
|
msi_reg_set_val_str( props, szDisplayName, buffer );
|
||||||
|
msi_free(buffer);
|
||||||
|
|
||||||
|
buffer = msi_dup_property( package, cszSourceDir );
|
||||||
|
msi_reg_set_val_str( props, INSTALLPROPERTY_INSTALLSOURCEW, buffer);
|
||||||
|
msi_free(buffer);
|
||||||
|
|
||||||
|
buffer = msi_dup_property( package, szManufacturer );
|
||||||
|
msi_reg_set_val_str( props, INSTALLPROPERTY_PUBLISHERW, buffer);
|
||||||
|
msi_free(buffer);
|
||||||
|
|
||||||
GetLocalTime(&systime);
|
GetLocalTime(&systime);
|
||||||
sprintfW(szDate,date_fmt,systime.wYear,systime.wMonth,systime.wDay);
|
sprintfW(szDate,date_fmt,systime.wYear,systime.wMonth,systime.wDay);
|
||||||
msi_reg_set_val_str( hkey, INSTALLPROPERTY_INSTALLDATEW, szDate );
|
msi_reg_set_val_str( hkey, INSTALLPROPERTY_INSTALLDATEW, szDate );
|
||||||
|
msi_reg_set_val_str( props, INSTALLPROPERTY_INSTALLDATEW, szDate );
|
||||||
|
|
||||||
langid = msi_get_property_int( package, szProductLanguage, 0 );
|
langid = msi_get_property_int( package, szProductLanguage, 0 );
|
||||||
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_LANGUAGEW, langid );
|
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_LANGUAGEW, langid );
|
||||||
|
|
||||||
buffer = msi_dup_property( package, szProductVersion );
|
buffer = msi_dup_property( package, szProductVersion );
|
||||||
|
msi_reg_set_val_str( props, szDisplayVersion, buffer );
|
||||||
if (buffer)
|
if (buffer)
|
||||||
{
|
{
|
||||||
DWORD verdword = msi_version_str_to_dword(buffer);
|
DWORD verdword = msi_version_str_to_dword(buffer);
|
||||||
|
|
||||||
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONW, verdword );
|
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONW, verdword );
|
||||||
|
msi_reg_set_val_dword( props, INSTALLPROPERTY_VERSIONW, verdword );
|
||||||
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONMAJORW, verdword>>24 );
|
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONMAJORW, verdword>>24 );
|
||||||
|
msi_reg_set_val_dword( props, INSTALLPROPERTY_VERSIONMAJORW, verdword>>24 );
|
||||||
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONMINORW, (verdword>>16)&0x00FF );
|
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONMINORW, (verdword>>16)&0x00FF );
|
||||||
|
msi_reg_set_val_dword( props, INSTALLPROPERTY_VERSIONMINORW, (verdword>>16)&0x00FF );
|
||||||
}
|
}
|
||||||
msi_free(buffer);
|
msi_free(buffer);
|
||||||
|
|
||||||
|
@ -4076,10 +4069,6 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
|
||||||
|
|
||||||
RegCloseKey(hudkey);
|
RegCloseKey(hudkey);
|
||||||
|
|
||||||
rc = MSIREG_OpenInstallPropertiesKey(package->ProductCode, &props, TRUE);
|
|
||||||
if (rc != ERROR_SUCCESS)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
msi_reg_set_val_dword( props, szWindowsInstaller, 1 );
|
msi_reg_set_val_dword( props, szWindowsInstaller, 1 );
|
||||||
RegCloseKey(props);
|
RegCloseKey(props);
|
||||||
|
|
||||||
|
@ -4232,13 +4221,13 @@ static UINT ACTION_ResolveSource(MSIPACKAGE* package)
|
||||||
DWORD size = 0;
|
DWORD size = 0;
|
||||||
|
|
||||||
rc = MsiSourceListGetInfoW(package->ProductCode, NULL,
|
rc = MsiSourceListGetInfoW(package->ProductCode, NULL,
|
||||||
MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
|
MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
|
||||||
INSTALLPROPERTY_DISKPROMPTW,NULL,&size);
|
INSTALLPROPERTY_DISKPROMPTW,NULL,&size);
|
||||||
if (rc == ERROR_MORE_DATA)
|
if (rc == ERROR_MORE_DATA)
|
||||||
{
|
{
|
||||||
prompt = msi_alloc(size * sizeof(WCHAR));
|
prompt = msi_alloc(size * sizeof(WCHAR));
|
||||||
MsiSourceListGetInfoW(package->ProductCode, NULL,
|
MsiSourceListGetInfoW(package->ProductCode, NULL,
|
||||||
MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
|
MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
|
||||||
INSTALLPROPERTY_DISKPROMPTW,prompt,&size);
|
INSTALLPROPERTY_DISKPROMPTW,prompt,&size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -4287,11 +4276,17 @@ static UINT ACTION_RegisterUser(MSIPACKAGE *package)
|
||||||
{0},
|
{0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (msi_check_unpublish(package))
|
||||||
|
{
|
||||||
|
MSIREG_DeleteUserDataProductKey(package->ProductCode);
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
productid = msi_dup_property( package, INSTALLPROPERTY_PRODUCTIDW );
|
productid = msi_dup_property( package, INSTALLPROPERTY_PRODUCTIDW );
|
||||||
if (!productid)
|
if (!productid)
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
rc = MSIREG_OpenUninstallKey(package->ProductCode,&hkey,TRUE);
|
rc = MSIREG_OpenInstallPropertiesKey(package->ProductCode, &hkey, TRUE);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
@ -4308,7 +4303,7 @@ end:
|
||||||
|
|
||||||
/* FIXME: call ui_actiondata */
|
/* FIXME: call ui_actiondata */
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4424,7 +4419,8 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
|
||||||
MSIRECORD *row;
|
MSIRECORD *row;
|
||||||
MSIFILE *file;
|
MSIFILE *file;
|
||||||
SC_HANDLE hscm, service = NULL;
|
SC_HANDLE hscm, service = NULL;
|
||||||
LPCWSTR name, disp, comp, depends, pass;
|
LPCWSTR comp, depends, pass;
|
||||||
|
LPWSTR name = NULL, disp = NULL;
|
||||||
LPCWSTR load_order, serv_name, key;
|
LPCWSTR load_order, serv_name, key;
|
||||||
DWORD serv_type, start_type;
|
DWORD serv_type, start_type;
|
||||||
DWORD err_control;
|
DWORD err_control;
|
||||||
|
@ -4451,8 +4447,8 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
|
||||||
if (depends && *depends)
|
if (depends && *depends)
|
||||||
FIXME("Dependency list unhandled!\n");
|
FIXME("Dependency list unhandled!\n");
|
||||||
|
|
||||||
name = MSI_RecordGetString(rec, 2);
|
deformat_string(package, MSI_RecordGetString(rec, 2), &name);
|
||||||
disp = MSI_RecordGetString(rec, 3);
|
deformat_string(package, MSI_RecordGetString(rec, 3), &disp);
|
||||||
serv_type = MSI_RecordGetInteger(rec, 4);
|
serv_type = MSI_RecordGetInteger(rec, 4);
|
||||||
err_control = MSI_RecordGetInteger(rec, 6);
|
err_control = MSI_RecordGetInteger(rec, 6);
|
||||||
load_order = MSI_RecordGetString(rec, 7);
|
load_order = MSI_RecordGetString(rec, 7);
|
||||||
|
@ -4490,6 +4486,8 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
|
||||||
done:
|
done:
|
||||||
CloseServiceHandle(service);
|
CloseServiceHandle(service);
|
||||||
CloseServiceHandle(hscm);
|
CloseServiceHandle(hscm);
|
||||||
|
msi_free(name);
|
||||||
|
msi_free(disp);
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -4629,6 +4627,130 @@ static UINT ACTION_StartServices( MSIPACKAGE *package )
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL stop_service_dependents(SC_HANDLE scm, SC_HANDLE service)
|
||||||
|
{
|
||||||
|
DWORD i, needed, count;
|
||||||
|
ENUM_SERVICE_STATUSW *dependencies;
|
||||||
|
SERVICE_STATUS ss;
|
||||||
|
SC_HANDLE depserv;
|
||||||
|
|
||||||
|
if (EnumDependentServicesW(service, SERVICE_ACTIVE, NULL,
|
||||||
|
0, &needed, &count))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (GetLastError() != ERROR_MORE_DATA)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
dependencies = msi_alloc(needed);
|
||||||
|
if (!dependencies)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!EnumDependentServicesW(service, SERVICE_ACTIVE, dependencies,
|
||||||
|
needed, &needed, &count))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
depserv = OpenServiceW(scm, dependencies[i].lpServiceName,
|
||||||
|
SERVICE_STOP | SERVICE_QUERY_STATUS);
|
||||||
|
if (!depserv)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!ControlService(depserv, SERVICE_CONTROL_STOP, &ss))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
msi_free(dependencies);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT ITERATE_StopService(MSIRECORD *rec, LPVOID param)
|
||||||
|
{
|
||||||
|
MSIPACKAGE *package = (MSIPACKAGE *)param;
|
||||||
|
MSICOMPONENT *comp;
|
||||||
|
SERVICE_STATUS status;
|
||||||
|
SERVICE_STATUS_PROCESS ssp;
|
||||||
|
SC_HANDLE scm = NULL, service = NULL;
|
||||||
|
LPWSTR name, args;
|
||||||
|
DWORD event, needed;
|
||||||
|
|
||||||
|
event = MSI_RecordGetInteger(rec, 3);
|
||||||
|
if (!(event & msidbServiceControlEventStop))
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
|
comp = get_loaded_component(package, MSI_RecordGetString(rec, 6));
|
||||||
|
if (!comp || comp->Action == INSTALLSTATE_UNKNOWN || comp->Action == INSTALLSTATE_ABSENT)
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
|
deformat_string(package, MSI_RecordGetString(rec, 2), &name);
|
||||||
|
deformat_string(package, MSI_RecordGetString(rec, 4), &args);
|
||||||
|
args = strdupW(MSI_RecordGetString(rec, 4));
|
||||||
|
|
||||||
|
scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||||
|
if (!scm)
|
||||||
|
{
|
||||||
|
WARN("Failed to open the SCM: %d\n", GetLastError());
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
service = OpenServiceW(scm, name,
|
||||||
|
SERVICE_STOP |
|
||||||
|
SERVICE_QUERY_STATUS |
|
||||||
|
SERVICE_ENUMERATE_DEPENDENTS);
|
||||||
|
if (!service)
|
||||||
|
{
|
||||||
|
WARN("Failed to open service (%s): %d\n",
|
||||||
|
debugstr_w(name), GetLastError());
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp,
|
||||||
|
sizeof(SERVICE_STATUS_PROCESS), &needed))
|
||||||
|
{
|
||||||
|
WARN("Failed to query service status (%s): %d\n",
|
||||||
|
debugstr_w(name), GetLastError());
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssp.dwCurrentState == SERVICE_STOPPED)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
stop_service_dependents(scm, service);
|
||||||
|
|
||||||
|
if (!ControlService(service, SERVICE_CONTROL_STOP, &status))
|
||||||
|
WARN("Failed to stop service (%s): %d\n", debugstr_w(name), GetLastError());
|
||||||
|
|
||||||
|
done:
|
||||||
|
CloseServiceHandle(service);
|
||||||
|
CloseServiceHandle(scm);
|
||||||
|
msi_free(name);
|
||||||
|
msi_free(args);
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT ACTION_StopServices( MSIPACKAGE *package )
|
||||||
|
{
|
||||||
|
UINT rc;
|
||||||
|
MSIQUERY *view;
|
||||||
|
|
||||||
|
static const WCHAR query[] = {
|
||||||
|
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
||||||
|
'S','e','r','v','i','c','e','C','o','n','t','r','o','l',0 };
|
||||||
|
|
||||||
|
rc = MSI_DatabaseOpenViewW(package->db, query, &view);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
|
rc = MSI_IterateRecords(view, NULL, ITERATE_StopService, package);
|
||||||
|
msiobj_release(&view->hdr);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static MSIFILE *msi_find_file( MSIPACKAGE *package, LPCWSTR filename )
|
static MSIFILE *msi_find_file( MSIPACKAGE *package, LPCWSTR filename )
|
||||||
{
|
{
|
||||||
MSIFILE *file;
|
MSIFILE *file;
|
||||||
|
@ -5211,7 +5333,7 @@ static BOOL add_wildcard(FILE_LIST *files, LPWSTR source, LPWSTR dest)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options)
|
static BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options)
|
||||||
{
|
{
|
||||||
WIN32_FIND_DATAW wfd;
|
WIN32_FIND_DATAW wfd;
|
||||||
HANDLE hfile;
|
HANDLE hfile;
|
||||||
|
@ -5240,6 +5362,10 @@ BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options)
|
||||||
msi_free(path);
|
msi_free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* no files match the wildcard */
|
||||||
|
if (list_empty(&files.entry))
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* only the first wildcard match gets renamed to dest */
|
/* only the first wildcard match gets renamed to dest */
|
||||||
file = LIST_ENTRY(list_head(&files.entry), FILE_LIST, entry);
|
file = LIST_ENTRY(list_head(&files.entry), FILE_LIST, entry);
|
||||||
size = (strrchrW(file->dest, '\\') - file->dest) + lstrlenW(file->destname) + 2;
|
size = (strrchrW(file->dest, '\\') - file->dest) + lstrlenW(file->destname) + 2;
|
||||||
|
@ -5461,13 +5587,6 @@ static UINT ACTION_SelfUnregModules( MSIPACKAGE *package )
|
||||||
return msi_unimplemented_action_stub( package, "SelfUnregModules", table );
|
return msi_unimplemented_action_stub( package, "SelfUnregModules", table );
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT ACTION_StopServices( MSIPACKAGE *package )
|
|
||||||
{
|
|
||||||
static const WCHAR table[] = {
|
|
||||||
'S','e','r','v','i','c','e','C','o','n','t','r','o','l',0 };
|
|
||||||
return msi_unimplemented_action_stub( package, "StopServices", table );
|
|
||||||
}
|
|
||||||
|
|
||||||
static UINT ACTION_DeleteServices( MSIPACKAGE *package )
|
static UINT ACTION_DeleteServices( MSIPACKAGE *package )
|
||||||
{
|
{
|
||||||
static const WCHAR table[] = {
|
static const WCHAR table[] = {
|
||||||
|
@ -5682,3 +5801,53 @@ static const struct _actions StandardActions[] = {
|
||||||
{ szWriteRegistryValues, ACTION_WriteRegistryValues },
|
{ szWriteRegistryValues, ACTION_WriteRegistryValues },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action,
|
||||||
|
UINT* rc, BOOL force )
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
BOOL run = force;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!run && !package->script->CurrentlyScripting)
|
||||||
|
run = TRUE;
|
||||||
|
|
||||||
|
if (!run)
|
||||||
|
{
|
||||||
|
if (strcmpW(action,szInstallFinalize) == 0 ||
|
||||||
|
strcmpW(action,szInstallExecute) == 0 ||
|
||||||
|
strcmpW(action,szInstallExecuteAgain) == 0)
|
||||||
|
run = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (StandardActions[i].action != NULL)
|
||||||
|
{
|
||||||
|
if (strcmpW(StandardActions[i].action, action)==0)
|
||||||
|
{
|
||||||
|
if (!run)
|
||||||
|
{
|
||||||
|
ui_actioninfo(package, action, TRUE, 0);
|
||||||
|
*rc = schedule_action(package,INSTALL_SCRIPT,action);
|
||||||
|
ui_actioninfo(package, action, FALSE, *rc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui_actionstart(package, action);
|
||||||
|
if (StandardActions[i].handler)
|
||||||
|
{
|
||||||
|
*rc = StandardActions[i].handler(package);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FIXME("unhandled standard action %s\n",debugstr_w(action));
|
||||||
|
*rc = ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -901,9 +901,6 @@ static UINT iterate_appsearch(MSIRECORD *row, LPVOID param)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* http://msdn.microsoft.com/library/en-us/msi/setup/appsearch_table.asp
|
|
||||||
* is the best reference for the AppSearch table and how it's used.
|
|
||||||
*/
|
|
||||||
UINT ACTION_AppSearch(MSIPACKAGE *package)
|
UINT ACTION_AppSearch(MSIPACKAGE *package)
|
||||||
{
|
{
|
||||||
static const WCHAR query[] = {
|
static const WCHAR query[] = {
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||||
|
|
||||||
|
#define REG_INDEX_CLASSES_ROOT 0
|
||||||
|
#define REG_INDEX_DYN_DATA 6
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
|
* AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
|
||||||
* called from AutomationObject::Invoke, and pass this function to create_automation_object.
|
* called from AutomationObject::Invoke, and pass this function to create_automation_object.
|
||||||
|
@ -150,7 +153,7 @@ HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID
|
||||||
|
|
||||||
/* Create the automation object, placing the result in the pointer ppObj. The automation object is created
|
/* Create the automation object, placing the result in the pointer ppObj. The automation object is created
|
||||||
* with the appropriate clsid and invocation function. */
|
* with the appropriate clsid and invocation function. */
|
||||||
HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter, LPVOID *ppObj, REFIID clsid,
|
static HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter, LPVOID *ppObj, REFIID clsid,
|
||||||
HRESULT (STDMETHODCALLTYPE *funcInvoke)(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,
|
HRESULT (STDMETHODCALLTYPE *funcInvoke)(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,
|
||||||
VARIANT*,EXCEPINFO*,UINT*),
|
VARIANT*,EXCEPINFO*,UINT*),
|
||||||
void (STDMETHODCALLTYPE *funcFree)(AutomationObject*),
|
void (STDMETHODCALLTYPE *funcFree)(AutomationObject*),
|
||||||
|
@ -191,7 +194,7 @@ HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter, LPVOI
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a list enumerator, placing the result in the pointer ppObj. */
|
/* Create a list enumerator, placing the result in the pointer ppObj. */
|
||||||
HRESULT create_list_enumerator(IUnknown *pUnkOuter, LPVOID *ppObj, AutomationObject *pObj, ULONG ulPos)
|
static HRESULT create_list_enumerator(IUnknown *pUnkOuter, LPVOID *ppObj, AutomationObject *pObj, ULONG ulPos)
|
||||||
{
|
{
|
||||||
ListEnumerator *object;
|
ListEnumerator *object;
|
||||||
|
|
||||||
|
@ -705,7 +708,7 @@ static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl =
|
||||||
/* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
|
/* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
|
||||||
This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
|
This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
|
||||||
using DispGetParam/VariantChangeType. */
|
using DispGetParam/VariantChangeType. */
|
||||||
HRESULT WINAPI DispGetParam_CopyOnly(
|
static HRESULT WINAPI DispGetParam_CopyOnly(
|
||||||
DISPPARAMS *pdispparams, /* [in] Parameter list */
|
DISPPARAMS *pdispparams, /* [in] Parameter list */
|
||||||
UINT *position, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
|
UINT *position, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
|
||||||
VARIANT *pvarResult) /* [out] Destination for resulting variant */
|
VARIANT *pvarResult) /* [out] Destination for resulting variant */
|
||||||
|
@ -1535,6 +1538,7 @@ static HRESULT WINAPI InstallerImpl_Invoke(
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
LPWSTR szString = NULL;
|
LPWSTR szString = NULL;
|
||||||
DWORD dwSize = 0;
|
DWORD dwSize = 0;
|
||||||
|
INSTALLUILEVEL ui;
|
||||||
|
|
||||||
VariantInit(&varg0);
|
VariantInit(&varg0);
|
||||||
VariantInit(&varg1);
|
VariantInit(&varg1);
|
||||||
|
@ -1627,6 +1631,31 @@ static HRESULT WINAPI InstallerImpl_Invoke(
|
||||||
else return DISP_E_MEMBERNOTFOUND;
|
else return DISP_E_MEMBERNOTFOUND;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DISPID_INSTALLER_UILEVEL:
|
||||||
|
if (wFlags & DISPATCH_PROPERTYPUT)
|
||||||
|
{
|
||||||
|
hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
if ((ui = MsiSetInternalUI(V_I4(&varg0), NULL) == INSTALLUILEVEL_NOCHANGE))
|
||||||
|
{
|
||||||
|
ERR("MsiSetInternalUI failed\n");
|
||||||
|
return DISP_E_EXCEPTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (wFlags & DISPATCH_PROPERTYGET)
|
||||||
|
{
|
||||||
|
if ((ui = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL) == INSTALLUILEVEL_NOCHANGE))
|
||||||
|
{
|
||||||
|
ERR("MsiSetInternalUI failed\n");
|
||||||
|
return DISP_E_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
V_VT(pVarResult) = VT_I4;
|
||||||
|
V_I4(pVarResult) = ui;
|
||||||
|
}
|
||||||
|
else return DISP_E_MEMBERNOTFOUND;
|
||||||
|
break;
|
||||||
|
|
||||||
case DISPID_INSTALLER_INSTALLPRODUCT:
|
case DISPID_INSTALLER_INSTALLPRODUCT:
|
||||||
if (wFlags & DISPATCH_METHOD)
|
if (wFlags & DISPATCH_METHOD)
|
||||||
{
|
{
|
||||||
|
@ -1685,6 +1714,11 @@ static HRESULT WINAPI InstallerImpl_Invoke(
|
||||||
VariantClear(&varg1);
|
VariantClear(&varg1);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (V_I4(&varg0) >= REG_INDEX_CLASSES_ROOT &&
|
||||||
|
V_I4(&varg0) <= REG_INDEX_DYN_DATA)
|
||||||
|
V_I4(&varg0) |= (UINT)HKEY_CLASSES_ROOT;
|
||||||
|
|
||||||
ret = RegOpenKeyW((HKEY)V_I4(&varg0), V_BSTR(&varg1), &hkey);
|
ret = RegOpenKeyW((HKEY)V_I4(&varg0), V_BSTR(&varg1), &hkey);
|
||||||
|
|
||||||
/* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
|
/* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
|
||||||
|
|
|
@ -317,7 +317,11 @@ value_i:
|
||||||
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
|
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
|
||||||
|
|
||||||
MSI_GetFeatureStateW(cond->package, $2, &install, &action );
|
MSI_GetFeatureStateW(cond->package, $2, &install, &action );
|
||||||
$$ = action;
|
if (action == INSTALLSTATE_UNKNOWN)
|
||||||
|
$$ = MSICONDITION_FALSE;
|
||||||
|
else
|
||||||
|
$$ = action;
|
||||||
|
|
||||||
msi_free( $2 );
|
msi_free( $2 );
|
||||||
}
|
}
|
||||||
| COND_EXCLAM identifier
|
| COND_EXCLAM identifier
|
||||||
|
|
|
@ -331,6 +331,9 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
|
||||||
msi_free(deformated);
|
msi_free(deformated);
|
||||||
break;
|
break;
|
||||||
case 51: /* Property set with formatted text. */
|
case 51: /* Property set with formatted text. */
|
||||||
|
if (!source)
|
||||||
|
break;
|
||||||
|
|
||||||
deformat_string(package,target,&deformated);
|
deformat_string(package,target,&deformated);
|
||||||
rc = MSI_SetPropertyW(package,source,deformated);
|
rc = MSI_SetPropertyW(package,source,deformated);
|
||||||
msi_free(deformated);
|
msi_free(deformated);
|
||||||
|
@ -857,12 +860,6 @@ static UINT HANDLE_CustomType23(MSIPACKAGE *package, LPCWSTR source,
|
||||||
lstrcatW(package_path, backslash);
|
lstrcatW(package_path, backslash);
|
||||||
lstrcatW(package_path, source);
|
lstrcatW(package_path, source);
|
||||||
|
|
||||||
if (GetFileAttributesW(package_path) == INVALID_FILE_ATTRIBUTES)
|
|
||||||
{
|
|
||||||
ERR("Source package does not exist: %s\n", debugstr_w(package_path));
|
|
||||||
return ERROR_FUNCTION_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("Installing package %s concurrently\n", debugstr_w(package_path));
|
TRACE("Installing package %s concurrently\n", debugstr_w(package_path));
|
||||||
|
|
||||||
info = do_msidbCAConcurrentInstall(package, type, package_path, target, action);
|
info = do_msidbCAConcurrentInstall(package, type, package_path, target, action);
|
||||||
|
|
|
@ -317,12 +317,18 @@ static void msi_parse_line(LPWSTR *line, LPWSTR **entries, DWORD *num_entries)
|
||||||
/* store pointers into the data */
|
/* store pointers into the data */
|
||||||
for (i = 0, ptr = *line; i < count; i++)
|
for (i = 0, ptr = *line; i < count; i++)
|
||||||
{
|
{
|
||||||
|
while (*ptr && *ptr == '\r') ptr++;
|
||||||
save = ptr;
|
save = ptr;
|
||||||
|
|
||||||
while (*ptr && *ptr != '\t' && *ptr != '\n') ptr++;
|
while (*ptr && *ptr != '\t' && *ptr != '\n' && *ptr != '\r') ptr++;
|
||||||
|
|
||||||
/* NULL-separate the data */
|
/* NULL-separate the data */
|
||||||
if (*ptr)
|
if (*ptr == '\n' || *ptr == '\r')
|
||||||
|
{
|
||||||
|
while (*ptr == '\n' || *ptr == '\r')
|
||||||
|
*(ptr++) = '\0';
|
||||||
|
}
|
||||||
|
else if (*ptr)
|
||||||
*ptr++ = '\0';
|
*ptr++ = '\0';
|
||||||
|
|
||||||
(*entries)[i] = save;
|
(*entries)[i] = save;
|
||||||
|
@ -342,7 +348,7 @@ static LPWSTR msi_build_createsql_prelude(LPWSTR table)
|
||||||
|
|
||||||
static const WCHAR create_fmt[] = {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','%','s','`',' ','(',' ',0};
|
static const WCHAR create_fmt[] = {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','%','s','`',' ','(',' ',0};
|
||||||
|
|
||||||
size = sizeof(create_fmt) + lstrlenW(table) - 2;
|
size = sizeof(create_fmt)/sizeof(create_fmt[0]) + lstrlenW(table) - 2;
|
||||||
prelude = msi_alloc(size * sizeof(WCHAR));
|
prelude = msi_alloc(size * sizeof(WCHAR));
|
||||||
if (!prelude)
|
if (!prelude)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -509,156 +515,88 @@ static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LPWSTR msi_build_insertsql_prelude(LPWSTR table)
|
static UINT construct_record(DWORD num_columns, LPWSTR *types,
|
||||||
|
LPWSTR *data, MSIRECORD **rec)
|
||||||
{
|
{
|
||||||
LPWSTR prelude;
|
UINT i;
|
||||||
DWORD size;
|
|
||||||
|
|
||||||
static const WCHAR insert_fmt[] = {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','%','s','`',' ','(',' ',0};
|
*rec = MSI_CreateRecord(num_columns);
|
||||||
|
if (!*rec)
|
||||||
size = sizeof(insert_fmt) + lstrlenW(table) - 2;
|
return ERROR_OUTOFMEMORY;
|
||||||
prelude = msi_alloc(size * sizeof(WCHAR));
|
|
||||||
if (!prelude)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
sprintfW(prelude, insert_fmt, table);
|
|
||||||
return prelude;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LPWSTR msi_build_insertsql_columns(LPWSTR *columns_data, LPWSTR *types, DWORD num_columns)
|
|
||||||
{
|
|
||||||
LPWSTR columns, p;
|
|
||||||
DWORD sql_size = 1, i;
|
|
||||||
WCHAR expanded[128];
|
|
||||||
|
|
||||||
static const WCHAR column_fmt[] = {'`','%','s','`',',',' ',0};
|
|
||||||
|
|
||||||
columns = msi_alloc_zero(sql_size * sizeof(WCHAR));
|
|
||||||
if (!columns)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < num_columns; i++)
|
|
||||||
{
|
|
||||||
sprintfW(expanded, column_fmt, columns_data[i]);
|
|
||||||
sql_size += lstrlenW(expanded);
|
|
||||||
|
|
||||||
if (i == num_columns - 1)
|
|
||||||
{
|
|
||||||
sql_size -= 2;
|
|
||||||
expanded[lstrlenW(expanded) - 2] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
p = msi_realloc(columns, sql_size * sizeof(WCHAR));
|
|
||||||
if (!p)
|
|
||||||
{
|
|
||||||
msi_free(columns);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
columns = p;
|
|
||||||
|
|
||||||
lstrcatW(columns, expanded);
|
|
||||||
}
|
|
||||||
|
|
||||||
return columns;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LPWSTR msi_build_insertsql_data(LPWSTR **records, LPWSTR *types, DWORD num_columns, DWORD irec)
|
|
||||||
{
|
|
||||||
LPWSTR columns, temp_columns;
|
|
||||||
DWORD sql_size = 1, i;
|
|
||||||
WCHAR expanded[128];
|
|
||||||
|
|
||||||
static const WCHAR str_fmt[] = {'\'','%','s','\'',',',' ',0};
|
|
||||||
static const WCHAR int_fmt[] = {'%','s',',',' ',0};
|
|
||||||
static const WCHAR empty[] = {'\'','\'',',',' ',0};
|
|
||||||
|
|
||||||
columns = msi_alloc_zero(sql_size * sizeof(WCHAR));
|
|
||||||
if (!columns)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < num_columns; i++)
|
for (i = 0; i < num_columns; i++)
|
||||||
{
|
{
|
||||||
switch (types[i][0])
|
switch (types[i][0])
|
||||||
{
|
{
|
||||||
case 'L': case 'l': case 'S': case 's':
|
case 'L': case 'l': case 'S': case 's':
|
||||||
sprintfW(expanded, str_fmt, records[irec][i]);
|
MSI_RecordSetStringW(*rec, i + 1, data[i]);
|
||||||
break;
|
break;
|
||||||
case 'I': case 'i':
|
case 'I': case 'i':
|
||||||
if (*records[0][i])
|
if (*data[i])
|
||||||
sprintfW(expanded, int_fmt, records[irec][i]);
|
MSI_RecordSetInteger(*rec, i + 1, atoiW(data[i]));
|
||||||
else
|
|
||||||
lstrcpyW(expanded, empty);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
HeapFree( GetProcessHeap(), 0, columns );
|
ERR("Unhandled column type: %c\n", types[i][0]);
|
||||||
return NULL;
|
msiobj_release(&(*rec)->hdr);
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == num_columns - 1)
|
|
||||||
expanded[lstrlenW(expanded) - 2] = '\0';
|
|
||||||
|
|
||||||
sql_size += lstrlenW(expanded);
|
|
||||||
temp_columns = msi_realloc(columns, sql_size * sizeof(WCHAR));
|
|
||||||
if (!temp_columns)
|
|
||||||
{
|
|
||||||
HeapFree( GetProcessHeap(), 0, columns);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
columns = temp_columns;
|
|
||||||
|
|
||||||
lstrcatW(columns, expanded);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return columns;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
|
static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
|
||||||
LPWSTR *labels, LPWSTR **records,
|
LPWSTR *labels, LPWSTR **records,
|
||||||
int num_columns, int num_records)
|
int num_columns, int num_records)
|
||||||
{
|
{
|
||||||
|
UINT r;
|
||||||
|
DWORD i, size;
|
||||||
MSIQUERY *view;
|
MSIQUERY *view;
|
||||||
LPWSTR insert_sql;
|
MSIRECORD *rec;
|
||||||
DWORD size, i;
|
LPWSTR query;
|
||||||
UINT r = ERROR_SUCCESS;
|
|
||||||
|
|
||||||
static const WCHAR mid[] = {' ',')',' ','V','A','L','U','E','S',' ','(',' ',0};
|
static const WCHAR select[] = {
|
||||||
static const WCHAR end[] = {' ',')',0};
|
'S','E','L','E','C','T',' ','*',' ',
|
||||||
|
'F','R','O','M',' ','`','%','s','`',0
|
||||||
|
};
|
||||||
|
|
||||||
|
size = lstrlenW(select) + lstrlenW(labels[0]) - 1;
|
||||||
|
query = msi_alloc(size * sizeof(WCHAR));
|
||||||
|
if (!query)
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
|
sprintfW(query, select, labels[0]);
|
||||||
|
|
||||||
|
r = MSI_DatabaseOpenViewW(db, query, &view);
|
||||||
|
msi_free(query);
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
while (MSI_ViewFetch(view, &rec) != ERROR_NO_MORE_ITEMS)
|
||||||
|
{
|
||||||
|
r = MSI_ViewModify(view, MSIMODIFY_DELETE, rec);
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
LPWSTR prelude = msi_build_insertsql_prelude(labels[0]);
|
|
||||||
LPWSTR columns_sql = msi_build_insertsql_columns(columns, types, num_columns);
|
|
||||||
|
|
||||||
for (i = 0; i < num_records; i++)
|
for (i = 0; i < num_records; i++)
|
||||||
{
|
{
|
||||||
LPWSTR data = msi_build_insertsql_data(records, types, num_columns, i);
|
r = construct_record(num_columns, types, records[i], &rec);
|
||||||
|
|
||||||
size = lstrlenW(prelude) + lstrlenW(columns_sql) + sizeof(mid) + lstrlenW(data) + sizeof(end) - 1;
|
|
||||||
insert_sql = msi_alloc(size * sizeof(WCHAR));
|
|
||||||
if (!insert_sql)
|
|
||||||
return ERROR_OUTOFMEMORY;
|
|
||||||
|
|
||||||
lstrcpyW(insert_sql, prelude);
|
|
||||||
lstrcatW(insert_sql, columns_sql);
|
|
||||||
lstrcatW(insert_sql, mid);
|
|
||||||
lstrcatW(insert_sql, data);
|
|
||||||
lstrcatW(insert_sql, end);
|
|
||||||
|
|
||||||
msi_free(data);
|
|
||||||
|
|
||||||
r = MSI_DatabaseOpenViewW( db, insert_sql, &view );
|
|
||||||
msi_free(insert_sql);
|
|
||||||
|
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
r = MSI_ViewExecute(view, NULL);
|
r = MSI_ViewModify(view, MSIMODIFY_INSERT, rec);
|
||||||
MSI_ViewClose(view);
|
if (r != ERROR_SUCCESS)
|
||||||
msiobj_release(&view->hdr);
|
{
|
||||||
|
msiobj_release(&rec->hdr);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
msiobj_release(&rec->hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
msi_free(prelude);
|
msiobj_release(&view->hdr);
|
||||||
msi_free(columns_sql);
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,11 +604,11 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
||||||
{
|
{
|
||||||
UINT r;
|
UINT r;
|
||||||
DWORD len, i;
|
DWORD len, i;
|
||||||
DWORD num_labels;
|
DWORD num_labels, num_types;
|
||||||
DWORD num_columns, num_records = 0;
|
DWORD num_columns, num_records = 0;
|
||||||
LPWSTR *columns, *types, *labels;
|
LPWSTR *columns, *types, *labels;
|
||||||
LPWSTR path, ptr, data;
|
LPWSTR path, ptr, data;
|
||||||
LPWSTR **records;
|
LPWSTR **records = NULL;
|
||||||
LPWSTR **temp_records;
|
LPWSTR **temp_records;
|
||||||
|
|
||||||
static const WCHAR backslash[] = {'\\',0};
|
static const WCHAR backslash[] = {'\\',0};
|
||||||
|
@ -693,9 +631,15 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
||||||
|
|
||||||
ptr = data;
|
ptr = data;
|
||||||
msi_parse_line( &ptr, &columns, &num_columns );
|
msi_parse_line( &ptr, &columns, &num_columns );
|
||||||
msi_parse_line( &ptr, &types, NULL );
|
msi_parse_line( &ptr, &types, &num_types );
|
||||||
msi_parse_line( &ptr, &labels, &num_labels );
|
msi_parse_line( &ptr, &labels, &num_labels );
|
||||||
|
|
||||||
|
if (num_columns != num_types)
|
||||||
|
{
|
||||||
|
r = ERROR_FUNCTION_FAILED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
records = msi_alloc(sizeof(LPWSTR *));
|
records = msi_alloc(sizeof(LPWSTR *));
|
||||||
if (!records)
|
if (!records)
|
||||||
{
|
{
|
||||||
|
@ -718,9 +662,15 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
||||||
records = temp_records;
|
records = temp_records;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns );
|
if (!TABLE_Exists(db, labels[0]))
|
||||||
if (r != ERROR_SUCCESS)
|
{
|
||||||
goto done;
|
r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
r = ERROR_FUNCTION_FAILED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records );
|
r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records );
|
||||||
|
|
||||||
|
@ -849,12 +799,29 @@ static UINT msi_export_row( MSIRECORD *row, void *arg )
|
||||||
return msi_export_record( arg, row, 1 );
|
return msi_export_record( arg, row, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT msi_export_forcecodepage( HANDLE handle )
|
||||||
|
{
|
||||||
|
DWORD sz;
|
||||||
|
|
||||||
|
static const char data[] = "\r\n\r\n0\t_ForceCodepage\r\n";
|
||||||
|
|
||||||
|
FIXME("Read the codepage from the strings table!\n");
|
||||||
|
|
||||||
|
sz = lstrlenA(data) + 1;
|
||||||
|
if (!WriteFile(handle, data, sz, &sz, NULL))
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
||||||
LPCWSTR folder, LPCWSTR file )
|
LPCWSTR folder, LPCWSTR file )
|
||||||
{
|
{
|
||||||
static const WCHAR query[] = {
|
static const WCHAR query[] = {
|
||||||
's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','%','s',0 };
|
's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','%','s',0 };
|
||||||
static const WCHAR szbs[] = { '\\', 0 };
|
static const WCHAR szbs[] = { '\\', 0 };
|
||||||
|
static const WCHAR forcecodepage[] = {
|
||||||
|
'_','F','o','r','c','e','C','o','d','e','p','a','g','e',0 };
|
||||||
MSIRECORD *rec = NULL;
|
MSIRECORD *rec = NULL;
|
||||||
MSIQUERY *view = NULL;
|
MSIQUERY *view = NULL;
|
||||||
LPWSTR filename;
|
LPWSTR filename;
|
||||||
|
@ -882,6 +849,12 @@ UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
if (!lstrcmpW( table, forcecodepage ))
|
||||||
|
{
|
||||||
|
r = msi_export_forcecodepage( handle );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
r = MSI_OpenQuery( db, &view, query, table );
|
r = MSI_OpenQuery( db, &view, query, table );
|
||||||
if (r == ERROR_SUCCESS)
|
if (r == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -915,8 +888,8 @@ UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
||||||
msiobj_release( &view->hdr );
|
msiobj_release( &view->hdr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
CloseHandle( handle );
|
CloseHandle( handle );
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1079,32 +1052,32 @@ static ULONG WINAPI mrd_Release( IWineMsiRemoteDatabase *iface )
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrd_IsTablePersistent( IWineMsiRemoteDatabase *iface,
|
static HRESULT WINAPI mrd_IsTablePersistent( IWineMsiRemoteDatabase *iface,
|
||||||
BSTR table, MSICONDITION *persistent )
|
BSTR table, MSICONDITION *persistent )
|
||||||
{
|
{
|
||||||
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
||||||
*persistent = MsiDatabaseIsTablePersistentW(This->database, (LPWSTR)table);
|
*persistent = MsiDatabaseIsTablePersistentW(This->database, (LPWSTR)table);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrd_GetPrimaryKeys( IWineMsiRemoteDatabase *iface,
|
static HRESULT WINAPI mrd_GetPrimaryKeys( IWineMsiRemoteDatabase *iface,
|
||||||
BSTR table, MSIHANDLE *keys )
|
BSTR table, MSIHANDLE *keys )
|
||||||
{
|
{
|
||||||
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
||||||
UINT r = MsiDatabaseGetPrimaryKeysW(This->database, (LPWSTR)table, keys);
|
UINT r = MsiDatabaseGetPrimaryKeysW(This->database, (LPWSTR)table, keys);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrd_GetSummaryInformation( IWineMsiRemoteDatabase *iface,
|
static HRESULT WINAPI mrd_GetSummaryInformation( IWineMsiRemoteDatabase *iface,
|
||||||
UINT updatecount, MSIHANDLE *suminfo )
|
UINT updatecount, MSIHANDLE *suminfo )
|
||||||
{
|
{
|
||||||
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
||||||
UINT r = MsiGetSummaryInformationW(This->database, NULL, updatecount, suminfo);
|
UINT r = MsiGetSummaryInformationW(This->database, NULL, updatecount, suminfo);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrd_OpenView( IWineMsiRemoteDatabase *iface,
|
static HRESULT WINAPI mrd_OpenView( IWineMsiRemoteDatabase *iface,
|
||||||
BSTR query, MSIHANDLE *view )
|
BSTR query, MSIHANDLE *view )
|
||||||
{
|
{
|
||||||
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
||||||
UINT r = MsiDatabaseOpenViewW(This->database, (LPWSTR)query, view);
|
UINT r = MsiDatabaseOpenViewW(This->database, (LPWSTR)query, view);
|
||||||
|
|
|
@ -50,12 +50,14 @@ extern HINSTANCE msi_hInstance;
|
||||||
struct msi_control_tag;
|
struct msi_control_tag;
|
||||||
typedef struct msi_control_tag msi_control;
|
typedef struct msi_control_tag msi_control;
|
||||||
typedef UINT (*msi_handler)( msi_dialog *, msi_control *, WPARAM );
|
typedef UINT (*msi_handler)( msi_dialog *, msi_control *, WPARAM );
|
||||||
|
typedef void (*msi_update)( msi_dialog *, msi_control * );
|
||||||
|
|
||||||
struct msi_control_tag
|
struct msi_control_tag
|
||||||
{
|
{
|
||||||
struct list entry;
|
struct list entry;
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
msi_handler handler;
|
msi_handler handler;
|
||||||
|
msi_update update;
|
||||||
LPWSTR property;
|
LPWSTR property;
|
||||||
LPWSTR value;
|
LPWSTR value;
|
||||||
HBITMAP hBitmap;
|
HBITMAP hBitmap;
|
||||||
|
@ -564,6 +566,16 @@ static HICON msi_load_icon( MSIDATABASE *db, LPCWSTR text, UINT attributes )
|
||||||
return msi_load_image( db, text, IMAGE_ICON, cx, cy, flags );
|
return msi_load_image( db, text, IMAGE_ICON, cx, cy, flags );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void msi_dialog_update_controls( msi_dialog *dialog, LPCWSTR property )
|
||||||
|
{
|
||||||
|
msi_control *control;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY( control, &dialog->controls, msi_control, entry )
|
||||||
|
{
|
||||||
|
if ( !lstrcmpW( control->property, property ) && control->update )
|
||||||
|
control->update( dialog, control );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* called from the Control Event subscription code */
|
/* called from the Control Event subscription code */
|
||||||
void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
|
void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
|
||||||
|
@ -855,6 +867,7 @@ static UINT msi_dialog_checkbox_control( msi_dialog *dialog, MSIRECORD *rec )
|
||||||
control = msi_dialog_add_control( dialog, rec, szButton,
|
control = msi_dialog_add_control( dialog, rec, szButton,
|
||||||
BS_CHECKBOX | BS_MULTILINE | WS_TABSTOP );
|
BS_CHECKBOX | BS_MULTILINE | WS_TABSTOP );
|
||||||
control->handler = msi_dialog_checkbox_handler;
|
control->handler = msi_dialog_checkbox_handler;
|
||||||
|
control->update = msi_dialog_checkbox_sync_state;
|
||||||
prop = MSI_RecordGetString( rec, 9 );
|
prop = MSI_RecordGetString( rec, 9 );
|
||||||
if( prop )
|
if( prop )
|
||||||
{
|
{
|
||||||
|
@ -2904,7 +2917,7 @@ static MSIRECORD *msi_get_dialog_record( msi_dialog *dialog )
|
||||||
|
|
||||||
rec = MSI_QueryGetRecord( package->db, query, dialog->name );
|
rec = MSI_QueryGetRecord( package->db, query, dialog->name );
|
||||||
if( !rec )
|
if( !rec )
|
||||||
ERR("query failed for dialog %s\n", debugstr_w(dialog->name));
|
WARN("query failed for dialog %s\n", debugstr_w(dialog->name));
|
||||||
|
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
|
@ -3083,6 +3096,7 @@ static UINT msi_dialog_set_property( msi_dialog *dialog, LPCWSTR event, LPCWSTR
|
||||||
if( strcmpW( szNullArg, arg ) )
|
if( strcmpW( szNullArg, arg ) )
|
||||||
deformat_string( dialog->package, arg, &arg_fmt );
|
deformat_string( dialog->package, arg, &arg_fmt );
|
||||||
MSI_SetPropertyW( dialog->package, prop, arg_fmt );
|
MSI_SetPropertyW( dialog->package, prop, arg_fmt );
|
||||||
|
msi_dialog_update_controls( dialog, prop );
|
||||||
msi_free( arg_fmt );
|
msi_free( arg_fmt );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -18,11 +18,6 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/controlevent_overview.asp
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
|
||||||
|
|
||||||
struct media_info {
|
struct media_info {
|
||||||
UINT disk_id;
|
UINT disk_id;
|
||||||
|
UINT type;
|
||||||
UINT last_sequence;
|
UINT last_sequence;
|
||||||
LPWSTR disk_prompt;
|
LPWSTR disk_prompt;
|
||||||
LPWSTR cabinet;
|
LPWSTR cabinet;
|
||||||
|
@ -400,10 +401,13 @@ static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
|
||||||
}
|
}
|
||||||
case fdintCLOSE_FILE_INFO:
|
case fdintCLOSE_FILE_INFO:
|
||||||
{
|
{
|
||||||
|
CabData *data = (CabData*) pfdin->pv;
|
||||||
FILETIME ft;
|
FILETIME ft;
|
||||||
FILETIME ftLocal;
|
FILETIME ftLocal;
|
||||||
HANDLE handle = (HANDLE) pfdin->hf;
|
HANDLE handle = (HANDLE) pfdin->hf;
|
||||||
|
|
||||||
|
data->mi->is_continuous = FALSE;
|
||||||
|
|
||||||
if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft))
|
if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft))
|
||||||
return -1;
|
return -1;
|
||||||
if (!LocalFileTimeToFileTime(&ft, &ftLocal))
|
if (!LocalFileTimeToFileTime(&ft, &ftLocal))
|
||||||
|
@ -504,6 +508,8 @@ static UINT load_media_info(MSIPACKAGE *package, MSIFILE *file, struct media_inf
|
||||||
{
|
{
|
||||||
MSIRECORD *row;
|
MSIRECORD *row;
|
||||||
LPWSTR source_dir;
|
LPWSTR source_dir;
|
||||||
|
LPWSTR source;
|
||||||
|
DWORD options;
|
||||||
UINT r;
|
UINT r;
|
||||||
|
|
||||||
static const WCHAR query[] = {
|
static const WCHAR query[] = {
|
||||||
|
@ -539,6 +545,9 @@ static UINT load_media_info(MSIPACKAGE *package, MSIFILE *file, struct media_inf
|
||||||
source_dir = msi_dup_property(package, cszSourceDir);
|
source_dir = msi_dup_property(package, cszSourceDir);
|
||||||
lstrcpyW(mi->source, source_dir);
|
lstrcpyW(mi->source, source_dir);
|
||||||
|
|
||||||
|
PathStripToRootW(source_dir);
|
||||||
|
mi->type = GetDriveTypeW(source_dir);
|
||||||
|
|
||||||
if (file->IsCompressed && mi->cabinet)
|
if (file->IsCompressed && mi->cabinet)
|
||||||
{
|
{
|
||||||
if (mi->cabinet[0] == '#')
|
if (mi->cabinet[0] == '#')
|
||||||
|
@ -554,17 +563,77 @@ static UINT load_media_info(MSIPACKAGE *package, MSIFILE *file, struct media_inf
|
||||||
lstrcatW(mi->source, mi->cabinet);
|
lstrcatW(mi->source, mi->cabinet);
|
||||||
}
|
}
|
||||||
|
|
||||||
msi_package_add_media_disk(package, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
|
options = MSICODE_PRODUCT;
|
||||||
mi->disk_id, mi->volume_label, mi->disk_prompt);
|
if (mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE)
|
||||||
|
{
|
||||||
|
source = source_dir;
|
||||||
|
options |= MSISOURCETYPE_MEDIA;
|
||||||
|
}
|
||||||
|
else if (package->BaseURL && UrlIsW(package->BaseURL, URLIS_URL))
|
||||||
|
{
|
||||||
|
source = package->BaseURL;
|
||||||
|
options |= MSISOURCETYPE_URL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
source = mi->source;
|
||||||
|
options |= MSISOURCETYPE_NETWORK;
|
||||||
|
}
|
||||||
|
|
||||||
msi_package_add_info(package, MSIINSTALLCONTEXT_USERMANAGED,
|
if (mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE)
|
||||||
MSICODE_PRODUCT | MSISOURCETYPE_MEDIA,
|
msi_package_add_media_disk(package, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||||
INSTALLPROPERTY_LASTUSEDSOURCEW, mi->source);
|
MSICODE_PRODUCT, mi->disk_id,
|
||||||
|
mi->volume_label, mi->disk_prompt);
|
||||||
|
|
||||||
|
msi_package_add_info(package, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||||
|
options, INSTALLPROPERTY_LASTUSEDSOURCEW, source);
|
||||||
|
|
||||||
msi_free(source_dir);
|
msi_free(source_dir);
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: search NETWORK and URL sources as well */
|
||||||
|
static UINT find_published_source(MSIPACKAGE *package, struct media_info *mi)
|
||||||
|
{
|
||||||
|
WCHAR source[MAX_PATH];
|
||||||
|
WCHAR volume[MAX_PATH];
|
||||||
|
WCHAR prompt[MAX_PATH];
|
||||||
|
DWORD volumesz, promptsz;
|
||||||
|
DWORD index, size, id;
|
||||||
|
UINT r;
|
||||||
|
|
||||||
|
r = MsiSourceListGetInfoW(package->ProductCode, NULL,
|
||||||
|
MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
|
||||||
|
INSTALLPROPERTY_LASTUSEDSOURCEW, source, &size);
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
volumesz = MAX_PATH;
|
||||||
|
promptsz = MAX_PATH;
|
||||||
|
while (MsiSourceListEnumMediaDisksW(package->ProductCode, NULL,
|
||||||
|
MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||||
|
MSICODE_PRODUCT, index++, &id,
|
||||||
|
volume, &volumesz, prompt, &promptsz) == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
mi->disk_id = id;
|
||||||
|
mi->volume_label = msi_realloc(mi->volume_label, ++volumesz * sizeof(WCHAR));
|
||||||
|
lstrcpyW(mi->volume_label, volume);
|
||||||
|
mi->disk_prompt = msi_realloc(mi->disk_prompt, ++promptsz * sizeof(WCHAR));
|
||||||
|
lstrcpyW(mi->disk_prompt, prompt);
|
||||||
|
|
||||||
|
if (source_matches_volume(mi, source))
|
||||||
|
{
|
||||||
|
/* FIXME: what about SourceDir */
|
||||||
|
lstrcpyW(mi->source, source);
|
||||||
|
lstrcatW(mi->source, mi->cabinet);
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
static UINT ready_media(MSIPACKAGE *package, MSIFILE *file, struct media_info *mi)
|
static UINT ready_media(MSIPACKAGE *package, MSIFILE *file, struct media_info *mi)
|
||||||
{
|
{
|
||||||
UINT rc = ERROR_SUCCESS;
|
UINT rc = ERROR_SUCCESS;
|
||||||
|
@ -602,14 +671,11 @@ static UINT ready_media(MSIPACKAGE *package, MSIFILE *file, struct media_info *m
|
||||||
{
|
{
|
||||||
LPWSTR source = msi_dup_property(package, cszSourceDir);
|
LPWSTR source = msi_dup_property(package, cszSourceDir);
|
||||||
BOOL matches;
|
BOOL matches;
|
||||||
UINT type;
|
|
||||||
|
|
||||||
PathStripToRootW(source);
|
|
||||||
type = GetDriveTypeW(source);
|
|
||||||
matches = source_matches_volume(mi, source);
|
matches = source_matches_volume(mi, source);
|
||||||
msi_free(source);
|
msi_free(source);
|
||||||
|
|
||||||
if ((type == DRIVE_CDROM || type == DRIVE_REMOVABLE) && !matches)
|
if ((mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE) && !matches)
|
||||||
{
|
{
|
||||||
rc = msi_change_media(package, mi);
|
rc = msi_change_media(package, mi);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
|
@ -620,8 +686,13 @@ static UINT ready_media(MSIPACKAGE *package, MSIFILE *file, struct media_info *m
|
||||||
if (file->IsCompressed &&
|
if (file->IsCompressed &&
|
||||||
GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES)
|
GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES)
|
||||||
{
|
{
|
||||||
ERR("Cabinet not found: %s\n", debugstr_w(mi->source));
|
/* FIXME: this might be done earlier in the install process */
|
||||||
return ERROR_INSTALL_FAILURE;
|
rc = find_published_source(package, mi);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("Cabinet not found: %s\n", debugstr_w(mi->source));
|
||||||
|
return ERROR_INSTALL_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
@ -739,21 +810,11 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||||
{
|
{
|
||||||
struct media_info *mi;
|
struct media_info *mi;
|
||||||
UINT rc = ERROR_SUCCESS;
|
UINT rc = ERROR_SUCCESS;
|
||||||
LPWSTR ptr;
|
|
||||||
MSIFILE *file;
|
MSIFILE *file;
|
||||||
|
|
||||||
/* increment progress bar each time action data is sent */
|
/* increment progress bar each time action data is sent */
|
||||||
ui_progress(package,1,1,0,0);
|
ui_progress(package,1,1,0,0);
|
||||||
|
|
||||||
/* handle the keys for the SourceList */
|
|
||||||
ptr = strrchrW(package->PackagePath,'\\');
|
|
||||||
if (ptr)
|
|
||||||
{
|
|
||||||
ptr++;
|
|
||||||
msi_package_add_info(package, MSIINSTALLCONTEXT_USERMANAGED,
|
|
||||||
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
schedule_install_files(package);
|
schedule_install_files(package);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -346,7 +346,7 @@ static LPWSTR build_default_format(const MSIRECORD* record)
|
||||||
sprintfW(index, fmt_index, i);
|
sprintfW(index, fmt_index, i);
|
||||||
str = MSI_RecordGetString(record, i);
|
str = MSI_RecordGetString(record, i);
|
||||||
len = (str) ? lstrlenW(str) : 0;
|
len = (str) ? lstrlenW(str) : 0;
|
||||||
len += (sizeof(fmt_null) - 3) + lstrlenW(index);
|
len += (sizeof(fmt_null)/sizeof(fmt_null[0]) - 3) + lstrlenW(index);
|
||||||
size += len;
|
size += len;
|
||||||
|
|
||||||
if (len > max_len)
|
if (len > max_len)
|
||||||
|
@ -544,6 +544,10 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
|
||||||
format->deformatted = str;
|
format->deformatted = str;
|
||||||
format->len = size - 1;
|
format->len = size - 1;
|
||||||
|
|
||||||
|
/* don't reformat the NULL */
|
||||||
|
if (replace && !*replace)
|
||||||
|
format->n++;
|
||||||
|
|
||||||
if (!replace)
|
if (!replace)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -727,9 +731,6 @@ static UINT replace_stack(FORMAT *format, STACK *stack, STACK *values)
|
||||||
msi_free(replaced);
|
msi_free(replaced);
|
||||||
format->n = beg->n + beg->len;
|
format->n = beg->n + beg->len;
|
||||||
|
|
||||||
if (type == FORMAT_PROPNULL)
|
|
||||||
format->n++;
|
|
||||||
|
|
||||||
top = stack_peek(stack);
|
top = stack_peek(stack);
|
||||||
if (top)
|
if (top)
|
||||||
{
|
{
|
||||||
|
|
|
@ -77,7 +77,7 @@ static UINT JOIN_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *v
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_rows = table->rows;
|
prev_rows *= table->rows;
|
||||||
cols += table->columns;
|
cols += table->columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ static UINT JOIN_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStr
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_rows = table->rows;
|
prev_rows *= table->rows;
|
||||||
cols += table->columns;
|
cols += table->columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,7 +341,8 @@ UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables )
|
||||||
r = TABLE_CreateView( db, tables, &table->view );
|
r = TABLE_CreateView( db, tables, &table->view );
|
||||||
if( r != ERROR_SUCCESS )
|
if( r != ERROR_SUCCESS )
|
||||||
{
|
{
|
||||||
ERR("can't create table\n");
|
WARN("can't create table: %s\n", debugstr_w(tables));
|
||||||
|
r = ERROR_BAD_QUERY_SYNTAX;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -365,12 +365,12 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
sz = sizeof(sourcepath);
|
sz = sizeof(sourcepath);
|
||||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||||
MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath,
|
MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath,
|
||||||
&sz);
|
&sz);
|
||||||
|
|
||||||
sz = sizeof(filename);
|
sz = sizeof(filename);
|
||||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||||
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
|
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
|
||||||
|
|
||||||
lstrcatW(sourcepath,filename);
|
lstrcatW(sourcepath,filename);
|
||||||
|
@ -561,114 +561,193 @@ done:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type)
|
||||||
|
{
|
||||||
|
DWORD dval;
|
||||||
|
LONG res;
|
||||||
|
WCHAR temp[20];
|
||||||
|
|
||||||
|
static const WCHAR format[] = {'%','d',0};
|
||||||
|
|
||||||
|
res = RegQueryValueExW(hkey, name, NULL, type, NULL, NULL);
|
||||||
|
if (res != ERROR_SUCCESS)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (*type == REG_SZ)
|
||||||
|
return msi_reg_get_val_str(hkey, name);
|
||||||
|
|
||||||
|
if (!msi_reg_get_val_dword(hkey, name, &dval))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sprintfW(temp, format, dval);
|
||||||
|
return strdupW(temp);
|
||||||
|
}
|
||||||
|
|
||||||
static UINT WINAPI MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
|
static UINT WINAPI MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
|
||||||
awstring *szValue, LPDWORD pcchValueBuf)
|
awstring *szValue, LPDWORD pcchValueBuf)
|
||||||
{
|
{
|
||||||
UINT r;
|
UINT r = ERROR_UNKNOWN_PROPERTY;
|
||||||
HKEY hkey;
|
HKEY prodkey, userdata, source;
|
||||||
LPWSTR val = NULL;
|
LPWSTR val = NULL;
|
||||||
|
WCHAR squished_pc[GUID_SIZE];
|
||||||
|
WCHAR packagecode[GUID_SIZE];
|
||||||
|
BOOL classes = FALSE;
|
||||||
|
BOOL badconfig = FALSE;
|
||||||
|
LONG res;
|
||||||
|
DWORD save, type = REG_NONE;
|
||||||
|
|
||||||
|
static WCHAR empty[] = {0};
|
||||||
|
static const WCHAR sourcelist[] = {
|
||||||
|
'S','o','u','r','c','e','L','i','s','t',0};
|
||||||
|
static const WCHAR display_name[] = {
|
||||||
|
'D','i','s','p','l','a','y','N','a','m','e',0};
|
||||||
|
static const WCHAR display_version[] = {
|
||||||
|
'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
|
||||||
|
static const WCHAR assignment[] = {
|
||||||
|
'A','s','s','i','g','n','m','e','n','t',0};
|
||||||
|
|
||||||
TRACE("%s %s %p %p\n", debugstr_w(szProduct),
|
TRACE("%s %s %p %p\n", debugstr_w(szProduct),
|
||||||
debugstr_w(szAttribute), szValue, pcchValueBuf);
|
debugstr_w(szAttribute), szValue, pcchValueBuf);
|
||||||
|
|
||||||
/*
|
if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute)
|
||||||
* FIXME: Values seem scattered/duplicated in the registry. Is there a system?
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szProduct[0] || !szAttribute)
|
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
/* check for special properties */
|
if (!squash_guid(szProduct, squished_pc))
|
||||||
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
r = MSIREG_OpenLocalManagedProductKey(szProduct, &prodkey, FALSE);
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
LPWSTR regval;
|
r = MSIREG_OpenUserProductsKey(szProduct, &prodkey, FALSE);
|
||||||
WCHAR packagecode[35];
|
|
||||||
|
|
||||||
r = MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE);
|
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
return ERROR_UNKNOWN_PRODUCT;
|
|
||||||
|
|
||||||
regval = msi_reg_get_val_str( hkey, szAttribute );
|
|
||||||
if (regval)
|
|
||||||
{
|
{
|
||||||
if (unsquash_guid(regval, packagecode))
|
r = MSIREG_OpenLocalClassesProductKey(szProduct, &prodkey, FALSE);
|
||||||
val = strdupW(packagecode);
|
if (r == ERROR_SUCCESS)
|
||||||
msi_free(regval);
|
classes = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegCloseKey(hkey);
|
|
||||||
}
|
}
|
||||||
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
|
|
||||||
{
|
|
||||||
static const WCHAR one[] = { '1',0 };
|
|
||||||
/*
|
|
||||||
* FIXME: should be in the Product key (user or system?)
|
|
||||||
* but isn't written yet...
|
|
||||||
*/
|
|
||||||
val = strdupW( one );
|
|
||||||
}
|
|
||||||
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
|
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW))
|
|
||||||
{
|
|
||||||
static const WCHAR fmt[] = { '%','u',0 };
|
|
||||||
WCHAR szVal[16];
|
|
||||||
DWORD regval;
|
|
||||||
|
|
||||||
r = MSIREG_OpenUninstallKey(szProduct, &hkey, FALSE);
|
if (classes)
|
||||||
if (r != ERROR_SUCCESS)
|
MSIREG_OpenLocalSystemProductKey(szProduct, &userdata, FALSE);
|
||||||
return ERROR_UNKNOWN_PRODUCT;
|
|
||||||
|
|
||||||
if (msi_reg_get_val_dword( hkey, szAttribute, ®val))
|
|
||||||
{
|
|
||||||
sprintfW(szVal, fmt, regval);
|
|
||||||
val = strdupW( szVal );
|
|
||||||
}
|
|
||||||
|
|
||||||
RegCloseKey(hkey);
|
|
||||||
}
|
|
||||||
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW))
|
|
||||||
{
|
|
||||||
r = MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE);
|
|
||||||
if (r != ERROR_SUCCESS)
|
|
||||||
return ERROR_UNKNOWN_PRODUCT;
|
|
||||||
|
|
||||||
val = msi_reg_get_val_str( hkey, szAttribute );
|
|
||||||
|
|
||||||
RegCloseKey(hkey);
|
|
||||||
}
|
|
||||||
else if (!szAttribute[0])
|
|
||||||
{
|
|
||||||
return ERROR_UNKNOWN_PROPERTY;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
|
MSIREG_OpenInstallPropertiesKey(szProduct, &userdata, FALSE);
|
||||||
|
|
||||||
|
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPLINKW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPTELEPHONEW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLDATEW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLSOURCEW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_LOCALPACKAGEW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_PUBLISHERW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_URLINFOABOUTW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_URLUPDATEINFOW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMINORW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMAJORW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTIDW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_REGCOMPANYW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_REGOWNERW))
|
||||||
{
|
{
|
||||||
static const WCHAR szDisplayVersion[] = {
|
if (!prodkey)
|
||||||
'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0 };
|
{
|
||||||
|
r = ERROR_UNKNOWN_PRODUCT;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
FIXME("%s\n", debugstr_w(szAttribute));
|
if (!userdata)
|
||||||
/* FIXME: some attribute values not tested... */
|
return ERROR_UNKNOWN_PROPERTY;
|
||||||
|
|
||||||
if (!lstrcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ))
|
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
|
||||||
szAttribute = szDisplayVersion;
|
szAttribute = display_name;
|
||||||
|
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW))
|
||||||
|
szAttribute = display_version;
|
||||||
|
|
||||||
r = MSIREG_OpenUninstallKey( szProduct, &hkey, FALSE );
|
val = msi_reg_get_value(userdata, szAttribute, &type);
|
||||||
if (r != ERROR_SUCCESS)
|
if (!val)
|
||||||
return ERROR_UNKNOWN_PRODUCT;
|
val = empty;
|
||||||
|
|
||||||
val = msi_reg_get_val_str( hkey, szAttribute );
|
|
||||||
|
|
||||||
RegCloseKey(hkey);
|
|
||||||
}
|
}
|
||||||
|
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTANCETYPEW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_TRANSFORMSW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTICONW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW) ||
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
|
||||||
|
{
|
||||||
|
if (!prodkey)
|
||||||
|
{
|
||||||
|
r = ERROR_UNKNOWN_PRODUCT;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("returning %s\n", debugstr_w(val));
|
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
|
||||||
|
szAttribute = assignment;
|
||||||
|
|
||||||
|
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW))
|
||||||
|
{
|
||||||
|
res = RegOpenKeyW(prodkey, sourcelist, &source);
|
||||||
|
if (res == ERROR_SUCCESS)
|
||||||
|
val = msi_reg_get_value(source, szAttribute, &type);
|
||||||
|
|
||||||
|
RegCloseKey(source);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val = msi_reg_get_value(prodkey, szAttribute, &type);
|
||||||
|
if (!val)
|
||||||
|
val = empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val != empty && type != REG_DWORD &&
|
||||||
|
!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
|
||||||
|
{
|
||||||
|
if (lstrlenW(val) != SQUISH_GUID_SIZE - 1)
|
||||||
|
badconfig = TRUE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsquash_guid(val, packagecode);
|
||||||
|
msi_free(val);
|
||||||
|
val = strdupW(packagecode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!val)
|
if (!val)
|
||||||
return ERROR_UNKNOWN_PROPERTY;
|
{
|
||||||
|
r = ERROR_UNKNOWN_PROPERTY;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
r = msi_strcpy_to_awstring( val, szValue, pcchValueBuf );
|
if (pcchValueBuf)
|
||||||
|
{
|
||||||
|
save = *pcchValueBuf;
|
||||||
|
|
||||||
msi_free(val);
|
if (lstrlenW(val) < *pcchValueBuf)
|
||||||
|
r = msi_strcpy_to_awstring(val, szValue, pcchValueBuf);
|
||||||
|
else if (szValue->str.a || szValue->str.w)
|
||||||
|
r = ERROR_MORE_DATA;
|
||||||
|
|
||||||
|
if (!badconfig)
|
||||||
|
*pcchValueBuf = lstrlenW(val);
|
||||||
|
else if (r == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
*pcchValueBuf = save;
|
||||||
|
r = ERROR_BAD_CONFIGURATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (badconfig)
|
||||||
|
r = ERROR_BAD_CONFIGURATION;
|
||||||
|
|
||||||
|
if (val != empty)
|
||||||
|
msi_free(val);
|
||||||
|
|
||||||
|
done:
|
||||||
|
RegCloseKey(prodkey);
|
||||||
|
RegCloseKey(userdata);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -718,6 +797,292 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
|
||||||
&buffer, pcchValueBuf );
|
&buffer, pcchValueBuf );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT WINAPI MsiGetProductInfoExA(LPCSTR szProductCode, LPCSTR szUserSid,
|
||||||
|
MSIINSTALLCONTEXT dwContext, LPCSTR szProperty,
|
||||||
|
LPSTR szValue, LPDWORD pcchValue)
|
||||||
|
{
|
||||||
|
LPWSTR product = NULL;
|
||||||
|
LPWSTR usersid = NULL;
|
||||||
|
LPWSTR property = NULL;
|
||||||
|
LPWSTR value = NULL;
|
||||||
|
DWORD len = 0;
|
||||||
|
UINT r;
|
||||||
|
|
||||||
|
TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode),
|
||||||
|
debugstr_a(szUserSid), dwContext, debugstr_a(szProperty),
|
||||||
|
szValue, pcchValue);
|
||||||
|
|
||||||
|
if (szValue && !pcchValue)
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (szProductCode) product = strdupAtoW(szProductCode);
|
||||||
|
if (szUserSid) usersid = strdupAtoW(szUserSid);
|
||||||
|
if (szProperty) property = strdupAtoW(szProperty);
|
||||||
|
|
||||||
|
r = MsiGetProductInfoExW(product, usersid, dwContext, property,
|
||||||
|
NULL, &len);
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
value = msi_alloc(++len * sizeof(WCHAR));
|
||||||
|
if (!value)
|
||||||
|
{
|
||||||
|
r = ERROR_OUTOFMEMORY;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = MsiGetProductInfoExW(product, usersid, dwContext, property,
|
||||||
|
value, &len);
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (!pcchValue)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
|
||||||
|
if (*pcchValue >= len)
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
|
||||||
|
else if (szValue)
|
||||||
|
{
|
||||||
|
r = ERROR_MORE_DATA;
|
||||||
|
if (*pcchValue > 0)
|
||||||
|
*szValue = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*pcchValue <= len || !szValue)
|
||||||
|
len = len * sizeof(WCHAR) - 1;
|
||||||
|
|
||||||
|
*pcchValue = len - 1;
|
||||||
|
|
||||||
|
done:
|
||||||
|
msi_free(product);
|
||||||
|
msi_free(usersid);
|
||||||
|
msi_free(property);
|
||||||
|
msi_free(value);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT msi_copy_outval(LPWSTR val, LPWSTR out, LPDWORD size)
|
||||||
|
{
|
||||||
|
UINT r;
|
||||||
|
|
||||||
|
if (!val)
|
||||||
|
return ERROR_UNKNOWN_PROPERTY;
|
||||||
|
|
||||||
|
if (out)
|
||||||
|
{
|
||||||
|
if (lstrlenW(val) >= *size)
|
||||||
|
{
|
||||||
|
r = ERROR_MORE_DATA;
|
||||||
|
if (*size > 0)
|
||||||
|
*out = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
lstrcpyW(out, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size)
|
||||||
|
*size = lstrlenW(val);
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
|
||||||
|
MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty,
|
||||||
|
LPWSTR szValue, LPDWORD pcchValue)
|
||||||
|
{
|
||||||
|
WCHAR squished_pc[GUID_SIZE];
|
||||||
|
LPWSTR val = NULL;
|
||||||
|
LPCWSTR package = NULL;
|
||||||
|
HKEY props = NULL, prod;
|
||||||
|
HKEY classes = NULL, managed;
|
||||||
|
HKEY hkey = NULL;
|
||||||
|
DWORD type;
|
||||||
|
UINT r = ERROR_UNKNOWN_PRODUCT;
|
||||||
|
|
||||||
|
static const WCHAR one[] = {'1',0};
|
||||||
|
static const WCHAR five[] = {'5',0};
|
||||||
|
static const WCHAR empty[] = {0};
|
||||||
|
static const WCHAR displayname[] = {
|
||||||
|
'D','i','s','p','l','a','y','N','a','m','e',0};
|
||||||
|
static const WCHAR displayversion[] = {
|
||||||
|
'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
|
||||||
|
static const WCHAR managed_local_package[] = {
|
||||||
|
'M','a','n','a','g','e','d','L','o','c','a','l',
|
||||||
|
'P','a','c','k','a','g','e',0};
|
||||||
|
|
||||||
|
TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode),
|
||||||
|
debugstr_w(szUserSid), dwContext, debugstr_w(szProperty),
|
||||||
|
szValue, pcchValue);
|
||||||
|
|
||||||
|
if (!szProductCode || !squash_guid(szProductCode, squished_pc))
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (szValue && !pcchValue)
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
|
||||||
|
dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
|
||||||
|
dwContext != MSIINSTALLCONTEXT_MACHINE)
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (!szProperty || !*szProperty)
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
MSIREG_OpenLocalManagedProductKey(szProductCode, &managed, FALSE);
|
||||||
|
MSIREG_OpenUserProductsKey(szProductCode, &prod, FALSE);
|
||||||
|
|
||||||
|
if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
|
||||||
|
{
|
||||||
|
package = INSTALLPROPERTY_LOCALPACKAGEW;
|
||||||
|
MSIREG_OpenInstallPropertiesKey(szProductCode, &props, FALSE);
|
||||||
|
|
||||||
|
if (!props && !prod)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
|
||||||
|
{
|
||||||
|
package = managed_local_package;
|
||||||
|
MSIREG_OpenInstallPropertiesKey(szProductCode, &props, FALSE);
|
||||||
|
|
||||||
|
if (!props && !managed)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
|
||||||
|
{
|
||||||
|
package = INSTALLPROPERTY_LOCALPACKAGEW;
|
||||||
|
MSIREG_OpenLocalSystemProductKey(szProductCode, &props, FALSE);
|
||||||
|
MSIREG_OpenLocalClassesProductKey(szProductCode, &classes, FALSE);
|
||||||
|
|
||||||
|
if (!props && !classes)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lstrcmpW(szProperty, INSTALLPROPERTY_HELPLINKW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_HELPTELEPHONEW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLLOCATIONW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLSOURCEW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_PUBLISHERW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_URLINFOABOUTW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_URLUPDATEINFOW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMINORW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMAJORW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTIDW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_REGCOMPANYW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_REGOWNERW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTANCETYPEW))
|
||||||
|
{
|
||||||
|
val = msi_reg_get_value(props, package, &type);
|
||||||
|
if (!val)
|
||||||
|
{
|
||||||
|
if (prod || classes)
|
||||||
|
r = ERROR_UNKNOWN_PROPERTY;
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
msi_free(val);
|
||||||
|
|
||||||
|
if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
|
||||||
|
szProperty = displayname;
|
||||||
|
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW))
|
||||||
|
szProperty = displayversion;
|
||||||
|
|
||||||
|
val = msi_reg_get_value(props, szProperty, &type);
|
||||||
|
if (!val)
|
||||||
|
val = strdupW(empty);
|
||||||
|
|
||||||
|
r = msi_copy_outval(val, szValue, pcchValue);
|
||||||
|
}
|
||||||
|
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_LANGUAGEW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTNAMEW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGECODEW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTICONW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGENAMEW) ||
|
||||||
|
!lstrcmpW(szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
|
||||||
|
{
|
||||||
|
if (!prod && !classes)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
|
||||||
|
hkey = prod;
|
||||||
|
else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
|
||||||
|
hkey = managed;
|
||||||
|
else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
|
||||||
|
hkey = classes;
|
||||||
|
|
||||||
|
val = msi_reg_get_value(hkey, szProperty, &type);
|
||||||
|
if (!val)
|
||||||
|
val = strdupW(empty);
|
||||||
|
|
||||||
|
r = msi_copy_outval(val, szValue, pcchValue);
|
||||||
|
}
|
||||||
|
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTSTATEW))
|
||||||
|
{
|
||||||
|
if (dwContext == MSIINSTALLCONTEXT_MACHINE)
|
||||||
|
{
|
||||||
|
if (props)
|
||||||
|
{
|
||||||
|
val = msi_reg_get_value(props, package, &type);
|
||||||
|
if (!val)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
msi_free(val);
|
||||||
|
val = strdupW(five);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
val = strdupW(one);
|
||||||
|
|
||||||
|
r = msi_copy_outval(val, szValue, pcchValue);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else if (props && (val = msi_reg_get_value(props, package, &type)))
|
||||||
|
{
|
||||||
|
msi_free(val);
|
||||||
|
val = strdupW(five);
|
||||||
|
r = msi_copy_outval(val, szValue, pcchValue);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prod || managed)
|
||||||
|
val = strdupW(one);
|
||||||
|
else
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
r = msi_copy_outval(val, szValue, pcchValue);
|
||||||
|
}
|
||||||
|
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW))
|
||||||
|
{
|
||||||
|
if (!prod && !classes)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* FIME */
|
||||||
|
val = strdupW(empty);
|
||||||
|
r = msi_copy_outval(val, szValue, pcchValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
r = ERROR_UNKNOWN_PROPERTY;
|
||||||
|
|
||||||
|
done:
|
||||||
|
RegCloseKey(props);
|
||||||
|
RegCloseKey(prod);
|
||||||
|
RegCloseKey(managed);
|
||||||
|
RegCloseKey(classes);
|
||||||
|
msi_free(val);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
|
UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
|
||||||
{
|
{
|
||||||
LPWSTR szwLogFile = NULL;
|
LPWSTR szwLogFile = NULL;
|
||||||
|
@ -849,7 +1214,7 @@ static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
|
||||||
return (res == ERROR_SUCCESS);
|
return (res == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL msi_comp_find_prodcode(LPCWSTR prodcode, LPWSTR squished_pc,
|
static BOOL msi_comp_find_prodcode(LPWSTR squished_pc,
|
||||||
MSIINSTALLCONTEXT context,
|
MSIINSTALLCONTEXT context,
|
||||||
LPCWSTR comp, DWORD *sz)
|
LPCWSTR comp, DWORD *sz)
|
||||||
{
|
{
|
||||||
|
@ -909,7 +1274,7 @@ UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
|
||||||
|
|
||||||
*pdwState = INSTALLSTATE_UNKNOWN;
|
*pdwState = INSTALLSTATE_UNKNOWN;
|
||||||
|
|
||||||
if (!msi_comp_find_prodcode(szProductCode, squished_pc, dwContext, szComponent, &sz))
|
if (!msi_comp_find_prodcode(squished_pc, dwContext, szComponent, &sz))
|
||||||
return ERROR_UNKNOWN_COMPONENT;
|
return ERROR_UNKNOWN_COMPONENT;
|
||||||
|
|
||||||
if (sz == 0)
|
if (sz == 0)
|
||||||
|
@ -1571,11 +1936,15 @@ UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
|
||||||
static const WCHAR szVersionResource[] = {'\\',0};
|
static const WCHAR szVersionResource[] = {'\\',0};
|
||||||
static const WCHAR szVersionFormat[] = {
|
static const WCHAR szVersionFormat[] = {
|
||||||
'%','d','.','%','d','.','%','d','.','%','d',0};
|
'%','d','.','%','d','.','%','d','.','%','d',0};
|
||||||
|
static const WCHAR szLangResource[] = {
|
||||||
|
'\\','V','a','r','F','i','l','e','I','n','f','o','\\',
|
||||||
|
'T','r','a','n','s','l','a','t','i','o','n',0};
|
||||||
static const WCHAR szLangFormat[] = {'%','d',0};
|
static const WCHAR szLangFormat[] = {'%','d',0};
|
||||||
UINT ret = 0;
|
UINT ret = 0;
|
||||||
DWORD dwVerLen, gle;
|
DWORD dwVerLen, gle;
|
||||||
LPVOID lpVer = NULL;
|
LPVOID lpVer = NULL;
|
||||||
VS_FIXEDFILEINFO *ffi;
|
VS_FIXEDFILEINFO *ffi;
|
||||||
|
USHORT *lang;
|
||||||
UINT puLen;
|
UINT puLen;
|
||||||
WCHAR tmp[32];
|
WCHAR tmp[32];
|
||||||
|
|
||||||
|
@ -1636,16 +2005,22 @@ UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
|
||||||
|
|
||||||
if (pcchLangBuf)
|
if (pcchLangBuf)
|
||||||
{
|
{
|
||||||
DWORD lang = GetUserDefaultLangID();
|
if (VerQueryValueW(lpVer, szLangResource, (LPVOID*)&lang, &puLen) &&
|
||||||
|
(puLen > 0))
|
||||||
|
{
|
||||||
|
wsprintfW(tmp, szLangFormat, *lang);
|
||||||
|
if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
|
||||||
|
|
||||||
FIXME("Retrieve language from file\n");
|
if (lstrlenW(tmp) >= *pcchLangBuf)
|
||||||
wsprintfW(tmp, szLangFormat, lang);
|
ret = ERROR_MORE_DATA;
|
||||||
if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
|
|
||||||
|
|
||||||
if (lstrlenW(tmp) >= *pcchLangBuf)
|
*pcchLangBuf = lstrlenW(tmp);
|
||||||
ret = ERROR_MORE_DATA;
|
}
|
||||||
|
else
|
||||||
*pcchLangBuf = lstrlenW(tmp);
|
{
|
||||||
|
if (lpLangBuf) *lpLangBuf = 0;
|
||||||
|
*pcchLangBuf = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
@ -2109,11 +2484,11 @@ UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLST
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
sz = sizeof(sourcepath);
|
sz = sizeof(sourcepath);
|
||||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||||
MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
|
MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
|
||||||
|
|
||||||
sz = sizeof(filename);
|
sz = sizeof(filename);
|
||||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||||
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
|
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
|
||||||
|
|
||||||
lstrcatW( sourcepath, filename );
|
lstrcatW( sourcepath, filename );
|
||||||
|
@ -2294,11 +2669,11 @@ UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
|
||||||
*ptr = 0;
|
*ptr = 0;
|
||||||
|
|
||||||
sz = sizeof(sourcepath);
|
sz = sizeof(sourcepath);
|
||||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||||
MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
|
MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
|
||||||
|
|
||||||
sz = sizeof(filename);
|
sz = sizeof(filename);
|
||||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||||
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
|
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
|
||||||
|
|
||||||
lstrcatW( sourcepath, filename );
|
lstrcatW( sourcepath, filename );
|
||||||
|
@ -2452,3 +2827,25 @@ UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
|
||||||
debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
|
debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
|
||||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* MsiIsProductElevatedW [MSI.@]
|
||||||
|
*/
|
||||||
|
UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated )
|
||||||
|
{
|
||||||
|
FIXME("%s %p - stub\n",
|
||||||
|
debugstr_w( szProduct ), pfElevated );
|
||||||
|
*pfElevated = TRUE;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* MsiIsProductElevatedA [MSI.@]
|
||||||
|
*/
|
||||||
|
UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated )
|
||||||
|
{
|
||||||
|
FIXME("%s %p - stub\n",
|
||||||
|
debugstr_a( szProduct ), pfElevated );
|
||||||
|
*pfElevated = TRUE;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
|
@ -207,8 +207,8 @@
|
||||||
211 stdcall MsiSourceListAddSourceW(wstr wstr long wstr)
|
211 stdcall MsiSourceListAddSourceW(wstr wstr long wstr)
|
||||||
212 stub MsiSourceListForceResolutionA
|
212 stub MsiSourceListForceResolutionA
|
||||||
213 stub MsiSourceListForceResolutionW
|
213 stub MsiSourceListForceResolutionW
|
||||||
214 stub MsiIsProductElevatedA
|
214 stdcall MsiIsProductElevatedA(str ptr)
|
||||||
215 stub MsiIsProductElevatedW
|
215 stdcall MsiIsProductElevatedW(wstr ptr)
|
||||||
216 stdcall MsiGetShortcutTargetA(str ptr ptr ptr)
|
216 stdcall MsiGetShortcutTargetA(str ptr ptr ptr)
|
||||||
217 stdcall MsiGetShortcutTargetW(wstr ptr ptr ptr)
|
217 stdcall MsiGetShortcutTargetW(wstr ptr ptr ptr)
|
||||||
218 stdcall MsiGetFileHashA(str long ptr)
|
218 stdcall MsiGetFileHashA(str long ptr)
|
||||||
|
@ -240,8 +240,8 @@
|
||||||
244 stub MsiGetPatchInfoExW
|
244 stub MsiGetPatchInfoExW
|
||||||
245 stdcall MsiEnumProductsExA(str str long long ptr ptr ptr ptr)
|
245 stdcall MsiEnumProductsExA(str str long long ptr ptr ptr ptr)
|
||||||
246 stdcall MsiEnumProductsExW(wstr wstr long long ptr ptr ptr ptr)
|
246 stdcall MsiEnumProductsExW(wstr wstr long long ptr ptr ptr ptr)
|
||||||
247 stub MsiGetProductInfoExA
|
247 stdcall MsiGetProductInfoExA(str str long str ptr ptr)
|
||||||
248 stub MsiGetProductInfoExW
|
248 stdcall MsiGetProductInfoExW(wstr wstr long wstr ptr ptr)
|
||||||
249 stdcall MsiQueryComponentStateA(str str long str ptr)
|
249 stdcall MsiQueryComponentStateA(str str long str ptr)
|
||||||
250 stdcall MsiQueryComponentStateW(wstr wstr long wstr ptr)
|
250 stdcall MsiQueryComponentStateW(wstr wstr long wstr ptr)
|
||||||
251 stub MsiQueryFeatureStateExA
|
251 stub MsiQueryFeatureStateExA
|
||||||
|
@ -257,16 +257,16 @@
|
||||||
261 stub MsiSourceListForceResolutionExA
|
261 stub MsiSourceListForceResolutionExA
|
||||||
262 stub MsiSourceListForceResolutionExW
|
262 stub MsiSourceListForceResolutionExW
|
||||||
263 stdcall MsiSourceListEnumSourcesA(str str long long long ptr ptr)
|
263 stdcall MsiSourceListEnumSourcesA(str str long long long ptr ptr)
|
||||||
264 stub MsiSourceListEnumSourcesW
|
264 stdcall MsiSourceListEnumSourcesW(wstr wstr long long long ptr ptr)
|
||||||
265 stdcall MsiSourceListGetInfoA(str str long long str ptr ptr)
|
265 stdcall MsiSourceListGetInfoA(str str long long str ptr ptr)
|
||||||
266 stdcall MsiSourceListGetInfoW(wstr wstr long long wstr ptr ptr)
|
266 stdcall MsiSourceListGetInfoW(wstr wstr long long wstr ptr ptr)
|
||||||
267 stub MsiSourceListSetInfoA
|
267 stdcall MsiSourceListSetInfoA(str str long long str str)
|
||||||
268 stdcall MsiSourceListSetInfoW(wstr wstr long long wstr wstr)
|
268 stdcall MsiSourceListSetInfoW(wstr wstr long long wstr wstr)
|
||||||
269 stub MsiEnumPatchesExA
|
269 stub MsiEnumPatchesExA
|
||||||
270 stub MsiEnumPatchesExW
|
270 stub MsiEnumPatchesExW
|
||||||
271 stub MsiSourceListEnumMediaDisksA
|
271 stdcall MsiSourceListEnumMediaDisksA(str str long long long ptr ptr ptr ptr ptr)
|
||||||
272 stub MsiSourceListEnumMediaDisksW
|
272 stdcall MsiSourceListEnumMediaDisksW(wstr wstr long long long ptr ptr ptr ptr ptr)
|
||||||
273 stub MsiSourceListAddMediaDiskA
|
273 stdcall MsiSourceListAddMediaDiskA(str str long long long str str)
|
||||||
274 stdcall MsiSourceListAddMediaDiskW(wstr wstr long long long wstr wstr)
|
274 stdcall MsiSourceListAddMediaDiskW(wstr wstr long long long wstr wstr)
|
||||||
275 stub MsiSourceListClearMediaDiskA
|
275 stub MsiSourceListClearMediaDiskA
|
||||||
276 stub MsiSourceListClearMediaDiskW
|
276 stub MsiSourceListClearMediaDiskW
|
||||||
|
|
|
@ -22,10 +22,10 @@ LANGUAGE LANG_KOREAN, SUBLANG_NEUTRAL
|
||||||
|
|
||||||
STRINGTABLE DISCARDABLE
|
STRINGTABLE DISCARDABLE
|
||||||
{
|
{
|
||||||
4 " 지정한 설치 패키지를 열 수 없습니다. 파일 경로를 확인하고 다시 시도하십시오."
|
4 " 지정한 설치 패키지를 열 수 없습니다. 파일 경로를 확인하고 다시 시도하십시오."
|
||||||
5 "%s 경로를 찾을수 없습니다"
|
5 "%s 경로를 찾을수 없습니다"
|
||||||
9 "디스크 %s 삽입"
|
9 "디스크 %s 삽입"
|
||||||
10 "절못된 매개변수"
|
10 "잘못된 매개변수"
|
||||||
11 "%s를 포함하는 폴더를 입력하세여"
|
11 "%s를 포함하는 폴더를 입력하세여"
|
||||||
12 "빠진 부분(feature)을 위한 설치 원본"
|
12 "빠진 부분(feature)을 위한 설치 원본"
|
||||||
13 "빠진 부분(feature)을 위한 네트워크 드라이브"
|
13 "빠진 부분(feature)을 위한 네트워크 드라이브"
|
||||||
|
|
|
@ -568,6 +568,7 @@ typedef struct tagMSISCRIPT
|
||||||
#define MSI_BUILDNUMBER 4000
|
#define MSI_BUILDNUMBER 4000
|
||||||
|
|
||||||
#define GUID_SIZE 39
|
#define GUID_SIZE 39
|
||||||
|
#define SQUISH_GUID_SIZE 33
|
||||||
|
|
||||||
#define MSIHANDLE_MAGIC 0x4d434923
|
#define MSIHANDLE_MAGIC 0x4d434923
|
||||||
|
|
||||||
|
@ -748,12 +749,10 @@ extern UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||||
extern UINT MSIREG_DeleteUninstallKey(LPCWSTR szProduct);
|
extern UINT MSIREG_DeleteUninstallKey(LPCWSTR szProduct);
|
||||||
extern UINT MSIREG_OpenUserProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
extern UINT MSIREG_OpenUserProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||||
extern UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create);
|
extern UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create);
|
||||||
extern UINT MSIREG_OpenFeatures(HKEY* key);
|
|
||||||
extern UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
extern UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||||
extern UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create);
|
extern UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create);
|
||||||
extern UINT MSIREG_OpenComponents(HKEY* key);
|
extern UINT MSIREG_OpenComponents(HKEY* key);
|
||||||
extern UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create);
|
extern UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create);
|
||||||
extern UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create);
|
|
||||||
extern UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create);
|
extern UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create);
|
||||||
extern UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
extern UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||||
extern UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create);
|
extern UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create);
|
||||||
|
@ -886,6 +885,8 @@ extern BOOL check_unique_action(const MSIPACKAGE *, LPCWSTR);
|
||||||
extern WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... );
|
extern WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... );
|
||||||
extern UINT msi_create_component_directories( MSIPACKAGE *package );
|
extern UINT msi_create_component_directories( MSIPACKAGE *package );
|
||||||
extern void msi_ui_error( DWORD msg_id, DWORD type );
|
extern void msi_ui_error( DWORD msg_id, DWORD type );
|
||||||
|
extern UINT msi_set_last_used_source(LPCWSTR product, LPCWSTR usersid,
|
||||||
|
MSIINSTALLCONTEXT context, DWORD options, LPCWSTR value);
|
||||||
|
|
||||||
/* control event stuff */
|
/* control event stuff */
|
||||||
extern VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event,
|
extern VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event,
|
||||||
|
|
|
@ -126,10 +126,25 @@ library WindowsInstaller
|
||||||
msiOpenDatabaseModePatchFile = 32
|
msiOpenDatabaseModePatchFile = 32
|
||||||
} MsiOpenDatabaseMode;
|
} MsiOpenDatabaseMode;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
msiUILevelNoChange = 0,
|
||||||
|
msiUILevelDefault = 1,
|
||||||
|
msiUILevelNone = 2,
|
||||||
|
msiUILevelBasic = 3,
|
||||||
|
msiUILevelReduced = 4,
|
||||||
|
msiUILevelFull = 5,
|
||||||
|
msiUILevelHideCancel = 32,
|
||||||
|
msiUILevelProgressOnly = 64,
|
||||||
|
msiUILevelEndDialog = 128,
|
||||||
|
msiUILevelSourceResOnly = 256
|
||||||
|
} MsiUILevel;
|
||||||
|
|
||||||
[ uuid(000C1090-0000-0000-C000-000000000046) ]
|
[ uuid(000C1090-0000-0000-C000-000000000046) ]
|
||||||
dispinterface Installer
|
dispinterface Installer
|
||||||
{
|
{
|
||||||
properties:
|
properties:
|
||||||
|
[id(DISPID_INSTALLER_UILEVEL)]
|
||||||
|
MsiUILevel UILevel;
|
||||||
methods:
|
methods:
|
||||||
[id(DISPID_INSTALLER_CREATERECORD)]
|
[id(DISPID_INSTALLER_CREATERECORD)]
|
||||||
Record *CreateRecord([in] long Count);
|
Record *CreateRecord([in] long Count);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#define DISPID_INSTALLER_CREATERECORD 1
|
#define DISPID_INSTALLER_CREATERECORD 1
|
||||||
#define DISPID_INSTALLER_OPENPACKAGE 2
|
#define DISPID_INSTALLER_OPENPACKAGE 2
|
||||||
#define DISPID_INSTALLER_OPENDATABASE 4
|
#define DISPID_INSTALLER_OPENDATABASE 4
|
||||||
|
#define DISPID_INSTALLER_UILEVEL 6
|
||||||
#define DISPID_INSTALLER_INSTALLPRODUCT 8
|
#define DISPID_INSTALLER_INSTALLPRODUCT 8
|
||||||
#define DISPID_INSTALLER_VERSION 9
|
#define DISPID_INSTALLER_VERSION 9
|
||||||
#define DISPID_INSTALLER_REGISTRYVALUE 11
|
#define DISPID_INSTALLER_REGISTRYVALUE 11
|
||||||
|
|
|
@ -332,12 +332,6 @@ done:
|
||||||
msi_free(version);
|
msi_free(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* There are a whole slew of these we need to set
|
|
||||||
*
|
|
||||||
*
|
|
||||||
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
|
|
||||||
*/
|
|
||||||
static VOID set_installer_properties(MSIPACKAGE *package)
|
static VOID set_installer_properties(MSIPACKAGE *package)
|
||||||
{
|
{
|
||||||
WCHAR pth[MAX_PATH];
|
WCHAR pth[MAX_PATH];
|
||||||
|
@ -347,11 +341,11 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
||||||
DWORD verval;
|
DWORD verval;
|
||||||
WCHAR verstr[10], bufstr[20];
|
WCHAR verstr[10], bufstr[20];
|
||||||
HDC dc;
|
HDC dc;
|
||||||
LPWSTR check;
|
|
||||||
HKEY hkey;
|
HKEY hkey;
|
||||||
LONG res;
|
LPWSTR username, companyname;
|
||||||
SYSTEM_INFO sys_info;
|
SYSTEM_INFO sys_info;
|
||||||
SYSTEMTIME systemtime;
|
SYSTEMTIME systemtime;
|
||||||
|
LANGID langid;
|
||||||
|
|
||||||
static const WCHAR cszbs[]={'\\',0};
|
static const WCHAR cszbs[]={'\\',0};
|
||||||
static const WCHAR CFF[] =
|
static const WCHAR CFF[] =
|
||||||
|
@ -420,9 +414,17 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
||||||
static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
|
static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
|
||||||
static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
|
static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
|
||||||
static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
|
static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
|
||||||
static const WCHAR szScreenFormat[] = {'%','d',0};
|
static const WCHAR szIntFormat[] = {'%','d',0};
|
||||||
static const WCHAR szIntel[] = { 'I','n','t','e','l',0 };
|
static const WCHAR szIntel[] = { 'I','n','t','e','l',0 };
|
||||||
static const WCHAR szAllUsers[] = { 'A','L','L','U','S','E','R','S',0 };
|
static const WCHAR szAllUsers[] = { 'A','L','L','U','S','E','R','S',0 };
|
||||||
|
static const WCHAR szUserInfo[] = {
|
||||||
|
'S','O','F','T','W','A','R','E','\\',
|
||||||
|
'M','i','c','r','o','s','o','f','t','\\',
|
||||||
|
'M','S',' ','S','e','t','u','p',' ','(','A','C','M','E',')','\\',
|
||||||
|
'U','s','e','r',' ','I','n','f','o',0
|
||||||
|
};
|
||||||
|
static const WCHAR szDefName[] = { 'D','e','f','N','a','m','e',0 };
|
||||||
|
static const WCHAR szDefCompany[] = { 'D','e','f','C','o','m','p','a','n','y',0 };
|
||||||
static const WCHAR szCurrentVersion[] = {
|
static const WCHAR szCurrentVersion[] = {
|
||||||
'S','O','F','T','W','A','R','E','\\',
|
'S','O','F','T','W','A','R','E','\\',
|
||||||
'M','i','c','r','o','s','o','f','t','\\',
|
'M','i','c','r','o','s','o','f','t','\\',
|
||||||
|
@ -437,6 +439,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
||||||
static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0};
|
static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0};
|
||||||
static const WCHAR szDate[] = {'D','a','t','e',0};
|
static const WCHAR szDate[] = {'D','a','t','e',0};
|
||||||
static const WCHAR szTime[] = {'T','i','m','e',0};
|
static const WCHAR szTime[] = {'T','i','m','e',0};
|
||||||
|
static const WCHAR szUserLangID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Other things that probably should be set:
|
* Other things that probably should be set:
|
||||||
|
@ -523,7 +526,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
||||||
/* Physical Memory is specified in MB. Using total amount. */
|
/* Physical Memory is specified in MB. Using total amount. */
|
||||||
msex.dwLength = sizeof(msex);
|
msex.dwLength = sizeof(msex);
|
||||||
GlobalMemoryStatusEx( &msex );
|
GlobalMemoryStatusEx( &msex );
|
||||||
sprintfW( bufstr, szScreenFormat, (int)(msex.ullTotalPhys/1024/1024));
|
sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys/1024/1024));
|
||||||
MSI_SetPropertyW(package, szPhysicalMemory, bufstr);
|
MSI_SetPropertyW(package, szPhysicalMemory, bufstr);
|
||||||
|
|
||||||
SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
|
SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
|
||||||
|
@ -570,42 +573,48 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
||||||
GetSystemInfo( &sys_info );
|
GetSystemInfo( &sys_info );
|
||||||
if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
|
if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
|
||||||
{
|
{
|
||||||
sprintfW( bufstr, szScreenFormat, sys_info.wProcessorLevel );
|
sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
|
||||||
MSI_SetPropertyW( package, szIntel, bufstr );
|
MSI_SetPropertyW( package, szIntel, bufstr );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Screen properties. */
|
/* Screen properties. */
|
||||||
dc = GetDC(0);
|
dc = GetDC(0);
|
||||||
sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, HORZRES ) );
|
sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, HORZRES ) );
|
||||||
MSI_SetPropertyW( package, szScreenX, bufstr );
|
MSI_SetPropertyW( package, szScreenX, bufstr );
|
||||||
sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, VERTRES ));
|
sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, VERTRES ));
|
||||||
MSI_SetPropertyW( package, szScreenY, bufstr );
|
MSI_SetPropertyW( package, szScreenY, bufstr );
|
||||||
sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, BITSPIXEL ));
|
sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, BITSPIXEL ));
|
||||||
MSI_SetPropertyW( package, szColorBits, bufstr );
|
MSI_SetPropertyW( package, szColorBits, bufstr );
|
||||||
ReleaseDC(0, dc);
|
ReleaseDC(0, dc);
|
||||||
|
|
||||||
/* USERNAME and COMPANYNAME */
|
/* USERNAME and COMPANYNAME */
|
||||||
res = RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey );
|
username = msi_dup_property( package, szUSERNAME );
|
||||||
if (res != ERROR_SUCCESS)
|
companyname = msi_dup_property( package, szCOMPANYNAME );
|
||||||
return;
|
|
||||||
|
|
||||||
check = msi_dup_property( package, szUSERNAME );
|
if ((!username || !companyname) &&
|
||||||
if (!check)
|
RegOpenKeyW( HKEY_CURRENT_USER, szUserInfo, &hkey ) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
LPWSTR user = msi_reg_get_val_str( hkey, szRegisteredUser );
|
if (!username &&
|
||||||
MSI_SetPropertyW( package, szUSERNAME, user );
|
(username = msi_reg_get_val_str( hkey, szDefName )))
|
||||||
msi_free( user );
|
MSI_SetPropertyW( package, szUSERNAME, username );
|
||||||
|
if (!companyname &&
|
||||||
|
(companyname = msi_reg_get_val_str( hkey, szDefCompany )))
|
||||||
|
MSI_SetPropertyW( package, szCOMPANYNAME, companyname );
|
||||||
|
CloseHandle( hkey );
|
||||||
}
|
}
|
||||||
|
if ((!username || !companyname) &&
|
||||||
msi_free( check );
|
RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey ) == ERROR_SUCCESS)
|
||||||
|
|
||||||
check = msi_dup_property( package, szCOMPANYNAME );
|
|
||||||
if (!check)
|
|
||||||
{
|
{
|
||||||
LPWSTR company = msi_reg_get_val_str( hkey, szRegisteredOrg );
|
if (!username &&
|
||||||
MSI_SetPropertyW( package, szCOMPANYNAME, company );
|
(username = msi_reg_get_val_str( hkey, szRegisteredUser )))
|
||||||
msi_free( company );
|
MSI_SetPropertyW( package, szUSERNAME, username );
|
||||||
|
if (!companyname &&
|
||||||
|
(companyname = msi_reg_get_val_str( hkey, szRegisteredOrg )))
|
||||||
|
MSI_SetPropertyW( package, szCOMPANYNAME, companyname );
|
||||||
|
CloseHandle( hkey );
|
||||||
}
|
}
|
||||||
|
msi_free( username );
|
||||||
|
msi_free( companyname );
|
||||||
|
|
||||||
if ( set_user_sid_prop( package ) != ERROR_SUCCESS)
|
if ( set_user_sid_prop( package ) != ERROR_SUCCESS)
|
||||||
ERR("Failed to set the UserSID property\n");
|
ERR("Failed to set the UserSID property\n");
|
||||||
|
@ -628,8 +637,10 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
||||||
|
|
||||||
set_msi_assembly_prop( package );
|
set_msi_assembly_prop( package );
|
||||||
|
|
||||||
msi_free( check );
|
langid = GetUserDefaultLangID();
|
||||||
CloseHandle( hkey );
|
sprintfW(bufstr, szIntFormat, langid);
|
||||||
|
|
||||||
|
MSI_SetPropertyW( package, szUserLangID, bufstr );
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT msi_load_summary_properties( MSIPACKAGE *package )
|
static UINT msi_load_summary_properties( MSIPACKAGE *package )
|
||||||
|
@ -1637,7 +1648,7 @@ static HRESULT WINAPI mrp_SetMsiHandle( IWineMsiRemotePackage *iface, MSIHANDLE
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *handle )
|
static HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *handle )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
IWineMsiRemoteDatabase *rdb = NULL;
|
IWineMsiRemoteDatabase *rdb = NULL;
|
||||||
|
@ -1664,7 +1675,7 @@ HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *h
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR *value, DWORD *size )
|
static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR *value, DWORD *size )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r;
|
UINT r;
|
||||||
|
@ -1676,63 +1687,63 @@ HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BST
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_SetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value )
|
static HRESULT WINAPI mrp_SetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiSetPropertyW(This->package, (LPWSTR)property, (LPWSTR)value);
|
UINT r = MsiSetPropertyW(This->package, (LPWSTR)property, (LPWSTR)value);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_ProcessMessage( IWineMsiRemotePackage *iface, INSTALLMESSAGE message, MSIHANDLE record )
|
static HRESULT WINAPI mrp_ProcessMessage( IWineMsiRemotePackage *iface, INSTALLMESSAGE message, MSIHANDLE record )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiProcessMessage(This->package, message, record);
|
UINT r = MsiProcessMessage(This->package, message, record);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_DoAction( IWineMsiRemotePackage *iface, BSTR action )
|
static HRESULT WINAPI mrp_DoAction( IWineMsiRemotePackage *iface, BSTR action )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiDoActionW(This->package, (LPWSTR)action);
|
UINT r = MsiDoActionW(This->package, (LPWSTR)action);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_Sequence( IWineMsiRemotePackage *iface, BSTR table, int sequence )
|
static HRESULT WINAPI mrp_Sequence( IWineMsiRemotePackage *iface, BSTR table, int sequence )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiSequenceW(This->package, (LPWSTR)table, sequence);
|
UINT r = MsiSequenceW(This->package, (LPWSTR)table, sequence);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
|
static HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiGetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
|
UINT r = MsiGetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_SetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value)
|
static HRESULT WINAPI mrp_SetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value)
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiSetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value);
|
UINT r = MsiSetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
|
static HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiGetSourcePathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
|
UINT r = MsiGetSourcePathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL *ret )
|
static HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL *ret )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
*ret = MsiGetMode(This->package, mode);
|
*ret = MsiGetMode(This->package, mode);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
|
static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
|
||||||
INSTALLSTATE *installed, INSTALLSTATE *action )
|
INSTALLSTATE *installed, INSTALLSTATE *action )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
|
@ -1740,14 +1751,14 @@ HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, INSTALLSTATE state )
|
static HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, INSTALLSTATE state )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiSetFeatureStateW(This->package, (LPWSTR)feature, state);
|
UINT r = MsiSetFeatureStateW(This->package, (LPWSTR)feature, state);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR component,
|
static HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR component,
|
||||||
INSTALLSTATE *installed, INSTALLSTATE *action )
|
INSTALLSTATE *installed, INSTALLSTATE *action )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
|
@ -1755,28 +1766,28 @@ HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR compone
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_SetComponentState( IWineMsiRemotePackage *iface, BSTR component, INSTALLSTATE state )
|
static HRESULT WINAPI mrp_SetComponentState( IWineMsiRemotePackage *iface, BSTR component, INSTALLSTATE state )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiSetComponentStateW(This->package, (LPWSTR)component, state);
|
UINT r = MsiSetComponentStateW(This->package, (LPWSTR)component, state);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_GetLanguage( IWineMsiRemotePackage *iface, LANGID *language )
|
static HRESULT WINAPI mrp_GetLanguage( IWineMsiRemotePackage *iface, LANGID *language )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
*language = MsiGetLanguage(This->package);
|
*language = MsiGetLanguage(This->package);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_SetInstallLevel( IWineMsiRemotePackage *iface, int level )
|
static HRESULT WINAPI mrp_SetInstallLevel( IWineMsiRemotePackage *iface, int level )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiSetInstallLevel(This->package, level);
|
UINT r = MsiSetInstallLevel(This->package, level);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE record,
|
static HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE record,
|
||||||
BSTR value, DWORD *size )
|
BSTR value, DWORD *size )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
|
@ -1784,7 +1795,7 @@ HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE record,
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR condition )
|
static HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR condition )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiEvaluateConditionW(This->package, (LPWSTR)condition);
|
UINT r = MsiEvaluateConditionW(This->package, (LPWSTR)condition);
|
||||||
|
|
|
@ -338,7 +338,13 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
|
||||||
TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
|
TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
|
||||||
|
|
||||||
if( iField > rec->count )
|
if( iField > rec->count )
|
||||||
return ERROR_INVALID_PARAMETER;
|
{
|
||||||
|
if ( szValue && *pcchValue > 0 )
|
||||||
|
szValue[0] = 0;
|
||||||
|
|
||||||
|
*pcchValue = 0;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
ret = ERROR_SUCCESS;
|
ret = ERROR_SUCCESS;
|
||||||
switch( rec->fields[iField].type )
|
switch( rec->fields[iField].type )
|
||||||
|
@ -414,7 +420,13 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
|
||||||
TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
|
TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
|
||||||
|
|
||||||
if( iField > rec->count )
|
if( iField > rec->count )
|
||||||
return ERROR_INVALID_PARAMETER;
|
{
|
||||||
|
if ( szValue && *pcchValue > 0 )
|
||||||
|
szValue[0] = 0;
|
||||||
|
|
||||||
|
*pcchValue = 0;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
ret = ERROR_SUCCESS;
|
ret = ERROR_SUCCESS;
|
||||||
switch( rec->fields[iField].type )
|
switch( rec->fields[iField].type )
|
||||||
|
@ -661,7 +673,7 @@ UINT MSI_RecordSetStream(MSIRECORD *rec, UINT iField, IStream *stream)
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT MSI_RecordSetStreamFromFileW(MSIRECORD *rec, UINT iField, LPCWSTR szFilename)
|
static UINT MSI_RecordSetStreamFromFileW(MSIRECORD *rec, UINT iField, LPCWSTR szFilename)
|
||||||
{
|
{
|
||||||
IStream *stm = NULL;
|
IStream *stm = NULL;
|
||||||
HRESULT r;
|
HRESULT r;
|
||||||
|
|
|
@ -52,14 +52,6 @@ static const WCHAR szUserFeatures_fmt[] = {
|
||||||
'F','e','a','t','u','r','e','s','\\',
|
'F','e','a','t','u','r','e','s','\\',
|
||||||
'%','s',0};
|
'%','s',0};
|
||||||
|
|
||||||
static const WCHAR szInstaller_Features[] = {
|
|
||||||
'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','\\',
|
|
||||||
'F','e','a','t','u','r','e','s',0 };
|
|
||||||
|
|
||||||
static const WCHAR szUserDataFeatures_fmt[] = {
|
static const WCHAR szUserDataFeatures_fmt[] = {
|
||||||
'S','o','f','t','w','a','r','e','\\',
|
'S','o','f','t','w','a','r','e','\\',
|
||||||
'M','i','c','r','o','s','o','f','t','\\',
|
'M','i','c','r','o','s','o','f','t','\\',
|
||||||
|
@ -87,15 +79,6 @@ static const WCHAR szInstaller_Components[] = {
|
||||||
'I','n','s','t','a','l','l','e','r','\\',
|
'I','n','s','t','a','l','l','e','r','\\',
|
||||||
'C','o','m','p','o','n','e','n','t','s',0 };
|
'C','o','m','p','o','n','e','n','t','s',0 };
|
||||||
|
|
||||||
static const WCHAR szInstaller_Components_fmt[] = {
|
|
||||||
'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','\\',
|
|
||||||
'C','o','m','p','o','n','e','n','t','s','\\',
|
|
||||||
'%','s',0};
|
|
||||||
|
|
||||||
static const WCHAR szUser_Components_fmt[] = {
|
static const WCHAR szUser_Components_fmt[] = {
|
||||||
'S','o','f','t','w','a','r','e','\\',
|
'S','o','f','t','w','a','r','e','\\',
|
||||||
'M','i','c','r','o','s','o','f','t','\\',
|
'M','i','c','r','o','s','o','f','t','\\',
|
||||||
|
@ -231,8 +214,6 @@ static const WCHAR szInstaller_LocalManagedProd_fmt[] = {
|
||||||
'I','n','s','t','a','l','l','e','r','\\',
|
'I','n','s','t','a','l','l','e','r','\\',
|
||||||
'P','r','o','d','u','c','t','s','\\','%','s',0};
|
'P','r','o','d','u','c','t','s','\\','%','s',0};
|
||||||
|
|
||||||
#define SQUISH_GUID_SIZE 33
|
|
||||||
|
|
||||||
BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
|
BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
|
||||||
{
|
{
|
||||||
DWORD i,n=0;
|
DWORD i,n=0;
|
||||||
|
@ -610,11 +591,6 @@ UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct)
|
||||||
return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
|
return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT MSIREG_OpenFeatures(HKEY* key)
|
|
||||||
{
|
|
||||||
return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Features,key);
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create)
|
UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create)
|
||||||
{
|
{
|
||||||
UINT rc;
|
UINT rc;
|
||||||
|
@ -671,27 +647,6 @@ UINT MSIREG_OpenComponents(HKEY* key)
|
||||||
return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Components,key);
|
return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Components,key);
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
|
|
||||||
{
|
|
||||||
UINT rc;
|
|
||||||
WCHAR squished_cc[GUID_SIZE];
|
|
||||||
WCHAR keypath[0x200];
|
|
||||||
|
|
||||||
TRACE("%s\n",debugstr_w(szComponent));
|
|
||||||
if (!squash_guid(szComponent,squished_cc))
|
|
||||||
return ERROR_FUNCTION_FAILED;
|
|
||||||
TRACE("squished (%s)\n", debugstr_w(squished_cc));
|
|
||||||
|
|
||||||
sprintfW(keypath,szInstaller_Components_fmt,squished_cc);
|
|
||||||
|
|
||||||
if (create)
|
|
||||||
rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
|
|
||||||
else
|
|
||||||
rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
|
UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
|
||||||
{
|
{
|
||||||
UINT rc;
|
UINT rc;
|
||||||
|
@ -853,11 +808,6 @@ UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct)
|
||||||
return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
|
return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT MSIREG_OpenProducts(HKEY* key)
|
|
||||||
{
|
|
||||||
return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Products,key);
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create)
|
UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create)
|
||||||
{
|
{
|
||||||
UINT rc;
|
UINT rc;
|
||||||
|
@ -1182,7 +1132,7 @@ UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
|
||||||
if (NULL == lpguid)
|
if (NULL == lpguid)
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
r = MSIREG_OpenProducts(&hkeyProducts);
|
r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_Products, &hkeyProducts);
|
||||||
if( r != ERROR_SUCCESS )
|
if( r != ERROR_SUCCESS )
|
||||||
return ERROR_NO_MORE_ITEMS;
|
return ERROR_NO_MORE_ITEMS;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -29,6 +29,7 @@
|
||||||
#include "msiquery.h"
|
#include "msiquery.h"
|
||||||
#include "objbase.h"
|
#include "objbase.h"
|
||||||
#include "msipriv.h"
|
#include "msipriv.h"
|
||||||
|
#include "query.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msidb);
|
||||||
|
|
||||||
typedef struct tabSTREAM
|
typedef struct tabSTREAM
|
||||||
{
|
{
|
||||||
int str_index;
|
UINT str_index;
|
||||||
LPWSTR name;
|
LPWSTR name;
|
||||||
IStream *stream;
|
IStream *stream;
|
||||||
} STREAM;
|
} STREAM;
|
||||||
|
@ -54,7 +55,7 @@ typedef struct tagMSISTREAMSVIEW
|
||||||
UINT row_size;
|
UINT row_size;
|
||||||
} MSISTREAMSVIEW;
|
} MSISTREAMSVIEW;
|
||||||
|
|
||||||
static BOOL streams_set_table_size(MSISTREAMSVIEW *sv, int size)
|
static BOOL streams_set_table_size(MSISTREAMSVIEW *sv, UINT size)
|
||||||
{
|
{
|
||||||
if (size >= sv->max_streams)
|
if (size >= sv->max_streams)
|
||||||
{
|
{
|
||||||
|
@ -372,7 +373,7 @@ static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRE
|
||||||
static UINT STREAMS_delete(struct tagMSIVIEW *view)
|
static UINT STREAMS_delete(struct tagMSIVIEW *view)
|
||||||
{
|
{
|
||||||
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
|
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
|
||||||
int i;
|
UINT i;
|
||||||
|
|
||||||
TRACE("(%p)\n", view);
|
TRACE("(%p)\n", view);
|
||||||
|
|
||||||
|
@ -439,7 +440,7 @@ static const MSIVIEWOPS streams_ops =
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static UINT add_streams_to_table(MSISTREAMSVIEW *sv)
|
static INT add_streams_to_table(MSISTREAMSVIEW *sv)
|
||||||
{
|
{
|
||||||
IEnumSTATSTG *stgenum = NULL;
|
IEnumSTATSTG *stgenum = NULL;
|
||||||
STATSTG stat;
|
STATSTG stat;
|
||||||
|
@ -498,6 +499,7 @@ static UINT add_streams_to_table(MSISTREAMSVIEW *sv)
|
||||||
UINT STREAMS_CreateView(MSIDATABASE *db, MSIVIEW **view)
|
UINT STREAMS_CreateView(MSIDATABASE *db, MSIVIEW **view)
|
||||||
{
|
{
|
||||||
MSISTREAMSVIEW *sv;
|
MSISTREAMSVIEW *sv;
|
||||||
|
INT rows;
|
||||||
|
|
||||||
TRACE("(%p, %p)\n", db, view);
|
TRACE("(%p, %p)\n", db, view);
|
||||||
|
|
||||||
|
@ -507,10 +509,10 @@ UINT STREAMS_CreateView(MSIDATABASE *db, MSIVIEW **view)
|
||||||
|
|
||||||
sv->view.ops = &streams_ops;
|
sv->view.ops = &streams_ops;
|
||||||
sv->db = db;
|
sv->db = db;
|
||||||
sv->num_rows = add_streams_to_table(sv);
|
rows = add_streams_to_table(sv);
|
||||||
|
if (rows < 0)
|
||||||
if (sv->num_rows < 0)
|
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
sv->num_rows = rows;
|
||||||
|
|
||||||
*view = (MSIVIEW *)sv;
|
*view = (MSIVIEW *)sv;
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "msidefs.h"
|
#include "msidefs.h"
|
||||||
#include "msipriv.h"
|
#include "msipriv.h"
|
||||||
#include "objidl.h"
|
#include "objidl.h"
|
||||||
|
#include "propvarutil.h"
|
||||||
#include "msiserver.h"
|
#include "msiserver.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||||
|
@ -78,6 +79,10 @@ typedef struct {
|
||||||
|
|
||||||
#include "poppack.h"
|
#include "poppack.h"
|
||||||
|
|
||||||
|
static HRESULT (WINAPI *pPropVariantChangeType)
|
||||||
|
(PROPVARIANT *ppropvarDest, REFPROPVARIANT propvarSrc,
|
||||||
|
PROPVAR_CHANGE_FLAGS flags, VARTYPE vt);
|
||||||
|
|
||||||
#define SECT_HDR_SIZE (sizeof(PROPERTYSECTIONHEADER))
|
#define SECT_HDR_SIZE (sizeof(PROPERTYSECTIONHEADER))
|
||||||
|
|
||||||
static const WCHAR szSumInfo[] = { 5 ,'S','u','m','m','a','r','y',
|
static const WCHAR szSumInfo[] = { 5 ,'S','u','m','m','a','r','y',
|
||||||
|
@ -144,6 +149,22 @@ static UINT get_property_count( const PROPVARIANT *property )
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT propvar_changetype(PROPVARIANT *changed, PROPVARIANT *property, VARTYPE vt)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
HMODULE propsys = LoadLibraryA("propsys.dll");
|
||||||
|
pPropVariantChangeType = (void *)GetProcAddress(propsys, "PropVariantChangeType");
|
||||||
|
|
||||||
|
if (!pPropVariantChangeType)
|
||||||
|
{
|
||||||
|
ERR("PropVariantChangeType function missing!\n");
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = pPropVariantChangeType(changed, property, 0, vt);
|
||||||
|
return (hr == S_OK) ? ERROR_SUCCESS : ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: doesn't deal with endian conversion */
|
/* FIXME: doesn't deal with endian conversion */
|
||||||
static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz )
|
static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz )
|
||||||
{
|
{
|
||||||
|
@ -151,7 +172,8 @@ static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz
|
||||||
DWORD i;
|
DWORD i;
|
||||||
int size;
|
int size;
|
||||||
PROPERTY_DATA *propdata;
|
PROPERTY_DATA *propdata;
|
||||||
PROPVARIANT *property;
|
PROPVARIANT property, *ptr;
|
||||||
|
PROPVARIANT changed;
|
||||||
PROPERTYIDOFFSET *idofs;
|
PROPERTYIDOFFSET *idofs;
|
||||||
PROPERTYSECTIONHEADER *section_hdr;
|
PROPERTYSECTIONHEADER *section_hdr;
|
||||||
|
|
||||||
|
@ -161,6 +183,12 @@ static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz
|
||||||
/* now set all the properties */
|
/* now set all the properties */
|
||||||
for( i = 0; i < section_hdr->cProperties; i++ )
|
for( i = 0; i < section_hdr->cProperties; i++ )
|
||||||
{
|
{
|
||||||
|
if( idofs[i].propid >= MSI_MAX_PROPS )
|
||||||
|
{
|
||||||
|
ERR("Unknown property ID %d\n", idofs[i].propid );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
type = get_type( idofs[i].propid );
|
type = get_type( idofs[i].propid );
|
||||||
if( type == VT_EMPTY )
|
if( type == VT_EMPTY )
|
||||||
{
|
{
|
||||||
|
@ -170,45 +198,41 @@ static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz
|
||||||
|
|
||||||
propdata = (PROPERTY_DATA*) &data[ idofs[i].dwOffset ];
|
propdata = (PROPERTY_DATA*) &data[ idofs[i].dwOffset ];
|
||||||
|
|
||||||
/* check the type is the same as we expect */
|
|
||||||
if( type != propdata->type )
|
|
||||||
{
|
|
||||||
ERR("wrong type %d != %d\n", type, propdata->type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check we don't run off the end of the data */
|
/* check we don't run off the end of the data */
|
||||||
size = sz - idofs[i].dwOffset - sizeof(DWORD);
|
size = sz - idofs[i].dwOffset - sizeof(DWORD);
|
||||||
if( sizeof(DWORD) > size ||
|
if( sizeof(DWORD) > size ||
|
||||||
( type == VT_FILETIME && sizeof(FILETIME) > size ) ||
|
( propdata->type == VT_FILETIME && sizeof(FILETIME) > size ) ||
|
||||||
( type == VT_LPSTR && (propdata->u.str.len + sizeof(DWORD)) > size ) )
|
( propdata->type == VT_LPSTR && (propdata->u.str.len + sizeof(DWORD)) > size ) )
|
||||||
{
|
{
|
||||||
ERR("not enough data\n");
|
ERR("not enough data\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( idofs[i].propid >= MSI_MAX_PROPS )
|
property.vt = propdata->type;
|
||||||
{
|
if( propdata->type == VT_LPSTR )
|
||||||
ERR("Unknown property ID %d\n", idofs[i].propid );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
property = &prop[ idofs[i].propid ];
|
|
||||||
property->vt = type;
|
|
||||||
|
|
||||||
if( type == VT_LPSTR )
|
|
||||||
{
|
{
|
||||||
LPSTR str = msi_alloc( propdata->u.str.len );
|
LPSTR str = msi_alloc( propdata->u.str.len );
|
||||||
memcpy( str, propdata->u.str.str, propdata->u.str.len );
|
memcpy( str, propdata->u.str.str, propdata->u.str.len );
|
||||||
str[ propdata->u.str.len - 1 ] = 0;
|
str[ propdata->u.str.len - 1 ] = 0;
|
||||||
property->u.pszVal = str;
|
property.u.pszVal = str;
|
||||||
}
|
}
|
||||||
else if( type == VT_FILETIME )
|
else if( propdata->type == VT_FILETIME )
|
||||||
property->u.filetime = propdata->u.ft;
|
property.u.filetime = propdata->u.ft;
|
||||||
else if( type == VT_I2 )
|
else if( propdata->type == VT_I2 )
|
||||||
property->u.iVal = propdata->u.i2;
|
property.u.iVal = propdata->u.i2;
|
||||||
else if( type == VT_I4 )
|
else if( propdata->type == VT_I4 )
|
||||||
property->u.lVal = propdata->u.i4;
|
property.u.lVal = propdata->u.i4;
|
||||||
|
|
||||||
|
/* check the type is the same as we expect */
|
||||||
|
if( type != propdata->type )
|
||||||
|
{
|
||||||
|
propvar_changetype(&changed, &property, type);
|
||||||
|
ptr = &changed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ptr = &property;
|
||||||
|
|
||||||
|
prop[ idofs[i].propid ] = *ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,7 +387,7 @@ static UINT save_summary_info( const MSISUMMARYINFO * si, IStream *stm )
|
||||||
|
|
||||||
/* write the format header */
|
/* write the format header */
|
||||||
sz = sizeof format_hdr;
|
sz = sizeof format_hdr;
|
||||||
memcpy( &format_hdr.fmtid, &FMTID_SummaryInformation, sizeof (FMTID) );
|
format_hdr.fmtid = FMTID_SummaryInformation;
|
||||||
format_hdr.dwOffset = sizeof format_hdr + sizeof set_hdr;
|
format_hdr.dwOffset = sizeof format_hdr + sizeof set_hdr;
|
||||||
r = IStream_Write( stm, &format_hdr, sz, &count );
|
r = IStream_Write( stm, &format_hdr, sz, &count );
|
||||||
if( FAILED(r) || count != sz )
|
if( FAILED(r) || count != sz )
|
||||||
|
@ -600,7 +624,7 @@ static UINT get_prop( MSIHANDLE handle, UINT uiProperty, UINT *puiDataType,
|
||||||
break;
|
break;
|
||||||
case VT_FILETIME:
|
case VT_FILETIME:
|
||||||
if( pftValue )
|
if( pftValue )
|
||||||
memcpy(pftValue, &prop->u.filetime, sizeof (FILETIME) );
|
*pftValue = prop->u.filetime;
|
||||||
break;
|
break;
|
||||||
case VT_EMPTY:
|
case VT_EMPTY:
|
||||||
break;
|
break;
|
||||||
|
@ -721,7 +745,7 @@ static UINT set_prop( MSIHANDLE handle, UINT uiProperty, UINT uiDataType,
|
||||||
prop->u.iVal = iValue;
|
prop->u.iVal = iValue;
|
||||||
break;
|
break;
|
||||||
case VT_FILETIME:
|
case VT_FILETIME:
|
||||||
memcpy( &prop->u.filetime, pftValue, sizeof prop->u.filetime );
|
prop->u.filetime = *pftValue;
|
||||||
break;
|
break;
|
||||||
case VT_LPSTR:
|
case VT_LPSTR:
|
||||||
if( str->unicode )
|
if( str->unicode )
|
||||||
|
|
|
@ -923,7 +923,7 @@ static UINT get_defaulttablecolumns( LPCWSTR name, MSICOLUMNINFO *colinfo, UINT
|
||||||
{
|
{
|
||||||
if (colinfo && (i < *sz) )
|
if (colinfo && (i < *sz) )
|
||||||
{
|
{
|
||||||
memcpy( &colinfo[i], &p[i], sizeof(MSICOLUMNINFO) );
|
colinfo[i] = p[i];
|
||||||
colinfo[i].tablename = strdupW( p[i].tablename );
|
colinfo[i].tablename = strdupW( p[i].tablename );
|
||||||
colinfo[i].colname = strdupW( p[i].colname );
|
colinfo[i].colname = strdupW( p[i].colname );
|
||||||
}
|
}
|
||||||
|
@ -1626,6 +1626,23 @@ static UINT modify_delete_row( struct tagMSIVIEW *view, MSIRECORD *rec )
|
||||||
return TABLE_delete_row(view, row);
|
return TABLE_delete_row(view, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT msi_refresh_record( struct tagMSIVIEW *view, MSIRECORD *rec, UINT row )
|
||||||
|
{
|
||||||
|
MSIRECORD *curr;
|
||||||
|
UINT r, i, count;
|
||||||
|
|
||||||
|
r = TABLE_get_row(view, row - 1, &curr);
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
count = MSI_RecordGetFieldCount(rec);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
MSI_RecordCopyField(curr, i + 1, rec, i + 1);
|
||||||
|
|
||||||
|
msiobj_release(&curr->hdr);
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
|
static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
|
||||||
MSIRECORD *rec, UINT row)
|
MSIRECORD *rec, UINT row)
|
||||||
{
|
{
|
||||||
|
@ -1657,11 +1674,14 @@ static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
|
||||||
r = TABLE_insert_row( view, rec, TRUE );
|
r = TABLE_insert_row( view, rec, TRUE );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MSIMODIFY_REFRESH:
|
||||||
|
r = msi_refresh_record( view, rec, row );
|
||||||
|
break;
|
||||||
|
|
||||||
case MSIMODIFY_UPDATE:
|
case MSIMODIFY_UPDATE:
|
||||||
r = msi_table_update( view, rec, row );
|
r = msi_table_update( view, rec, row );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSIMODIFY_REFRESH:
|
|
||||||
case MSIMODIFY_ASSIGN:
|
case MSIMODIFY_ASSIGN:
|
||||||
case MSIMODIFY_REPLACE:
|
case MSIMODIFY_REPLACE:
|
||||||
case MSIMODIFY_MERGE:
|
case MSIMODIFY_MERGE:
|
||||||
|
@ -2034,6 +2054,9 @@ static UINT TABLE_sort(struct tagMSIVIEW *view, column_info *columns)
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (rows == 0)
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
order = msi_alloc_zero(sizeof(MSIORDERINFO) + sizeof(UINT) * cols);
|
order = msi_alloc_zero(sizeof(MSIORDERINFO) + sizeof(UINT) * cols);
|
||||||
if (!order)
|
if (!order)
|
||||||
return ERROR_OUTOFMEMORY;
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
|
@ -88,7 +88,7 @@ static UINT find_entry_in_hash(MSIHASHENTRY **table, UINT row, UINT *val)
|
||||||
|
|
||||||
if (!(entry = table[row % MSI_HASH_TABLE_SIZE]))
|
if (!(entry = table[row % MSI_HASH_TABLE_SIZE]))
|
||||||
{
|
{
|
||||||
ERR("Row not found in hash table!\n");
|
WARN("Row not found in hash table!\n");
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,12 +503,15 @@ static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
|
||||||
MSIRECORD *rec, UINT row )
|
MSIRECORD *rec, UINT row )
|
||||||
{
|
{
|
||||||
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
|
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
|
||||||
|
UINT r;
|
||||||
|
|
||||||
TRACE("%p %d %p\n", wv, eModifyMode, rec );
|
TRACE("%p %d %p\n", wv, eModifyMode, rec);
|
||||||
|
|
||||||
if( !wv->table )
|
r = WHERE_execute(view, NULL);
|
||||||
return ERROR_FUNCTION_FAILED;
|
if (r != ERROR_SUCCESS)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
find_entry_in_hash(wv->reorder, row - 1, &row);
|
||||||
return wv->table->ops->modify( wv->table, eModifyMode, rec, row );
|
return wv->table->ops->modify( wv->table, eModifyMode, rec, row );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue