Autosyncing with Wine HEAD

svn path=/trunk/; revision=32849
This commit is contained in:
The Wine Synchronizer 2008-04-04 13:43:40 +00:00
parent 5ef42dd10a
commit e1e678b0f2
25 changed files with 1872 additions and 746 deletions

View file

@ -18,14 +18,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
/*
* Pages I need
*
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/installexecutesequence_table.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/standard_actions_reference.asp
*/
#include <stdarg.h> #include <stdarg.h>
#define COBJMACROS #define COBJMACROS
@ -55,6 +47,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran); static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
static UINT ACTION_ProcessUISequence(MSIPACKAGE *package); static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI); static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI);
static BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action, UINT* rc, BOOL force);
/* /*
* consts and values used * consts and values used
@ -241,8 +234,6 @@ struct _actions {
STANDARDACTIONHANDLER handler; STANDARDACTIONHANDLER handler;
}; };
static const struct _actions StandardActions[];
/******************************************************** /********************************************************
* helper functions * helper functions
@ -573,7 +564,7 @@ static UINT msi_apply_transforms( MSIPACKAGE *package )
for( i=0; xforms && xforms[i] && r == ERROR_SUCCESS; i++ ) for( i=0; xforms && xforms[i] && r == ERROR_SUCCESS; i++ )
{ {
if (xforms[i][0] == ':') if (xforms[i][0] == ':')
r = msi_apply_substorage_transform( package, package->db, &xforms[i][1] ); r = msi_apply_substorage_transform( package, package->db, xforms[i] );
else else
r = MSI_DatabaseApplyTransformW( package->db, xforms[i], 0 ); r = MSI_DatabaseApplyTransformW( package->db, xforms[i], 0 );
} }
@ -584,7 +575,7 @@ static UINT msi_apply_transforms( MSIPACKAGE *package )
return r; return r;
} }
BOOL ui_sequence_exists( MSIPACKAGE *package ) static BOOL ui_sequence_exists( MSIPACKAGE *package )
{ {
MSIQUERY *view; MSIQUERY *view;
UINT rc; UINT rc;
@ -973,56 +964,6 @@ static UINT ACTION_ProcessUISequence(MSIPACKAGE *package)
/******************************************************** /********************************************************
* ACTION helper functions and functions that perform the actions * ACTION helper functions and functions that perform the actions
*******************************************************/ *******************************************************/
static BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action,
UINT* rc, BOOL force )
{
BOOL ret = FALSE;
BOOL run = force;
int i;
if (!run && !package->script->CurrentlyScripting)
run = TRUE;
if (!run)
{
if (strcmpW(action,szInstallFinalize) == 0 ||
strcmpW(action,szInstallExecute) == 0 ||
strcmpW(action,szInstallExecuteAgain) == 0)
run = TRUE;
}
i = 0;
while (StandardActions[i].action != NULL)
{
if (strcmpW(StandardActions[i].action, action)==0)
{
if (!run)
{
ui_actioninfo(package, action, TRUE, 0);
*rc = schedule_action(package,INSTALL_SCRIPT,action);
ui_actioninfo(package, action, FALSE, *rc);
}
else
{
ui_actionstart(package, action);
if (StandardActions[i].handler)
{
*rc = StandardActions[i].handler(package);
}
else
{
FIXME("unhandled standard action %s\n",debugstr_w(action));
*rc = ERROR_SUCCESS;
}
}
ret = TRUE;
break;
}
i++;
}
return ret;
}
static BOOL ACTION_HandleCustomAction( MSIPACKAGE* package, LPCWSTR action, static BOOL ACTION_HandleCustomAction( MSIPACKAGE* package, LPCWSTR action,
UINT* rc, UINT script, BOOL force ) UINT* rc, UINT script, BOOL force )
{ {
@ -1061,7 +1002,7 @@ UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, UINT script,
if (!handled) if (!handled)
{ {
FIXME("unhandled msi action %s\n",debugstr_w(action)); WARN("unhandled msi action %s\n",debugstr_w(action));
rc = ERROR_FUNCTION_NOT_CALLED; rc = ERROR_FUNCTION_NOT_CALLED;
} }
@ -1085,7 +1026,7 @@ UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action, UINT scrip
if (!handled) if (!handled)
{ {
FIXME("unhandled msi action %s\n",debugstr_w(action)); WARN("unhandled msi action %s\n",debugstr_w(action));
rc = ERROR_FUNCTION_NOT_CALLED; rc = ERROR_FUNCTION_NOT_CALLED;
} }
@ -2322,7 +2263,6 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type,
{ {
static const WCHAR szMulti[] = {'[','~',']',0}; static const WCHAR szMulti[] = {'[','~',']',0};
LPCWSTR ptr; LPCWSTR ptr;
LPWSTR newdata;
*type=REG_SZ; *type=REG_SZ;
if (value[0]=='#') if (value[0]=='#')
@ -2350,19 +2290,8 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type,
/* add double NULL terminator */ /* add double NULL terminator */
if (*type == REG_MULTI_SZ) if (*type == REG_MULTI_SZ)
{ {
*size += sizeof(WCHAR); *size += 2 * sizeof(WCHAR); /* two NULL terminators */
newdata = msi_alloc(*size); data = msi_realloc_zero(data, *size);
if (!newdata)
{
msi_free(data);
return NULL;
}
memcpy(newdata, data, *size - 1);
newdata[*size] = '\0';
msi_free(data);
data = (LPSTR)newdata;
} }
} }
return data; return data;
@ -2503,10 +2432,6 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
deformat_string(package, name, &deformated); deformat_string(package, name, &deformated);
/* get the double nulls to terminate SZ_MULTI */
if (type == REG_MULTI_SZ)
size +=sizeof(WCHAR);
if (!check_first) if (!check_first)
{ {
TRACE("Setting value %s of %s\n",debugstr_w(deformated), TRACE("Setting value %s of %s\n",debugstr_w(deformated),
@ -3379,6 +3304,7 @@ static BOOL msi_check_publish(MSIPACKAGE *package)
static UINT ACTION_PublishProduct(MSIPACKAGE *package) static UINT ACTION_PublishProduct(MSIPACKAGE *package)
{ {
UINT rc; UINT rc;
LPWSTR packname;
MSIQUERY * view; MSIQUERY * view;
MSISOURCELISTINFO *info; MSISOURCELISTINFO *info;
MSIMEDIADISK *disk; MSIMEDIADISK *disk;
@ -3389,12 +3315,16 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
HKEY hkey=0; HKEY hkey=0;
HKEY hukey=0; HKEY hukey=0;
HKEY hudkey=0, props=0; HKEY hudkey=0, props=0;
HKEY source;
static const WCHAR szProductLanguage[] = static const WCHAR szProductLanguage[] =
{'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0}; {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
static const WCHAR szARPProductIcon[] = static const WCHAR szARPProductIcon[] =
{'A','R','P','P','R','O','D','U','C','T','I','C','O','N',0}; {'A','R','P','P','R','O','D','U','C','T','I','C','O','N',0};
static const WCHAR szProductVersion[] = static const WCHAR szProductVersion[] =
{'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0}; {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
static const WCHAR szSourceList[] =
{'S','o','u','r','c','e','L','i','s','t',0};
static const WCHAR szEmpty[] = {0};
DWORD langid; DWORD langid;
LPWSTR buffer; LPWSTR buffer;
DWORD size; DWORD size;
@ -3423,6 +3353,12 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
goto end; goto end;
rc = RegCreateKeyW(hukey, szSourceList, &source);
if (rc != ERROR_SUCCESS)
goto end;
RegCloseKey(source);
rc = MSIREG_OpenUserDataProductKey(package->ProductCode,&hudkey,TRUE); rc = MSIREG_OpenUserDataProductKey(package->ProductCode,&hudkey,TRUE);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
goto end; goto end;
@ -3436,7 +3372,14 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
msi_free(buffer); msi_free(buffer);
langid = msi_get_property_int( package, szProductLanguage, 0 ); langid = msi_get_property_int( package, szProductLanguage, 0 );
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_LANGUAGEW, langid ); msi_reg_set_val_dword( hukey, INSTALLPROPERTY_LANGUAGEW, langid );
packname = strrchrW( package->PackagePath, '\\' ) + 1;
msi_reg_set_val_str( hukey, INSTALLPROPERTY_PACKAGENAMEW, packname );
/* FIXME */
msi_reg_set_val_dword( hukey, INSTALLPROPERTY_AUTHORIZED_LUA_APPW, 0 );
msi_reg_set_val_dword( props, INSTALLPROPERTY_INSTANCETYPEW, 0 );
buffer = msi_dup_property( package, szARPProductIcon ); buffer = msi_dup_property( package, szARPProductIcon );
if (buffer) if (buffer)
@ -3451,10 +3394,29 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
if (buffer) if (buffer)
{ {
DWORD verdword = msi_version_str_to_dword(buffer); DWORD verdword = msi_version_str_to_dword(buffer);
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONW, verdword ); msi_reg_set_val_dword( hukey, INSTALLPROPERTY_VERSIONW, verdword );
} }
msi_free(buffer); msi_free(buffer);
buffer = strrchrW( package->PackagePath, '\\') + 1;
rc = MsiSourceListSetInfoW( package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
INSTALLPROPERTY_PACKAGENAMEW, buffer );
if (rc != ERROR_SUCCESS)
goto end;
rc = MsiSourceListSetInfoW( package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
INSTALLPROPERTY_MEDIAPACKAGEPATHW, szEmpty );
if (rc != ERROR_SUCCESS)
goto end;
rc = MsiSourceListSetInfoW( package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
INSTALLPROPERTY_DISKPROMPTW, szEmpty );
if (rc != ERROR_SUCCESS)
goto end;
/* FIXME: Need to write more keys to the user registry */ /* FIXME: Need to write more keys to the user registry */
hDb= alloc_msihandle( &package->db->hdr ); hDb= alloc_msihandle( &package->db->hdr );
@ -3472,12 +3434,10 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
guidbuffer, &size); guidbuffer, &size);
if (rc == ERROR_SUCCESS) if (rc == ERROR_SUCCESS)
{ {
WCHAR squashed[GUID_SIZE];
/* for now we only care about the first guid */ /* for now we only care about the first guid */
LPWSTR ptr = strchrW(guidbuffer,';'); LPWSTR ptr = strchrW(guidbuffer,';');
if (ptr) *ptr = 0; if (ptr) *ptr = 0;
squash_guid(guidbuffer,squashed); msi_reg_set_val_str( hukey, INSTALLPROPERTY_PACKAGECODEW, guidbuffer );
msi_reg_set_val_str( hukey, INSTALLPROPERTY_PACKAGECODEW, squashed );
} }
else else
{ {
@ -3495,9 +3455,13 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
/* publish the SourceList info */ /* publish the SourceList info */
LIST_FOR_EACH_ENTRY(info, &package->sourcelist_info, MSISOURCELISTINFO, entry) LIST_FOR_EACH_ENTRY(info, &package->sourcelist_info, MSISOURCELISTINFO, entry)
{ {
MsiSourceListSetInfoW(package->ProductCode, NULL, if (!lstrcmpW(info->property, INSTALLPROPERTY_LASTUSEDSOURCEW))
info->context, info->options, msi_set_last_used_source(package->ProductCode, NULL, info->context,
info->property, info->value); info->options, info->value);
else
MsiSourceListSetInfoW(package->ProductCode, NULL,
info->context, info->options,
info->property, info->value);
} }
LIST_FOR_EACH_ENTRY(disk, &package->sourcelist_media, MSIMEDIADISK, entry) LIST_FOR_EACH_ENTRY(disk, &package->sourcelist_media, MSIMEDIADISK, entry)
@ -4000,6 +3964,14 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
{'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0}; {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
static const WCHAR szProductVersion[] = static const WCHAR szProductVersion[] =
{'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0}; {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
static const WCHAR szProductName[] =
{'P','r','o','d','u','c','t','N','a','m','e',0};
static const WCHAR szDisplayName[] =
{'D','i','s','p','l','a','y','N','a','m','e',0};
static const WCHAR szDisplayVersion[] =
{'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
static const WCHAR szManufacturer[] =
{'M','a','n','u','f','a','c','t','u','r','e','r',0};
SYSTEMTIME systime; SYSTEMTIME systime;
static const WCHAR date_fmt[] = {'%','i','%','0','2','i','%','0','2','i',0}; static const WCHAR date_fmt[] = {'%','i','%','0','2','i','%','0','2','i',0};
@ -4014,6 +3986,10 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
return rc; return rc;
rc = MSIREG_OpenInstallPropertiesKey(package->ProductCode, &props, TRUE);
if (rc != ERROR_SUCCESS)
return rc;
/* dump all the info i can grab */ /* dump all the info i can grab */
/* FIXME: Flesh out more information */ /* FIXME: Flesh out more information */
@ -4031,22 +4007,39 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
/* FIXME: Write real Estimated Size when we have it */ /* FIXME: Write real Estimated Size when we have it */
msi_reg_set_val_dword( hkey, szEstimatedSize, 0 ); msi_reg_set_val_dword( hkey, szEstimatedSize, 0 );
buffer = msi_dup_property( package, szProductName );
msi_reg_set_val_str( props, szDisplayName, buffer );
msi_free(buffer);
buffer = msi_dup_property( package, cszSourceDir );
msi_reg_set_val_str( props, INSTALLPROPERTY_INSTALLSOURCEW, buffer);
msi_free(buffer);
buffer = msi_dup_property( package, szManufacturer );
msi_reg_set_val_str( props, INSTALLPROPERTY_PUBLISHERW, buffer);
msi_free(buffer);
GetLocalTime(&systime); GetLocalTime(&systime);
sprintfW(szDate,date_fmt,systime.wYear,systime.wMonth,systime.wDay); sprintfW(szDate,date_fmt,systime.wYear,systime.wMonth,systime.wDay);
msi_reg_set_val_str( hkey, INSTALLPROPERTY_INSTALLDATEW, szDate ); msi_reg_set_val_str( hkey, INSTALLPROPERTY_INSTALLDATEW, szDate );
msi_reg_set_val_str( props, INSTALLPROPERTY_INSTALLDATEW, szDate );
langid = msi_get_property_int( package, szProductLanguage, 0 ); langid = msi_get_property_int( package, szProductLanguage, 0 );
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_LANGUAGEW, langid ); msi_reg_set_val_dword( hkey, INSTALLPROPERTY_LANGUAGEW, langid );
buffer = msi_dup_property( package, szProductVersion ); buffer = msi_dup_property( package, szProductVersion );
msi_reg_set_val_str( props, szDisplayVersion, buffer );
if (buffer) if (buffer)
{ {
DWORD verdword = msi_version_str_to_dword(buffer); DWORD verdword = msi_version_str_to_dword(buffer);
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONW, verdword ); msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONW, verdword );
msi_reg_set_val_dword( props, INSTALLPROPERTY_VERSIONW, verdword );
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONMAJORW, verdword>>24 ); msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONMAJORW, verdword>>24 );
msi_reg_set_val_dword( props, INSTALLPROPERTY_VERSIONMAJORW, verdword>>24 );
msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONMINORW, (verdword>>16)&0x00FF ); msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONMINORW, (verdword>>16)&0x00FF );
msi_reg_set_val_dword( props, INSTALLPROPERTY_VERSIONMINORW, (verdword>>16)&0x00FF );
} }
msi_free(buffer); msi_free(buffer);
@ -4076,10 +4069,6 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
RegCloseKey(hudkey); RegCloseKey(hudkey);
rc = MSIREG_OpenInstallPropertiesKey(package->ProductCode, &props, TRUE);
if (rc != ERROR_SUCCESS)
return rc;
msi_reg_set_val_dword( props, szWindowsInstaller, 1 ); msi_reg_set_val_dword( props, szWindowsInstaller, 1 );
RegCloseKey(props); RegCloseKey(props);
@ -4232,13 +4221,13 @@ static UINT ACTION_ResolveSource(MSIPACKAGE* package)
DWORD size = 0; DWORD size = 0;
rc = MsiSourceListGetInfoW(package->ProductCode, NULL, rc = MsiSourceListGetInfoW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
INSTALLPROPERTY_DISKPROMPTW,NULL,&size); INSTALLPROPERTY_DISKPROMPTW,NULL,&size);
if (rc == ERROR_MORE_DATA) if (rc == ERROR_MORE_DATA)
{ {
prompt = msi_alloc(size * sizeof(WCHAR)); prompt = msi_alloc(size * sizeof(WCHAR));
MsiSourceListGetInfoW(package->ProductCode, NULL, MsiSourceListGetInfoW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
INSTALLPROPERTY_DISKPROMPTW,prompt,&size); INSTALLPROPERTY_DISKPROMPTW,prompt,&size);
} }
else else
@ -4287,11 +4276,17 @@ static UINT ACTION_RegisterUser(MSIPACKAGE *package)
{0}, {0},
}; };
if (msi_check_unpublish(package))
{
MSIREG_DeleteUserDataProductKey(package->ProductCode);
return ERROR_SUCCESS;
}
productid = msi_dup_property( package, INSTALLPROPERTY_PRODUCTIDW ); productid = msi_dup_property( package, INSTALLPROPERTY_PRODUCTIDW );
if (!productid) if (!productid)
return ERROR_SUCCESS; return ERROR_SUCCESS;
rc = MSIREG_OpenUninstallKey(package->ProductCode,&hkey,TRUE); rc = MSIREG_OpenInstallPropertiesKey(package->ProductCode, &hkey, TRUE);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
goto end; goto end;
@ -4308,7 +4303,7 @@ end:
/* FIXME: call ui_actiondata */ /* FIXME: call ui_actiondata */
return ERROR_SUCCESS; return rc;
} }
@ -4424,7 +4419,8 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
MSIRECORD *row; MSIRECORD *row;
MSIFILE *file; MSIFILE *file;
SC_HANDLE hscm, service = NULL; SC_HANDLE hscm, service = NULL;
LPCWSTR name, disp, comp, depends, pass; LPCWSTR comp, depends, pass;
LPWSTR name = NULL, disp = NULL;
LPCWSTR load_order, serv_name, key; LPCWSTR load_order, serv_name, key;
DWORD serv_type, start_type; DWORD serv_type, start_type;
DWORD err_control; DWORD err_control;
@ -4451,8 +4447,8 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
if (depends && *depends) if (depends && *depends)
FIXME("Dependency list unhandled!\n"); FIXME("Dependency list unhandled!\n");
name = MSI_RecordGetString(rec, 2); deformat_string(package, MSI_RecordGetString(rec, 2), &name);
disp = MSI_RecordGetString(rec, 3); deformat_string(package, MSI_RecordGetString(rec, 3), &disp);
serv_type = MSI_RecordGetInteger(rec, 4); serv_type = MSI_RecordGetInteger(rec, 4);
err_control = MSI_RecordGetInteger(rec, 6); err_control = MSI_RecordGetInteger(rec, 6);
load_order = MSI_RecordGetString(rec, 7); load_order = MSI_RecordGetString(rec, 7);
@ -4490,6 +4486,8 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
done: done:
CloseServiceHandle(service); CloseServiceHandle(service);
CloseServiceHandle(hscm); CloseServiceHandle(hscm);
msi_free(name);
msi_free(disp);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -4629,6 +4627,130 @@ static UINT ACTION_StartServices( MSIPACKAGE *package )
return rc; return rc;
} }
static BOOL stop_service_dependents(SC_HANDLE scm, SC_HANDLE service)
{
DWORD i, needed, count;
ENUM_SERVICE_STATUSW *dependencies;
SERVICE_STATUS ss;
SC_HANDLE depserv;
if (EnumDependentServicesW(service, SERVICE_ACTIVE, NULL,
0, &needed, &count))
return TRUE;
if (GetLastError() != ERROR_MORE_DATA)
return FALSE;
dependencies = msi_alloc(needed);
if (!dependencies)
return FALSE;
if (!EnumDependentServicesW(service, SERVICE_ACTIVE, dependencies,
needed, &needed, &count))
goto error;
for (i = 0; i < count; i++)
{
depserv = OpenServiceW(scm, dependencies[i].lpServiceName,
SERVICE_STOP | SERVICE_QUERY_STATUS);
if (!depserv)
goto error;
if (!ControlService(depserv, SERVICE_CONTROL_STOP, &ss))
goto error;
}
return TRUE;
error:
msi_free(dependencies);
return FALSE;
}
static UINT ITERATE_StopService(MSIRECORD *rec, LPVOID param)
{
MSIPACKAGE *package = (MSIPACKAGE *)param;
MSICOMPONENT *comp;
SERVICE_STATUS status;
SERVICE_STATUS_PROCESS ssp;
SC_HANDLE scm = NULL, service = NULL;
LPWSTR name, args;
DWORD event, needed;
event = MSI_RecordGetInteger(rec, 3);
if (!(event & msidbServiceControlEventStop))
return ERROR_SUCCESS;
comp = get_loaded_component(package, MSI_RecordGetString(rec, 6));
if (!comp || comp->Action == INSTALLSTATE_UNKNOWN || comp->Action == INSTALLSTATE_ABSENT)
return ERROR_SUCCESS;
deformat_string(package, MSI_RecordGetString(rec, 2), &name);
deformat_string(package, MSI_RecordGetString(rec, 4), &args);
args = strdupW(MSI_RecordGetString(rec, 4));
scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (!scm)
{
WARN("Failed to open the SCM: %d\n", GetLastError());
goto done;
}
service = OpenServiceW(scm, name,
SERVICE_STOP |
SERVICE_QUERY_STATUS |
SERVICE_ENUMERATE_DEPENDENTS);
if (!service)
{
WARN("Failed to open service (%s): %d\n",
debugstr_w(name), GetLastError());
goto done;
}
if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS), &needed))
{
WARN("Failed to query service status (%s): %d\n",
debugstr_w(name), GetLastError());
goto done;
}
if (ssp.dwCurrentState == SERVICE_STOPPED)
goto done;
stop_service_dependents(scm, service);
if (!ControlService(service, SERVICE_CONTROL_STOP, &status))
WARN("Failed to stop service (%s): %d\n", debugstr_w(name), GetLastError());
done:
CloseServiceHandle(service);
CloseServiceHandle(scm);
msi_free(name);
msi_free(args);
return ERROR_SUCCESS;
}
static UINT ACTION_StopServices( MSIPACKAGE *package )
{
UINT rc;
MSIQUERY *view;
static const WCHAR query[] = {
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'S','e','r','v','i','c','e','C','o','n','t','r','o','l',0 };
rc = MSI_DatabaseOpenViewW(package->db, query, &view);
if (rc != ERROR_SUCCESS)
return ERROR_SUCCESS;
rc = MSI_IterateRecords(view, NULL, ITERATE_StopService, package);
msiobj_release(&view->hdr);
return rc;
}
static MSIFILE *msi_find_file( MSIPACKAGE *package, LPCWSTR filename ) static MSIFILE *msi_find_file( MSIPACKAGE *package, LPCWSTR filename )
{ {
MSIFILE *file; MSIFILE *file;
@ -5211,7 +5333,7 @@ static BOOL add_wildcard(FILE_LIST *files, LPWSTR source, LPWSTR dest)
return TRUE; return TRUE;
} }
BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options) static BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options)
{ {
WIN32_FIND_DATAW wfd; WIN32_FIND_DATAW wfd;
HANDLE hfile; HANDLE hfile;
@ -5240,6 +5362,10 @@ BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options)
msi_free(path); msi_free(path);
} }
/* no files match the wildcard */
if (list_empty(&files.entry))
goto done;
/* only the first wildcard match gets renamed to dest */ /* only the first wildcard match gets renamed to dest */
file = LIST_ENTRY(list_head(&files.entry), FILE_LIST, entry); file = LIST_ENTRY(list_head(&files.entry), FILE_LIST, entry);
size = (strrchrW(file->dest, '\\') - file->dest) + lstrlenW(file->destname) + 2; size = (strrchrW(file->dest, '\\') - file->dest) + lstrlenW(file->destname) + 2;
@ -5461,13 +5587,6 @@ static UINT ACTION_SelfUnregModules( MSIPACKAGE *package )
return msi_unimplemented_action_stub( package, "SelfUnregModules", table ); return msi_unimplemented_action_stub( package, "SelfUnregModules", table );
} }
static UINT ACTION_StopServices( MSIPACKAGE *package )
{
static const WCHAR table[] = {
'S','e','r','v','i','c','e','C','o','n','t','r','o','l',0 };
return msi_unimplemented_action_stub( package, "StopServices", table );
}
static UINT ACTION_DeleteServices( MSIPACKAGE *package ) static UINT ACTION_DeleteServices( MSIPACKAGE *package )
{ {
static const WCHAR table[] = { static const WCHAR table[] = {
@ -5682,3 +5801,53 @@ static const struct _actions StandardActions[] = {
{ szWriteRegistryValues, ACTION_WriteRegistryValues }, { szWriteRegistryValues, ACTION_WriteRegistryValues },
{ NULL, NULL }, { NULL, NULL },
}; };
static BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action,
UINT* rc, BOOL force )
{
BOOL ret = FALSE;
BOOL run = force;
int i;
if (!run && !package->script->CurrentlyScripting)
run = TRUE;
if (!run)
{
if (strcmpW(action,szInstallFinalize) == 0 ||
strcmpW(action,szInstallExecute) == 0 ||
strcmpW(action,szInstallExecuteAgain) == 0)
run = TRUE;
}
i = 0;
while (StandardActions[i].action != NULL)
{
if (strcmpW(StandardActions[i].action, action)==0)
{
if (!run)
{
ui_actioninfo(package, action, TRUE, 0);
*rc = schedule_action(package,INSTALL_SCRIPT,action);
ui_actioninfo(package, action, FALSE, *rc);
}
else
{
ui_actionstart(package, action);
if (StandardActions[i].handler)
{
*rc = StandardActions[i].handler(package);
}
else
{
FIXME("unhandled standard action %s\n",debugstr_w(action));
*rc = ERROR_SUCCESS;
}
}
ret = TRUE;
break;
}
i++;
}
return ret;
}

View file

@ -901,9 +901,6 @@ static UINT iterate_appsearch(MSIRECORD *row, LPVOID param)
return r; return r;
} }
/* http://msdn.microsoft.com/library/en-us/msi/setup/appsearch_table.asp
* is the best reference for the AppSearch table and how it's used.
*/
UINT ACTION_AppSearch(MSIPACKAGE *package) UINT ACTION_AppSearch(MSIPACKAGE *package)
{ {
static const WCHAR query[] = { static const WCHAR query[] = {

View file

@ -39,6 +39,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
#define REG_INDEX_CLASSES_ROOT 0
#define REG_INDEX_DYN_DATA 6
/* /*
* AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
* called from AutomationObject::Invoke, and pass this function to create_automation_object. * called from AutomationObject::Invoke, and pass this function to create_automation_object.
@ -150,7 +153,7 @@ HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID
/* Create the automation object, placing the result in the pointer ppObj. The automation object is created /* Create the automation object, placing the result in the pointer ppObj. The automation object is created
* with the appropriate clsid and invocation function. */ * with the appropriate clsid and invocation function. */
HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter, LPVOID *ppObj, REFIID clsid, static HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter, LPVOID *ppObj, REFIID clsid,
HRESULT (STDMETHODCALLTYPE *funcInvoke)(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*, HRESULT (STDMETHODCALLTYPE *funcInvoke)(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,
VARIANT*,EXCEPINFO*,UINT*), VARIANT*,EXCEPINFO*,UINT*),
void (STDMETHODCALLTYPE *funcFree)(AutomationObject*), void (STDMETHODCALLTYPE *funcFree)(AutomationObject*),
@ -191,7 +194,7 @@ HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter, LPVOI
} }
/* Create a list enumerator, placing the result in the pointer ppObj. */ /* Create a list enumerator, placing the result in the pointer ppObj. */
HRESULT create_list_enumerator(IUnknown *pUnkOuter, LPVOID *ppObj, AutomationObject *pObj, ULONG ulPos) static HRESULT create_list_enumerator(IUnknown *pUnkOuter, LPVOID *ppObj, AutomationObject *pObj, ULONG ulPos)
{ {
ListEnumerator *object; ListEnumerator *object;
@ -705,7 +708,7 @@ static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl =
/* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam. /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
This function is only for VARIANT type parameters that have several types that cannot be properly discriminated This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
using DispGetParam/VariantChangeType. */ using DispGetParam/VariantChangeType. */
HRESULT WINAPI DispGetParam_CopyOnly( static HRESULT WINAPI DispGetParam_CopyOnly(
DISPPARAMS *pdispparams, /* [in] Parameter list */ DISPPARAMS *pdispparams, /* [in] Parameter list */
UINT *position, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */ UINT *position, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
VARIANT *pvarResult) /* [out] Destination for resulting variant */ VARIANT *pvarResult) /* [out] Destination for resulting variant */
@ -1535,6 +1538,7 @@ static HRESULT WINAPI InstallerImpl_Invoke(
HRESULT hr; HRESULT hr;
LPWSTR szString = NULL; LPWSTR szString = NULL;
DWORD dwSize = 0; DWORD dwSize = 0;
INSTALLUILEVEL ui;
VariantInit(&varg0); VariantInit(&varg0);
VariantInit(&varg1); VariantInit(&varg1);
@ -1627,6 +1631,31 @@ static HRESULT WINAPI InstallerImpl_Invoke(
else return DISP_E_MEMBERNOTFOUND; else return DISP_E_MEMBERNOTFOUND;
break; break;
case DISPID_INSTALLER_UILEVEL:
if (wFlags & DISPATCH_PROPERTYPUT)
{
hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
if (FAILED(hr)) return hr;
if ((ui = MsiSetInternalUI(V_I4(&varg0), NULL) == INSTALLUILEVEL_NOCHANGE))
{
ERR("MsiSetInternalUI failed\n");
return DISP_E_EXCEPTION;
}
}
else if (wFlags & DISPATCH_PROPERTYGET)
{
if ((ui = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL) == INSTALLUILEVEL_NOCHANGE))
{
ERR("MsiSetInternalUI failed\n");
return DISP_E_EXCEPTION;
}
V_VT(pVarResult) = VT_I4;
V_I4(pVarResult) = ui;
}
else return DISP_E_MEMBERNOTFOUND;
break;
case DISPID_INSTALLER_INSTALLPRODUCT: case DISPID_INSTALLER_INSTALLPRODUCT:
if (wFlags & DISPATCH_METHOD) if (wFlags & DISPATCH_METHOD)
{ {
@ -1685,6 +1714,11 @@ static HRESULT WINAPI InstallerImpl_Invoke(
VariantClear(&varg1); VariantClear(&varg1);
return hr; return hr;
} }
if (V_I4(&varg0) >= REG_INDEX_CLASSES_ROOT &&
V_I4(&varg0) <= REG_INDEX_DYN_DATA)
V_I4(&varg0) |= (UINT)HKEY_CLASSES_ROOT;
ret = RegOpenKeyW((HKEY)V_I4(&varg0), V_BSTR(&varg1), &hkey); ret = RegOpenKeyW((HKEY)V_I4(&varg0), V_BSTR(&varg1), &hkey);
/* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */ /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */

View file

@ -317,7 +317,11 @@ value_i:
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN; INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MSI_GetFeatureStateW(cond->package, $2, &install, &action ); MSI_GetFeatureStateW(cond->package, $2, &install, &action );
$$ = action; if (action == INSTALLSTATE_UNKNOWN)
$$ = MSICONDITION_FALSE;
else
$$ = action;
msi_free( $2 ); msi_free( $2 );
} }
| COND_EXCLAM identifier | COND_EXCLAM identifier

View file

@ -331,6 +331,9 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
msi_free(deformated); msi_free(deformated);
break; break;
case 51: /* Property set with formatted text. */ case 51: /* Property set with formatted text. */
if (!source)
break;
deformat_string(package,target,&deformated); deformat_string(package,target,&deformated);
rc = MSI_SetPropertyW(package,source,deformated); rc = MSI_SetPropertyW(package,source,deformated);
msi_free(deformated); msi_free(deformated);
@ -857,12 +860,6 @@ static UINT HANDLE_CustomType23(MSIPACKAGE *package, LPCWSTR source,
lstrcatW(package_path, backslash); lstrcatW(package_path, backslash);
lstrcatW(package_path, source); lstrcatW(package_path, source);
if (GetFileAttributesW(package_path) == INVALID_FILE_ATTRIBUTES)
{
ERR("Source package does not exist: %s\n", debugstr_w(package_path));
return ERROR_FUNCTION_FAILED;
}
TRACE("Installing package %s concurrently\n", debugstr_w(package_path)); TRACE("Installing package %s concurrently\n", debugstr_w(package_path));
info = do_msidbCAConcurrentInstall(package, type, package_path, target, action); info = do_msidbCAConcurrentInstall(package, type, package_path, target, action);

View file

@ -317,12 +317,18 @@ static void msi_parse_line(LPWSTR *line, LPWSTR **entries, DWORD *num_entries)
/* store pointers into the data */ /* store pointers into the data */
for (i = 0, ptr = *line; i < count; i++) for (i = 0, ptr = *line; i < count; i++)
{ {
while (*ptr && *ptr == '\r') ptr++;
save = ptr; save = ptr;
while (*ptr && *ptr != '\t' && *ptr != '\n') ptr++; while (*ptr && *ptr != '\t' && *ptr != '\n' && *ptr != '\r') ptr++;
/* NULL-separate the data */ /* NULL-separate the data */
if (*ptr) if (*ptr == '\n' || *ptr == '\r')
{
while (*ptr == '\n' || *ptr == '\r')
*(ptr++) = '\0';
}
else if (*ptr)
*ptr++ = '\0'; *ptr++ = '\0';
(*entries)[i] = save; (*entries)[i] = save;
@ -342,7 +348,7 @@ static LPWSTR msi_build_createsql_prelude(LPWSTR table)
static const WCHAR create_fmt[] = {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','%','s','`',' ','(',' ',0}; static const WCHAR create_fmt[] = {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','%','s','`',' ','(',' ',0};
size = sizeof(create_fmt) + lstrlenW(table) - 2; size = sizeof(create_fmt)/sizeof(create_fmt[0]) + lstrlenW(table) - 2;
prelude = msi_alloc(size * sizeof(WCHAR)); prelude = msi_alloc(size * sizeof(WCHAR));
if (!prelude) if (!prelude)
return NULL; return NULL;
@ -509,156 +515,88 @@ static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
return r; return r;
} }
static LPWSTR msi_build_insertsql_prelude(LPWSTR table) static UINT construct_record(DWORD num_columns, LPWSTR *types,
LPWSTR *data, MSIRECORD **rec)
{ {
LPWSTR prelude; UINT i;
DWORD size;
static const WCHAR insert_fmt[] = {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','%','s','`',' ','(',' ',0}; *rec = MSI_CreateRecord(num_columns);
if (!*rec)
size = sizeof(insert_fmt) + lstrlenW(table) - 2; return ERROR_OUTOFMEMORY;
prelude = msi_alloc(size * sizeof(WCHAR));
if (!prelude)
return NULL;
sprintfW(prelude, insert_fmt, table);
return prelude;
}
static LPWSTR msi_build_insertsql_columns(LPWSTR *columns_data, LPWSTR *types, DWORD num_columns)
{
LPWSTR columns, p;
DWORD sql_size = 1, i;
WCHAR expanded[128];
static const WCHAR column_fmt[] = {'`','%','s','`',',',' ',0};
columns = msi_alloc_zero(sql_size * sizeof(WCHAR));
if (!columns)
return NULL;
for (i = 0; i < num_columns; i++)
{
sprintfW(expanded, column_fmt, columns_data[i]);
sql_size += lstrlenW(expanded);
if (i == num_columns - 1)
{
sql_size -= 2;
expanded[lstrlenW(expanded) - 2] = '\0';
}
p = msi_realloc(columns, sql_size * sizeof(WCHAR));
if (!p)
{
msi_free(columns);
return NULL;
}
columns = p;
lstrcatW(columns, expanded);
}
return columns;
}
static LPWSTR msi_build_insertsql_data(LPWSTR **records, LPWSTR *types, DWORD num_columns, DWORD irec)
{
LPWSTR columns, temp_columns;
DWORD sql_size = 1, i;
WCHAR expanded[128];
static const WCHAR str_fmt[] = {'\'','%','s','\'',',',' ',0};
static const WCHAR int_fmt[] = {'%','s',',',' ',0};
static const WCHAR empty[] = {'\'','\'',',',' ',0};
columns = msi_alloc_zero(sql_size * sizeof(WCHAR));
if (!columns)
return NULL;
for (i = 0; i < num_columns; i++) for (i = 0; i < num_columns; i++)
{ {
switch (types[i][0]) switch (types[i][0])
{ {
case 'L': case 'l': case 'S': case 's': case 'L': case 'l': case 'S': case 's':
sprintfW(expanded, str_fmt, records[irec][i]); MSI_RecordSetStringW(*rec, i + 1, data[i]);
break; break;
case 'I': case 'i': case 'I': case 'i':
if (*records[0][i]) if (*data[i])
sprintfW(expanded, int_fmt, records[irec][i]); MSI_RecordSetInteger(*rec, i + 1, atoiW(data[i]));
else
lstrcpyW(expanded, empty);
break; break;
default: default:
HeapFree( GetProcessHeap(), 0, columns ); ERR("Unhandled column type: %c\n", types[i][0]);
return NULL; msiobj_release(&(*rec)->hdr);
return ERROR_FUNCTION_FAILED;
} }
if (i == num_columns - 1)
expanded[lstrlenW(expanded) - 2] = '\0';
sql_size += lstrlenW(expanded);
temp_columns = msi_realloc(columns, sql_size * sizeof(WCHAR));
if (!temp_columns)
{
HeapFree( GetProcessHeap(), 0, columns);
return NULL;
}
columns = temp_columns;
lstrcatW(columns, expanded);
} }
return columns; return ERROR_SUCCESS;
} }
static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types, static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
LPWSTR *labels, LPWSTR **records, LPWSTR *labels, LPWSTR **records,
int num_columns, int num_records) int num_columns, int num_records)
{ {
UINT r;
DWORD i, size;
MSIQUERY *view; MSIQUERY *view;
LPWSTR insert_sql; MSIRECORD *rec;
DWORD size, i; LPWSTR query;
UINT r = ERROR_SUCCESS;
static const WCHAR mid[] = {' ',')',' ','V','A','L','U','E','S',' ','(',' ',0}; static const WCHAR select[] = {
static const WCHAR end[] = {' ',')',0}; 'S','E','L','E','C','T',' ','*',' ',
'F','R','O','M',' ','`','%','s','`',0
};
size = lstrlenW(select) + lstrlenW(labels[0]) - 1;
query = msi_alloc(size * sizeof(WCHAR));
if (!query)
return ERROR_OUTOFMEMORY;
sprintfW(query, select, labels[0]);
r = MSI_DatabaseOpenViewW(db, query, &view);
msi_free(query);
if (r != ERROR_SUCCESS)
return r;
while (MSI_ViewFetch(view, &rec) != ERROR_NO_MORE_ITEMS)
{
r = MSI_ViewModify(view, MSIMODIFY_DELETE, rec);
if (r != ERROR_SUCCESS)
goto done;
}
LPWSTR prelude = msi_build_insertsql_prelude(labels[0]);
LPWSTR columns_sql = msi_build_insertsql_columns(columns, types, num_columns);
for (i = 0; i < num_records; i++) for (i = 0; i < num_records; i++)
{ {
LPWSTR data = msi_build_insertsql_data(records, types, num_columns, i); r = construct_record(num_columns, types, records[i], &rec);
size = lstrlenW(prelude) + lstrlenW(columns_sql) + sizeof(mid) + lstrlenW(data) + sizeof(end) - 1;
insert_sql = msi_alloc(size * sizeof(WCHAR));
if (!insert_sql)
return ERROR_OUTOFMEMORY;
lstrcpyW(insert_sql, prelude);
lstrcatW(insert_sql, columns_sql);
lstrcatW(insert_sql, mid);
lstrcatW(insert_sql, data);
lstrcatW(insert_sql, end);
msi_free(data);
r = MSI_DatabaseOpenViewW( db, insert_sql, &view );
msi_free(insert_sql);
if (r != ERROR_SUCCESS) if (r != ERROR_SUCCESS)
goto done; goto done;
r = MSI_ViewExecute(view, NULL); r = MSI_ViewModify(view, MSIMODIFY_INSERT, rec);
MSI_ViewClose(view); if (r != ERROR_SUCCESS)
msiobj_release(&view->hdr); {
msiobj_release(&rec->hdr);
goto done;
}
msiobj_release(&rec->hdr);
} }
done: done:
msi_free(prelude); msiobj_release(&view->hdr);
msi_free(columns_sql);
return r; return r;
} }
@ -666,11 +604,11 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
{ {
UINT r; UINT r;
DWORD len, i; DWORD len, i;
DWORD num_labels; DWORD num_labels, num_types;
DWORD num_columns, num_records = 0; DWORD num_columns, num_records = 0;
LPWSTR *columns, *types, *labels; LPWSTR *columns, *types, *labels;
LPWSTR path, ptr, data; LPWSTR path, ptr, data;
LPWSTR **records; LPWSTR **records = NULL;
LPWSTR **temp_records; LPWSTR **temp_records;
static const WCHAR backslash[] = {'\\',0}; static const WCHAR backslash[] = {'\\',0};
@ -693,9 +631,15 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
ptr = data; ptr = data;
msi_parse_line( &ptr, &columns, &num_columns ); msi_parse_line( &ptr, &columns, &num_columns );
msi_parse_line( &ptr, &types, NULL ); msi_parse_line( &ptr, &types, &num_types );
msi_parse_line( &ptr, &labels, &num_labels ); msi_parse_line( &ptr, &labels, &num_labels );
if (num_columns != num_types)
{
r = ERROR_FUNCTION_FAILED;
goto done;
}
records = msi_alloc(sizeof(LPWSTR *)); records = msi_alloc(sizeof(LPWSTR *));
if (!records) if (!records)
{ {
@ -718,9 +662,15 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
records = temp_records; records = temp_records;
} }
r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns ); if (!TABLE_Exists(db, labels[0]))
if (r != ERROR_SUCCESS) {
goto done; r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns );
if (r != ERROR_SUCCESS)
{
r = ERROR_FUNCTION_FAILED;
goto done;
}
}
r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records ); r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records );
@ -849,12 +799,29 @@ static UINT msi_export_row( MSIRECORD *row, void *arg )
return msi_export_record( arg, row, 1 ); return msi_export_record( arg, row, 1 );
} }
static UINT msi_export_forcecodepage( HANDLE handle )
{
DWORD sz;
static const char data[] = "\r\n\r\n0\t_ForceCodepage\r\n";
FIXME("Read the codepage from the strings table!\n");
sz = lstrlenA(data) + 1;
if (!WriteFile(handle, data, sz, &sz, NULL))
return ERROR_FUNCTION_FAILED;
return ERROR_SUCCESS;
}
UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table, UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
LPCWSTR folder, LPCWSTR file ) LPCWSTR folder, LPCWSTR file )
{ {
static const WCHAR query[] = { static const WCHAR query[] = {
's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','%','s',0 }; 's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','%','s',0 };
static const WCHAR szbs[] = { '\\', 0 }; static const WCHAR szbs[] = { '\\', 0 };
static const WCHAR forcecodepage[] = {
'_','F','o','r','c','e','C','o','d','e','p','a','g','e',0 };
MSIRECORD *rec = NULL; MSIRECORD *rec = NULL;
MSIQUERY *view = NULL; MSIQUERY *view = NULL;
LPWSTR filename; LPWSTR filename;
@ -882,6 +849,12 @@ UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
if (handle == INVALID_HANDLE_VALUE) if (handle == INVALID_HANDLE_VALUE)
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
if (!lstrcmpW( table, forcecodepage ))
{
r = msi_export_forcecodepage( handle );
goto done;
}
r = MSI_OpenQuery( db, &view, query, table ); r = MSI_OpenQuery( db, &view, query, table );
if (r == ERROR_SUCCESS) if (r == ERROR_SUCCESS)
{ {
@ -915,8 +888,8 @@ UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
msiobj_release( &view->hdr ); msiobj_release( &view->hdr );
} }
done:
CloseHandle( handle ); CloseHandle( handle );
return r; return r;
} }
@ -1079,32 +1052,32 @@ static ULONG WINAPI mrd_Release( IWineMsiRemoteDatabase *iface )
return r; return r;
} }
HRESULT WINAPI mrd_IsTablePersistent( IWineMsiRemoteDatabase *iface, static HRESULT WINAPI mrd_IsTablePersistent( IWineMsiRemoteDatabase *iface,
BSTR table, MSICONDITION *persistent ) BSTR table, MSICONDITION *persistent )
{ {
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface ); msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
*persistent = MsiDatabaseIsTablePersistentW(This->database, (LPWSTR)table); *persistent = MsiDatabaseIsTablePersistentW(This->database, (LPWSTR)table);
return S_OK; return S_OK;
} }
HRESULT WINAPI mrd_GetPrimaryKeys( IWineMsiRemoteDatabase *iface, static HRESULT WINAPI mrd_GetPrimaryKeys( IWineMsiRemoteDatabase *iface,
BSTR table, MSIHANDLE *keys ) BSTR table, MSIHANDLE *keys )
{ {
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface ); msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
UINT r = MsiDatabaseGetPrimaryKeysW(This->database, (LPWSTR)table, keys); UINT r = MsiDatabaseGetPrimaryKeysW(This->database, (LPWSTR)table, keys);
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrd_GetSummaryInformation( IWineMsiRemoteDatabase *iface, static HRESULT WINAPI mrd_GetSummaryInformation( IWineMsiRemoteDatabase *iface,
UINT updatecount, MSIHANDLE *suminfo ) UINT updatecount, MSIHANDLE *suminfo )
{ {
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface ); msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
UINT r = MsiGetSummaryInformationW(This->database, NULL, updatecount, suminfo); UINT r = MsiGetSummaryInformationW(This->database, NULL, updatecount, suminfo);
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrd_OpenView( IWineMsiRemoteDatabase *iface, static HRESULT WINAPI mrd_OpenView( IWineMsiRemoteDatabase *iface,
BSTR query, MSIHANDLE *view ) BSTR query, MSIHANDLE *view )
{ {
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface ); msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
UINT r = MsiDatabaseOpenViewW(This->database, (LPWSTR)query, view); UINT r = MsiDatabaseOpenViewW(This->database, (LPWSTR)query, view);

View file

@ -50,12 +50,14 @@ extern HINSTANCE msi_hInstance;
struct msi_control_tag; struct msi_control_tag;
typedef struct msi_control_tag msi_control; typedef struct msi_control_tag msi_control;
typedef UINT (*msi_handler)( msi_dialog *, msi_control *, WPARAM ); typedef UINT (*msi_handler)( msi_dialog *, msi_control *, WPARAM );
typedef void (*msi_update)( msi_dialog *, msi_control * );
struct msi_control_tag struct msi_control_tag
{ {
struct list entry; struct list entry;
HWND hwnd; HWND hwnd;
msi_handler handler; msi_handler handler;
msi_update update;
LPWSTR property; LPWSTR property;
LPWSTR value; LPWSTR value;
HBITMAP hBitmap; HBITMAP hBitmap;
@ -564,6 +566,16 @@ static HICON msi_load_icon( MSIDATABASE *db, LPCWSTR text, UINT attributes )
return msi_load_image( db, text, IMAGE_ICON, cx, cy, flags ); return msi_load_image( db, text, IMAGE_ICON, cx, cy, flags );
} }
static void msi_dialog_update_controls( msi_dialog *dialog, LPCWSTR property )
{
msi_control *control;
LIST_FOR_EACH_ENTRY( control, &dialog->controls, msi_control, entry )
{
if ( !lstrcmpW( control->property, property ) && control->update )
control->update( dialog, control );
}
}
/* called from the Control Event subscription code */ /* called from the Control Event subscription code */
void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control, void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
@ -855,6 +867,7 @@ static UINT msi_dialog_checkbox_control( msi_dialog *dialog, MSIRECORD *rec )
control = msi_dialog_add_control( dialog, rec, szButton, control = msi_dialog_add_control( dialog, rec, szButton,
BS_CHECKBOX | BS_MULTILINE | WS_TABSTOP ); BS_CHECKBOX | BS_MULTILINE | WS_TABSTOP );
control->handler = msi_dialog_checkbox_handler; control->handler = msi_dialog_checkbox_handler;
control->update = msi_dialog_checkbox_sync_state;
prop = MSI_RecordGetString( rec, 9 ); prop = MSI_RecordGetString( rec, 9 );
if( prop ) if( prop )
{ {
@ -2904,7 +2917,7 @@ static MSIRECORD *msi_get_dialog_record( msi_dialog *dialog )
rec = MSI_QueryGetRecord( package->db, query, dialog->name ); rec = MSI_QueryGetRecord( package->db, query, dialog->name );
if( !rec ) if( !rec )
ERR("query failed for dialog %s\n", debugstr_w(dialog->name)); WARN("query failed for dialog %s\n", debugstr_w(dialog->name));
return rec; return rec;
} }
@ -3083,6 +3096,7 @@ static UINT msi_dialog_set_property( msi_dialog *dialog, LPCWSTR event, LPCWSTR
if( strcmpW( szNullArg, arg ) ) if( strcmpW( szNullArg, arg ) )
deformat_string( dialog->package, arg, &arg_fmt ); deformat_string( dialog->package, arg, &arg_fmt );
MSI_SetPropertyW( dialog->package, prop, arg_fmt ); MSI_SetPropertyW( dialog->package, prop, arg_fmt );
msi_dialog_update_controls( dialog, prop );
msi_free( arg_fmt ); msi_free( arg_fmt );
} }
else else

View file

@ -18,11 +18,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
/*
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/controlevent_overview.asp
*/
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>

View file

@ -59,6 +59,7 @@ static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
struct media_info { struct media_info {
UINT disk_id; UINT disk_id;
UINT type;
UINT last_sequence; UINT last_sequence;
LPWSTR disk_prompt; LPWSTR disk_prompt;
LPWSTR cabinet; LPWSTR cabinet;
@ -400,10 +401,13 @@ static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
} }
case fdintCLOSE_FILE_INFO: case fdintCLOSE_FILE_INFO:
{ {
CabData *data = (CabData*) pfdin->pv;
FILETIME ft; FILETIME ft;
FILETIME ftLocal; FILETIME ftLocal;
HANDLE handle = (HANDLE) pfdin->hf; HANDLE handle = (HANDLE) pfdin->hf;
data->mi->is_continuous = FALSE;
if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft)) if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft))
return -1; return -1;
if (!LocalFileTimeToFileTime(&ft, &ftLocal)) if (!LocalFileTimeToFileTime(&ft, &ftLocal))
@ -504,6 +508,8 @@ static UINT load_media_info(MSIPACKAGE *package, MSIFILE *file, struct media_inf
{ {
MSIRECORD *row; MSIRECORD *row;
LPWSTR source_dir; LPWSTR source_dir;
LPWSTR source;
DWORD options;
UINT r; UINT r;
static const WCHAR query[] = { static const WCHAR query[] = {
@ -539,6 +545,9 @@ static UINT load_media_info(MSIPACKAGE *package, MSIFILE *file, struct media_inf
source_dir = msi_dup_property(package, cszSourceDir); source_dir = msi_dup_property(package, cszSourceDir);
lstrcpyW(mi->source, source_dir); lstrcpyW(mi->source, source_dir);
PathStripToRootW(source_dir);
mi->type = GetDriveTypeW(source_dir);
if (file->IsCompressed && mi->cabinet) if (file->IsCompressed && mi->cabinet)
{ {
if (mi->cabinet[0] == '#') if (mi->cabinet[0] == '#')
@ -554,17 +563,77 @@ static UINT load_media_info(MSIPACKAGE *package, MSIFILE *file, struct media_inf
lstrcatW(mi->source, mi->cabinet); lstrcatW(mi->source, mi->cabinet);
} }
msi_package_add_media_disk(package, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, options = MSICODE_PRODUCT;
mi->disk_id, mi->volume_label, mi->disk_prompt); if (mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE)
{
source = source_dir;
options |= MSISOURCETYPE_MEDIA;
}
else if (package->BaseURL && UrlIsW(package->BaseURL, URLIS_URL))
{
source = package->BaseURL;
options |= MSISOURCETYPE_URL;
}
else
{
source = mi->source;
options |= MSISOURCETYPE_NETWORK;
}
msi_package_add_info(package, MSIINSTALLCONTEXT_USERMANAGED, if (mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE)
MSICODE_PRODUCT | MSISOURCETYPE_MEDIA, msi_package_add_media_disk(package, MSIINSTALLCONTEXT_USERUNMANAGED,
INSTALLPROPERTY_LASTUSEDSOURCEW, mi->source); MSICODE_PRODUCT, mi->disk_id,
mi->volume_label, mi->disk_prompt);
msi_package_add_info(package, MSIINSTALLCONTEXT_USERUNMANAGED,
options, INSTALLPROPERTY_LASTUSEDSOURCEW, source);
msi_free(source_dir); msi_free(source_dir);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
/* FIXME: search NETWORK and URL sources as well */
static UINT find_published_source(MSIPACKAGE *package, struct media_info *mi)
{
WCHAR source[MAX_PATH];
WCHAR volume[MAX_PATH];
WCHAR prompt[MAX_PATH];
DWORD volumesz, promptsz;
DWORD index, size, id;
UINT r;
r = MsiSourceListGetInfoW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
INSTALLPROPERTY_LASTUSEDSOURCEW, source, &size);
if (r != ERROR_SUCCESS)
return r;
index = 0;
volumesz = MAX_PATH;
promptsz = MAX_PATH;
while (MsiSourceListEnumMediaDisksW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED,
MSICODE_PRODUCT, index++, &id,
volume, &volumesz, prompt, &promptsz) == ERROR_SUCCESS)
{
mi->disk_id = id;
mi->volume_label = msi_realloc(mi->volume_label, ++volumesz * sizeof(WCHAR));
lstrcpyW(mi->volume_label, volume);
mi->disk_prompt = msi_realloc(mi->disk_prompt, ++promptsz * sizeof(WCHAR));
lstrcpyW(mi->disk_prompt, prompt);
if (source_matches_volume(mi, source))
{
/* FIXME: what about SourceDir */
lstrcpyW(mi->source, source);
lstrcatW(mi->source, mi->cabinet);
return ERROR_SUCCESS;
}
}
return ERROR_FUNCTION_FAILED;
}
static UINT ready_media(MSIPACKAGE *package, MSIFILE *file, struct media_info *mi) static UINT ready_media(MSIPACKAGE *package, MSIFILE *file, struct media_info *mi)
{ {
UINT rc = ERROR_SUCCESS; UINT rc = ERROR_SUCCESS;
@ -602,14 +671,11 @@ static UINT ready_media(MSIPACKAGE *package, MSIFILE *file, struct media_info *m
{ {
LPWSTR source = msi_dup_property(package, cszSourceDir); LPWSTR source = msi_dup_property(package, cszSourceDir);
BOOL matches; BOOL matches;
UINT type;
PathStripToRootW(source);
type = GetDriveTypeW(source);
matches = source_matches_volume(mi, source); matches = source_matches_volume(mi, source);
msi_free(source); msi_free(source);
if ((type == DRIVE_CDROM || type == DRIVE_REMOVABLE) && !matches) if ((mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE) && !matches)
{ {
rc = msi_change_media(package, mi); rc = msi_change_media(package, mi);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
@ -620,8 +686,13 @@ static UINT ready_media(MSIPACKAGE *package, MSIFILE *file, struct media_info *m
if (file->IsCompressed && if (file->IsCompressed &&
GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES) GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES)
{ {
ERR("Cabinet not found: %s\n", debugstr_w(mi->source)); /* FIXME: this might be done earlier in the install process */
return ERROR_INSTALL_FAILURE; rc = find_published_source(package, mi);
if (rc != ERROR_SUCCESS)
{
ERR("Cabinet not found: %s\n", debugstr_w(mi->source));
return ERROR_INSTALL_FAILURE;
}
} }
return ERROR_SUCCESS; return ERROR_SUCCESS;
@ -739,21 +810,11 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
{ {
struct media_info *mi; struct media_info *mi;
UINT rc = ERROR_SUCCESS; UINT rc = ERROR_SUCCESS;
LPWSTR ptr;
MSIFILE *file; MSIFILE *file;
/* increment progress bar each time action data is sent */ /* increment progress bar each time action data is sent */
ui_progress(package,1,1,0,0); ui_progress(package,1,1,0,0);
/* handle the keys for the SourceList */
ptr = strrchrW(package->PackagePath,'\\');
if (ptr)
{
ptr++;
msi_package_add_info(package, MSIINSTALLCONTEXT_USERMANAGED,
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, ptr);
}
schedule_install_files(package); schedule_install_files(package);
/* /*

View file

@ -346,7 +346,7 @@ static LPWSTR build_default_format(const MSIRECORD* record)
sprintfW(index, fmt_index, i); sprintfW(index, fmt_index, i);
str = MSI_RecordGetString(record, i); str = MSI_RecordGetString(record, i);
len = (str) ? lstrlenW(str) : 0; len = (str) ? lstrlenW(str) : 0;
len += (sizeof(fmt_null) - 3) + lstrlenW(index); len += (sizeof(fmt_null)/sizeof(fmt_null[0]) - 3) + lstrlenW(index);
size += len; size += len;
if (len > max_len) if (len > max_len)
@ -544,6 +544,10 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
format->deformatted = str; format->deformatted = str;
format->len = size - 1; format->len = size - 1;
/* don't reformat the NULL */
if (replace && !*replace)
format->n++;
if (!replace) if (!replace)
return NULL; return NULL;
@ -727,9 +731,6 @@ static UINT replace_stack(FORMAT *format, STACK *stack, STACK *values)
msi_free(replaced); msi_free(replaced);
format->n = beg->n + beg->len; format->n = beg->n + beg->len;
if (type == FORMAT_PROPNULL)
format->n++;
top = stack_peek(stack); top = stack_peek(stack);
if (top) if (top)
{ {

View file

@ -77,7 +77,7 @@ static UINT JOIN_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *v
break; break;
} }
prev_rows = table->rows; prev_rows *= table->rows;
cols += table->columns; cols += table->columns;
} }
@ -108,7 +108,7 @@ static UINT JOIN_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStr
break; break;
} }
prev_rows = table->rows; prev_rows *= table->rows;
cols += table->columns; cols += table->columns;
} }
@ -341,7 +341,8 @@ UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables )
r = TABLE_CreateView( db, tables, &table->view ); r = TABLE_CreateView( db, tables, &table->view );
if( r != ERROR_SUCCESS ) if( r != ERROR_SUCCESS )
{ {
ERR("can't create table\n"); WARN("can't create table: %s\n", debugstr_w(tables));
r = ERROR_BAD_QUERY_SYNTAX;
goto end; goto end;
} }

View file

@ -365,12 +365,12 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
} }
sz = sizeof(sourcepath); sz = sizeof(sourcepath);
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath,
&sz); &sz);
sz = sizeof(filename); sz = sizeof(filename);
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz); MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
lstrcatW(sourcepath,filename); lstrcatW(sourcepath,filename);
@ -561,114 +561,193 @@ done:
return rc; return rc;
} }
static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type)
{
DWORD dval;
LONG res;
WCHAR temp[20];
static const WCHAR format[] = {'%','d',0};
res = RegQueryValueExW(hkey, name, NULL, type, NULL, NULL);
if (res != ERROR_SUCCESS)
return NULL;
if (*type == REG_SZ)
return msi_reg_get_val_str(hkey, name);
if (!msi_reg_get_val_dword(hkey, name, &dval))
return NULL;
sprintfW(temp, format, dval);
return strdupW(temp);
}
static UINT WINAPI MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, static UINT WINAPI MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
awstring *szValue, LPDWORD pcchValueBuf) awstring *szValue, LPDWORD pcchValueBuf)
{ {
UINT r; UINT r = ERROR_UNKNOWN_PROPERTY;
HKEY hkey; HKEY prodkey, userdata, source;
LPWSTR val = NULL; LPWSTR val = NULL;
WCHAR squished_pc[GUID_SIZE];
WCHAR packagecode[GUID_SIZE];
BOOL classes = FALSE;
BOOL badconfig = FALSE;
LONG res;
DWORD save, type = REG_NONE;
static WCHAR empty[] = {0};
static const WCHAR sourcelist[] = {
'S','o','u','r','c','e','L','i','s','t',0};
static const WCHAR display_name[] = {
'D','i','s','p','l','a','y','N','a','m','e',0};
static const WCHAR display_version[] = {
'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
static const WCHAR assignment[] = {
'A','s','s','i','g','n','m','e','n','t',0};
TRACE("%s %s %p %p\n", debugstr_w(szProduct), TRACE("%s %s %p %p\n", debugstr_w(szProduct),
debugstr_w(szAttribute), szValue, pcchValueBuf); debugstr_w(szAttribute), szValue, pcchValueBuf);
/* if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute)
* FIXME: Values seem scattered/duplicated in the registry. Is there a system?
*/
if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szProduct[0] || !szAttribute)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
/* check for special properties */ if (!squash_guid(szProduct, squished_pc))
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW)) return ERROR_INVALID_PARAMETER;
r = MSIREG_OpenLocalManagedProductKey(szProduct, &prodkey, FALSE);
if (r != ERROR_SUCCESS)
{ {
LPWSTR regval; r = MSIREG_OpenUserProductsKey(szProduct, &prodkey, FALSE);
WCHAR packagecode[35];
r = MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE);
if (r != ERROR_SUCCESS) if (r != ERROR_SUCCESS)
return ERROR_UNKNOWN_PRODUCT;
regval = msi_reg_get_val_str( hkey, szAttribute );
if (regval)
{ {
if (unsquash_guid(regval, packagecode)) r = MSIREG_OpenLocalClassesProductKey(szProduct, &prodkey, FALSE);
val = strdupW(packagecode); if (r == ERROR_SUCCESS)
msi_free(regval); classes = TRUE;
} }
RegCloseKey(hkey);
} }
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
{
static const WCHAR one[] = { '1',0 };
/*
* FIXME: should be in the Product key (user or system?)
* but isn't written yet...
*/
val = strdupW( one );
}
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW))
{
static const WCHAR fmt[] = { '%','u',0 };
WCHAR szVal[16];
DWORD regval;
r = MSIREG_OpenUninstallKey(szProduct, &hkey, FALSE); if (classes)
if (r != ERROR_SUCCESS) MSIREG_OpenLocalSystemProductKey(szProduct, &userdata, FALSE);
return ERROR_UNKNOWN_PRODUCT;
if (msi_reg_get_val_dword( hkey, szAttribute, &regval))
{
sprintfW(szVal, fmt, regval);
val = strdupW( szVal );
}
RegCloseKey(hkey);
}
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW))
{
r = MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE);
if (r != ERROR_SUCCESS)
return ERROR_UNKNOWN_PRODUCT;
val = msi_reg_get_val_str( hkey, szAttribute );
RegCloseKey(hkey);
}
else if (!szAttribute[0])
{
return ERROR_UNKNOWN_PROPERTY;
}
else else
MSIREG_OpenInstallPropertiesKey(szProduct, &userdata, FALSE);
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPLINKW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPTELEPHONEW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLDATEW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLSOURCEW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_LOCALPACKAGEW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PUBLISHERW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_URLINFOABOUTW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_URLUPDATEINFOW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMINORW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMAJORW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTIDW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_REGCOMPANYW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_REGOWNERW))
{ {
static const WCHAR szDisplayVersion[] = { if (!prodkey)
'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0 }; {
r = ERROR_UNKNOWN_PRODUCT;
goto done;
}
FIXME("%s\n", debugstr_w(szAttribute)); if (!userdata)
/* FIXME: some attribute values not tested... */ return ERROR_UNKNOWN_PROPERTY;
if (!lstrcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW )) if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
szAttribute = szDisplayVersion; szAttribute = display_name;
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW))
szAttribute = display_version;
r = MSIREG_OpenUninstallKey( szProduct, &hkey, FALSE ); val = msi_reg_get_value(userdata, szAttribute, &type);
if (r != ERROR_SUCCESS) if (!val)
return ERROR_UNKNOWN_PRODUCT; val = empty;
val = msi_reg_get_val_str( hkey, szAttribute );
RegCloseKey(hkey);
} }
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTANCETYPEW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_TRANSFORMSW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTICONW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW) ||
!lstrcmpW(szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
{
if (!prodkey)
{
r = ERROR_UNKNOWN_PRODUCT;
goto done;
}
TRACE("returning %s\n", debugstr_w(val)); if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
szAttribute = assignment;
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW))
{
res = RegOpenKeyW(prodkey, sourcelist, &source);
if (res == ERROR_SUCCESS)
val = msi_reg_get_value(source, szAttribute, &type);
RegCloseKey(source);
}
else
{
val = msi_reg_get_value(prodkey, szAttribute, &type);
if (!val)
val = empty;
}
if (val != empty && type != REG_DWORD &&
!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
{
if (lstrlenW(val) != SQUISH_GUID_SIZE - 1)
badconfig = TRUE;
else
{
unsquash_guid(val, packagecode);
msi_free(val);
val = strdupW(packagecode);
}
}
}
if (!val) if (!val)
return ERROR_UNKNOWN_PROPERTY; {
r = ERROR_UNKNOWN_PROPERTY;
goto done;
}
r = msi_strcpy_to_awstring( val, szValue, pcchValueBuf ); if (pcchValueBuf)
{
save = *pcchValueBuf;
msi_free(val); if (lstrlenW(val) < *pcchValueBuf)
r = msi_strcpy_to_awstring(val, szValue, pcchValueBuf);
else if (szValue->str.a || szValue->str.w)
r = ERROR_MORE_DATA;
if (!badconfig)
*pcchValueBuf = lstrlenW(val);
else if (r == ERROR_SUCCESS)
{
*pcchValueBuf = save;
r = ERROR_BAD_CONFIGURATION;
}
}
else if (badconfig)
r = ERROR_BAD_CONFIGURATION;
if (val != empty)
msi_free(val);
done:
RegCloseKey(prodkey);
RegCloseKey(userdata);
return r; return r;
} }
@ -718,6 +797,292 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
&buffer, pcchValueBuf ); &buffer, pcchValueBuf );
} }
UINT WINAPI MsiGetProductInfoExA(LPCSTR szProductCode, LPCSTR szUserSid,
MSIINSTALLCONTEXT dwContext, LPCSTR szProperty,
LPSTR szValue, LPDWORD pcchValue)
{
LPWSTR product = NULL;
LPWSTR usersid = NULL;
LPWSTR property = NULL;
LPWSTR value = NULL;
DWORD len = 0;
UINT r;
TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode),
debugstr_a(szUserSid), dwContext, debugstr_a(szProperty),
szValue, pcchValue);
if (szValue && !pcchValue)
return ERROR_INVALID_PARAMETER;
if (szProductCode) product = strdupAtoW(szProductCode);
if (szUserSid) usersid = strdupAtoW(szUserSid);
if (szProperty) property = strdupAtoW(szProperty);
r = MsiGetProductInfoExW(product, usersid, dwContext, property,
NULL, &len);
if (r != ERROR_SUCCESS)
goto done;
value = msi_alloc(++len * sizeof(WCHAR));
if (!value)
{
r = ERROR_OUTOFMEMORY;
goto done;
}
r = MsiGetProductInfoExW(product, usersid, dwContext, property,
value, &len);
if (r != ERROR_SUCCESS)
goto done;
if (!pcchValue)
goto done;
len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
if (*pcchValue >= len)
WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
else if (szValue)
{
r = ERROR_MORE_DATA;
if (*pcchValue > 0)
*szValue = '\0';
}
if (*pcchValue <= len || !szValue)
len = len * sizeof(WCHAR) - 1;
*pcchValue = len - 1;
done:
msi_free(product);
msi_free(usersid);
msi_free(property);
msi_free(value);
return r;
}
static UINT msi_copy_outval(LPWSTR val, LPWSTR out, LPDWORD size)
{
UINT r;
if (!val)
return ERROR_UNKNOWN_PROPERTY;
if (out)
{
if (lstrlenW(val) >= *size)
{
r = ERROR_MORE_DATA;
if (*size > 0)
*out = '\0';
}
else
lstrcpyW(out, val);
}
if (size)
*size = lstrlenW(val);
return ERROR_SUCCESS;
}
UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty,
LPWSTR szValue, LPDWORD pcchValue)
{
WCHAR squished_pc[GUID_SIZE];
LPWSTR val = NULL;
LPCWSTR package = NULL;
HKEY props = NULL, prod;
HKEY classes = NULL, managed;
HKEY hkey = NULL;
DWORD type;
UINT r = ERROR_UNKNOWN_PRODUCT;
static const WCHAR one[] = {'1',0};
static const WCHAR five[] = {'5',0};
static const WCHAR empty[] = {0};
static const WCHAR displayname[] = {
'D','i','s','p','l','a','y','N','a','m','e',0};
static const WCHAR displayversion[] = {
'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
static const WCHAR managed_local_package[] = {
'M','a','n','a','g','e','d','L','o','c','a','l',
'P','a','c','k','a','g','e',0};
TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode),
debugstr_w(szUserSid), dwContext, debugstr_w(szProperty),
szValue, pcchValue);
if (!szProductCode || !squash_guid(szProductCode, squished_pc))
return ERROR_INVALID_PARAMETER;
if (szValue && !pcchValue)
return ERROR_INVALID_PARAMETER;
if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
dwContext != MSIINSTALLCONTEXT_MACHINE)
return ERROR_INVALID_PARAMETER;
if (!szProperty || !*szProperty)
return ERROR_INVALID_PARAMETER;
if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
return ERROR_INVALID_PARAMETER;
MSIREG_OpenLocalManagedProductKey(szProductCode, &managed, FALSE);
MSIREG_OpenUserProductsKey(szProductCode, &prod, FALSE);
if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
{
package = INSTALLPROPERTY_LOCALPACKAGEW;
MSIREG_OpenInstallPropertiesKey(szProductCode, &props, FALSE);
if (!props && !prod)
goto done;
}
else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
{
package = managed_local_package;
MSIREG_OpenInstallPropertiesKey(szProductCode, &props, FALSE);
if (!props && !managed)
goto done;
}
else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
{
package = INSTALLPROPERTY_LOCALPACKAGEW;
MSIREG_OpenLocalSystemProductKey(szProductCode, &props, FALSE);
MSIREG_OpenLocalClassesProductKey(szProductCode, &classes, FALSE);
if (!props && !classes)
goto done;
}
if (!lstrcmpW(szProperty, INSTALLPROPERTY_HELPLINKW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_HELPTELEPHONEW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLLOCATIONW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLSOURCEW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_PUBLISHERW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_URLINFOABOUTW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_URLUPDATEINFOW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMINORW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMAJORW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTIDW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_REGCOMPANYW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_REGOWNERW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTANCETYPEW))
{
val = msi_reg_get_value(props, package, &type);
if (!val)
{
if (prod || classes)
r = ERROR_UNKNOWN_PROPERTY;
goto done;
}
msi_free(val);
if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
szProperty = displayname;
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW))
szProperty = displayversion;
val = msi_reg_get_value(props, szProperty, &type);
if (!val)
val = strdupW(empty);
r = msi_copy_outval(val, szValue, pcchValue);
}
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_LANGUAGEW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTNAMEW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGECODEW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTICONW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGENAMEW) ||
!lstrcmpW(szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
{
if (!prod && !classes)
goto done;
if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
hkey = prod;
else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
hkey = managed;
else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
hkey = classes;
val = msi_reg_get_value(hkey, szProperty, &type);
if (!val)
val = strdupW(empty);
r = msi_copy_outval(val, szValue, pcchValue);
}
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTSTATEW))
{
if (dwContext == MSIINSTALLCONTEXT_MACHINE)
{
if (props)
{
val = msi_reg_get_value(props, package, &type);
if (!val)
goto done;
msi_free(val);
val = strdupW(five);
}
else
val = strdupW(one);
r = msi_copy_outval(val, szValue, pcchValue);
goto done;
}
else if (props && (val = msi_reg_get_value(props, package, &type)))
{
msi_free(val);
val = strdupW(five);
r = msi_copy_outval(val, szValue, pcchValue);
goto done;
}
if (prod || managed)
val = strdupW(one);
else
goto done;
r = msi_copy_outval(val, szValue, pcchValue);
}
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW))
{
if (!prod && !classes)
goto done;
/* FIME */
val = strdupW(empty);
r = msi_copy_outval(val, szValue, pcchValue);
}
else
r = ERROR_UNKNOWN_PROPERTY;
done:
RegCloseKey(props);
RegCloseKey(prod);
RegCloseKey(managed);
RegCloseKey(classes);
msi_free(val);
return r;
}
UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes) UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
{ {
LPWSTR szwLogFile = NULL; LPWSTR szwLogFile = NULL;
@ -849,7 +1214,7 @@ static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
return (res == ERROR_SUCCESS); return (res == ERROR_SUCCESS);
} }
static BOOL msi_comp_find_prodcode(LPCWSTR prodcode, LPWSTR squished_pc, static BOOL msi_comp_find_prodcode(LPWSTR squished_pc,
MSIINSTALLCONTEXT context, MSIINSTALLCONTEXT context,
LPCWSTR comp, DWORD *sz) LPCWSTR comp, DWORD *sz)
{ {
@ -909,7 +1274,7 @@ UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
*pdwState = INSTALLSTATE_UNKNOWN; *pdwState = INSTALLSTATE_UNKNOWN;
if (!msi_comp_find_prodcode(szProductCode, squished_pc, dwContext, szComponent, &sz)) if (!msi_comp_find_prodcode(squished_pc, dwContext, szComponent, &sz))
return ERROR_UNKNOWN_COMPONENT; return ERROR_UNKNOWN_COMPONENT;
if (sz == 0) if (sz == 0)
@ -1571,11 +1936,15 @@ UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
static const WCHAR szVersionResource[] = {'\\',0}; static const WCHAR szVersionResource[] = {'\\',0};
static const WCHAR szVersionFormat[] = { static const WCHAR szVersionFormat[] = {
'%','d','.','%','d','.','%','d','.','%','d',0}; '%','d','.','%','d','.','%','d','.','%','d',0};
static const WCHAR szLangResource[] = {
'\\','V','a','r','F','i','l','e','I','n','f','o','\\',
'T','r','a','n','s','l','a','t','i','o','n',0};
static const WCHAR szLangFormat[] = {'%','d',0}; static const WCHAR szLangFormat[] = {'%','d',0};
UINT ret = 0; UINT ret = 0;
DWORD dwVerLen, gle; DWORD dwVerLen, gle;
LPVOID lpVer = NULL; LPVOID lpVer = NULL;
VS_FIXEDFILEINFO *ffi; VS_FIXEDFILEINFO *ffi;
USHORT *lang;
UINT puLen; UINT puLen;
WCHAR tmp[32]; WCHAR tmp[32];
@ -1636,16 +2005,22 @@ UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
if (pcchLangBuf) if (pcchLangBuf)
{ {
DWORD lang = GetUserDefaultLangID(); if (VerQueryValueW(lpVer, szLangResource, (LPVOID*)&lang, &puLen) &&
(puLen > 0))
{
wsprintfW(tmp, szLangFormat, *lang);
if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
FIXME("Retrieve language from file\n"); if (lstrlenW(tmp) >= *pcchLangBuf)
wsprintfW(tmp, szLangFormat, lang); ret = ERROR_MORE_DATA;
if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
if (lstrlenW(tmp) >= *pcchLangBuf) *pcchLangBuf = lstrlenW(tmp);
ret = ERROR_MORE_DATA; }
else
*pcchLangBuf = lstrlenW(tmp); {
if (lpLangBuf) *lpLangBuf = 0;
*pcchLangBuf = 0;
}
} }
end: end:
@ -2109,11 +2484,11 @@ UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLST
return r; return r;
sz = sizeof(sourcepath); sz = sizeof(sourcepath);
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz); MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
sz = sizeof(filename); sz = sizeof(filename);
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz); MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
lstrcatW( sourcepath, filename ); lstrcatW( sourcepath, filename );
@ -2294,11 +2669,11 @@ UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
*ptr = 0; *ptr = 0;
sz = sizeof(sourcepath); sz = sizeof(sourcepath);
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz); MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
sz = sizeof(filename); sz = sizeof(filename);
MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz); MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
lstrcatW( sourcepath, filename ); lstrcatW( sourcepath, filename );
@ -2452,3 +2827,25 @@ UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems ); debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
} }
/***********************************************************************
* MsiIsProductElevatedW [MSI.@]
*/
UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated )
{
FIXME("%s %p - stub\n",
debugstr_w( szProduct ), pfElevated );
*pfElevated = TRUE;
return ERROR_SUCCESS;
}
/***********************************************************************
* MsiIsProductElevatedA [MSI.@]
*/
UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated )
{
FIXME("%s %p - stub\n",
debugstr_a( szProduct ), pfElevated );
*pfElevated = TRUE;
return ERROR_SUCCESS;
}

View file

@ -207,8 +207,8 @@
211 stdcall MsiSourceListAddSourceW(wstr wstr long wstr) 211 stdcall MsiSourceListAddSourceW(wstr wstr long wstr)
212 stub MsiSourceListForceResolutionA 212 stub MsiSourceListForceResolutionA
213 stub MsiSourceListForceResolutionW 213 stub MsiSourceListForceResolutionW
214 stub MsiIsProductElevatedA 214 stdcall MsiIsProductElevatedA(str ptr)
215 stub MsiIsProductElevatedW 215 stdcall MsiIsProductElevatedW(wstr ptr)
216 stdcall MsiGetShortcutTargetA(str ptr ptr ptr) 216 stdcall MsiGetShortcutTargetA(str ptr ptr ptr)
217 stdcall MsiGetShortcutTargetW(wstr ptr ptr ptr) 217 stdcall MsiGetShortcutTargetW(wstr ptr ptr ptr)
218 stdcall MsiGetFileHashA(str long ptr) 218 stdcall MsiGetFileHashA(str long ptr)
@ -240,8 +240,8 @@
244 stub MsiGetPatchInfoExW 244 stub MsiGetPatchInfoExW
245 stdcall MsiEnumProductsExA(str str long long ptr ptr ptr ptr) 245 stdcall MsiEnumProductsExA(str str long long ptr ptr ptr ptr)
246 stdcall MsiEnumProductsExW(wstr wstr long long ptr ptr ptr ptr) 246 stdcall MsiEnumProductsExW(wstr wstr long long ptr ptr ptr ptr)
247 stub MsiGetProductInfoExA 247 stdcall MsiGetProductInfoExA(str str long str ptr ptr)
248 stub MsiGetProductInfoExW 248 stdcall MsiGetProductInfoExW(wstr wstr long wstr ptr ptr)
249 stdcall MsiQueryComponentStateA(str str long str ptr) 249 stdcall MsiQueryComponentStateA(str str long str ptr)
250 stdcall MsiQueryComponentStateW(wstr wstr long wstr ptr) 250 stdcall MsiQueryComponentStateW(wstr wstr long wstr ptr)
251 stub MsiQueryFeatureStateExA 251 stub MsiQueryFeatureStateExA
@ -257,16 +257,16 @@
261 stub MsiSourceListForceResolutionExA 261 stub MsiSourceListForceResolutionExA
262 stub MsiSourceListForceResolutionExW 262 stub MsiSourceListForceResolutionExW
263 stdcall MsiSourceListEnumSourcesA(str str long long long ptr ptr) 263 stdcall MsiSourceListEnumSourcesA(str str long long long ptr ptr)
264 stub MsiSourceListEnumSourcesW 264 stdcall MsiSourceListEnumSourcesW(wstr wstr long long long ptr ptr)
265 stdcall MsiSourceListGetInfoA(str str long long str ptr ptr) 265 stdcall MsiSourceListGetInfoA(str str long long str ptr ptr)
266 stdcall MsiSourceListGetInfoW(wstr wstr long long wstr ptr ptr) 266 stdcall MsiSourceListGetInfoW(wstr wstr long long wstr ptr ptr)
267 stub MsiSourceListSetInfoA 267 stdcall MsiSourceListSetInfoA(str str long long str str)
268 stdcall MsiSourceListSetInfoW(wstr wstr long long wstr wstr) 268 stdcall MsiSourceListSetInfoW(wstr wstr long long wstr wstr)
269 stub MsiEnumPatchesExA 269 stub MsiEnumPatchesExA
270 stub MsiEnumPatchesExW 270 stub MsiEnumPatchesExW
271 stub MsiSourceListEnumMediaDisksA 271 stdcall MsiSourceListEnumMediaDisksA(str str long long long ptr ptr ptr ptr ptr)
272 stub MsiSourceListEnumMediaDisksW 272 stdcall MsiSourceListEnumMediaDisksW(wstr wstr long long long ptr ptr ptr ptr ptr)
273 stub MsiSourceListAddMediaDiskA 273 stdcall MsiSourceListAddMediaDiskA(str str long long long str str)
274 stdcall MsiSourceListAddMediaDiskW(wstr wstr long long long wstr wstr) 274 stdcall MsiSourceListAddMediaDiskW(wstr wstr long long long wstr wstr)
275 stub MsiSourceListClearMediaDiskA 275 stub MsiSourceListClearMediaDiskA
276 stub MsiSourceListClearMediaDiskW 276 stub MsiSourceListClearMediaDiskW

View file

@ -22,10 +22,10 @@ LANGUAGE LANG_KOREAN, SUBLANG_NEUTRAL
STRINGTABLE DISCARDABLE STRINGTABLE DISCARDABLE
{ {
4 " 지정한 설치 패키지를 열 수 없습니다. 파일 경로를 확인하고 다시 시도하십시오." 4 " 지정한 설치 패키지를 열 수 없습니다. 파일 경로를 확인하고 다시 시도하십시오."
5 "%s 경로를 찾을수 없습니다" 5 "%s 경로를 찾을수 없습니다"
9 "디스크 %s 삽입" 9 "디스크 %s 삽입"
10 "못된 매개변수" 10 "못된 매개변수"
11 "%s를 포함하는 폴더를 입력하세여" 11 "%s를 포함하는 폴더를 입력하세여"
12 "빠진 부분(feature)을 위한 설치 원본" 12 "빠진 부분(feature)을 위한 설치 원본"
13 "빠진 부분(feature)을 위한 네트워크 드라이브" 13 "빠진 부분(feature)을 위한 네트워크 드라이브"

View file

@ -568,6 +568,7 @@ typedef struct tagMSISCRIPT
#define MSI_BUILDNUMBER 4000 #define MSI_BUILDNUMBER 4000
#define GUID_SIZE 39 #define GUID_SIZE 39
#define SQUISH_GUID_SIZE 33
#define MSIHANDLE_MAGIC 0x4d434923 #define MSIHANDLE_MAGIC 0x4d434923
@ -748,12 +749,10 @@ extern UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create);
extern UINT MSIREG_DeleteUninstallKey(LPCWSTR szProduct); extern UINT MSIREG_DeleteUninstallKey(LPCWSTR szProduct);
extern UINT MSIREG_OpenUserProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create); extern UINT MSIREG_OpenUserProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create);
extern UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create); extern UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create);
extern UINT MSIREG_OpenFeatures(HKEY* key);
extern UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create); extern UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create);
extern UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create); extern UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create);
extern UINT MSIREG_OpenComponents(HKEY* key); extern UINT MSIREG_OpenComponents(HKEY* key);
extern UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create); extern UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create);
extern UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create);
extern UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create); extern UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create);
extern UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create); extern UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create);
extern UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create); extern UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create);
@ -886,6 +885,8 @@ extern BOOL check_unique_action(const MSIPACKAGE *, LPCWSTR);
extern WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... ); extern WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... );
extern UINT msi_create_component_directories( MSIPACKAGE *package ); extern UINT msi_create_component_directories( MSIPACKAGE *package );
extern void msi_ui_error( DWORD msg_id, DWORD type ); extern void msi_ui_error( DWORD msg_id, DWORD type );
extern UINT msi_set_last_used_source(LPCWSTR product, LPCWSTR usersid,
MSIINSTALLCONTEXT context, DWORD options, LPCWSTR value);
/* control event stuff */ /* control event stuff */
extern VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event, extern VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event,

View file

@ -126,10 +126,25 @@ library WindowsInstaller
msiOpenDatabaseModePatchFile = 32 msiOpenDatabaseModePatchFile = 32
} MsiOpenDatabaseMode; } MsiOpenDatabaseMode;
typedef enum {
msiUILevelNoChange = 0,
msiUILevelDefault = 1,
msiUILevelNone = 2,
msiUILevelBasic = 3,
msiUILevelReduced = 4,
msiUILevelFull = 5,
msiUILevelHideCancel = 32,
msiUILevelProgressOnly = 64,
msiUILevelEndDialog = 128,
msiUILevelSourceResOnly = 256
} MsiUILevel;
[ uuid(000C1090-0000-0000-C000-000000000046) ] [ uuid(000C1090-0000-0000-C000-000000000046) ]
dispinterface Installer dispinterface Installer
{ {
properties: properties:
[id(DISPID_INSTALLER_UILEVEL)]
MsiUILevel UILevel;
methods: methods:
[id(DISPID_INSTALLER_CREATERECORD)] [id(DISPID_INSTALLER_CREATERECORD)]
Record *CreateRecord([in] long Count); Record *CreateRecord([in] long Count);

View file

@ -19,6 +19,7 @@
#define DISPID_INSTALLER_CREATERECORD 1 #define DISPID_INSTALLER_CREATERECORD 1
#define DISPID_INSTALLER_OPENPACKAGE 2 #define DISPID_INSTALLER_OPENPACKAGE 2
#define DISPID_INSTALLER_OPENDATABASE 4 #define DISPID_INSTALLER_OPENDATABASE 4
#define DISPID_INSTALLER_UILEVEL 6
#define DISPID_INSTALLER_INSTALLPRODUCT 8 #define DISPID_INSTALLER_INSTALLPRODUCT 8
#define DISPID_INSTALLER_VERSION 9 #define DISPID_INSTALLER_VERSION 9
#define DISPID_INSTALLER_REGISTRYVALUE 11 #define DISPID_INSTALLER_REGISTRYVALUE 11

View file

@ -332,12 +332,6 @@ done:
msi_free(version); msi_free(version);
} }
/*
* There are a whole slew of these we need to set
*
*
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
*/
static VOID set_installer_properties(MSIPACKAGE *package) static VOID set_installer_properties(MSIPACKAGE *package)
{ {
WCHAR pth[MAX_PATH]; WCHAR pth[MAX_PATH];
@ -347,11 +341,11 @@ static VOID set_installer_properties(MSIPACKAGE *package)
DWORD verval; DWORD verval;
WCHAR verstr[10], bufstr[20]; WCHAR verstr[10], bufstr[20];
HDC dc; HDC dc;
LPWSTR check;
HKEY hkey; HKEY hkey;
LONG res; LPWSTR username, companyname;
SYSTEM_INFO sys_info; SYSTEM_INFO sys_info;
SYSTEMTIME systemtime; SYSTEMTIME systemtime;
LANGID langid;
static const WCHAR cszbs[]={'\\',0}; static const WCHAR cszbs[]={'\\',0};
static const WCHAR CFF[] = static const WCHAR CFF[] =
@ -420,9 +414,17 @@ static VOID set_installer_properties(MSIPACKAGE *package)
static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0}; static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0}; static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0}; static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
static const WCHAR szScreenFormat[] = {'%','d',0}; static const WCHAR szIntFormat[] = {'%','d',0};
static const WCHAR szIntel[] = { 'I','n','t','e','l',0 }; static const WCHAR szIntel[] = { 'I','n','t','e','l',0 };
static const WCHAR szAllUsers[] = { 'A','L','L','U','S','E','R','S',0 }; static const WCHAR szAllUsers[] = { 'A','L','L','U','S','E','R','S',0 };
static const WCHAR szUserInfo[] = {
'S','O','F','T','W','A','R','E','\\',
'M','i','c','r','o','s','o','f','t','\\',
'M','S',' ','S','e','t','u','p',' ','(','A','C','M','E',')','\\',
'U','s','e','r',' ','I','n','f','o',0
};
static const WCHAR szDefName[] = { 'D','e','f','N','a','m','e',0 };
static const WCHAR szDefCompany[] = { 'D','e','f','C','o','m','p','a','n','y',0 };
static const WCHAR szCurrentVersion[] = { static const WCHAR szCurrentVersion[] = {
'S','O','F','T','W','A','R','E','\\', 'S','O','F','T','W','A','R','E','\\',
'M','i','c','r','o','s','o','f','t','\\', 'M','i','c','r','o','s','o','f','t','\\',
@ -437,6 +439,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0}; static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0};
static const WCHAR szDate[] = {'D','a','t','e',0}; static const WCHAR szDate[] = {'D','a','t','e',0};
static const WCHAR szTime[] = {'T','i','m','e',0}; static const WCHAR szTime[] = {'T','i','m','e',0};
static const WCHAR szUserLangID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0};
/* /*
* Other things that probably should be set: * Other things that probably should be set:
@ -523,7 +526,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
/* Physical Memory is specified in MB. Using total amount. */ /* Physical Memory is specified in MB. Using total amount. */
msex.dwLength = sizeof(msex); msex.dwLength = sizeof(msex);
GlobalMemoryStatusEx( &msex ); GlobalMemoryStatusEx( &msex );
sprintfW( bufstr, szScreenFormat, (int)(msex.ullTotalPhys/1024/1024)); sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys/1024/1024));
MSI_SetPropertyW(package, szPhysicalMemory, bufstr); MSI_SetPropertyW(package, szPhysicalMemory, bufstr);
SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth); SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
@ -570,42 +573,48 @@ static VOID set_installer_properties(MSIPACKAGE *package)
GetSystemInfo( &sys_info ); GetSystemInfo( &sys_info );
if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
{ {
sprintfW( bufstr, szScreenFormat, sys_info.wProcessorLevel ); sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
MSI_SetPropertyW( package, szIntel, bufstr ); MSI_SetPropertyW( package, szIntel, bufstr );
} }
/* Screen properties. */ /* Screen properties. */
dc = GetDC(0); dc = GetDC(0);
sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, HORZRES ) ); sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, HORZRES ) );
MSI_SetPropertyW( package, szScreenX, bufstr ); MSI_SetPropertyW( package, szScreenX, bufstr );
sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, VERTRES )); sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, VERTRES ));
MSI_SetPropertyW( package, szScreenY, bufstr ); MSI_SetPropertyW( package, szScreenY, bufstr );
sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, BITSPIXEL )); sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, BITSPIXEL ));
MSI_SetPropertyW( package, szColorBits, bufstr ); MSI_SetPropertyW( package, szColorBits, bufstr );
ReleaseDC(0, dc); ReleaseDC(0, dc);
/* USERNAME and COMPANYNAME */ /* USERNAME and COMPANYNAME */
res = RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey ); username = msi_dup_property( package, szUSERNAME );
if (res != ERROR_SUCCESS) companyname = msi_dup_property( package, szCOMPANYNAME );
return;
check = msi_dup_property( package, szUSERNAME ); if ((!username || !companyname) &&
if (!check) RegOpenKeyW( HKEY_CURRENT_USER, szUserInfo, &hkey ) == ERROR_SUCCESS)
{ {
LPWSTR user = msi_reg_get_val_str( hkey, szRegisteredUser ); if (!username &&
MSI_SetPropertyW( package, szUSERNAME, user ); (username = msi_reg_get_val_str( hkey, szDefName )))
msi_free( user ); MSI_SetPropertyW( package, szUSERNAME, username );
if (!companyname &&
(companyname = msi_reg_get_val_str( hkey, szDefCompany )))
MSI_SetPropertyW( package, szCOMPANYNAME, companyname );
CloseHandle( hkey );
} }
if ((!username || !companyname) &&
msi_free( check ); RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey ) == ERROR_SUCCESS)
check = msi_dup_property( package, szCOMPANYNAME );
if (!check)
{ {
LPWSTR company = msi_reg_get_val_str( hkey, szRegisteredOrg ); if (!username &&
MSI_SetPropertyW( package, szCOMPANYNAME, company ); (username = msi_reg_get_val_str( hkey, szRegisteredUser )))
msi_free( company ); MSI_SetPropertyW( package, szUSERNAME, username );
if (!companyname &&
(companyname = msi_reg_get_val_str( hkey, szRegisteredOrg )))
MSI_SetPropertyW( package, szCOMPANYNAME, companyname );
CloseHandle( hkey );
} }
msi_free( username );
msi_free( companyname );
if ( set_user_sid_prop( package ) != ERROR_SUCCESS) if ( set_user_sid_prop( package ) != ERROR_SUCCESS)
ERR("Failed to set the UserSID property\n"); ERR("Failed to set the UserSID property\n");
@ -628,8 +637,10 @@ static VOID set_installer_properties(MSIPACKAGE *package)
set_msi_assembly_prop( package ); set_msi_assembly_prop( package );
msi_free( check ); langid = GetUserDefaultLangID();
CloseHandle( hkey ); sprintfW(bufstr, szIntFormat, langid);
MSI_SetPropertyW( package, szUserLangID, bufstr );
} }
static UINT msi_load_summary_properties( MSIPACKAGE *package ) static UINT msi_load_summary_properties( MSIPACKAGE *package )
@ -1637,7 +1648,7 @@ static HRESULT WINAPI mrp_SetMsiHandle( IWineMsiRemotePackage *iface, MSIHANDLE
return S_OK; return S_OK;
} }
HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *handle ) static HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *handle )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
IWineMsiRemoteDatabase *rdb = NULL; IWineMsiRemoteDatabase *rdb = NULL;
@ -1664,7 +1675,7 @@ HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *h
return S_OK; return S_OK;
} }
HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR *value, DWORD *size ) static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR *value, DWORD *size )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
UINT r; UINT r;
@ -1676,63 +1687,63 @@ HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BST
return S_OK; return S_OK;
} }
HRESULT WINAPI mrp_SetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value ) static HRESULT WINAPI mrp_SetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
UINT r = MsiSetPropertyW(This->package, (LPWSTR)property, (LPWSTR)value); UINT r = MsiSetPropertyW(This->package, (LPWSTR)property, (LPWSTR)value);
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrp_ProcessMessage( IWineMsiRemotePackage *iface, INSTALLMESSAGE message, MSIHANDLE record ) static HRESULT WINAPI mrp_ProcessMessage( IWineMsiRemotePackage *iface, INSTALLMESSAGE message, MSIHANDLE record )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
UINT r = MsiProcessMessage(This->package, message, record); UINT r = MsiProcessMessage(This->package, message, record);
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrp_DoAction( IWineMsiRemotePackage *iface, BSTR action ) static HRESULT WINAPI mrp_DoAction( IWineMsiRemotePackage *iface, BSTR action )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
UINT r = MsiDoActionW(This->package, (LPWSTR)action); UINT r = MsiDoActionW(This->package, (LPWSTR)action);
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrp_Sequence( IWineMsiRemotePackage *iface, BSTR table, int sequence ) static HRESULT WINAPI mrp_Sequence( IWineMsiRemotePackage *iface, BSTR table, int sequence )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
UINT r = MsiSequenceW(This->package, (LPWSTR)table, sequence); UINT r = MsiSequenceW(This->package, (LPWSTR)table, sequence);
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size ) static HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
UINT r = MsiGetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value, size); UINT r = MsiGetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrp_SetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value) static HRESULT WINAPI mrp_SetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value)
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
UINT r = MsiSetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value); UINT r = MsiSetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value);
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size ) static HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
UINT r = MsiGetSourcePathW(This->package, (LPWSTR)folder, (LPWSTR)value, size); UINT r = MsiGetSourcePathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL *ret ) static HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL *ret )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
*ret = MsiGetMode(This->package, mode); *ret = MsiGetMode(This->package, mode);
return S_OK; return S_OK;
} }
HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
INSTALLSTATE *installed, INSTALLSTATE *action ) INSTALLSTATE *installed, INSTALLSTATE *action )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
@ -1740,14 +1751,14 @@ HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, INSTALLSTATE state ) static HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, INSTALLSTATE state )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
UINT r = MsiSetFeatureStateW(This->package, (LPWSTR)feature, state); UINT r = MsiSetFeatureStateW(This->package, (LPWSTR)feature, state);
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR component, static HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR component,
INSTALLSTATE *installed, INSTALLSTATE *action ) INSTALLSTATE *installed, INSTALLSTATE *action )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
@ -1755,28 +1766,28 @@ HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR compone
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrp_SetComponentState( IWineMsiRemotePackage *iface, BSTR component, INSTALLSTATE state ) static HRESULT WINAPI mrp_SetComponentState( IWineMsiRemotePackage *iface, BSTR component, INSTALLSTATE state )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
UINT r = MsiSetComponentStateW(This->package, (LPWSTR)component, state); UINT r = MsiSetComponentStateW(This->package, (LPWSTR)component, state);
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrp_GetLanguage( IWineMsiRemotePackage *iface, LANGID *language ) static HRESULT WINAPI mrp_GetLanguage( IWineMsiRemotePackage *iface, LANGID *language )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
*language = MsiGetLanguage(This->package); *language = MsiGetLanguage(This->package);
return S_OK; return S_OK;
} }
HRESULT WINAPI mrp_SetInstallLevel( IWineMsiRemotePackage *iface, int level ) static HRESULT WINAPI mrp_SetInstallLevel( IWineMsiRemotePackage *iface, int level )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
UINT r = MsiSetInstallLevel(This->package, level); UINT r = MsiSetInstallLevel(This->package, level);
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE record, static HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE record,
BSTR value, DWORD *size ) BSTR value, DWORD *size )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
@ -1784,7 +1795,7 @@ HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE record,
return HRESULT_FROM_WIN32(r); return HRESULT_FROM_WIN32(r);
} }
HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR condition ) static HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR condition )
{ {
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
UINT r = MsiEvaluateConditionW(This->package, (LPWSTR)condition); UINT r = MsiEvaluateConditionW(This->package, (LPWSTR)condition);

View file

@ -338,7 +338,13 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue); TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
if( iField > rec->count ) if( iField > rec->count )
return ERROR_INVALID_PARAMETER; {
if ( szValue && *pcchValue > 0 )
szValue[0] = 0;
*pcchValue = 0;
return ERROR_SUCCESS;
}
ret = ERROR_SUCCESS; ret = ERROR_SUCCESS;
switch( rec->fields[iField].type ) switch( rec->fields[iField].type )
@ -414,7 +420,13 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue); TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
if( iField > rec->count ) if( iField > rec->count )
return ERROR_INVALID_PARAMETER; {
if ( szValue && *pcchValue > 0 )
szValue[0] = 0;
*pcchValue = 0;
return ERROR_SUCCESS;
}
ret = ERROR_SUCCESS; ret = ERROR_SUCCESS;
switch( rec->fields[iField].type ) switch( rec->fields[iField].type )
@ -661,7 +673,7 @@ UINT MSI_RecordSetStream(MSIRECORD *rec, UINT iField, IStream *stream)
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
UINT MSI_RecordSetStreamFromFileW(MSIRECORD *rec, UINT iField, LPCWSTR szFilename) static UINT MSI_RecordSetStreamFromFileW(MSIRECORD *rec, UINT iField, LPCWSTR szFilename)
{ {
IStream *stm = NULL; IStream *stm = NULL;
HRESULT r; HRESULT r;

View file

@ -52,14 +52,6 @@ static const WCHAR szUserFeatures_fmt[] = {
'F','e','a','t','u','r','e','s','\\', 'F','e','a','t','u','r','e','s','\\',
'%','s',0}; '%','s',0};
static const WCHAR szInstaller_Features[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'I','n','s','t','a','l','l','e','r','\\',
'F','e','a','t','u','r','e','s',0 };
static const WCHAR szUserDataFeatures_fmt[] = { static const WCHAR szUserDataFeatures_fmt[] = {
'S','o','f','t','w','a','r','e','\\', 'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\', 'M','i','c','r','o','s','o','f','t','\\',
@ -87,15 +79,6 @@ static const WCHAR szInstaller_Components[] = {
'I','n','s','t','a','l','l','e','r','\\', 'I','n','s','t','a','l','l','e','r','\\',
'C','o','m','p','o','n','e','n','t','s',0 }; 'C','o','m','p','o','n','e','n','t','s',0 };
static const WCHAR szInstaller_Components_fmt[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'I','n','s','t','a','l','l','e','r','\\',
'C','o','m','p','o','n','e','n','t','s','\\',
'%','s',0};
static const WCHAR szUser_Components_fmt[] = { static const WCHAR szUser_Components_fmt[] = {
'S','o','f','t','w','a','r','e','\\', 'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\', 'M','i','c','r','o','s','o','f','t','\\',
@ -231,8 +214,6 @@ static const WCHAR szInstaller_LocalManagedProd_fmt[] = {
'I','n','s','t','a','l','l','e','r','\\', 'I','n','s','t','a','l','l','e','r','\\',
'P','r','o','d','u','c','t','s','\\','%','s',0}; 'P','r','o','d','u','c','t','s','\\','%','s',0};
#define SQUISH_GUID_SIZE 33
BOOL unsquash_guid(LPCWSTR in, LPWSTR out) BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
{ {
DWORD i,n=0; DWORD i,n=0;
@ -610,11 +591,6 @@ UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct)
return RegDeleteTreeW(HKEY_CURRENT_USER, keypath); return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
} }
UINT MSIREG_OpenFeatures(HKEY* key)
{
return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Features,key);
}
UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create) UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create)
{ {
UINT rc; UINT rc;
@ -671,27 +647,6 @@ UINT MSIREG_OpenComponents(HKEY* key)
return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Components,key); return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Components,key);
} }
UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
{
UINT rc;
WCHAR squished_cc[GUID_SIZE];
WCHAR keypath[0x200];
TRACE("%s\n",debugstr_w(szComponent));
if (!squash_guid(szComponent,squished_cc))
return ERROR_FUNCTION_FAILED;
TRACE("squished (%s)\n", debugstr_w(squished_cc));
sprintfW(keypath,szInstaller_Components_fmt,squished_cc);
if (create)
rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
else
rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
return rc;
}
UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create) UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
{ {
UINT rc; UINT rc;
@ -853,11 +808,6 @@ UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct)
return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath); return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
} }
UINT MSIREG_OpenProducts(HKEY* key)
{
return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Products,key);
}
UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create) UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create)
{ {
UINT rc; UINT rc;
@ -1182,7 +1132,7 @@ UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
if (NULL == lpguid) if (NULL == lpguid)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
r = MSIREG_OpenProducts(&hkeyProducts); r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_Products, &hkeyProducts);
if( r != ERROR_SUCCESS ) if( r != ERROR_SUCCESS )
return ERROR_NO_MORE_ITEMS; return ERROR_NO_MORE_ITEMS;

File diff suppressed because it is too large Load diff

View file

@ -29,6 +29,7 @@
#include "msiquery.h" #include "msiquery.h"
#include "objbase.h" #include "objbase.h"
#include "msipriv.h" #include "msipriv.h"
#include "query.h"
#include "wine/debug.h" #include "wine/debug.h"
@ -39,7 +40,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msidb);
typedef struct tabSTREAM typedef struct tabSTREAM
{ {
int str_index; UINT str_index;
LPWSTR name; LPWSTR name;
IStream *stream; IStream *stream;
} STREAM; } STREAM;
@ -54,7 +55,7 @@ typedef struct tagMSISTREAMSVIEW
UINT row_size; UINT row_size;
} MSISTREAMSVIEW; } MSISTREAMSVIEW;
static BOOL streams_set_table_size(MSISTREAMSVIEW *sv, int size) static BOOL streams_set_table_size(MSISTREAMSVIEW *sv, UINT size)
{ {
if (size >= sv->max_streams) if (size >= sv->max_streams)
{ {
@ -372,7 +373,7 @@ static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRE
static UINT STREAMS_delete(struct tagMSIVIEW *view) static UINT STREAMS_delete(struct tagMSIVIEW *view)
{ {
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
int i; UINT i;
TRACE("(%p)\n", view); TRACE("(%p)\n", view);
@ -439,7 +440,7 @@ static const MSIVIEWOPS streams_ops =
NULL, NULL,
}; };
static UINT add_streams_to_table(MSISTREAMSVIEW *sv) static INT add_streams_to_table(MSISTREAMSVIEW *sv)
{ {
IEnumSTATSTG *stgenum = NULL; IEnumSTATSTG *stgenum = NULL;
STATSTG stat; STATSTG stat;
@ -498,6 +499,7 @@ static UINT add_streams_to_table(MSISTREAMSVIEW *sv)
UINT STREAMS_CreateView(MSIDATABASE *db, MSIVIEW **view) UINT STREAMS_CreateView(MSIDATABASE *db, MSIVIEW **view)
{ {
MSISTREAMSVIEW *sv; MSISTREAMSVIEW *sv;
INT rows;
TRACE("(%p, %p)\n", db, view); TRACE("(%p, %p)\n", db, view);
@ -507,10 +509,10 @@ UINT STREAMS_CreateView(MSIDATABASE *db, MSIVIEW **view)
sv->view.ops = &streams_ops; sv->view.ops = &streams_ops;
sv->db = db; sv->db = db;
sv->num_rows = add_streams_to_table(sv); rows = add_streams_to_table(sv);
if (rows < 0)
if (sv->num_rows < 0)
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
sv->num_rows = rows;
*view = (MSIVIEW *)sv; *view = (MSIVIEW *)sv;

View file

@ -34,6 +34,7 @@
#include "msidefs.h" #include "msidefs.h"
#include "msipriv.h" #include "msipriv.h"
#include "objidl.h" #include "objidl.h"
#include "propvarutil.h"
#include "msiserver.h" #include "msiserver.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -78,6 +79,10 @@ typedef struct {
#include "poppack.h" #include "poppack.h"
static HRESULT (WINAPI *pPropVariantChangeType)
(PROPVARIANT *ppropvarDest, REFPROPVARIANT propvarSrc,
PROPVAR_CHANGE_FLAGS flags, VARTYPE vt);
#define SECT_HDR_SIZE (sizeof(PROPERTYSECTIONHEADER)) #define SECT_HDR_SIZE (sizeof(PROPERTYSECTIONHEADER))
static const WCHAR szSumInfo[] = { 5 ,'S','u','m','m','a','r','y', static const WCHAR szSumInfo[] = { 5 ,'S','u','m','m','a','r','y',
@ -144,6 +149,22 @@ static UINT get_property_count( const PROPVARIANT *property )
return n; return n;
} }
static UINT propvar_changetype(PROPVARIANT *changed, PROPVARIANT *property, VARTYPE vt)
{
HRESULT hr;
HMODULE propsys = LoadLibraryA("propsys.dll");
pPropVariantChangeType = (void *)GetProcAddress(propsys, "PropVariantChangeType");
if (!pPropVariantChangeType)
{
ERR("PropVariantChangeType function missing!\n");
return ERROR_FUNCTION_FAILED;
}
hr = pPropVariantChangeType(changed, property, 0, vt);
return (hr == S_OK) ? ERROR_SUCCESS : ERROR_FUNCTION_FAILED;
}
/* FIXME: doesn't deal with endian conversion */ /* FIXME: doesn't deal with endian conversion */
static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz ) static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz )
{ {
@ -151,7 +172,8 @@ static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz
DWORD i; DWORD i;
int size; int size;
PROPERTY_DATA *propdata; PROPERTY_DATA *propdata;
PROPVARIANT *property; PROPVARIANT property, *ptr;
PROPVARIANT changed;
PROPERTYIDOFFSET *idofs; PROPERTYIDOFFSET *idofs;
PROPERTYSECTIONHEADER *section_hdr; PROPERTYSECTIONHEADER *section_hdr;
@ -161,6 +183,12 @@ static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz
/* now set all the properties */ /* now set all the properties */
for( i = 0; i < section_hdr->cProperties; i++ ) for( i = 0; i < section_hdr->cProperties; i++ )
{ {
if( idofs[i].propid >= MSI_MAX_PROPS )
{
ERR("Unknown property ID %d\n", idofs[i].propid );
break;
}
type = get_type( idofs[i].propid ); type = get_type( idofs[i].propid );
if( type == VT_EMPTY ) if( type == VT_EMPTY )
{ {
@ -170,45 +198,41 @@ static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz
propdata = (PROPERTY_DATA*) &data[ idofs[i].dwOffset ]; propdata = (PROPERTY_DATA*) &data[ idofs[i].dwOffset ];
/* check the type is the same as we expect */
if( type != propdata->type )
{
ERR("wrong type %d != %d\n", type, propdata->type);
break;
}
/* check we don't run off the end of the data */ /* check we don't run off the end of the data */
size = sz - idofs[i].dwOffset - sizeof(DWORD); size = sz - idofs[i].dwOffset - sizeof(DWORD);
if( sizeof(DWORD) > size || if( sizeof(DWORD) > size ||
( type == VT_FILETIME && sizeof(FILETIME) > size ) || ( propdata->type == VT_FILETIME && sizeof(FILETIME) > size ) ||
( type == VT_LPSTR && (propdata->u.str.len + sizeof(DWORD)) > size ) ) ( propdata->type == VT_LPSTR && (propdata->u.str.len + sizeof(DWORD)) > size ) )
{ {
ERR("not enough data\n"); ERR("not enough data\n");
break; break;
} }
if( idofs[i].propid >= MSI_MAX_PROPS ) property.vt = propdata->type;
{ if( propdata->type == VT_LPSTR )
ERR("Unknown property ID %d\n", idofs[i].propid );
break;
}
property = &prop[ idofs[i].propid ];
property->vt = type;
if( type == VT_LPSTR )
{ {
LPSTR str = msi_alloc( propdata->u.str.len ); LPSTR str = msi_alloc( propdata->u.str.len );
memcpy( str, propdata->u.str.str, propdata->u.str.len ); memcpy( str, propdata->u.str.str, propdata->u.str.len );
str[ propdata->u.str.len - 1 ] = 0; str[ propdata->u.str.len - 1 ] = 0;
property->u.pszVal = str; property.u.pszVal = str;
} }
else if( type == VT_FILETIME ) else if( propdata->type == VT_FILETIME )
property->u.filetime = propdata->u.ft; property.u.filetime = propdata->u.ft;
else if( type == VT_I2 ) else if( propdata->type == VT_I2 )
property->u.iVal = propdata->u.i2; property.u.iVal = propdata->u.i2;
else if( type == VT_I4 ) else if( propdata->type == VT_I4 )
property->u.lVal = propdata->u.i4; property.u.lVal = propdata->u.i4;
/* check the type is the same as we expect */
if( type != propdata->type )
{
propvar_changetype(&changed, &property, type);
ptr = &changed;
}
else
ptr = &property;
prop[ idofs[i].propid ] = *ptr;
} }
} }
@ -363,7 +387,7 @@ static UINT save_summary_info( const MSISUMMARYINFO * si, IStream *stm )
/* write the format header */ /* write the format header */
sz = sizeof format_hdr; sz = sizeof format_hdr;
memcpy( &format_hdr.fmtid, &FMTID_SummaryInformation, sizeof (FMTID) ); format_hdr.fmtid = FMTID_SummaryInformation;
format_hdr.dwOffset = sizeof format_hdr + sizeof set_hdr; format_hdr.dwOffset = sizeof format_hdr + sizeof set_hdr;
r = IStream_Write( stm, &format_hdr, sz, &count ); r = IStream_Write( stm, &format_hdr, sz, &count );
if( FAILED(r) || count != sz ) if( FAILED(r) || count != sz )
@ -600,7 +624,7 @@ static UINT get_prop( MSIHANDLE handle, UINT uiProperty, UINT *puiDataType,
break; break;
case VT_FILETIME: case VT_FILETIME:
if( pftValue ) if( pftValue )
memcpy(pftValue, &prop->u.filetime, sizeof (FILETIME) ); *pftValue = prop->u.filetime;
break; break;
case VT_EMPTY: case VT_EMPTY:
break; break;
@ -721,7 +745,7 @@ static UINT set_prop( MSIHANDLE handle, UINT uiProperty, UINT uiDataType,
prop->u.iVal = iValue; prop->u.iVal = iValue;
break; break;
case VT_FILETIME: case VT_FILETIME:
memcpy( &prop->u.filetime, pftValue, sizeof prop->u.filetime ); prop->u.filetime = *pftValue;
break; break;
case VT_LPSTR: case VT_LPSTR:
if( str->unicode ) if( str->unicode )

View file

@ -923,7 +923,7 @@ static UINT get_defaulttablecolumns( LPCWSTR name, MSICOLUMNINFO *colinfo, UINT
{ {
if (colinfo && (i < *sz) ) if (colinfo && (i < *sz) )
{ {
memcpy( &colinfo[i], &p[i], sizeof(MSICOLUMNINFO) ); colinfo[i] = p[i];
colinfo[i].tablename = strdupW( p[i].tablename ); colinfo[i].tablename = strdupW( p[i].tablename );
colinfo[i].colname = strdupW( p[i].colname ); colinfo[i].colname = strdupW( p[i].colname );
} }
@ -1626,6 +1626,23 @@ static UINT modify_delete_row( struct tagMSIVIEW *view, MSIRECORD *rec )
return TABLE_delete_row(view, row); return TABLE_delete_row(view, row);
} }
static UINT msi_refresh_record( struct tagMSIVIEW *view, MSIRECORD *rec, UINT row )
{
MSIRECORD *curr;
UINT r, i, count;
r = TABLE_get_row(view, row - 1, &curr);
if (r != ERROR_SUCCESS)
return r;
count = MSI_RecordGetFieldCount(rec);
for (i = 0; i < count; i++)
MSI_RecordCopyField(curr, i + 1, rec, i + 1);
msiobj_release(&curr->hdr);
return ERROR_SUCCESS;
}
static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
MSIRECORD *rec, UINT row) MSIRECORD *rec, UINT row)
{ {
@ -1657,11 +1674,14 @@ static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
r = TABLE_insert_row( view, rec, TRUE ); r = TABLE_insert_row( view, rec, TRUE );
break; break;
case MSIMODIFY_REFRESH:
r = msi_refresh_record( view, rec, row );
break;
case MSIMODIFY_UPDATE: case MSIMODIFY_UPDATE:
r = msi_table_update( view, rec, row ); r = msi_table_update( view, rec, row );
break; break;
case MSIMODIFY_REFRESH:
case MSIMODIFY_ASSIGN: case MSIMODIFY_ASSIGN:
case MSIMODIFY_REPLACE: case MSIMODIFY_REPLACE:
case MSIMODIFY_MERGE: case MSIMODIFY_MERGE:
@ -2034,6 +2054,9 @@ static UINT TABLE_sort(struct tagMSIVIEW *view, column_info *columns)
if (r != ERROR_SUCCESS) if (r != ERROR_SUCCESS)
return r; return r;
if (rows == 0)
return ERROR_SUCCESS;
order = msi_alloc_zero(sizeof(MSIORDERINFO) + sizeof(UINT) * cols); order = msi_alloc_zero(sizeof(MSIORDERINFO) + sizeof(UINT) * cols);
if (!order) if (!order)
return ERROR_OUTOFMEMORY; return ERROR_OUTOFMEMORY;

View file

@ -88,7 +88,7 @@ static UINT find_entry_in_hash(MSIHASHENTRY **table, UINT row, UINT *val)
if (!(entry = table[row % MSI_HASH_TABLE_SIZE])) if (!(entry = table[row % MSI_HASH_TABLE_SIZE]))
{ {
ERR("Row not found in hash table!\n"); WARN("Row not found in hash table!\n");
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
} }
@ -503,12 +503,15 @@ static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
MSIRECORD *rec, UINT row ) MSIRECORD *rec, UINT row )
{ {
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view; MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
UINT r;
TRACE("%p %d %p\n", wv, eModifyMode, rec ); TRACE("%p %d %p\n", wv, eModifyMode, rec);
if( !wv->table ) r = WHERE_execute(view, NULL);
return ERROR_FUNCTION_FAILED; if (r != ERROR_SUCCESS)
return r;
find_entry_in_hash(wv->reorder, row - 1, &row);
return wv->table->ops->modify( wv->table, eModifyMode, rec, row ); return wv->table->ops->modify( wv->table, eModifyMode, rec, row );
} }