mirror of
https://github.com/reactos/reactos.git
synced 2024-12-30 19:14:31 +00:00
Autosyncing with Wine HEAD
svn path=/trunk/; revision=32849
This commit is contained in:
parent
5ef42dd10a
commit
e1e678b0f2
25 changed files with 1872 additions and 746 deletions
|
@ -18,14 +18,6 @@
|
|||
* 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>
|
||||
|
||||
#define COBJMACROS
|
||||
|
@ -55,6 +47,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
|||
static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
|
||||
static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
|
||||
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
|
||||
|
@ -241,8 +234,6 @@ struct _actions {
|
|||
STANDARDACTIONHANDLER handler;
|
||||
};
|
||||
|
||||
static const struct _actions StandardActions[];
|
||||
|
||||
|
||||
/********************************************************
|
||||
* helper functions
|
||||
|
@ -573,7 +564,7 @@ static UINT msi_apply_transforms( MSIPACKAGE *package )
|
|||
for( i=0; xforms && xforms[i] && r == ERROR_SUCCESS; i++ )
|
||||
{
|
||||
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
|
||||
r = MSI_DatabaseApplyTransformW( package->db, xforms[i], 0 );
|
||||
}
|
||||
|
@ -584,7 +575,7 @@ static UINT msi_apply_transforms( MSIPACKAGE *package )
|
|||
return r;
|
||||
}
|
||||
|
||||
BOOL ui_sequence_exists( MSIPACKAGE *package )
|
||||
static BOOL ui_sequence_exists( MSIPACKAGE *package )
|
||||
{
|
||||
MSIQUERY *view;
|
||||
UINT rc;
|
||||
|
@ -973,56 +964,6 @@ static UINT ACTION_ProcessUISequence(MSIPACKAGE *package)
|
|||
/********************************************************
|
||||
* 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,
|
||||
UINT* rc, UINT script, BOOL force )
|
||||
{
|
||||
|
@ -1061,7 +1002,7 @@ UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, UINT script,
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1085,7 +1026,7 @@ UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action, UINT scrip
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2322,7 +2263,6 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type,
|
|||
{
|
||||
static const WCHAR szMulti[] = {'[','~',']',0};
|
||||
LPCWSTR ptr;
|
||||
LPWSTR newdata;
|
||||
*type=REG_SZ;
|
||||
|
||||
if (value[0]=='#')
|
||||
|
@ -2350,19 +2290,8 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type,
|
|||
/* add double NULL terminator */
|
||||
if (*type == REG_MULTI_SZ)
|
||||
{
|
||||
*size += sizeof(WCHAR);
|
||||
newdata = msi_alloc(*size);
|
||||
if (!newdata)
|
||||
{
|
||||
msi_free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(newdata, data, *size - 1);
|
||||
newdata[*size] = '\0';
|
||||
|
||||
msi_free(data);
|
||||
data = (LPSTR)newdata;
|
||||
*size += 2 * sizeof(WCHAR); /* two NULL terminators */
|
||||
data = msi_realloc_zero(data, *size);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
|
@ -2503,10 +2432,6 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
|
|||
|
||||
deformat_string(package, name, &deformated);
|
||||
|
||||
/* get the double nulls to terminate SZ_MULTI */
|
||||
if (type == REG_MULTI_SZ)
|
||||
size +=sizeof(WCHAR);
|
||||
|
||||
if (!check_first)
|
||||
{
|
||||
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)
|
||||
{
|
||||
UINT rc;
|
||||
LPWSTR packname;
|
||||
MSIQUERY * view;
|
||||
MSISOURCELISTINFO *info;
|
||||
MSIMEDIADISK *disk;
|
||||
|
@ -3389,12 +3315,16 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
|||
HKEY hkey=0;
|
||||
HKEY hukey=0;
|
||||
HKEY hudkey=0, props=0;
|
||||
HKEY source;
|
||||
static const WCHAR szProductLanguage[] =
|
||||
{'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
|
||||
static const WCHAR szARPProductIcon[] =
|
||||
{'A','R','P','P','R','O','D','U','C','T','I','C','O','N',0};
|
||||
static const WCHAR szProductVersion[] =
|
||||
{'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;
|
||||
LPWSTR buffer;
|
||||
DWORD size;
|
||||
|
@ -3423,6 +3353,12 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
|||
if (rc != ERROR_SUCCESS)
|
||||
goto end;
|
||||
|
||||
rc = RegCreateKeyW(hukey, szSourceList, &source);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
goto end;
|
||||
|
||||
RegCloseKey(source);
|
||||
|
||||
rc = MSIREG_OpenUserDataProductKey(package->ProductCode,&hudkey,TRUE);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
goto end;
|
||||
|
@ -3436,7 +3372,14 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
|||
msi_free(buffer);
|
||||
|
||||
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 );
|
||||
if (buffer)
|
||||
|
@ -3451,10 +3394,29 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
|||
if (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);
|
||||
|
||||
|
||||
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 */
|
||||
|
||||
hDb= alloc_msihandle( &package->db->hdr );
|
||||
|
@ -3472,12 +3434,10 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
|||
guidbuffer, &size);
|
||||
if (rc == ERROR_SUCCESS)
|
||||
{
|
||||
WCHAR squashed[GUID_SIZE];
|
||||
/* for now we only care about the first guid */
|
||||
LPWSTR ptr = strchrW(guidbuffer,';');
|
||||
if (ptr) *ptr = 0;
|
||||
squash_guid(guidbuffer,squashed);
|
||||
msi_reg_set_val_str( hukey, INSTALLPROPERTY_PACKAGECODEW, squashed );
|
||||
msi_reg_set_val_str( hukey, INSTALLPROPERTY_PACKAGECODEW, guidbuffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3495,9 +3455,13 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
|
|||
/* publish the SourceList info */
|
||||
LIST_FOR_EACH_ENTRY(info, &package->sourcelist_info, MSISOURCELISTINFO, entry)
|
||||
{
|
||||
MsiSourceListSetInfoW(package->ProductCode, NULL,
|
||||
info->context, info->options,
|
||||
info->property, info->value);
|
||||
if (!lstrcmpW(info->property, INSTALLPROPERTY_LASTUSEDSOURCEW))
|
||||
msi_set_last_used_source(package->ProductCode, NULL, info->context,
|
||||
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)
|
||||
|
@ -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};
|
||||
static const WCHAR szProductVersion[] =
|
||||
{'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;
|
||||
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)
|
||||
return rc;
|
||||
|
||||
rc = MSIREG_OpenInstallPropertiesKey(package->ProductCode, &props, TRUE);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
/* dump all the info i can grab */
|
||||
/* FIXME: Flesh out more information */
|
||||
|
||||
|
@ -4031,22 +4007,39 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
|
|||
|
||||
/* FIXME: Write real Estimated Size when we have it */
|
||||
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);
|
||||
sprintfW(szDate,date_fmt,systime.wYear,systime.wMonth,systime.wDay);
|
||||
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 );
|
||||
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_LANGUAGEW, langid );
|
||||
|
||||
buffer = msi_dup_property( package, szProductVersion );
|
||||
msi_reg_set_val_str( props, szDisplayVersion, buffer );
|
||||
if (buffer)
|
||||
{
|
||||
DWORD verdword = msi_version_str_to_dword(buffer);
|
||||
|
||||
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( props, INSTALLPROPERTY_VERSIONMAJORW, verdword>>24 );
|
||||
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);
|
||||
|
||||
|
@ -4076,10 +4069,6 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
|
|||
|
||||
RegCloseKey(hudkey);
|
||||
|
||||
rc = MSIREG_OpenInstallPropertiesKey(package->ProductCode, &props, TRUE);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
msi_reg_set_val_dword( props, szWindowsInstaller, 1 );
|
||||
RegCloseKey(props);
|
||||
|
||||
|
@ -4232,13 +4221,13 @@ static UINT ACTION_ResolveSource(MSIPACKAGE* package)
|
|||
DWORD size = 0;
|
||||
|
||||
rc = MsiSourceListGetInfoW(package->ProductCode, NULL,
|
||||
MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
|
||||
MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
|
||||
INSTALLPROPERTY_DISKPROMPTW,NULL,&size);
|
||||
if (rc == ERROR_MORE_DATA)
|
||||
{
|
||||
prompt = msi_alloc(size * sizeof(WCHAR));
|
||||
MsiSourceListGetInfoW(package->ProductCode, NULL,
|
||||
MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
|
||||
MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
|
||||
INSTALLPROPERTY_DISKPROMPTW,prompt,&size);
|
||||
}
|
||||
else
|
||||
|
@ -4287,11 +4276,17 @@ static UINT ACTION_RegisterUser(MSIPACKAGE *package)
|
|||
{0},
|
||||
};
|
||||
|
||||
if (msi_check_unpublish(package))
|
||||
{
|
||||
MSIREG_DeleteUserDataProductKey(package->ProductCode);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
productid = msi_dup_property( package, INSTALLPROPERTY_PRODUCTIDW );
|
||||
if (!productid)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
rc = MSIREG_OpenUninstallKey(package->ProductCode,&hkey,TRUE);
|
||||
rc = MSIREG_OpenInstallPropertiesKey(package->ProductCode, &hkey, TRUE);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
goto end;
|
||||
|
||||
|
@ -4308,7 +4303,7 @@ end:
|
|||
|
||||
/* FIXME: call ui_actiondata */
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4424,7 +4419,8 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
|
|||
MSIRECORD *row;
|
||||
MSIFILE *file;
|
||||
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;
|
||||
DWORD serv_type, start_type;
|
||||
DWORD err_control;
|
||||
|
@ -4451,8 +4447,8 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
|
|||
if (depends && *depends)
|
||||
FIXME("Dependency list unhandled!\n");
|
||||
|
||||
name = MSI_RecordGetString(rec, 2);
|
||||
disp = MSI_RecordGetString(rec, 3);
|
||||
deformat_string(package, MSI_RecordGetString(rec, 2), &name);
|
||||
deformat_string(package, MSI_RecordGetString(rec, 3), &disp);
|
||||
serv_type = MSI_RecordGetInteger(rec, 4);
|
||||
err_control = MSI_RecordGetInteger(rec, 6);
|
||||
load_order = MSI_RecordGetString(rec, 7);
|
||||
|
@ -4490,6 +4486,8 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
|
|||
done:
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(hscm);
|
||||
msi_free(name);
|
||||
msi_free(disp);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -4629,6 +4627,130 @@ static UINT ACTION_StartServices( MSIPACKAGE *package )
|
|||
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 )
|
||||
{
|
||||
MSIFILE *file;
|
||||
|
@ -5211,7 +5333,7 @@ static BOOL add_wildcard(FILE_LIST *files, LPWSTR source, LPWSTR dest)
|
|||
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;
|
||||
HANDLE hfile;
|
||||
|
@ -5240,6 +5362,10 @@ BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options)
|
|||
msi_free(path);
|
||||
}
|
||||
|
||||
/* no files match the wildcard */
|
||||
if (list_empty(&files.entry))
|
||||
goto done;
|
||||
|
||||
/* only the first wildcard match gets renamed to dest */
|
||||
file = LIST_ENTRY(list_head(&files.entry), FILE_LIST, entry);
|
||||
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 );
|
||||
}
|
||||
|
||||
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 const WCHAR table[] = {
|
||||
|
@ -5682,3 +5801,53 @@ static const struct _actions StandardActions[] = {
|
|||
{ szWriteRegistryValues, ACTION_WriteRegistryValues },
|
||||
{ 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;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
static const WCHAR query[] = {
|
||||
|
|
|
@ -39,6 +39,9 @@
|
|||
|
||||
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
|
||||
* 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
|
||||
* 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*,
|
||||
VARIANT*,EXCEPINFO*,UINT*),
|
||||
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. */
|
||||
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;
|
||||
|
||||
|
@ -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.
|
||||
This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
|
||||
using DispGetParam/VariantChangeType. */
|
||||
HRESULT WINAPI DispGetParam_CopyOnly(
|
||||
static HRESULT WINAPI DispGetParam_CopyOnly(
|
||||
DISPPARAMS *pdispparams, /* [in] Parameter list */
|
||||
UINT *position, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
|
||||
VARIANT *pvarResult) /* [out] Destination for resulting variant */
|
||||
|
@ -1535,6 +1538,7 @@ static HRESULT WINAPI InstallerImpl_Invoke(
|
|||
HRESULT hr;
|
||||
LPWSTR szString = NULL;
|
||||
DWORD dwSize = 0;
|
||||
INSTALLUILEVEL ui;
|
||||
|
||||
VariantInit(&varg0);
|
||||
VariantInit(&varg1);
|
||||
|
@ -1627,6 +1631,31 @@ static HRESULT WINAPI InstallerImpl_Invoke(
|
|||
else return DISP_E_MEMBERNOTFOUND;
|
||||
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:
|
||||
if (wFlags & DISPATCH_METHOD)
|
||||
{
|
||||
|
@ -1685,6 +1714,11 @@ static HRESULT WINAPI InstallerImpl_Invoke(
|
|||
VariantClear(&varg1);
|
||||
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);
|
||||
|
||||
/* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
|
||||
|
|
|
@ -317,7 +317,11 @@ value_i:
|
|||
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
|
||||
|
||||
MSI_GetFeatureStateW(cond->package, $2, &install, &action );
|
||||
$$ = action;
|
||||
if (action == INSTALLSTATE_UNKNOWN)
|
||||
$$ = MSICONDITION_FALSE;
|
||||
else
|
||||
$$ = action;
|
||||
|
||||
msi_free( $2 );
|
||||
}
|
||||
| COND_EXCLAM identifier
|
||||
|
|
|
@ -331,6 +331,9 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
|
|||
msi_free(deformated);
|
||||
break;
|
||||
case 51: /* Property set with formatted text. */
|
||||
if (!source)
|
||||
break;
|
||||
|
||||
deformat_string(package,target,&deformated);
|
||||
rc = MSI_SetPropertyW(package,source,deformated);
|
||||
msi_free(deformated);
|
||||
|
@ -857,12 +860,6 @@ static UINT HANDLE_CustomType23(MSIPACKAGE *package, LPCWSTR source,
|
|||
lstrcatW(package_path, backslash);
|
||||
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));
|
||||
|
||||
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 */
|
||||
for (i = 0, ptr = *line; i < count; i++)
|
||||
{
|
||||
while (*ptr && *ptr == '\r') ptr++;
|
||||
save = ptr;
|
||||
|
||||
while (*ptr && *ptr != '\t' && *ptr != '\n') ptr++;
|
||||
while (*ptr && *ptr != '\t' && *ptr != '\n' && *ptr != '\r') ptr++;
|
||||
|
||||
/* NULL-separate the data */
|
||||
if (*ptr)
|
||||
if (*ptr == '\n' || *ptr == '\r')
|
||||
{
|
||||
while (*ptr == '\n' || *ptr == '\r')
|
||||
*(ptr++) = '\0';
|
||||
}
|
||||
else if (*ptr)
|
||||
*ptr++ = '\0';
|
||||
|
||||
(*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};
|
||||
|
||||
size = sizeof(create_fmt) + lstrlenW(table) - 2;
|
||||
size = sizeof(create_fmt)/sizeof(create_fmt[0]) + lstrlenW(table) - 2;
|
||||
prelude = msi_alloc(size * sizeof(WCHAR));
|
||||
if (!prelude)
|
||||
return NULL;
|
||||
|
@ -509,156 +515,88 @@ static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
|
|||
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;
|
||||
DWORD size;
|
||||
UINT i;
|
||||
|
||||
static const WCHAR insert_fmt[] = {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','%','s','`',' ','(',' ',0};
|
||||
|
||||
size = sizeof(insert_fmt) + lstrlenW(table) - 2;
|
||||
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;
|
||||
*rec = MSI_CreateRecord(num_columns);
|
||||
if (!*rec)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
for (i = 0; i < num_columns; i++)
|
||||
{
|
||||
switch (types[i][0])
|
||||
{
|
||||
case 'L': case 'l': case 'S': case 's':
|
||||
sprintfW(expanded, str_fmt, records[irec][i]);
|
||||
MSI_RecordSetStringW(*rec, i + 1, data[i]);
|
||||
break;
|
||||
case 'I': case 'i':
|
||||
if (*records[0][i])
|
||||
sprintfW(expanded, int_fmt, records[irec][i]);
|
||||
else
|
||||
lstrcpyW(expanded, empty);
|
||||
if (*data[i])
|
||||
MSI_RecordSetInteger(*rec, i + 1, atoiW(data[i]));
|
||||
break;
|
||||
default:
|
||||
HeapFree( GetProcessHeap(), 0, columns );
|
||||
return NULL;
|
||||
ERR("Unhandled column type: %c\n", types[i][0]);
|
||||
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,
|
||||
LPWSTR *labels, LPWSTR **records,
|
||||
int num_columns, int num_records)
|
||||
{
|
||||
UINT r;
|
||||
DWORD i, size;
|
||||
MSIQUERY *view;
|
||||
LPWSTR insert_sql;
|
||||
DWORD size, i;
|
||||
UINT r = ERROR_SUCCESS;
|
||||
MSIRECORD *rec;
|
||||
LPWSTR query;
|
||||
|
||||
static const WCHAR mid[] = {' ',')',' ','V','A','L','U','E','S',' ','(',' ',0};
|
||||
static const WCHAR end[] = {' ',')',0};
|
||||
static const WCHAR select[] = {
|
||||
'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++)
|
||||
{
|
||||
LPWSTR data = msi_build_insertsql_data(records, types, num_columns, i);
|
||||
|
||||
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);
|
||||
|
||||
r = construct_record(num_columns, types, records[i], &rec);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
r = MSI_ViewExecute(view, NULL);
|
||||
MSI_ViewClose(view);
|
||||
msiobj_release(&view->hdr);
|
||||
r = MSI_ViewModify(view, MSIMODIFY_INSERT, rec);
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
msiobj_release(&rec->hdr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
msiobj_release(&rec->hdr);
|
||||
}
|
||||
|
||||
done:
|
||||
msi_free(prelude);
|
||||
msi_free(columns_sql);
|
||||
|
||||
msiobj_release(&view->hdr);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -666,11 +604,11 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
|||
{
|
||||
UINT r;
|
||||
DWORD len, i;
|
||||
DWORD num_labels;
|
||||
DWORD num_labels, num_types;
|
||||
DWORD num_columns, num_records = 0;
|
||||
LPWSTR *columns, *types, *labels;
|
||||
LPWSTR path, ptr, data;
|
||||
LPWSTR **records;
|
||||
LPWSTR **records = NULL;
|
||||
LPWSTR **temp_records;
|
||||
|
||||
static const WCHAR backslash[] = {'\\',0};
|
||||
|
@ -693,9 +631,15 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
|||
|
||||
ptr = data;
|
||||
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 );
|
||||
|
||||
if (num_columns != num_types)
|
||||
{
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
records = msi_alloc(sizeof(LPWSTR *));
|
||||
if (!records)
|
||||
{
|
||||
|
@ -718,9 +662,15 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
|||
records = temp_records;
|
||||
}
|
||||
|
||||
r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns );
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
if (!TABLE_Exists(db, labels[0]))
|
||||
{
|
||||
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 );
|
||||
|
||||
|
@ -849,12 +799,29 @@ static UINT msi_export_row( MSIRECORD *row, void *arg )
|
|||
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,
|
||||
LPCWSTR folder, LPCWSTR file )
|
||||
{
|
||||
static const WCHAR query[] = {
|
||||
's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','%','s',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;
|
||||
MSIQUERY *view = NULL;
|
||||
LPWSTR filename;
|
||||
|
@ -882,6 +849,12 @@ UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
|||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
if (!lstrcmpW( table, forcecodepage ))
|
||||
{
|
||||
r = msi_export_forcecodepage( handle );
|
||||
goto done;
|
||||
}
|
||||
|
||||
r = MSI_OpenQuery( db, &view, query, table );
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
|
@ -915,8 +888,8 @@ UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
|||
msiobj_release( &view->hdr );
|
||||
}
|
||||
|
||||
done:
|
||||
CloseHandle( handle );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -1079,32 +1052,32 @@ static ULONG WINAPI mrd_Release( IWineMsiRemoteDatabase *iface )
|
|||
return r;
|
||||
}
|
||||
|
||||
HRESULT WINAPI mrd_IsTablePersistent( IWineMsiRemoteDatabase *iface,
|
||||
BSTR table, MSICONDITION *persistent )
|
||||
static HRESULT WINAPI mrd_IsTablePersistent( IWineMsiRemoteDatabase *iface,
|
||||
BSTR table, MSICONDITION *persistent )
|
||||
{
|
||||
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
||||
*persistent = MsiDatabaseIsTablePersistentW(This->database, (LPWSTR)table);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI mrd_GetPrimaryKeys( IWineMsiRemoteDatabase *iface,
|
||||
BSTR table, MSIHANDLE *keys )
|
||||
static HRESULT WINAPI mrd_GetPrimaryKeys( IWineMsiRemoteDatabase *iface,
|
||||
BSTR table, MSIHANDLE *keys )
|
||||
{
|
||||
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
||||
UINT r = MsiDatabaseGetPrimaryKeysW(This->database, (LPWSTR)table, keys);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
||||
HRESULT WINAPI mrd_GetSummaryInformation( IWineMsiRemoteDatabase *iface,
|
||||
UINT updatecount, MSIHANDLE *suminfo )
|
||||
static HRESULT WINAPI mrd_GetSummaryInformation( IWineMsiRemoteDatabase *iface,
|
||||
UINT updatecount, MSIHANDLE *suminfo )
|
||||
{
|
||||
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
||||
UINT r = MsiGetSummaryInformationW(This->database, NULL, updatecount, suminfo);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
||||
HRESULT WINAPI mrd_OpenView( IWineMsiRemoteDatabase *iface,
|
||||
BSTR query, MSIHANDLE *view )
|
||||
static HRESULT WINAPI mrd_OpenView( IWineMsiRemoteDatabase *iface,
|
||||
BSTR query, MSIHANDLE *view )
|
||||
{
|
||||
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
||||
UINT r = MsiDatabaseOpenViewW(This->database, (LPWSTR)query, view);
|
||||
|
|
|
@ -50,12 +50,14 @@ extern HINSTANCE msi_hInstance;
|
|||
struct msi_control_tag;
|
||||
typedef struct msi_control_tag msi_control;
|
||||
typedef UINT (*msi_handler)( msi_dialog *, msi_control *, WPARAM );
|
||||
typedef void (*msi_update)( msi_dialog *, msi_control * );
|
||||
|
||||
struct msi_control_tag
|
||||
{
|
||||
struct list entry;
|
||||
HWND hwnd;
|
||||
msi_handler handler;
|
||||
msi_update update;
|
||||
LPWSTR property;
|
||||
LPWSTR value;
|
||||
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 );
|
||||
}
|
||||
|
||||
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 */
|
||||
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,
|
||||
BS_CHECKBOX | BS_MULTILINE | WS_TABSTOP );
|
||||
control->handler = msi_dialog_checkbox_handler;
|
||||
control->update = msi_dialog_checkbox_sync_state;
|
||||
prop = MSI_RecordGetString( rec, 9 );
|
||||
if( prop )
|
||||
{
|
||||
|
@ -2904,7 +2917,7 @@ static MSIRECORD *msi_get_dialog_record( msi_dialog *dialog )
|
|||
|
||||
rec = MSI_QueryGetRecord( package->db, query, dialog->name );
|
||||
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;
|
||||
}
|
||||
|
@ -3083,6 +3096,7 @@ static UINT msi_dialog_set_property( msi_dialog *dialog, LPCWSTR event, LPCWSTR
|
|||
if( strcmpW( szNullArg, arg ) )
|
||||
deformat_string( dialog->package, arg, &arg_fmt );
|
||||
MSI_SetPropertyW( dialog->package, prop, arg_fmt );
|
||||
msi_dialog_update_controls( dialog, prop );
|
||||
msi_free( arg_fmt );
|
||||
}
|
||||
else
|
||||
|
|
|
@ -18,11 +18,6 @@
|
|||
* 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 <stdio.h>
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
|
|||
|
||||
struct media_info {
|
||||
UINT disk_id;
|
||||
UINT type;
|
||||
UINT last_sequence;
|
||||
LPWSTR disk_prompt;
|
||||
LPWSTR cabinet;
|
||||
|
@ -400,10 +401,13 @@ static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
|
|||
}
|
||||
case fdintCLOSE_FILE_INFO:
|
||||
{
|
||||
CabData *data = (CabData*) pfdin->pv;
|
||||
FILETIME ft;
|
||||
FILETIME ftLocal;
|
||||
HANDLE handle = (HANDLE) pfdin->hf;
|
||||
|
||||
data->mi->is_continuous = FALSE;
|
||||
|
||||
if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft))
|
||||
return -1;
|
||||
if (!LocalFileTimeToFileTime(&ft, &ftLocal))
|
||||
|
@ -504,6 +508,8 @@ static UINT load_media_info(MSIPACKAGE *package, MSIFILE *file, struct media_inf
|
|||
{
|
||||
MSIRECORD *row;
|
||||
LPWSTR source_dir;
|
||||
LPWSTR source;
|
||||
DWORD options;
|
||||
UINT r;
|
||||
|
||||
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);
|
||||
lstrcpyW(mi->source, source_dir);
|
||||
|
||||
PathStripToRootW(source_dir);
|
||||
mi->type = GetDriveTypeW(source_dir);
|
||||
|
||||
if (file->IsCompressed && mi->cabinet)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
msi_package_add_media_disk(package, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
|
||||
mi->disk_id, mi->volume_label, mi->disk_prompt);
|
||||
options = MSICODE_PRODUCT;
|
||||
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,
|
||||
MSICODE_PRODUCT | MSISOURCETYPE_MEDIA,
|
||||
INSTALLPROPERTY_LASTUSEDSOURCEW, mi->source);
|
||||
if (mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE)
|
||||
msi_package_add_media_disk(package, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
BOOL matches;
|
||||
UINT type;
|
||||
|
||||
PathStripToRootW(source);
|
||||
type = GetDriveTypeW(source);
|
||||
matches = source_matches_volume(mi, 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);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
|
@ -620,8 +686,13 @@ static UINT ready_media(MSIPACKAGE *package, MSIFILE *file, struct media_info *m
|
|||
if (file->IsCompressed &&
|
||||
GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
ERR("Cabinet not found: %s\n", debugstr_w(mi->source));
|
||||
return ERROR_INSTALL_FAILURE;
|
||||
/* FIXME: this might be done earlier in the install process */
|
||||
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;
|
||||
|
@ -739,21 +810,11 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
|||
{
|
||||
struct media_info *mi;
|
||||
UINT rc = ERROR_SUCCESS;
|
||||
LPWSTR ptr;
|
||||
MSIFILE *file;
|
||||
|
||||
/* increment progress bar each time action data is sent */
|
||||
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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -346,7 +346,7 @@ static LPWSTR build_default_format(const MSIRECORD* record)
|
|||
sprintfW(index, fmt_index, i);
|
||||
str = MSI_RecordGetString(record, i);
|
||||
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;
|
||||
|
||||
if (len > max_len)
|
||||
|
@ -544,6 +544,10 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
|
|||
format->deformatted = str;
|
||||
format->len = size - 1;
|
||||
|
||||
/* don't reformat the NULL */
|
||||
if (replace && !*replace)
|
||||
format->n++;
|
||||
|
||||
if (!replace)
|
||||
return NULL;
|
||||
|
||||
|
@ -727,9 +731,6 @@ static UINT replace_stack(FORMAT *format, STACK *stack, STACK *values)
|
|||
msi_free(replaced);
|
||||
format->n = beg->n + beg->len;
|
||||
|
||||
if (type == FORMAT_PROPNULL)
|
||||
format->n++;
|
||||
|
||||
top = stack_peek(stack);
|
||||
if (top)
|
||||
{
|
||||
|
|
|
@ -77,7 +77,7 @@ static UINT JOIN_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *v
|
|||
break;
|
||||
}
|
||||
|
||||
prev_rows = table->rows;
|
||||
prev_rows *= table->rows;
|
||||
cols += table->columns;
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ static UINT JOIN_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStr
|
|||
break;
|
||||
}
|
||||
|
||||
prev_rows = table->rows;
|
||||
prev_rows *= table->rows;
|
||||
cols += table->columns;
|
||||
}
|
||||
|
||||
|
@ -341,7 +341,8 @@ UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables )
|
|||
r = TABLE_CreateView( db, tables, &table->view );
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -365,12 +365,12 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
|
|||
}
|
||||
|
||||
sz = sizeof(sourcepath);
|
||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||
MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath,
|
||||
&sz);
|
||||
|
||||
sz = sizeof(filename);
|
||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
|
||||
|
||||
lstrcatW(sourcepath,filename);
|
||||
|
@ -561,114 +561,193 @@ done:
|
|||
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,
|
||||
awstring *szValue, LPDWORD pcchValueBuf)
|
||||
{
|
||||
UINT r;
|
||||
HKEY hkey;
|
||||
UINT r = ERROR_UNKNOWN_PROPERTY;
|
||||
HKEY prodkey, userdata, source;
|
||||
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),
|
||||
debugstr_w(szAttribute), szValue, pcchValueBuf);
|
||||
|
||||
/*
|
||||
* FIXME: Values seem scattered/duplicated in the registry. Is there a system?
|
||||
*/
|
||||
|
||||
if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szProduct[0] || !szAttribute)
|
||||
if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
/* check for special properties */
|
||||
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
|
||||
if (!squash_guid(szProduct, squished_pc))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
r = MSIREG_OpenLocalManagedProductKey(szProduct, &prodkey, FALSE);
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
LPWSTR regval;
|
||||
WCHAR packagecode[35];
|
||||
|
||||
r = MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE);
|
||||
r = MSIREG_OpenUserProductsKey(szProduct, &prodkey, FALSE);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return ERROR_UNKNOWN_PRODUCT;
|
||||
|
||||
regval = msi_reg_get_val_str( hkey, szAttribute );
|
||||
if (regval)
|
||||
{
|
||||
if (unsquash_guid(regval, packagecode))
|
||||
val = strdupW(packagecode);
|
||||
msi_free(regval);
|
||||
r = MSIREG_OpenLocalClassesProductKey(szProduct, &prodkey, FALSE);
|
||||
if (r == ERROR_SUCCESS)
|
||||
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 (r != ERROR_SUCCESS)
|
||||
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;
|
||||
}
|
||||
if (classes)
|
||||
MSIREG_OpenLocalSystemProductKey(szProduct, &userdata, FALSE);
|
||||
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[] = {
|
||||
'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0 };
|
||||
if (!prodkey)
|
||||
{
|
||||
r = ERROR_UNKNOWN_PRODUCT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
FIXME("%s\n", debugstr_w(szAttribute));
|
||||
/* FIXME: some attribute values not tested... */
|
||||
if (!userdata)
|
||||
return ERROR_UNKNOWN_PROPERTY;
|
||||
|
||||
if (!lstrcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ))
|
||||
szAttribute = szDisplayVersion;
|
||||
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
|
||||
szAttribute = display_name;
|
||||
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW))
|
||||
szAttribute = display_version;
|
||||
|
||||
r = MSIREG_OpenUninstallKey( szProduct, &hkey, FALSE );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return ERROR_UNKNOWN_PRODUCT;
|
||||
|
||||
val = msi_reg_get_val_str( hkey, szAttribute );
|
||||
|
||||
RegCloseKey(hkey);
|
||||
val = msi_reg_get_value(userdata, szAttribute, &type);
|
||||
if (!val)
|
||||
val = empty;
|
||||
}
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -718,6 +797,292 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
|
|||
&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)
|
||||
{
|
||||
LPWSTR szwLogFile = NULL;
|
||||
|
@ -849,7 +1214,7 @@ static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
|
|||
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,
|
||||
LPCWSTR comp, DWORD *sz)
|
||||
{
|
||||
|
@ -909,7 +1274,7 @@ UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
|
|||
|
||||
*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;
|
||||
|
||||
if (sz == 0)
|
||||
|
@ -1571,11 +1936,15 @@ UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
|
|||
static const WCHAR szVersionResource[] = {'\\',0};
|
||||
static const WCHAR szVersionFormat[] = {
|
||||
'%','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};
|
||||
UINT ret = 0;
|
||||
DWORD dwVerLen, gle;
|
||||
LPVOID lpVer = NULL;
|
||||
VS_FIXEDFILEINFO *ffi;
|
||||
USHORT *lang;
|
||||
UINT puLen;
|
||||
WCHAR tmp[32];
|
||||
|
||||
|
@ -1636,16 +2005,22 @@ UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
|
|||
|
||||
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");
|
||||
wsprintfW(tmp, szLangFormat, lang);
|
||||
if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
|
||||
if (lstrlenW(tmp) >= *pcchLangBuf)
|
||||
ret = ERROR_MORE_DATA;
|
||||
|
||||
if (lstrlenW(tmp) >= *pcchLangBuf)
|
||||
ret = ERROR_MORE_DATA;
|
||||
|
||||
*pcchLangBuf = lstrlenW(tmp);
|
||||
*pcchLangBuf = lstrlenW(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lpLangBuf) *lpLangBuf = 0;
|
||||
*pcchLangBuf = 0;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
|
@ -2109,11 +2484,11 @@ UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLST
|
|||
return r;
|
||||
|
||||
sz = sizeof(sourcepath);
|
||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||
MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
|
||||
|
||||
sz = sizeof(filename);
|
||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
|
||||
|
||||
lstrcatW( sourcepath, filename );
|
||||
|
@ -2294,11 +2669,11 @@ UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
|
|||
*ptr = 0;
|
||||
|
||||
sz = sizeof(sourcepath);
|
||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||
MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
|
||||
|
||||
sz = sizeof(filename);
|
||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
||||
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
|
||||
|
||||
lstrcatW( sourcepath, filename );
|
||||
|
@ -2452,3 +2827,25 @@ UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
|
|||
debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
|
||||
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)
|
||||
212 stub MsiSourceListForceResolutionA
|
||||
213 stub MsiSourceListForceResolutionW
|
||||
214 stub MsiIsProductElevatedA
|
||||
215 stub MsiIsProductElevatedW
|
||||
214 stdcall MsiIsProductElevatedA(str ptr)
|
||||
215 stdcall MsiIsProductElevatedW(wstr ptr)
|
||||
216 stdcall MsiGetShortcutTargetA(str ptr ptr ptr)
|
||||
217 stdcall MsiGetShortcutTargetW(wstr ptr ptr ptr)
|
||||
218 stdcall MsiGetFileHashA(str long ptr)
|
||||
|
@ -240,8 +240,8 @@
|
|||
244 stub MsiGetPatchInfoExW
|
||||
245 stdcall MsiEnumProductsExA(str str long long ptr ptr ptr ptr)
|
||||
246 stdcall MsiEnumProductsExW(wstr wstr long long ptr ptr ptr ptr)
|
||||
247 stub MsiGetProductInfoExA
|
||||
248 stub MsiGetProductInfoExW
|
||||
247 stdcall MsiGetProductInfoExA(str str long str ptr ptr)
|
||||
248 stdcall MsiGetProductInfoExW(wstr wstr long wstr ptr ptr)
|
||||
249 stdcall MsiQueryComponentStateA(str str long str ptr)
|
||||
250 stdcall MsiQueryComponentStateW(wstr wstr long wstr ptr)
|
||||
251 stub MsiQueryFeatureStateExA
|
||||
|
@ -257,16 +257,16 @@
|
|||
261 stub MsiSourceListForceResolutionExA
|
||||
262 stub MsiSourceListForceResolutionExW
|
||||
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)
|
||||
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)
|
||||
269 stub MsiEnumPatchesExA
|
||||
270 stub MsiEnumPatchesExW
|
||||
271 stub MsiSourceListEnumMediaDisksA
|
||||
272 stub MsiSourceListEnumMediaDisksW
|
||||
273 stub MsiSourceListAddMediaDiskA
|
||||
271 stdcall MsiSourceListEnumMediaDisksA(str str long long long ptr ptr ptr ptr ptr)
|
||||
272 stdcall MsiSourceListEnumMediaDisksW(wstr wstr long long long ptr ptr ptr ptr ptr)
|
||||
273 stdcall MsiSourceListAddMediaDiskA(str str long long long str str)
|
||||
274 stdcall MsiSourceListAddMediaDiskW(wstr wstr long long long wstr wstr)
|
||||
275 stub MsiSourceListClearMediaDiskA
|
||||
276 stub MsiSourceListClearMediaDiskW
|
||||
|
|
|
@ -22,10 +22,10 @@ LANGUAGE LANG_KOREAN, SUBLANG_NEUTRAL
|
|||
|
||||
STRINGTABLE DISCARDABLE
|
||||
{
|
||||
4 " 지정한 설치 패키지를 열 수 없습니다. 파일 경로를 확인하고 다시 시도하십시오."
|
||||
4 " 지정한 설치 패키지를 열 수 없습니다. 파일 경로를 확인하고 다시 시도하십시오."
|
||||
5 "%s 경로를 찾을수 없습니다"
|
||||
9 "디스크 %s 삽입"
|
||||
10 "절못된 매개변수"
|
||||
10 "잘못된 매개변수"
|
||||
11 "%s를 포함하는 폴더를 입력하세여"
|
||||
12 "빠진 부분(feature)을 위한 설치 원본"
|
||||
13 "빠진 부분(feature)을 위한 네트워크 드라이브"
|
||||
|
|
|
@ -568,6 +568,7 @@ typedef struct tagMSISCRIPT
|
|||
#define MSI_BUILDNUMBER 4000
|
||||
|
||||
#define GUID_SIZE 39
|
||||
#define SQUISH_GUID_SIZE 33
|
||||
|
||||
#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_OpenUserProductsKey(LPCWSTR szProduct, 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_OpenUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create);
|
||||
extern UINT MSIREG_OpenComponents(HKEY* key);
|
||||
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_OpenProductsKey(LPCWSTR szProduct, 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 UINT msi_create_component_directories( MSIPACKAGE *package );
|
||||
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 */
|
||||
extern VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event,
|
||||
|
|
|
@ -126,10 +126,25 @@ library WindowsInstaller
|
|||
msiOpenDatabaseModePatchFile = 32
|
||||
} 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) ]
|
||||
dispinterface Installer
|
||||
{
|
||||
properties:
|
||||
[id(DISPID_INSTALLER_UILEVEL)]
|
||||
MsiUILevel UILevel;
|
||||
methods:
|
||||
[id(DISPID_INSTALLER_CREATERECORD)]
|
||||
Record *CreateRecord([in] long Count);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define DISPID_INSTALLER_CREATERECORD 1
|
||||
#define DISPID_INSTALLER_OPENPACKAGE 2
|
||||
#define DISPID_INSTALLER_OPENDATABASE 4
|
||||
#define DISPID_INSTALLER_UILEVEL 6
|
||||
#define DISPID_INSTALLER_INSTALLPRODUCT 8
|
||||
#define DISPID_INSTALLER_VERSION 9
|
||||
#define DISPID_INSTALLER_REGISTRYVALUE 11
|
||||
|
|
|
@ -332,12 +332,6 @@ done:
|
|||
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)
|
||||
{
|
||||
WCHAR pth[MAX_PATH];
|
||||
|
@ -347,11 +341,11 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
|||
DWORD verval;
|
||||
WCHAR verstr[10], bufstr[20];
|
||||
HDC dc;
|
||||
LPWSTR check;
|
||||
HKEY hkey;
|
||||
LONG res;
|
||||
LPWSTR username, companyname;
|
||||
SYSTEM_INFO sys_info;
|
||||
SYSTEMTIME systemtime;
|
||||
LANGID langid;
|
||||
|
||||
static const WCHAR cszbs[]={'\\',0};
|
||||
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 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 szScreenFormat[] = {'%','d',0};
|
||||
static const WCHAR szIntFormat[] = {'%','d',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 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[] = {
|
||||
'S','O','F','T','W','A','R','E','\\',
|
||||
'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 szDate[] = {'D','a','t','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:
|
||||
|
@ -523,7 +526,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
|||
/* Physical Memory is specified in MB. Using total amount. */
|
||||
msex.dwLength = sizeof(msex);
|
||||
GlobalMemoryStatusEx( &msex );
|
||||
sprintfW( bufstr, szScreenFormat, (int)(msex.ullTotalPhys/1024/1024));
|
||||
sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys/1024/1024));
|
||||
MSI_SetPropertyW(package, szPhysicalMemory, bufstr);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
|
||||
|
@ -570,42 +573,48 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
|||
GetSystemInfo( &sys_info );
|
||||
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 );
|
||||
}
|
||||
|
||||
/* Screen properties. */
|
||||
dc = GetDC(0);
|
||||
sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, HORZRES ) );
|
||||
sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, HORZRES ) );
|
||||
MSI_SetPropertyW( package, szScreenX, bufstr );
|
||||
sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, VERTRES ));
|
||||
sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, VERTRES ));
|
||||
MSI_SetPropertyW( package, szScreenY, bufstr );
|
||||
sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, BITSPIXEL ));
|
||||
sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, BITSPIXEL ));
|
||||
MSI_SetPropertyW( package, szColorBits, bufstr );
|
||||
ReleaseDC(0, dc);
|
||||
|
||||
/* USERNAME and COMPANYNAME */
|
||||
res = RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey );
|
||||
if (res != ERROR_SUCCESS)
|
||||
return;
|
||||
username = msi_dup_property( package, szUSERNAME );
|
||||
companyname = msi_dup_property( package, szCOMPANYNAME );
|
||||
|
||||
check = msi_dup_property( package, szUSERNAME );
|
||||
if (!check)
|
||||
if ((!username || !companyname) &&
|
||||
RegOpenKeyW( HKEY_CURRENT_USER, szUserInfo, &hkey ) == ERROR_SUCCESS)
|
||||
{
|
||||
LPWSTR user = msi_reg_get_val_str( hkey, szRegisteredUser );
|
||||
MSI_SetPropertyW( package, szUSERNAME, user );
|
||||
msi_free( user );
|
||||
if (!username &&
|
||||
(username = msi_reg_get_val_str( hkey, szDefName )))
|
||||
MSI_SetPropertyW( package, szUSERNAME, username );
|
||||
if (!companyname &&
|
||||
(companyname = msi_reg_get_val_str( hkey, szDefCompany )))
|
||||
MSI_SetPropertyW( package, szCOMPANYNAME, companyname );
|
||||
CloseHandle( hkey );
|
||||
}
|
||||
|
||||
msi_free( check );
|
||||
|
||||
check = msi_dup_property( package, szCOMPANYNAME );
|
||||
if (!check)
|
||||
if ((!username || !companyname) &&
|
||||
RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey ) == ERROR_SUCCESS)
|
||||
{
|
||||
LPWSTR company = msi_reg_get_val_str( hkey, szRegisteredOrg );
|
||||
MSI_SetPropertyW( package, szCOMPANYNAME, company );
|
||||
msi_free( company );
|
||||
if (!username &&
|
||||
(username = msi_reg_get_val_str( hkey, szRegisteredUser )))
|
||||
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)
|
||||
ERR("Failed to set the UserSID property\n");
|
||||
|
@ -628,8 +637,10 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
|||
|
||||
set_msi_assembly_prop( package );
|
||||
|
||||
msi_free( check );
|
||||
CloseHandle( hkey );
|
||||
langid = GetUserDefaultLangID();
|
||||
sprintfW(bufstr, szIntFormat, langid);
|
||||
|
||||
MSI_SetPropertyW( package, szUserLangID, bufstr );
|
||||
}
|
||||
|
||||
static UINT msi_load_summary_properties( MSIPACKAGE *package )
|
||||
|
@ -1637,7 +1648,7 @@ static HRESULT WINAPI mrp_SetMsiHandle( IWineMsiRemotePackage *iface, MSIHANDLE
|
|||
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 );
|
||||
IWineMsiRemoteDatabase *rdb = NULL;
|
||||
|
@ -1664,7 +1675,7 @@ HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *h
|
|||
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 );
|
||||
UINT r;
|
||||
|
@ -1676,63 +1687,63 @@ HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BST
|
|||
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 );
|
||||
UINT r = MsiSetPropertyW(This->package, (LPWSTR)property, (LPWSTR)value);
|
||||
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 );
|
||||
UINT r = MsiProcessMessage(This->package, message, record);
|
||||
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 );
|
||||
UINT r = MsiDoActionW(This->package, (LPWSTR)action);
|
||||
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 );
|
||||
UINT r = MsiSequenceW(This->package, (LPWSTR)table, sequence);
|
||||
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 );
|
||||
UINT r = MsiGetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
|
||||
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 );
|
||||
UINT r = MsiSetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value);
|
||||
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 );
|
||||
UINT r = MsiGetSourcePathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
|
||||
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 );
|
||||
*ret = MsiGetMode(This->package, mode);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
|
||||
static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
|
||||
INSTALLSTATE *installed, INSTALLSTATE *action )
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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 );
|
||||
UINT r = MsiSetFeatureStateW(This->package, (LPWSTR)feature, state);
|
||||
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 )
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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 );
|
||||
UINT r = MsiSetComponentStateW(This->package, (LPWSTR)component, state);
|
||||
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 );
|
||||
*language = MsiGetLanguage(This->package);
|
||||
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 );
|
||||
UINT r = MsiSetInstallLevel(This->package, level);
|
||||
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 )
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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 );
|
||||
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);
|
||||
|
||||
if( iField > rec->count )
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
{
|
||||
if ( szValue && *pcchValue > 0 )
|
||||
szValue[0] = 0;
|
||||
|
||||
*pcchValue = 0;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
ret = ERROR_SUCCESS;
|
||||
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);
|
||||
|
||||
if( iField > rec->count )
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
{
|
||||
if ( szValue && *pcchValue > 0 )
|
||||
szValue[0] = 0;
|
||||
|
||||
*pcchValue = 0;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
ret = ERROR_SUCCESS;
|
||||
switch( rec->fields[iField].type )
|
||||
|
@ -661,7 +673,7 @@ UINT MSI_RecordSetStream(MSIRECORD *rec, UINT iField, IStream *stream)
|
|||
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;
|
||||
HRESULT r;
|
||||
|
|
|
@ -52,14 +52,6 @@ static const WCHAR szUserFeatures_fmt[] = {
|
|||
'F','e','a','t','u','r','e','s','\\',
|
||||
'%','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[] = {
|
||||
'S','o','f','t','w','a','r','e','\\',
|
||||
'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','\\',
|
||||
'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[] = {
|
||||
'S','o','f','t','w','a','r','e','\\',
|
||||
'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','\\',
|
||||
'P','r','o','d','u','c','t','s','\\','%','s',0};
|
||||
|
||||
#define SQUISH_GUID_SIZE 33
|
||||
|
||||
BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
|
||||
{
|
||||
DWORD i,n=0;
|
||||
|
@ -610,11 +591,6 @@ UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct)
|
|||
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 rc;
|
||||
|
@ -671,27 +647,6 @@ UINT MSIREG_OpenComponents(HKEY* 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 rc;
|
||||
|
@ -853,11 +808,6 @@ UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct)
|
|||
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 rc;
|
||||
|
@ -1182,7 +1132,7 @@ UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
|
|||
if (NULL == lpguid)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
r = MSIREG_OpenProducts(&hkeyProducts);
|
||||
r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_Products, &hkeyProducts);
|
||||
if( r != ERROR_SUCCESS )
|
||||
return ERROR_NO_MORE_ITEMS;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -29,6 +29,7 @@
|
|||
#include "msiquery.h"
|
||||
#include "objbase.h"
|
||||
#include "msipriv.h"
|
||||
#include "query.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
|
@ -39,7 +40,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msidb);
|
|||
|
||||
typedef struct tabSTREAM
|
||||
{
|
||||
int str_index;
|
||||
UINT str_index;
|
||||
LPWSTR name;
|
||||
IStream *stream;
|
||||
} STREAM;
|
||||
|
@ -54,7 +55,7 @@ typedef struct tagMSISTREAMSVIEW
|
|||
UINT row_size;
|
||||
} 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)
|
||||
{
|
||||
|
@ -372,7 +373,7 @@ static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRE
|
|||
static UINT STREAMS_delete(struct tagMSIVIEW *view)
|
||||
{
|
||||
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
|
||||
int i;
|
||||
UINT i;
|
||||
|
||||
TRACE("(%p)\n", view);
|
||||
|
||||
|
@ -439,7 +440,7 @@ static const MSIVIEWOPS streams_ops =
|
|||
NULL,
|
||||
};
|
||||
|
||||
static UINT add_streams_to_table(MSISTREAMSVIEW *sv)
|
||||
static INT add_streams_to_table(MSISTREAMSVIEW *sv)
|
||||
{
|
||||
IEnumSTATSTG *stgenum = NULL;
|
||||
STATSTG stat;
|
||||
|
@ -498,6 +499,7 @@ static UINT add_streams_to_table(MSISTREAMSVIEW *sv)
|
|||
UINT STREAMS_CreateView(MSIDATABASE *db, MSIVIEW **view)
|
||||
{
|
||||
MSISTREAMSVIEW *sv;
|
||||
INT rows;
|
||||
|
||||
TRACE("(%p, %p)\n", db, view);
|
||||
|
||||
|
@ -507,10 +509,10 @@ UINT STREAMS_CreateView(MSIDATABASE *db, MSIVIEW **view)
|
|||
|
||||
sv->view.ops = &streams_ops;
|
||||
sv->db = db;
|
||||
sv->num_rows = add_streams_to_table(sv);
|
||||
|
||||
if (sv->num_rows < 0)
|
||||
rows = add_streams_to_table(sv);
|
||||
if (rows < 0)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
sv->num_rows = rows;
|
||||
|
||||
*view = (MSIVIEW *)sv;
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "msidefs.h"
|
||||
#include "msipriv.h"
|
||||
#include "objidl.h"
|
||||
#include "propvarutil.h"
|
||||
#include "msiserver.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||
|
@ -78,6 +79,10 @@ typedef struct {
|
|||
|
||||
#include "poppack.h"
|
||||
|
||||
static HRESULT (WINAPI *pPropVariantChangeType)
|
||||
(PROPVARIANT *ppropvarDest, REFPROPVARIANT propvarSrc,
|
||||
PROPVAR_CHANGE_FLAGS flags, VARTYPE vt);
|
||||
|
||||
#define SECT_HDR_SIZE (sizeof(PROPERTYSECTIONHEADER))
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
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;
|
||||
int size;
|
||||
PROPERTY_DATA *propdata;
|
||||
PROPVARIANT *property;
|
||||
PROPVARIANT property, *ptr;
|
||||
PROPVARIANT changed;
|
||||
PROPERTYIDOFFSET *idofs;
|
||||
PROPERTYSECTIONHEADER *section_hdr;
|
||||
|
||||
|
@ -161,6 +183,12 @@ static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz
|
|||
/* now set all the properties */
|
||||
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 );
|
||||
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 ];
|
||||
|
||||
/* 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 */
|
||||
size = sz - idofs[i].dwOffset - sizeof(DWORD);
|
||||
if( sizeof(DWORD) > size ||
|
||||
( type == VT_FILETIME && sizeof(FILETIME) > size ) ||
|
||||
( type == VT_LPSTR && (propdata->u.str.len + sizeof(DWORD)) > size ) )
|
||||
( propdata->type == VT_FILETIME && sizeof(FILETIME) > size ) ||
|
||||
( propdata->type == VT_LPSTR && (propdata->u.str.len + sizeof(DWORD)) > size ) )
|
||||
{
|
||||
ERR("not enough data\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if( idofs[i].propid >= MSI_MAX_PROPS )
|
||||
{
|
||||
ERR("Unknown property ID %d\n", idofs[i].propid );
|
||||
break;
|
||||
}
|
||||
|
||||
property = &prop[ idofs[i].propid ];
|
||||
property->vt = type;
|
||||
|
||||
if( type == VT_LPSTR )
|
||||
property.vt = propdata->type;
|
||||
if( propdata->type == VT_LPSTR )
|
||||
{
|
||||
LPSTR str = msi_alloc( propdata->u.str.len );
|
||||
memcpy( str, propdata->u.str.str, propdata->u.str.len );
|
||||
str[ propdata->u.str.len - 1 ] = 0;
|
||||
property->u.pszVal = str;
|
||||
property.u.pszVal = str;
|
||||
}
|
||||
else if( type == VT_FILETIME )
|
||||
property->u.filetime = propdata->u.ft;
|
||||
else if( type == VT_I2 )
|
||||
property->u.iVal = propdata->u.i2;
|
||||
else if( type == VT_I4 )
|
||||
property->u.lVal = propdata->u.i4;
|
||||
else if( propdata->type == VT_FILETIME )
|
||||
property.u.filetime = propdata->u.ft;
|
||||
else if( propdata->type == VT_I2 )
|
||||
property.u.iVal = propdata->u.i2;
|
||||
else if( propdata->type == VT_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 */
|
||||
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;
|
||||
r = IStream_Write( stm, &format_hdr, sz, &count );
|
||||
if( FAILED(r) || count != sz )
|
||||
|
@ -600,7 +624,7 @@ static UINT get_prop( MSIHANDLE handle, UINT uiProperty, UINT *puiDataType,
|
|||
break;
|
||||
case VT_FILETIME:
|
||||
if( pftValue )
|
||||
memcpy(pftValue, &prop->u.filetime, sizeof (FILETIME) );
|
||||
*pftValue = prop->u.filetime;
|
||||
break;
|
||||
case VT_EMPTY:
|
||||
break;
|
||||
|
@ -721,7 +745,7 @@ static UINT set_prop( MSIHANDLE handle, UINT uiProperty, UINT uiDataType,
|
|||
prop->u.iVal = iValue;
|
||||
break;
|
||||
case VT_FILETIME:
|
||||
memcpy( &prop->u.filetime, pftValue, sizeof prop->u.filetime );
|
||||
prop->u.filetime = *pftValue;
|
||||
break;
|
||||
case VT_LPSTR:
|
||||
if( str->unicode )
|
||||
|
|
|
@ -923,7 +923,7 @@ static UINT get_defaulttablecolumns( LPCWSTR name, MSICOLUMNINFO *colinfo, UINT
|
|||
{
|
||||
if (colinfo && (i < *sz) )
|
||||
{
|
||||
memcpy( &colinfo[i], &p[i], sizeof(MSICOLUMNINFO) );
|
||||
colinfo[i] = p[i];
|
||||
colinfo[i].tablename = strdupW( p[i].tablename );
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
MSIRECORD *rec, UINT row)
|
||||
{
|
||||
|
@ -1657,11 +1674,14 @@ static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
|
|||
r = TABLE_insert_row( view, rec, TRUE );
|
||||
break;
|
||||
|
||||
case MSIMODIFY_REFRESH:
|
||||
r = msi_refresh_record( view, rec, row );
|
||||
break;
|
||||
|
||||
case MSIMODIFY_UPDATE:
|
||||
r = msi_table_update( view, rec, row );
|
||||
break;
|
||||
|
||||
case MSIMODIFY_REFRESH:
|
||||
case MSIMODIFY_ASSIGN:
|
||||
case MSIMODIFY_REPLACE:
|
||||
case MSIMODIFY_MERGE:
|
||||
|
@ -2034,6 +2054,9 @@ static UINT TABLE_sort(struct tagMSIVIEW *view, column_info *columns)
|
|||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
if (rows == 0)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
order = msi_alloc_zero(sizeof(MSIORDERINFO) + sizeof(UINT) * cols);
|
||||
if (!order)
|
||||
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]))
|
||||
{
|
||||
ERR("Row not found in hash table!\n");
|
||||
WARN("Row not found in hash table!\n");
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -503,12 +503,15 @@ static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
|
|||
MSIRECORD *rec, UINT row )
|
||||
{
|
||||
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 )
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
r = WHERE_execute(view, NULL);
|
||||
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 );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue