mirror of
https://github.com/reactos/reactos.git
synced 2024-12-30 19:14:31 +00:00
[MSI]
- Sync to Wine-1.3.5. svn path=/trunk/; revision=49219
This commit is contained in:
parent
12cded29f1
commit
955c4d7d77
23 changed files with 869 additions and 362 deletions
|
@ -1785,7 +1785,7 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
|
|||
BOOL feature_state = ((feature->Level > 0) &&
|
||||
(feature->Level <= level));
|
||||
|
||||
if ((feature_state) && (feature->Action == INSTALLSTATE_UNKNOWN))
|
||||
if (feature_state && feature->ActionRequest == INSTALLSTATE_UNKNOWN)
|
||||
{
|
||||
if (feature->Attributes & msidbFeatureAttributesFavorSource)
|
||||
msi_feature_set_state(package, feature, INSTALLSTATE_SOURCE);
|
||||
|
@ -1814,7 +1814,7 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
|
|||
{
|
||||
BOOL selected = feature->Level > 0 && feature->Level <= level;
|
||||
|
||||
if (selected && feature->Action == INSTALLSTATE_UNKNOWN)
|
||||
if (selected && feature->ActionRequest == INSTALLSTATE_UNKNOWN)
|
||||
{
|
||||
msi_feature_set_state(package, feature, feature->Installed);
|
||||
}
|
||||
|
@ -1839,7 +1839,7 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
|
|||
LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
|
||||
{
|
||||
if (cl->component->ForceLocalState &&
|
||||
feature->Action == INSTALLSTATE_SOURCE)
|
||||
feature->ActionRequest == INSTALLSTATE_SOURCE)
|
||||
{
|
||||
msi_feature_set_state(package, feature, INSTALLSTATE_LOCAL);
|
||||
break;
|
||||
|
@ -1850,7 +1850,7 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
|
|||
{
|
||||
component = cl->component;
|
||||
|
||||
switch (feature->Action)
|
||||
switch (feature->ActionRequest)
|
||||
{
|
||||
case INSTALLSTATE_ABSENT:
|
||||
component->anyAbsent = 1;
|
||||
|
@ -2371,17 +2371,43 @@ static const WCHAR *get_root_key( MSIPACKAGE *package, INT root, HKEY *root_key
|
|||
return ret;
|
||||
}
|
||||
|
||||
static WCHAR *get_keypath( MSIPACKAGE *package, HKEY root, const WCHAR *path )
|
||||
{
|
||||
static const WCHAR prefixW[] = {'S','O','F','T','W','A','R','E','\\'};
|
||||
static const UINT len = sizeof(prefixW) / sizeof(prefixW[0]);
|
||||
|
||||
if (is_64bit && package->platform == PLATFORM_INTEL &&
|
||||
root == HKEY_LOCAL_MACHINE && !strncmpiW( path, prefixW, len ))
|
||||
{
|
||||
UINT size;
|
||||
WCHAR *path_32node;
|
||||
|
||||
size = (strlenW( path ) + strlenW( szWow6432Node ) + 1) * sizeof(WCHAR);
|
||||
path_32node = msi_alloc( size );
|
||||
if (!path_32node)
|
||||
return NULL;
|
||||
|
||||
memcpy( path_32node, path, len * sizeof(WCHAR) );
|
||||
path_32node[len] = 0;
|
||||
strcatW( path_32node, szWow6432Node );
|
||||
strcatW( path_32node, szBackSlash );
|
||||
strcatW( path_32node, path + len );
|
||||
return path_32node;
|
||||
}
|
||||
|
||||
return strdupW( path );
|
||||
}
|
||||
|
||||
static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
|
||||
{
|
||||
MSIPACKAGE *package = param;
|
||||
LPSTR value_data = NULL;
|
||||
HKEY root_key, hkey;
|
||||
DWORD type,size;
|
||||
LPWSTR deformated;
|
||||
LPWSTR deformated, uikey, keypath;
|
||||
LPCWSTR szRoot, component, name, key, value;
|
||||
MSICOMPONENT *comp;
|
||||
MSIRECORD * uirow;
|
||||
LPWSTR uikey;
|
||||
INT root;
|
||||
BOOL check_first = FALSE;
|
||||
UINT rc;
|
||||
|
@ -2432,14 +2458,14 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
|
|||
strcpyW(uikey,szRoot);
|
||||
strcatW(uikey,deformated);
|
||||
|
||||
if (RegCreateKeyW( root_key, deformated, &hkey))
|
||||
keypath = get_keypath( package, root_key, deformated );
|
||||
msi_free( deformated );
|
||||
if (RegCreateKeyW( root_key, keypath, &hkey ))
|
||||
{
|
||||
ERR("Could not create key %s\n",debugstr_w(deformated));
|
||||
msi_free(deformated);
|
||||
ERR("Could not create key %s\n", debugstr_w(keypath));
|
||||
msi_free(uikey);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
msi_free(deformated);
|
||||
|
||||
value = MSI_RecordGetString(row,5);
|
||||
if (value)
|
||||
|
@ -2554,7 +2580,7 @@ static UINT ITERATE_RemoveRegistryValuesOnUninstall( MSIRECORD *row, LPVOID para
|
|||
{
|
||||
MSIPACKAGE *package = param;
|
||||
LPCWSTR component, name, key_str, root_key_str;
|
||||
LPWSTR deformated_key, deformated_name, ui_key_str;
|
||||
LPWSTR deformated_key, deformated_name, ui_key_str, keypath;
|
||||
MSICOMPONENT *comp;
|
||||
MSIRECORD *uirow;
|
||||
BOOL delete_key = FALSE;
|
||||
|
@ -2610,8 +2636,10 @@ static UINT ITERATE_RemoveRegistryValuesOnUninstall( MSIRECORD *row, LPVOID para
|
|||
|
||||
deformat_string( package, name, &deformated_name );
|
||||
|
||||
delete_reg_key_or_value( hkey_root, deformated_key, deformated_name, delete_key );
|
||||
keypath = get_keypath( package, hkey_root, deformated_key );
|
||||
msi_free( deformated_key );
|
||||
delete_reg_key_or_value( hkey_root, keypath, deformated_name, delete_key );
|
||||
msi_free( keypath );
|
||||
|
||||
uirow = MSI_CreateRecord( 2 );
|
||||
MSI_RecordSetStringW( uirow, 1, ui_key_str );
|
||||
|
@ -2629,7 +2657,7 @@ static UINT ITERATE_RemoveRegistryValuesOnInstall( MSIRECORD *row, LPVOID param
|
|||
{
|
||||
MSIPACKAGE *package = param;
|
||||
LPCWSTR component, name, key_str, root_key_str;
|
||||
LPWSTR deformated_key, deformated_name, ui_key_str;
|
||||
LPWSTR deformated_key, deformated_name, ui_key_str, keypath;
|
||||
MSICOMPONENT *comp;
|
||||
MSIRECORD *uirow;
|
||||
BOOL delete_key = FALSE;
|
||||
|
@ -2682,8 +2710,10 @@ static UINT ITERATE_RemoveRegistryValuesOnInstall( MSIRECORD *row, LPVOID param
|
|||
|
||||
deformat_string( package, name, &deformated_name );
|
||||
|
||||
delete_reg_key_or_value( hkey_root, deformated_key, deformated_name, delete_key );
|
||||
keypath = get_keypath( package, hkey_root, deformated_key );
|
||||
msi_free( deformated_key );
|
||||
delete_reg_key_or_value( hkey_root, keypath, deformated_name, delete_key );
|
||||
msi_free( keypath );
|
||||
|
||||
uirow = MSI_CreateRecord( 2 );
|
||||
MSI_RecordSetStringW( uirow, 1, ui_key_str );
|
||||
|
@ -3891,7 +3921,7 @@ static UINT msi_publish_patches( MSIPACKAGE *package )
|
|||
WCHAR *p, *all_patches = NULL;
|
||||
DWORD len = 0;
|
||||
|
||||
r = MSIREG_OpenProductKey( package->ProductCode, NULL, package->Context, &product_key, FALSE );
|
||||
r = MSIREG_OpenProductKey( package->ProductCode, NULL, package->Context, &product_key, TRUE );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
|
@ -4759,7 +4789,7 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
|
|||
if (!msi_check_publish(package))
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
rc = MSIREG_OpenUninstallKey(package->ProductCode, &hkey, TRUE);
|
||||
rc = MSIREG_OpenUninstallKey(package, &hkey, TRUE);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
|
@ -4839,7 +4869,7 @@ static UINT msi_unpublish_product(MSIPACKAGE *package, WCHAR *remove)
|
|||
|
||||
MSIREG_DeleteProductKey(package->ProductCode);
|
||||
MSIREG_DeleteUserDataProductKey(package->ProductCode);
|
||||
MSIREG_DeleteUninstallKey(package->ProductCode);
|
||||
MSIREG_DeleteUninstallKey(package);
|
||||
|
||||
if (package->Context == MSIINSTALLCONTEXT_MACHINE)
|
||||
{
|
||||
|
@ -7498,7 +7528,7 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
|
|||
msi_clone_properties( package );
|
||||
|
||||
msi_parse_command_line( package, szCommandLine, FALSE );
|
||||
msi_adjust_allusers_property( package );
|
||||
msi_adjust_privilege_properties( package );
|
||||
msi_set_context( package );
|
||||
|
||||
if (needs_ui_sequence( package))
|
||||
|
|
|
@ -89,7 +89,7 @@ static UINT ACTION_AppSearchGetSignature(MSIPACKAGE *package, MSISIGNATURE *sig,
|
|||
'S','i','g','n','a','t','u','r','e',' ',
|
||||
'w','h','e','r','e',' ','S','i','g','n','a','t','u','r','e',' ','=',' ',
|
||||
'\'','%','s','\'',0};
|
||||
LPWSTR minVersion, maxVersion;
|
||||
LPWSTR minVersion, maxVersion, p;
|
||||
MSIRECORD *row;
|
||||
DWORD time;
|
||||
|
||||
|
@ -106,6 +106,12 @@ static UINT ACTION_AppSearchGetSignature(MSIPACKAGE *package, MSISIGNATURE *sig,
|
|||
|
||||
/* get properties */
|
||||
sig->File = msi_dup_record_field(row,2);
|
||||
if ((p = strchrW(sig->File, '|')))
|
||||
{
|
||||
p++;
|
||||
memmove(sig->File, p, (strlenW(p) + 1) * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
minVersion = msi_dup_record_field(row,3);
|
||||
if (minVersion)
|
||||
{
|
||||
|
|
|
@ -804,12 +804,19 @@ static UINT register_appid(const MSIAPPID *appid, LPCWSTR app )
|
|||
UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
|
||||
{
|
||||
static const WCHAR szFileType_fmt[] = {'F','i','l','e','T','y','p','e','\\','%','s','\\','%','i',0};
|
||||
const WCHAR *keypath;
|
||||
MSIRECORD *uirow;
|
||||
HKEY hkey,hkey2,hkey3;
|
||||
MSICLASS *cls;
|
||||
|
||||
load_classes_and_such(package);
|
||||
if (RegCreateKeyW(HKEY_CLASSES_ROOT, szCLSID, &hkey) != ERROR_SUCCESS)
|
||||
|
||||
if (is_64bit && package->platform == PLATFORM_INTEL)
|
||||
keypath = szWow6432NodeCLSID;
|
||||
else
|
||||
keypath = szCLSID;
|
||||
|
||||
if (RegCreateKeyW(HKEY_CLASSES_ROOT, keypath, &hkey) != ERROR_SUCCESS)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
|
||||
|
@ -963,12 +970,19 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
|
|||
UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package )
|
||||
{
|
||||
static const WCHAR szFileType[] = {'F','i','l','e','T','y','p','e','\\',0};
|
||||
const WCHAR *keypath;
|
||||
MSIRECORD *uirow;
|
||||
MSICLASS *cls;
|
||||
HKEY hkey, hkey2;
|
||||
|
||||
load_classes_and_such( package );
|
||||
if (RegOpenKeyW( HKEY_CLASSES_ROOT, szCLSID, &hkey ) != ERROR_SUCCESS)
|
||||
|
||||
if (is_64bit && package->platform == PLATFORM_INTEL)
|
||||
keypath = szWow6432NodeCLSID;
|
||||
else
|
||||
keypath = szCLSID;
|
||||
|
||||
if (RegOpenKeyW( HKEY_CLASSES_ROOT, keypath, &hkey ) != ERROR_SUCCESS)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
|
||||
|
@ -1072,7 +1086,7 @@ static UINT register_progid( const MSIPROGID* progid )
|
|||
if (clsid)
|
||||
msi_reg_set_subkey_val( hkey, szCLSID, NULL, clsid );
|
||||
else
|
||||
ERR("%s has no class\n", debugstr_w( progid->ProgID ) );
|
||||
TRACE("%s has no class\n", debugstr_w( progid->ProgID ) );
|
||||
|
||||
if (progid->Description)
|
||||
msi_reg_set_val_str( hkey, NULL, progid->Description );
|
||||
|
|
|
@ -2329,11 +2329,21 @@ static INT compare_substring( LPCWSTR a, INT operator, LPCWSTR b )
|
|||
case COND_LHS:
|
||||
return 0 == strncmpW( a, b, lstrlenW( b ) );
|
||||
case COND_RHS:
|
||||
return 0 == lstrcmpW( a + (lstrlenW( a ) - lstrlenW( b )), b );
|
||||
{
|
||||
int l = lstrlenW( a );
|
||||
int r = lstrlenW( b );
|
||||
if (r > l) return 0;
|
||||
return 0 == lstrcmpW( a + (l - r), b );
|
||||
}
|
||||
case COND_ILHS:
|
||||
return 0 == strncmpiW( a, b, lstrlenW( b ) );
|
||||
case COND_IRHS:
|
||||
return 0 == lstrcmpiW( a + (lstrlenW( a ) - lstrlenW( b )), b );
|
||||
{
|
||||
int l = lstrlenW( a );
|
||||
int r = lstrlenW( b );
|
||||
if (r > l) return 0;
|
||||
return 0 == lstrcmpiW( a + (l - r), b );
|
||||
}
|
||||
default:
|
||||
ERR("invalid substring operator\n");
|
||||
return 0;
|
||||
|
|
|
@ -462,11 +462,21 @@ static INT compare_substring( LPCWSTR a, INT operator, LPCWSTR b )
|
|||
case COND_LHS:
|
||||
return 0 == strncmpW( a, b, lstrlenW( b ) );
|
||||
case COND_RHS:
|
||||
return 0 == lstrcmpW( a + (lstrlenW( a ) - lstrlenW( b )), b );
|
||||
{
|
||||
int l = lstrlenW( a );
|
||||
int r = lstrlenW( b );
|
||||
if (r > l) return 0;
|
||||
return 0 == lstrcmpW( a + (l - r), b );
|
||||
}
|
||||
case COND_ILHS:
|
||||
return 0 == strncmpiW( a, b, lstrlenW( b ) );
|
||||
case COND_IRHS:
|
||||
return 0 == lstrcmpiW( a + (lstrlenW( a ) - lstrlenW( b )), b );
|
||||
{
|
||||
int l = lstrlenW( a );
|
||||
int r = lstrlenW( b );
|
||||
if (r > l) return 0;
|
||||
return 0 == lstrcmpiW( a + (l - r), b );
|
||||
}
|
||||
default:
|
||||
ERR("invalid substring operator\n");
|
||||
return 0;
|
||||
|
|
|
@ -222,13 +222,6 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
|
|||
if (type & msidbCustomActionTypeNoImpersonate)
|
||||
WARN("msidbCustomActionTypeNoImpersonate not handled\n");
|
||||
|
||||
if (type & msidbCustomActionTypeRollback)
|
||||
{
|
||||
FIXME("Rollback only action... rollbacks not supported yet\n");
|
||||
schedule_action(package, ROLLBACK_SCRIPT, action);
|
||||
rc = ERROR_SUCCESS;
|
||||
goto end;
|
||||
}
|
||||
if (!execute)
|
||||
{
|
||||
LPWSTR actiondata = msi_dup_property(package->db, action);
|
||||
|
@ -238,12 +231,17 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
|
|||
|
||||
if (type & msidbCustomActionTypeCommit)
|
||||
{
|
||||
TRACE("Deferring Commit Action!\n");
|
||||
TRACE("Deferring commit action\n");
|
||||
schedule_action(package, COMMIT_SCRIPT, deferred);
|
||||
}
|
||||
else if (type & msidbCustomActionTypeRollback)
|
||||
{
|
||||
FIXME("Deferring rollback only action... rollbacks not supported yet\n");
|
||||
schedule_action(package, ROLLBACK_SCRIPT, deferred);
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("Deferring Action!\n");
|
||||
TRACE("Deferring action\n");
|
||||
schedule_action(package, INSTALL_SCRIPT, deferred);
|
||||
}
|
||||
|
||||
|
@ -258,20 +256,14 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
|
|||
{
|
||||
LPWSTR actiondata = msi_dup_property( package->db, action );
|
||||
|
||||
switch (script)
|
||||
{
|
||||
case INSTALL_SCRIPT:
|
||||
if (type & msidbCustomActionTypeInScript)
|
||||
package->scheduled_action_running = TRUE;
|
||||
break;
|
||||
case COMMIT_SCRIPT:
|
||||
|
||||
if (type & msidbCustomActionTypeCommit)
|
||||
package->commit_action_running = TRUE;
|
||||
break;
|
||||
case ROLLBACK_SCRIPT:
|
||||
|
||||
if (type & msidbCustomActionTypeRollback)
|
||||
package->rollback_action_running = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (deferred_data)
|
||||
set_deferred_action_props(package, deferred_data);
|
||||
|
|
|
@ -241,7 +241,7 @@ static VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
|
|||
free_cached_tables( db );
|
||||
free_streams( db );
|
||||
free_transforms( db );
|
||||
msi_destroy_stringtable( db->strings );
|
||||
if (db->strings) msi_destroy_stringtable( db->strings );
|
||||
IStorage_Release( db->storage );
|
||||
if (db->deletefile)
|
||||
{
|
||||
|
@ -255,6 +255,43 @@ static VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
|
|||
}
|
||||
}
|
||||
|
||||
static HRESULT db_initialize( IStorage *stg, const GUID *clsid )
|
||||
{
|
||||
static const WCHAR szTables[] = { '_','T','a','b','l','e','s',0 };
|
||||
HRESULT hr;
|
||||
|
||||
hr = IStorage_SetClass( stg, clsid );
|
||||
if (FAILED( hr ))
|
||||
{
|
||||
WARN("failed to set class id 0x%08x\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* create the _Tables stream */
|
||||
hr = write_stream_data( stg, szTables, NULL, 0, TRUE );
|
||||
if (FAILED( hr ))
|
||||
{
|
||||
WARN("failed to create _Tables stream 0x%08x\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = msi_init_string_table( stg );
|
||||
if (FAILED( hr ))
|
||||
{
|
||||
WARN("failed to initialize string table 0x%08x\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = IStorage_Commit( stg, 0 );
|
||||
if (FAILED( hr ))
|
||||
{
|
||||
WARN("failed to commit changes 0x%08x\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
|
||||
{
|
||||
IStorage *stg = NULL;
|
||||
|
@ -266,8 +303,6 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
|
|||
BOOL created = FALSE, patch = FALSE;
|
||||
WCHAR path[MAX_PATH];
|
||||
|
||||
static const WCHAR szTables[] = { '_','T','a','b','l','e','s',0 };
|
||||
|
||||
TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) );
|
||||
|
||||
if( !pdb )
|
||||
|
@ -298,28 +333,28 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
|
|||
r = StgOpenStorage( szDBPath, NULL,
|
||||
STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
|
||||
}
|
||||
else if( szPersist == MSIDBOPEN_CREATE || szPersist == MSIDBOPEN_CREATEDIRECT )
|
||||
else if( szPersist == MSIDBOPEN_CREATE )
|
||||
{
|
||||
/* FIXME: MSIDBOPEN_CREATE should case STGM_TRANSACTED flag to be
|
||||
* used here: */
|
||||
r = StgCreateDocfile( szDBPath,
|
||||
STGM_CREATE|STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg);
|
||||
if( r == ERROR_SUCCESS )
|
||||
{
|
||||
IStorage_SetClass( stg, patch ? &CLSID_MsiPatch : &CLSID_MsiDatabase );
|
||||
/* create the _Tables stream */
|
||||
r = write_stream_data(stg, szTables, NULL, 0, TRUE);
|
||||
if (SUCCEEDED(r))
|
||||
r = msi_init_string_table( stg );
|
||||
}
|
||||
STGM_CREATE|STGM_TRANSACTED|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg );
|
||||
|
||||
if( SUCCEEDED(r) )
|
||||
r = db_initialize( stg, patch ? &CLSID_MsiPatch : &CLSID_MsiDatabase );
|
||||
created = TRUE;
|
||||
}
|
||||
else if( szPersist == MSIDBOPEN_CREATEDIRECT )
|
||||
{
|
||||
r = StgCreateDocfile( szDBPath,
|
||||
STGM_CREATE|STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg );
|
||||
|
||||
if( SUCCEEDED(r) )
|
||||
r = db_initialize( stg, patch ? &CLSID_MsiPatch : &CLSID_MsiDatabase );
|
||||
created = TRUE;
|
||||
}
|
||||
else if( szPersist == MSIDBOPEN_TRANSACT )
|
||||
{
|
||||
/* FIXME: MSIDBOPEN_TRANSACT should case STGM_TRANSACTED flag to be
|
||||
* used here: */
|
||||
r = StgOpenStorage( szDBPath, NULL,
|
||||
STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
|
||||
STGM_TRANSACTED|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
|
||||
}
|
||||
else if( szPersist == MSIDBOPEN_DIRECT )
|
||||
{
|
||||
|
|
|
@ -60,8 +60,6 @@ static UINT JOIN_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *v
|
|||
UINT cols = 0;
|
||||
UINT prev_rows = 1;
|
||||
|
||||
TRACE("%d, %d\n", row, col);
|
||||
|
||||
if (col == 0 || col > jv->columns)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
|
@ -225,10 +223,12 @@ static UINT JOIN_get_column_info( struct tagMSIVIEW *view,
|
|||
static UINT join_find_row( MSIJOINVIEW *jv, MSIRECORD *rec, UINT *row )
|
||||
{
|
||||
LPCWSTR str;
|
||||
UINT i, id, data;
|
||||
UINT r, i, id, data;
|
||||
|
||||
str = MSI_RecordGetString( rec, 1 );
|
||||
msi_string2idW( jv->db->strings, str, &id );
|
||||
r = msi_string2idW( jv->db->strings, str, &id );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
for (i = 0; i < jv->rows; i++)
|
||||
{
|
||||
|
|
|
@ -211,9 +211,6 @@ static INT_PTR CDECL cabinet_open_stream( char *pszFile, int oflag, int pmode )
|
|||
UINT r;
|
||||
IStream *stm;
|
||||
|
||||
if (oflag)
|
||||
WARN("ignoring open flags 0x%08x\n", oflag);
|
||||
|
||||
r = db_get_raw_stream( cab_stream.db, cab_stream.name, &stm );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
|
@ -358,6 +355,40 @@ done:
|
|||
return res;
|
||||
}
|
||||
|
||||
static INT_PTR cabinet_next_cabinet_stream( FDINOTIFICATIONTYPE fdint,
|
||||
PFDINOTIFICATION pfdin )
|
||||
{
|
||||
MSICABDATA *data = pfdin->pv;
|
||||
MSIMEDIAINFO *mi = data->mi;
|
||||
UINT rc;
|
||||
|
||||
msi_free( mi->disk_prompt );
|
||||
msi_free( mi->cabinet );
|
||||
msi_free( mi->volume_label );
|
||||
mi->disk_prompt = NULL;
|
||||
mi->cabinet = NULL;
|
||||
mi->volume_label = NULL;
|
||||
|
||||
mi->disk_id++;
|
||||
mi->is_continuous = TRUE;
|
||||
|
||||
rc = msi_media_get_disk_info( data->package, mi );
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
ERR("Failed to get next cabinet information: %u\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
msi_free( cab_stream.name );
|
||||
cab_stream.name = encode_streamname( FALSE, mi->cabinet + 1 );
|
||||
if (!cab_stream.name)
|
||||
return -1;
|
||||
|
||||
TRACE("next cabinet is %s\n", debugstr_w(mi->cabinet));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint,
|
||||
PFDINOTIFICATION pfdin)
|
||||
{
|
||||
|
@ -494,6 +525,12 @@ static INT_PTR CDECL cabinet_notify_stream( FDINOTIFICATIONTYPE fdint, PFDINOTIF
|
|||
{
|
||||
switch (fdint)
|
||||
{
|
||||
case fdintPARTIAL_FILE:
|
||||
return cabinet_partial_file( fdint, pfdin );
|
||||
|
||||
case fdintNEXT_CABINET:
|
||||
return cabinet_next_cabinet_stream( fdint, pfdin );
|
||||
|
||||
case fdintCOPY_FILE:
|
||||
return cabinet_copy_file( fdint, pfdin );
|
||||
|
||||
|
|
|
@ -3779,3 +3779,44 @@ UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent,
|
|||
FIXME("(%s %s %d\n", debugstr_w(szProduct), debugstr_w(szComponent), eInstallState);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MsiBeginTransactionA [MSI.@]
|
||||
*/
|
||||
UINT WINAPI MsiBeginTransactionA( LPCSTR name, DWORD attrs, MSIHANDLE *id, HANDLE *event )
|
||||
{
|
||||
WCHAR *nameW;
|
||||
UINT r;
|
||||
|
||||
FIXME("%s %u %p %p\n", debugstr_a(name), attrs, id, event);
|
||||
|
||||
nameW = strdupAtoW( name );
|
||||
if (name && !nameW)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
r = MsiBeginTransactionW( nameW, attrs, id, event );
|
||||
msi_free( nameW );
|
||||
return r;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MsiBeginTransactionW [MSI.@]
|
||||
*/
|
||||
UINT WINAPI MsiBeginTransactionW( LPCWSTR name, DWORD attrs, MSIHANDLE *id, HANDLE *event )
|
||||
{
|
||||
FIXME("%s %u %p %p\n", debugstr_w(name), attrs, id, event);
|
||||
|
||||
*id = (MSIHANDLE)0xdeadbeef;
|
||||
*event = (HANDLE)0xdeadbeef;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MsiEndTransaction [MSI.@]
|
||||
*/
|
||||
UINT WINAPI MsiEndTransaction( DWORD state )
|
||||
{
|
||||
FIXME("%u\n", state);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@
|
|||
178 stdcall MsiGetPatchInfoA(str str ptr ptr)
|
||||
179 stdcall MsiGetPatchInfoW(wstr wstr ptr ptr)
|
||||
180 stdcall MsiEnumPatchesA(str long ptr ptr ptr)
|
||||
181 stdcall MsiEnumPatchesW(str long ptr ptr ptr)
|
||||
181 stdcall MsiEnumPatchesW(wstr long ptr ptr ptr)
|
||||
182 stdcall -private DllGetVersion(ptr)
|
||||
183 stub MsiGetProductCodeFromPackageCodeA
|
||||
184 stub MsiGetProductCodeFromPackageCodeW
|
||||
|
@ -214,7 +214,7 @@
|
|||
218 stdcall MsiGetFileHashA(str long ptr)
|
||||
219 stdcall MsiGetFileHashW(wstr long ptr)
|
||||
220 stub MsiEnumComponentCostsA
|
||||
221 stdcall MsiEnumComponentCostsW(long str long long ptr ptr ptr ptr)
|
||||
221 stdcall MsiEnumComponentCostsW(long wstr long long ptr ptr ptr ptr)
|
||||
222 stdcall MsiCreateAndVerifyInstallerDirectory(long)
|
||||
223 stdcall MsiGetFileSignatureInformationA(str long ptr ptr ptr)
|
||||
224 stdcall MsiGetFileSignatureInformationW(wstr long ptr ptr ptr)
|
||||
|
@ -277,9 +277,9 @@
|
|||
281 stdcall MsiSetExternalUIRecord(ptr long ptr ptr)
|
||||
282 stub MsiGetPatchFileListA
|
||||
283 stub MsiGetPatchFileListW
|
||||
284 stub MsiBeginTransactionA
|
||||
285 stub MsiBeginTransactionW
|
||||
286 stub MsiEndTransaction
|
||||
284 stdcall MsiBeginTransactionA(str long ptr ptr)
|
||||
285 stdcall MsiBeginTransactionW(wstr long ptr ptr)
|
||||
286 stdcall MsiEndTransaction(long)
|
||||
287 stub MsiJoinTransaction
|
||||
288 stub MsiSetOfflineContextW
|
||||
289 stub MsiEnumComponentsExA
|
||||
|
|
|
@ -24,39 +24,39 @@ LANGUAGE LANG_FINNISH, SUBLANG_DEFAULT
|
|||
|
||||
STRINGTABLE
|
||||
{
|
||||
4 "The specified installation package could not be opened. Please check the file path and try again."
|
||||
4 "Annettua asennuspakettia ei voitu avata. Tarkista tiedoston polku ja yritä uudelleen."
|
||||
5 "Polkua %s ei löydy."
|
||||
9 "Anna levy %s"
|
||||
10 "Windows Installer %s\n\n" \
|
||||
"Usage:\n" \
|
||||
"msiexec command {required parameter} [optional parammeter]\n\n" \
|
||||
"Install a product:\n" \
|
||||
"\t/i {package|productcode} [property]\n" \
|
||||
"\t/package {package|productcode} [property]\n" \
|
||||
"\t/a package [property]\n" \
|
||||
"Repair an installation:\n" \
|
||||
"\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
|
||||
"Uninstall a product:\n" \
|
||||
"\t/uninstall {package|productcode} [property]\n" \
|
||||
"\t/x {package|productcode} [property]\n" \
|
||||
"Advertise a product:\n" \
|
||||
"\t/j[u|m] package [/t transform] [/g languageid]\n" \
|
||||
"Apply a patch:\n" \
|
||||
"\t/p patchpackage [property]\n" \
|
||||
"\t/p patchpackage /a package [property]\n" \
|
||||
"Log and UI Modifiers for above commands:\n" \
|
||||
"\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
|
||||
"Käyttö:\n" \
|
||||
"msiexec komento {pakollinen parametri} [valinnainen parametri]\n\n" \
|
||||
"Asenna tuote:\n" \
|
||||
"\t/i {paketti|tuotekoodi} [ominaisuus]\n" \
|
||||
"\t/package {paketti|tuotekoodi} [ominaisuus]\n" \
|
||||
"\t/a {paketti} [ominaisuus]\n" \
|
||||
"Korjaa asennus:\n" \
|
||||
"\t/f[p|o|e|d|c|a|u|m|s|v] {paketti|tuotekoodi}\n" \
|
||||
"Poista tuote:\n" \
|
||||
"\t/uninstall {paketti|tuotekoodi} [ominaisuus]\n" \
|
||||
"\t/x {paketti|tuotekoodi} [ominaisuus]\n" \
|
||||
"Mainosta (advertise) tuotetta:\n" \
|
||||
"\t/j[u|m] paketti [/t muunnos] [/g kielitunnus]\n" \
|
||||
"Asenna korjaus:\n" \
|
||||
"\t/p korjauspaketti [ominaisuus]\n" \
|
||||
"\t/p korjauspaketti /a paketti [ominaisuus]\n" \
|
||||
"Loki- ja käyttöliittymäasetukset edellisille komennoille:\n" \
|
||||
"\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] lokitiedosto\n" \
|
||||
"\t/q{|n|b|r|f|n+|b+|b-}\n" \
|
||||
"Register MSI Service:\n" \
|
||||
"Rekisteröi MSI-palvelu:\n" \
|
||||
"\t/y\n" \
|
||||
"Unregister MSI Service:\n" \
|
||||
"Peru MSI-palvelun rekisteröinti:\n" \
|
||||
"\t/z\n" \
|
||||
"Display this help:\n" \
|
||||
"Näytä tämä ohje:\n" \
|
||||
"\t/help\n" \
|
||||
"\t/?\n"
|
||||
11 "Anna kansio, joka sisältää %s"
|
||||
11 "Anna kansio, jossa on %s"
|
||||
12 "Ominaisuuden asennuslähde puuttuu."
|
||||
13 "Ominaisuuden verkkolevy puuttuu."
|
||||
14 "Ominaisuus:"
|
||||
15 "Valitse kansio, joka sisältää %s"
|
||||
15 "Valitse kansio, jossa on %s"
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "fdi.h"
|
||||
#include "msi.h"
|
||||
#include "msiquery.h"
|
||||
#include "msidefs.h"
|
||||
#include "objbase.h"
|
||||
#include "objidl.h"
|
||||
#include "winnls.h"
|
||||
|
@ -36,6 +37,8 @@
|
|||
#include "wine/list.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
static const BOOL is_64bit = sizeof(void *) > sizeof(int);
|
||||
|
||||
#define MSI_DATASIZEMASK 0x00ff
|
||||
#define MSITYPE_VALID 0x0100
|
||||
#define MSITYPE_LOCALIZABLE 0x200
|
||||
|
@ -45,6 +48,7 @@
|
|||
#define MSITYPE_TEMPORARY 0x4000
|
||||
|
||||
#define MAX_STREAM_NAME_LEN 62
|
||||
#define LONG_STR_BYTES 3
|
||||
|
||||
/* Install UI level mask for AND operation to exclude flags */
|
||||
#define INSTALLUILEVEL_MASK 0x0007
|
||||
|
@ -103,6 +107,7 @@ typedef struct tagMSIFIELD
|
|||
union
|
||||
{
|
||||
INT iVal;
|
||||
INT_PTR pVal;
|
||||
LPWSTR szwVal;
|
||||
IStream *stream;
|
||||
} u;
|
||||
|
@ -303,10 +308,21 @@ struct tagMSIVIEW
|
|||
struct msi_dialog_tag;
|
||||
typedef struct msi_dialog_tag msi_dialog;
|
||||
|
||||
enum platform
|
||||
{
|
||||
PLATFORM_INTEL,
|
||||
PLATFORM_INTEL64,
|
||||
PLATFORM_X64
|
||||
};
|
||||
|
||||
typedef struct tagMSIPACKAGE
|
||||
{
|
||||
MSIOBJECTHDR hdr;
|
||||
MSIDATABASE *db;
|
||||
INT version;
|
||||
enum platform platform;
|
||||
UINT num_langids;
|
||||
LANGID *langids;
|
||||
struct list patches;
|
||||
struct list components;
|
||||
struct list features;
|
||||
|
@ -388,7 +404,6 @@ typedef struct tagMSIFEATURE
|
|||
typedef struct tagMSICOMPONENT
|
||||
{
|
||||
struct list entry;
|
||||
DWORD magic;
|
||||
LPWSTR Component;
|
||||
LPWSTR ComponentId;
|
||||
LPWSTR Directory;
|
||||
|
@ -595,9 +610,9 @@ typedef struct tagMSISCRIPT
|
|||
#define MSIHANDLETYPE_PACKAGE 5
|
||||
#define MSIHANDLETYPE_PREVIEW 6
|
||||
|
||||
#define MSI_MAJORVERSION 3
|
||||
#define MSI_MINORVERSION 1
|
||||
#define MSI_BUILDNUMBER 4000
|
||||
#define MSI_MAJORVERSION 4
|
||||
#define MSI_MINORVERSION 5
|
||||
#define MSI_BUILDNUMBER 6001
|
||||
|
||||
#define GUID_SIZE 39
|
||||
#define SQUISH_GUID_SIZE 33
|
||||
|
@ -672,7 +687,7 @@ extern VOID msi_destroy_stringtable( string_table *st );
|
|||
extern const WCHAR *msi_string_lookup_id( const string_table *st, UINT id );
|
||||
extern HRESULT msi_init_string_table( IStorage *stg );
|
||||
extern string_table *msi_load_string_table( IStorage *stg, UINT *bytes_per_strref );
|
||||
extern UINT msi_save_string_table( const string_table *st, IStorage *storage );
|
||||
extern UINT msi_save_string_table( const string_table *st, IStorage *storage, UINT *bytes_per_strref );
|
||||
|
||||
extern BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name );
|
||||
extern MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR table );
|
||||
|
@ -709,11 +724,13 @@ extern UINT MSI_RecordGetIStream( MSIRECORD *, UINT, IStream **);
|
|||
extern const WCHAR *MSI_RecordGetString( const MSIRECORD *, UINT );
|
||||
extern MSIRECORD *MSI_CreateRecord( UINT );
|
||||
extern UINT MSI_RecordSetInteger( MSIRECORD *, UINT, int );
|
||||
extern UINT MSI_RecordSetIntPtr( MSIRECORD *, UINT, INT_PTR );
|
||||
extern UINT MSI_RecordSetStringW( MSIRECORD *, UINT, LPCWSTR );
|
||||
extern BOOL MSI_RecordIsNull( MSIRECORD *, UINT );
|
||||
extern UINT MSI_RecordGetStringW( MSIRECORD * , UINT, LPWSTR, LPDWORD);
|
||||
extern UINT MSI_RecordGetStringA( MSIRECORD *, UINT, LPSTR, LPDWORD);
|
||||
extern int MSI_RecordGetInteger( MSIRECORD *, UINT );
|
||||
extern INT_PTR MSI_RecordGetIntPtr( MSIRECORD *, UINT );
|
||||
extern UINT MSI_RecordReadStream( MSIRECORD *, UINT, char *, LPDWORD);
|
||||
extern UINT MSI_RecordSetStream(MSIRECORD *, UINT, IStream *);
|
||||
extern UINT MSI_RecordGetFieldCount( const MSIRECORD *rec );
|
||||
|
@ -765,7 +782,7 @@ extern UINT msi_package_add_info(MSIPACKAGE *, DWORD, DWORD, LPCWSTR, LPWSTR);
|
|||
extern UINT msi_package_add_media_disk(MSIPACKAGE *, DWORD, DWORD, DWORD, LPWSTR, LPWSTR);
|
||||
extern UINT msi_clone_properties(MSIPACKAGE *);
|
||||
extern UINT msi_set_context(MSIPACKAGE *);
|
||||
extern void msi_adjust_allusers_property(MSIPACKAGE *);
|
||||
extern void msi_adjust_privilege_properties(MSIPACKAGE *);
|
||||
extern UINT MSI_GetFeatureCost(MSIPACKAGE *, MSIFEATURE *, MSICOSTTREE, INSTALLSTATE, LPINT);
|
||||
|
||||
/* for deformating */
|
||||
|
@ -776,8 +793,8 @@ extern BOOL unsquash_guid(LPCWSTR in, LPWSTR out);
|
|||
extern BOOL squash_guid(LPCWSTR in, LPWSTR out);
|
||||
extern BOOL encode_base85_guid(GUID *,LPWSTR);
|
||||
extern BOOL decode_base85_guid(LPCWSTR,GUID*);
|
||||
extern UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||
extern UINT MSIREG_DeleteUninstallKey(LPCWSTR szProduct);
|
||||
extern UINT MSIREG_OpenUninstallKey(MSIPACKAGE *package, HKEY *key, BOOL create);
|
||||
extern UINT MSIREG_DeleteUninstallKey(MSIPACKAGE *package);
|
||||
extern UINT MSIREG_OpenProductKey(LPCWSTR szProduct, LPCWSTR szUserSid,
|
||||
MSIINSTALLCONTEXT context, HKEY* key, BOOL create);
|
||||
extern UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
|
||||
|
@ -843,6 +860,7 @@ extern UINT msi_spawn_error_dialog( MSIPACKAGE*, LPWSTR, LPWSTR );
|
|||
/* summary information */
|
||||
extern MSISUMMARYINFO *MSI_GetSummaryInformationW( IStorage *stg, UINT uiUpdateCount );
|
||||
extern LPWSTR msi_suminfo_dup_string( MSISUMMARYINFO *si, UINT uiProperty );
|
||||
extern INT msi_suminfo_get_int32( MSISUMMARYINFO *si, UINT uiProperty );
|
||||
extern LPWSTR msi_get_suminfo_product( IStorage *stg );
|
||||
extern UINT msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns );
|
||||
|
||||
|
@ -915,6 +933,10 @@ static inline void msi_feature_set_state(MSIPACKAGE *package,
|
|||
feature->ActionRequest = state;
|
||||
feature->Action = state;
|
||||
}
|
||||
if (feature->Attributes & msidbFeatureAttributesUIDisallowAbsent)
|
||||
{
|
||||
feature->Action = INSTALLSTATE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void msi_component_set_state(MSIPACKAGE *package,
|
||||
|
@ -1123,6 +1145,12 @@ static const WCHAR szMIMEDatabase[] = {'M','I','M','E','\\','D','a','t','a','b',
|
|||
static const WCHAR szLocalPackage[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
|
||||
static const WCHAR szOriginalDatabase[] = {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
|
||||
static const WCHAR szUpgradeCode[] = {'U','p','g','r','a','d','e','C','o','d','e',0};
|
||||
static const WCHAR szAdminUser[] = {'A','d','m','i','n','U','s','e','r',0};
|
||||
static const WCHAR szIntel[] = {'I','n','t','e','l',0};
|
||||
static const WCHAR szIntel64[] = {'I','n','t','e','l','6','4',0};
|
||||
static const WCHAR szX64[] = {'x','6','4',0};
|
||||
static const WCHAR szWow6432NodeCLSID[] = {'W','o','w','6','4','3','2','N','o','d','e','\\','C','L','S','I','D',0};
|
||||
static const WCHAR szWow6432Node[] = {'W','o','w','6','4','3','2','N','o','d','e',0};
|
||||
|
||||
/* memory allocation macro functions */
|
||||
static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);
|
||||
|
|
|
@ -382,7 +382,7 @@ UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec)
|
|||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
query->row ++;
|
||||
MSI_RecordSetInteger(*prec, 0, (int)query);
|
||||
MSI_RecordSetIntPtr(*prec, 0, (INT_PTR)query);
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -617,7 +617,7 @@ UINT MSI_ViewModify( MSIQUERY *query, MSIMODIFY mode, MSIRECORD *rec )
|
|||
if ( !view || !view->ops->modify)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
if ( mode == MSIMODIFY_UPDATE && MSI_RecordGetInteger( rec, 0 ) != (int)query )
|
||||
if ( mode == MSIMODIFY_UPDATE && MSI_RecordGetIntPtr( rec, 0 ) != (INT_PTR)query )
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
r = view->ops->modify( view, mode, rec, query->row );
|
||||
|
@ -901,6 +901,9 @@ UINT MSI_DatabaseGetPrimaryKeys( MSIDATABASE *db,
|
|||
MSIQUERY *query = NULL;
|
||||
UINT r;
|
||||
|
||||
if (!TABLE_Exists( db, table ))
|
||||
return ERROR_INVALID_TABLE;
|
||||
|
||||
r = MSI_OpenQuery( db, &query, sql, table );
|
||||
if( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
|
|
|
@ -280,6 +280,7 @@ static void free_package_structures( MSIPACKAGE *package )
|
|||
msi_free( package->ProductCode );
|
||||
msi_free( package->ActionFormat );
|
||||
msi_free( package->LastAction );
|
||||
msi_free( package->langids );
|
||||
|
||||
/* cleanup control event subscriptions */
|
||||
ControlEvent_CleanupSubscriptions( package );
|
||||
|
@ -417,7 +418,7 @@ static UINT set_installed_prop( MSIPACKAGE *package )
|
|||
HKEY hkey = 0;
|
||||
UINT r;
|
||||
|
||||
r = MSIREG_OpenUninstallKey( package->ProductCode, &hkey, FALSE );
|
||||
r = MSIREG_OpenUninstallKey( package, &hkey, FALSE );
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey( hkey );
|
||||
|
@ -618,72 +619,49 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
|||
SYSTEMTIME systemtime;
|
||||
LANGID langid;
|
||||
|
||||
static const WCHAR CFF[] =
|
||||
{'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR PFF[] =
|
||||
{'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR CADF[] =
|
||||
{'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR FaF[] =
|
||||
{'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR FoF[] =
|
||||
{'F','o','n','t','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR SendTF[] =
|
||||
{'S','e','n','d','T','o','F','o','l','d','e','r',0};
|
||||
static const WCHAR SMF[] =
|
||||
{'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
|
||||
static const WCHAR StF[] =
|
||||
{'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
|
||||
static const WCHAR TemplF[] =
|
||||
{'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
|
||||
static const WCHAR DF[] =
|
||||
{'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
|
||||
static const WCHAR PMF[] =
|
||||
{'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
|
||||
static const WCHAR ATF[] =
|
||||
{'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR ADF[] =
|
||||
{'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR SF[] =
|
||||
{'S','y','s','t','e','m','F','o','l','d','e','r',0};
|
||||
static const WCHAR SF16[] =
|
||||
{'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0};
|
||||
static const WCHAR LADF[] =
|
||||
{'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR MPF[] =
|
||||
{'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR PF[] =
|
||||
{'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
|
||||
static const WCHAR WF[] =
|
||||
{'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR WV[] =
|
||||
{'W','i','n','d','o','w','s','V','o','l','u','m','e',0};
|
||||
static const WCHAR TF[]=
|
||||
{'T','e','m','p','F','o','l','d','e','r',0};
|
||||
static const WCHAR szAdminUser[] =
|
||||
{'A','d','m','i','n','U','s','e','r',0};
|
||||
static const WCHAR szPriv[] =
|
||||
{'P','r','i','v','i','l','e','g','e','d',0};
|
||||
static const WCHAR v9x[] = { 'V','e','r','s','i','o','n','9','X',0 };
|
||||
static const WCHAR vNT[] = { 'V','e','r','s','i','o','n','N','T',0 };
|
||||
static const WCHAR szMsiNTProductType[] = { 'M','s','i','N','T','P','r','o','d','u','c','t','T','y','p','e',0 };
|
||||
static const WCHAR szCommonFilesFolder[] = {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR szProgramFilesFolder[] = {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR szCommonAppDataFolder[] = {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR szFavoritesFolder[] = {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR szFontsFolder[] = {'F','o','n','t','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR szSendToFolder[] = {'S','e','n','d','T','o','F','o','l','d','e','r',0};
|
||||
static const WCHAR szStartMenuFolder[] = {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
|
||||
static const WCHAR szStartupFolder[] = {'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
|
||||
static const WCHAR szTemplateFolder[] = {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
|
||||
static const WCHAR szDesktopFolder[] = {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
|
||||
static const WCHAR szProgramMenuFolder[] = {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
|
||||
static const WCHAR szAdminToolsFolder[] = {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR szAppDataFolder[] = {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR szSystemFolder[] = {'S','y','s','t','e','m','F','o','l','d','e','r',0};
|
||||
static const WCHAR szSystem16Folder[] = {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0};
|
||||
static const WCHAR szLocalAppDataFolder[] = {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR szMyPicturesFolder[] = {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR szPersonalFolder[] = {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
|
||||
static const WCHAR szWindowsFolder[] = {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR szWindowsVolume[] = {'W','i','n','d','o','w','s','V','o','l','u','m','e',0};
|
||||
static const WCHAR szTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
|
||||
static const WCHAR szPrivileged[] = {'P','r','i','v','i','l','e','g','e','d',0};
|
||||
static const WCHAR szVersion9x[] = {'V','e','r','s','i','o','n','9','X',0};
|
||||
static const WCHAR szVersionNT[] = {'V','e','r','s','i','o','n','N','T',0};
|
||||
static const WCHAR szMsiNTProductType[] = {'M','s','i','N','T','P','r','o','d','u','c','t','T','y','p','e',0};
|
||||
static const WCHAR szFormat[] = {'%','l','i',0};
|
||||
static const WCHAR szWinBuild[] =
|
||||
{'W','i','n','d','o','w','s','B','u','i','l','d', 0 };
|
||||
static const WCHAR szSPL[] =
|
||||
{'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0 };
|
||||
static const WCHAR szWindowsBuild[] = {'W','i','n','d','o','w','s','B','u','i','l','d',0};
|
||||
static const WCHAR szServicePackLevel[] = {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0};
|
||||
static const WCHAR szSix[] = {'6',0 };
|
||||
|
||||
static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 };
|
||||
static const WCHAR szVersionDatabase[] = { 'V','e','r','s','i','o','n','D','a','t','a','b','a','s','e',0 };
|
||||
static const WCHAR szPhysicalMemory[] = { 'P','h','y','s','i','c','a','l','M','e','m','o','r','y',0 };
|
||||
static const WCHAR szFormat2[] = {'%','l','i','.','%','l','i',0};
|
||||
/* Screen properties */
|
||||
static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
|
||||
static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
|
||||
static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
|
||||
static const WCHAR szIntFormat[] = {'%','d',0};
|
||||
static const WCHAR szIntel[] = { 'I','n','t','e','l',0 };
|
||||
static const WCHAR szMsiAMD64[] = { 'M','s','i','A','M','D','6','4',0 };
|
||||
static const WCHAR szMsix64[] = { 'M','s','i','x','6','4',0 };
|
||||
static const WCHAR szSystem64Folder[] = { 'S','y','s','t','e','m','6','4','F','o','l','d','e','r',0 };
|
||||
static const WCHAR szCommonFiles64Folder[] = { 'C','o','m','m','o','n','F','i','l','e','s','6','4','F','o','l','d','e','r',0 };
|
||||
static const WCHAR szProgramFiles64Folder[] = { 'P','r','o','g','r','a','m','F','i','l','e','s','6','4','F','o','l','d','e','r',0 };
|
||||
static const WCHAR szVersionNT64[] = { 'V','e','r','s','i','o','n','N','T','6','4',0 };
|
||||
static const WCHAR szUserInfo[] = {
|
||||
'S','O','F','T','W','A','R','E','\\',
|
||||
'M','i','c','r','o','s','o','f','t','\\',
|
||||
|
@ -699,17 +677,20 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
|||
'C','u','r','r','e','n','t','V','e','r','s','i','o','n',0
|
||||
};
|
||||
static const WCHAR szRegisteredUser[] = {'R','e','g','i','s','t','e','r','e','d','O','w','n','e','r',0};
|
||||
static const WCHAR szRegisteredOrg[] = {
|
||||
static const WCHAR szRegisteredOrganization[] = {
|
||||
'R','e','g','i','s','t','e','r','e','d','O','r','g','a','n','i','z','a','t','i','o','n',0
|
||||
};
|
||||
static const WCHAR szUSERNAME[] = {'U','S','E','R','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 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};
|
||||
static const WCHAR szUserLanguageID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0};
|
||||
static const WCHAR szSystemLangID[] = {'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0};
|
||||
static const WCHAR szProductState[] = {'P','r','o','d','u','c','t','S','t','a','t','e',0};
|
||||
static const WCHAR szLogonUser[] = {'L','o','g','o','n','U','s','e','r',0};
|
||||
static const WCHAR szNetHoodFolder[] = {'N','e','t','H','o','o','d','F','o','l','d','e','r',0};
|
||||
static const WCHAR szPrintHoodFolder[] = {'P','r','i','n','t','H','o','o','d','F','o','l','d','e','r',0};
|
||||
static const WCHAR szRecentFolder[] = {'R','e','c','e','n','t','F','o','l','d','e','r',0};
|
||||
|
||||
/*
|
||||
* Other things that probably should be set:
|
||||
|
@ -720,130 +701,175 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
|||
* RedirectedDllSupport
|
||||
*/
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, CFF, pth);
|
||||
msi_set_property(package->db, szCommonAppDataFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, PFF, pth);
|
||||
msi_set_property(package->db, szFavoritesFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, CADF, pth);
|
||||
msi_set_property(package->db, szFontsFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_FAVORITES,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, FaF, pth);
|
||||
msi_set_property(package->db, szSendToFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_FONTS,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, FoF, pth);
|
||||
msi_set_property(package->db, szStartMenuFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_SENDTO,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, SendTF, pth);
|
||||
msi_set_property(package->db, szStartupFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_STARTMENU,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, SMF, pth);
|
||||
msi_set_property(package->db, szTemplateFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_STARTUP,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, StF, pth);
|
||||
msi_set_property(package->db, szDesktopFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_TEMPLATES,NULL,0,pth);
|
||||
/* FIXME: set to AllUsers profile path if ALLUSERS is set */
|
||||
SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, TemplF, pth);
|
||||
msi_set_property(package->db, szProgramMenuFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_DESKTOP,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, DF, pth);
|
||||
msi_set_property(package->db, szAdminToolsFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_PROGRAMS,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, PMF, pth);
|
||||
msi_set_property(package->db, szAppDataFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, ATF, pth);
|
||||
msi_set_property(package->db, szSystemFolder, pth);
|
||||
msi_set_property(package->db, szSystem16Folder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, ADF, pth);
|
||||
msi_set_property(package->db, szLocalAppDataFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, SF, pth);
|
||||
msi_set_property(package->db, SF16, pth);
|
||||
msi_set_property(package->db, szMyPicturesFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, LADF, pth);
|
||||
msi_set_property(package->db, szPersonalFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, MPF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, PF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, WF, pth);
|
||||
msi_set_property(package->db, szWindowsFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, szPrintHoodFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, szNetHoodFolder, pth);
|
||||
|
||||
SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth);
|
||||
strcatW(pth, szBackSlash);
|
||||
msi_set_property(package->db, szRecentFolder, pth);
|
||||
|
||||
/* Physical Memory is specified in MB. Using total amount. */
|
||||
msex.dwLength = sizeof(msex);
|
||||
GlobalMemoryStatusEx( &msex );
|
||||
sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys/1024/1024));
|
||||
sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) );
|
||||
msi_set_property(package->db, szPhysicalMemory, bufstr);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
|
||||
SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
|
||||
ptr = strchrW(pth,'\\');
|
||||
if (ptr)
|
||||
*(ptr+1) = 0;
|
||||
msi_set_property(package->db, WV, pth);
|
||||
if (ptr) *(ptr + 1) = 0;
|
||||
msi_set_property(package->db, szWindowsVolume, pth);
|
||||
|
||||
GetTempPathW(MAX_PATH,pth);
|
||||
msi_set_property(package->db, TF, pth);
|
||||
|
||||
msi_set_property(package->db, szTempFolder, pth);
|
||||
|
||||
/* in a wine environment the user is always admin and privileged */
|
||||
msi_set_property(package->db, szAdminUser, szOne);
|
||||
msi_set_property(package->db, szPriv, szOne);
|
||||
msi_set_property(package->db, szPrivileged, szOne);
|
||||
|
||||
/* set the os things */
|
||||
OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
|
||||
GetVersionExW((OSVERSIONINFOW *)&OSVersion);
|
||||
verval = OSVersion.dwMinorVersion+OSVersion.dwMajorVersion*100;
|
||||
sprintfW(verstr,szFormat,verval);
|
||||
verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100;
|
||||
sprintfW(verstr, szFormat, verval);
|
||||
switch (OSVersion.dwPlatformId)
|
||||
{
|
||||
case VER_PLATFORM_WIN32_WINDOWS:
|
||||
msi_set_property(package->db, v9x, verstr);
|
||||
msi_set_property(package->db, szVersion9x, verstr);
|
||||
break;
|
||||
case VER_PLATFORM_WIN32_NT:
|
||||
msi_set_property(package->db, vNT, verstr);
|
||||
sprintfW(verstr,szFormat,OSVersion.wProductType);
|
||||
msi_set_property(package->db, szVersionNT, verstr);
|
||||
sprintfW(verstr, szFormat,OSVersion.wProductType);
|
||||
msi_set_property(package->db, szMsiNTProductType, verstr);
|
||||
break;
|
||||
}
|
||||
sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
|
||||
msi_set_property(package->db, szWinBuild, verstr);
|
||||
sprintfW(verstr, szFormat, OSVersion.dwBuildNumber);
|
||||
msi_set_property(package->db, szWindowsBuild, verstr);
|
||||
/* just fudge this */
|
||||
msi_set_property(package->db, szSPL, szSix);
|
||||
msi_set_property(package->db, szServicePackLevel, szSix);
|
||||
|
||||
sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
|
||||
msi_set_property( package->db, szVersionMsi, bufstr );
|
||||
sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100);
|
||||
msi_set_property( package->db, szVersionDatabase, bufstr );
|
||||
|
||||
GetSystemInfo( &sys_info );
|
||||
GetNativeSystemInfo( &sys_info );
|
||||
sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
|
||||
if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
|
||||
{
|
||||
sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
|
||||
msi_set_property( package->db, szIntel, bufstr );
|
||||
|
||||
GetSystemDirectoryW( pth, MAX_PATH );
|
||||
PathAddBackslashW( pth );
|
||||
msi_set_property( package->db, szSystemFolder, pth );
|
||||
|
||||
SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth );
|
||||
PathAddBackslashW( pth );
|
||||
msi_set_property( package->db, szProgramFilesFolder, pth );
|
||||
|
||||
SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth );
|
||||
PathAddBackslashW( pth );
|
||||
msi_set_property( package->db, szCommonFilesFolder, pth );
|
||||
}
|
||||
else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
|
||||
{
|
||||
msi_set_property( package->db, szMsiAMD64, bufstr );
|
||||
msi_set_property( package->db, szMsix64, bufstr );
|
||||
msi_set_property( package->db, szVersionNT64, verstr );
|
||||
|
||||
GetSystemDirectoryW( pth, MAX_PATH );
|
||||
PathAddBackslashW( pth );
|
||||
msi_set_property( package->db, szSystem64Folder, pth );
|
||||
|
||||
GetSystemWow64DirectoryW( pth, MAX_PATH );
|
||||
PathAddBackslashW( pth );
|
||||
msi_set_property( package->db, szSystemFolder, pth );
|
||||
|
||||
SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth );
|
||||
PathAddBackslashW( pth );
|
||||
msi_set_property( package->db, szProgramFiles64Folder, pth );
|
||||
|
||||
SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, pth );
|
||||
PathAddBackslashW( pth );
|
||||
msi_set_property( package->db, szProgramFilesFolder, pth );
|
||||
|
||||
SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth );
|
||||
PathAddBackslashW( pth );
|
||||
msi_set_property( package->db, szCommonFiles64Folder, pth );
|
||||
|
||||
SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, pth );
|
||||
PathAddBackslashW( pth );
|
||||
msi_set_property( package->db, szCommonFilesFolder, pth );
|
||||
}
|
||||
|
||||
/* Screen properties. */
|
||||
|
@ -878,7 +904,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
|||
(username = msi_reg_get_val_str( hkey, szRegisteredUser )))
|
||||
msi_set_property( package->db, szUSERNAME, username );
|
||||
if (!companyname &&
|
||||
(companyname = msi_reg_get_val_str( hkey, szRegisteredOrg )))
|
||||
(companyname = msi_reg_get_val_str( hkey, szRegisteredOrganization )))
|
||||
msi_set_property( package->db, szCOMPANYNAME, companyname );
|
||||
CloseHandle( hkey );
|
||||
}
|
||||
|
@ -908,7 +934,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
|||
|
||||
langid = GetUserDefaultLangID();
|
||||
sprintfW(bufstr, szIntFormat, langid);
|
||||
msi_set_property( package->db, szUserLangID, bufstr );
|
||||
msi_set_property( package->db, szUserLanguageID, bufstr );
|
||||
|
||||
langid = GetSystemDefaultLangID();
|
||||
sprintfW(bufstr, szIntFormat, langid);
|
||||
|
@ -1042,7 +1068,7 @@ static UINT msi_load_admin_properties(MSIPACKAGE *package)
|
|||
return r;
|
||||
}
|
||||
|
||||
void msi_adjust_allusers_property( MSIPACKAGE *package )
|
||||
void msi_adjust_privilege_properties( MSIPACKAGE *package )
|
||||
{
|
||||
/* FIXME: this should depend on the user's privileges */
|
||||
if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2)
|
||||
|
@ -1050,6 +1076,7 @@ void msi_adjust_allusers_property( MSIPACKAGE *package )
|
|||
TRACE("resetting ALLUSERS property from 2 to 1\n");
|
||||
msi_set_property( package->db, szAllUsers, szOne );
|
||||
}
|
||||
msi_set_property( package->db, szAdminUser, szOne );
|
||||
}
|
||||
|
||||
MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
|
||||
|
@ -1074,7 +1101,7 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
|
|||
|
||||
create_temp_property_table( package );
|
||||
msi_clone_properties( package );
|
||||
msi_adjust_allusers_property( package );
|
||||
msi_adjust_privilege_properties( package );
|
||||
|
||||
package->ProductCode = msi_dup_property( package->db, szProductCode );
|
||||
package->script = msi_alloc_zero( sizeof(MSISCRIPT) );
|
||||
|
@ -1119,7 +1146,10 @@ static UINT copy_package_to_temp( LPCWSTR szPackage, LPWSTR filename )
|
|||
if( !CopyFileW( szPackage, filename, FALSE ) )
|
||||
{
|
||||
UINT error = GetLastError();
|
||||
ERR("failed to copy package %s to %s (%u)\n", debugstr_w(szPackage), debugstr_w(filename), error);
|
||||
if ( error == ERROR_FILE_NOT_FOUND )
|
||||
ERR("can't find %s\n", debugstr_w(szPackage));
|
||||
else
|
||||
ERR("failed to copy package %s to %s (%u)\n", debugstr_w(szPackage), debugstr_w(filename), error);
|
||||
DeleteFileW( filename );
|
||||
return error;
|
||||
}
|
||||
|
@ -1257,6 +1287,92 @@ static UINT apply_registered_patch( MSIPACKAGE *package, LPCWSTR patch_code )
|
|||
return r;
|
||||
}
|
||||
|
||||
static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
|
||||
{
|
||||
WCHAR *template, *p, *q;
|
||||
DWORD i, count;
|
||||
|
||||
package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT );
|
||||
TRACE("version: %d\n", package->version);
|
||||
|
||||
template = msi_suminfo_dup_string( si, PID_TEMPLATE );
|
||||
if (!template)
|
||||
return ERROR_SUCCESS; /* native accepts missing template property */
|
||||
|
||||
TRACE("template: %s\n", debugstr_w(template));
|
||||
|
||||
p = strchrW( template, ';' );
|
||||
if (!p)
|
||||
{
|
||||
WARN("invalid template string %s\n", debugstr_w(template));
|
||||
msi_free( template );
|
||||
return ERROR_PATCH_PACKAGE_INVALID;
|
||||
}
|
||||
*p = 0;
|
||||
if (!template[0] || !strcmpW( template, szIntel ))
|
||||
package->platform = PLATFORM_INTEL;
|
||||
else if (!strcmpW( template, szIntel64 ))
|
||||
package->platform = PLATFORM_INTEL64;
|
||||
else if (!strcmpW( template, szX64 ))
|
||||
package->platform = PLATFORM_X64;
|
||||
else
|
||||
{
|
||||
WARN("unknown platform %s\n", debugstr_w(template));
|
||||
msi_free( template );
|
||||
return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
|
||||
}
|
||||
|
||||
count = 1;
|
||||
for (q = ++p; (q = strchrW( q, ',' )); q++) count++;
|
||||
|
||||
package->langids = msi_alloc( count * sizeof(LANGID) );
|
||||
if (!package->langids)
|
||||
{
|
||||
msi_free( template );
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (*p)
|
||||
{
|
||||
q = strchrW( p, ',' );
|
||||
if (q) *q = 0;
|
||||
package->langids[i] = atoiW( p );
|
||||
if (!q) break;
|
||||
p = q + 1;
|
||||
i++;
|
||||
}
|
||||
package->num_langids = i + 1;
|
||||
|
||||
msi_free( template );
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT validate_package( MSIPACKAGE *package )
|
||||
{
|
||||
BOOL is_wow64;
|
||||
UINT i;
|
||||
|
||||
IsWow64Process( GetCurrentProcess(), &is_wow64 );
|
||||
if (package->platform == PLATFORM_X64)
|
||||
{
|
||||
if (!is_64bit && !is_wow64)
|
||||
return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
|
||||
if (package->version < 200)
|
||||
return ERROR_INSTALL_PACKAGE_INVALID;
|
||||
}
|
||||
if (!package->num_langids)
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
for (i = 0; i < package->num_langids; i++)
|
||||
{
|
||||
if (!package->langids[i] || IsValidLocale( package->langids[i], LCID_INSTALLED ))
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
return ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
|
||||
{
|
||||
static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0};
|
||||
|
@ -1269,6 +1385,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
|
|||
WCHAR temppath[MAX_PATH], localfile[MAX_PATH], cachefile[MAX_PATH];
|
||||
LPCWSTR file = szPackage;
|
||||
DWORD index = 0;
|
||||
MSISUMMARYINFO *si;
|
||||
|
||||
TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
|
||||
|
||||
|
@ -1339,7 +1456,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
|
|||
* read/write, which is safe because we always create a copy that is thrown
|
||||
* away when we're done.
|
||||
*/
|
||||
r = MSI_OpenDatabaseW( file, MSIDBOPEN_DIRECT, &db );
|
||||
r = MSI_OpenDatabaseW( file, MSIDBOPEN_TRANSACT, &db );
|
||||
if( r != ERROR_SUCCESS )
|
||||
{
|
||||
if (file != szPackage)
|
||||
|
@ -1368,6 +1485,29 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
|
|||
if( file != szPackage )
|
||||
track_tempfile( package, file );
|
||||
|
||||
si = MSI_GetSummaryInformationW( db->storage, 0 );
|
||||
if (!si)
|
||||
{
|
||||
WARN("failed to load summary info %u\n", r);
|
||||
msiobj_release( &package->hdr );
|
||||
return ERROR_INSTALL_PACKAGE_INVALID;
|
||||
}
|
||||
|
||||
r = msi_parse_summary( si, package );
|
||||
msiobj_release( &si->hdr );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
WARN("failed to parse summary info %u\n", r);
|
||||
msiobj_release( &package->hdr );
|
||||
return r;
|
||||
}
|
||||
|
||||
r = validate_package( package );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
msiobj_release( &package->hdr );
|
||||
return r;
|
||||
}
|
||||
msi_set_property( package->db, Database, db->path );
|
||||
|
||||
if( UrlIsW( szPackage, URLIS_URL ) )
|
||||
|
@ -1398,7 +1538,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
|
|||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
ERR("registered patch failed to apply %u\n", r);
|
||||
MSI_FreePackage( (MSIOBJECTHDR *)package );
|
||||
msiobj_release( &package->hdr );
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -1408,7 +1548,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
|
|||
if (index)
|
||||
{
|
||||
msi_clone_properties( package );
|
||||
msi_adjust_allusers_property( package );
|
||||
msi_adjust_privilege_properties( package );
|
||||
}
|
||||
|
||||
*pPackage = package;
|
||||
|
|
|
@ -45,6 +45,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msidb);
|
|||
#define MSIFIELD_INT 1
|
||||
#define MSIFIELD_WSTR 3
|
||||
#define MSIFIELD_STREAM 4
|
||||
#define MSIFIELD_INTPTR 5
|
||||
|
||||
static void MSI_FreeField( MSIFIELD *field )
|
||||
{
|
||||
|
@ -52,6 +53,7 @@ static void MSI_FreeField( MSIFIELD *field )
|
|||
{
|
||||
case MSIFIELD_NULL:
|
||||
case MSIFIELD_INT:
|
||||
case MSIFIELD_INTPTR:
|
||||
break;
|
||||
case MSIFIELD_WSTR:
|
||||
msi_free( field->u.szwVal);
|
||||
|
@ -177,6 +179,9 @@ UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n,
|
|||
case MSIFIELD_INT:
|
||||
out->u.iVal = in->u.iVal;
|
||||
break;
|
||||
case MSIFIELD_INTPTR:
|
||||
out->u.pVal = in->u.pVal;
|
||||
break;
|
||||
case MSIFIELD_WSTR:
|
||||
str = strdupW( in->u.szwVal );
|
||||
if ( !str )
|
||||
|
@ -200,6 +205,32 @@ UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n,
|
|||
return r;
|
||||
}
|
||||
|
||||
INT_PTR MSI_RecordGetIntPtr( MSIRECORD *rec, UINT iField )
|
||||
{
|
||||
int ret;
|
||||
|
||||
TRACE( "%p %d\n", rec, iField );
|
||||
|
||||
if( iField > rec->count )
|
||||
return MININT_PTR;
|
||||
|
||||
switch( rec->fields[iField].type )
|
||||
{
|
||||
case MSIFIELD_INT:
|
||||
return rec->fields[iField].u.iVal;
|
||||
case MSIFIELD_INTPTR:
|
||||
return rec->fields[iField].u.pVal;
|
||||
case MSIFIELD_WSTR:
|
||||
if( string2intW( rec->fields[iField].u.szwVal, &ret ) )
|
||||
return ret;
|
||||
return MININT_PTR;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return MININT_PTR;
|
||||
}
|
||||
|
||||
int MSI_RecordGetInteger( MSIRECORD *rec, UINT iField)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -213,6 +244,8 @@ int MSI_RecordGetInteger( MSIRECORD *rec, UINT iField)
|
|||
{
|
||||
case MSIFIELD_INT:
|
||||
return rec->fields[iField].u.iVal;
|
||||
case MSIFIELD_INTPTR:
|
||||
return rec->fields[iField].u.pVal;
|
||||
case MSIFIELD_WSTR:
|
||||
if( string2intW( rec->fields[iField].u.szwVal, &ret ) )
|
||||
return ret;
|
||||
|
@ -267,6 +300,20 @@ UINT WINAPI MsiRecordClearData( MSIHANDLE handle )
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT MSI_RecordSetIntPtr( MSIRECORD *rec, UINT iField, INT_PTR pVal )
|
||||
{
|
||||
TRACE("%p %u %ld\n", rec, iField, pVal);
|
||||
|
||||
if( iField > rec->count )
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
MSI_FreeField( &rec->fields[iField] );
|
||||
rec->fields[iField].type = MSIFIELD_INTPTR;
|
||||
rec->fields[iField].u.pVal = pVal;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT MSI_RecordSetInteger( MSIRECORD *rec, UINT iField, int iVal )
|
||||
{
|
||||
TRACE("%p %u %d\n", rec, iField, iVal);
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||
|
||||
|
||||
/*
|
||||
* This module will be all the helper functions for registry access by the
|
||||
* installer bits.
|
||||
|
@ -103,6 +102,15 @@ static const WCHAR szUninstall_fmt[] = {
|
|||
'U','n','i','n','s','t','a','l','l','\\',
|
||||
'%','s',0 };
|
||||
|
||||
static const WCHAR szUninstall_32node_fmt[] = {
|
||||
'S','o','f','t','w','a','r','e','\\',
|
||||
'W','o','w','6','4','3','2','N','o','d','e','\\',
|
||||
'M','i','c','r','o','s','o','f','t','\\',
|
||||
'W','i','n','d','o','w','s','\\',
|
||||
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
|
||||
'U','n','i','n','s','t','a','l','l','\\',
|
||||
'%','s',0 };
|
||||
|
||||
static const WCHAR szUserProduct[] = {
|
||||
'S','o','f','t','w','a','r','e','\\',
|
||||
'M','i','c','r','o','s','o','f','t','\\',
|
||||
|
@ -509,28 +517,36 @@ static UINT get_user_sid(LPWSTR *usersid)
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create)
|
||||
UINT MSIREG_OpenUninstallKey(MSIPACKAGE *package, HKEY *key, BOOL create)
|
||||
{
|
||||
UINT rc;
|
||||
WCHAR keypath[0x200];
|
||||
TRACE("%s\n",debugstr_w(szProduct));
|
||||
|
||||
sprintfW(keypath,szUninstall_fmt,szProduct);
|
||||
TRACE("%s\n", debugstr_w(package->ProductCode));
|
||||
|
||||
if (is_64bit && package->platform == PLATFORM_INTEL)
|
||||
sprintfW(keypath, szUninstall_32node_fmt, package->ProductCode);
|
||||
else
|
||||
sprintfW(keypath, szUninstall_fmt, package->ProductCode);
|
||||
|
||||
if (create)
|
||||
rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
|
||||
rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, KEY_ALL_ACCESS, NULL, key, NULL);
|
||||
else
|
||||
rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
|
||||
rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, KEY_ALL_ACCESS, key);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
UINT MSIREG_DeleteUninstallKey(LPCWSTR szProduct)
|
||||
UINT MSIREG_DeleteUninstallKey(MSIPACKAGE *package)
|
||||
{
|
||||
WCHAR keypath[0x200];
|
||||
TRACE("%s\n",debugstr_w(szProduct));
|
||||
|
||||
sprintfW(keypath,szUninstall_fmt,szProduct);
|
||||
TRACE("%s\n", debugstr_w(package->ProductCode));
|
||||
|
||||
if (is_64bit && package->platform == PLATFORM_INTEL)
|
||||
sprintfW(keypath, szUninstall_32node_fmt, package->ProductCode);
|
||||
else
|
||||
sprintfW(keypath, szUninstall_fmt, package->ProductCode);
|
||||
|
||||
return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
|
||||
}
|
||||
|
|
|
@ -334,10 +334,12 @@ static UINT STORAGES_get_column_info(struct tagMSIVIEW *view, UINT n,
|
|||
static UINT storages_find_row(MSISTORAGESVIEW *sv, MSIRECORD *rec, UINT *row)
|
||||
{
|
||||
LPCWSTR str;
|
||||
UINT i, id, data;
|
||||
UINT r, i, id, data;
|
||||
|
||||
str = MSI_RecordGetString(rec, 1);
|
||||
msi_string2idW(sv->db->strings, str, &id);
|
||||
r = msi_string2idW(sv->db->strings, str, &id);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
for (i = 0; i < sv->num_rows; i++)
|
||||
{
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright 2002-2004, Mike McCormack for CodeWeavers
|
||||
* Copyright 2007 Robert Shearman for CodeWeavers
|
||||
* Copyright 2010 Hans Leidekker for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -40,8 +41,6 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msidb);
|
||||
|
||||
#define LONG_STR_BYTES 3
|
||||
|
||||
typedef struct _msistring
|
||||
{
|
||||
USHORT persistent_refcount;
|
||||
|
@ -564,7 +563,7 @@ end:
|
|||
return st;
|
||||
}
|
||||
|
||||
UINT msi_save_string_table( const string_table *st, IStorage *storage )
|
||||
UINT msi_save_string_table( const string_table *st, IStorage *storage, UINT *bytes_per_strref )
|
||||
{
|
||||
UINT i, datasize = 0, poolsize = 0, sz, used, r, codepage, n;
|
||||
UINT ret = ERROR_FUNCTION_FAILED;
|
||||
|
@ -593,8 +592,16 @@ UINT msi_save_string_table( const string_table *st, IStorage *storage )
|
|||
|
||||
used = 0;
|
||||
codepage = st->codepage;
|
||||
pool[0]=codepage&0xffff;
|
||||
pool[1]=(codepage>>16);
|
||||
pool[0] = codepage & 0xffff;
|
||||
pool[1] = codepage >> 16;
|
||||
if (st->maxcount > 0xffff)
|
||||
{
|
||||
pool[1] |= 0x8000;
|
||||
*bytes_per_strref = LONG_STR_BYTES;
|
||||
}
|
||||
else
|
||||
*bytes_per_strref = sizeof(USHORT);
|
||||
|
||||
n = 1;
|
||||
for( i=1; i<st->maxcount; i++ )
|
||||
{
|
||||
|
|
|
@ -469,7 +469,7 @@ UINT WINAPI MsiGetSummaryInformationW( MSIHANDLE hDatabase,
|
|||
if( !pHandle )
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if( szDatabase )
|
||||
if( szDatabase && szDatabase[0] )
|
||||
{
|
||||
LPCWSTR persist = uiUpdateCount ? MSIDBOPEN_TRANSACT : MSIDBOPEN_READONLY;
|
||||
|
||||
|
@ -644,6 +644,18 @@ LPWSTR msi_suminfo_dup_string( MSISUMMARYINFO *si, UINT uiProperty )
|
|||
return strdupAtoW( prop->u.pszVal );
|
||||
}
|
||||
|
||||
INT msi_suminfo_get_int32( MSISUMMARYINFO *si, UINT uiProperty )
|
||||
{
|
||||
PROPVARIANT *prop;
|
||||
|
||||
if ( uiProperty >= MSI_MAX_PROPS )
|
||||
return -1;
|
||||
prop = &si->property[uiProperty];
|
||||
if( prop->vt != VT_I4 )
|
||||
return -1;
|
||||
return prop->u.lVal;
|
||||
}
|
||||
|
||||
LPWSTR msi_get_suminfo_product( IStorage *stg )
|
||||
{
|
||||
MSISUMMARYINFO *si;
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
WINE_DEFAULT_DEBUG_CHANNEL(msidb);
|
||||
|
||||
#define MSITABLE_HASH_TABLE_SIZE 37
|
||||
#define LONG_STR_BYTES 3
|
||||
|
||||
typedef struct tagMSICOLUMNHASHENTRY
|
||||
{
|
||||
|
@ -117,13 +116,13 @@ static UINT get_tablecolumns( MSIDATABASE *db,
|
|||
LPCWSTR szTableName, MSICOLUMNINFO *colinfo, UINT *sz);
|
||||
static void msi_free_colinfo( MSICOLUMNINFO *colinfo, UINT count );
|
||||
|
||||
static inline UINT bytes_per_column( MSIDATABASE *db, const MSICOLUMNINFO *col )
|
||||
static inline UINT bytes_per_column( MSIDATABASE *db, const MSICOLUMNINFO *col, UINT bytes_per_strref )
|
||||
{
|
||||
if( MSITYPE_IS_BINARY(col->type) )
|
||||
return 2;
|
||||
|
||||
if( col->type & MSITYPE_STRING )
|
||||
return db->bytes_per_strref;
|
||||
return bytes_per_strref;
|
||||
|
||||
if( (col->type & 0xff) <= 2)
|
||||
return 2;
|
||||
|
@ -399,24 +398,33 @@ static void free_table( MSITABLE *table )
|
|||
msi_free( table );
|
||||
}
|
||||
|
||||
static UINT msi_table_get_row_size( MSIDATABASE *db,const MSICOLUMNINFO *cols,
|
||||
UINT count )
|
||||
static UINT msi_table_get_row_size( MSIDATABASE *db, const MSICOLUMNINFO *cols, UINT count, UINT bytes_per_strref )
|
||||
{
|
||||
const MSICOLUMNINFO *last_col = &cols[count-1];
|
||||
const MSICOLUMNINFO *last_col;
|
||||
|
||||
if (!count)
|
||||
return 0;
|
||||
return last_col->offset + bytes_per_column( db, last_col );
|
||||
|
||||
if (bytes_per_strref != LONG_STR_BYTES)
|
||||
{
|
||||
UINT i, size = 0;
|
||||
for (i = 0; i < count; i++) size += bytes_per_column( db, &cols[i], bytes_per_strref );
|
||||
return size;
|
||||
}
|
||||
last_col = &cols[count - 1];
|
||||
return last_col->offset + bytes_per_column( db, last_col, bytes_per_strref );
|
||||
}
|
||||
|
||||
/* add this table to the list of cached tables in the database */
|
||||
static UINT read_table_from_storage( MSIDATABASE *db, MSITABLE *t, IStorage *stg )
|
||||
{
|
||||
BYTE *rawdata = NULL;
|
||||
UINT rawsize = 0, i, j, row_size = 0;
|
||||
UINT rawsize = 0, i, j, row_size, row_size_mem;
|
||||
|
||||
TRACE("%s\n",debugstr_w(t->name));
|
||||
|
||||
row_size = msi_table_get_row_size( db, t->colinfo, t->col_count );
|
||||
row_size = msi_table_get_row_size( db, t->colinfo, t->col_count, db->bytes_per_strref );
|
||||
row_size_mem = msi_table_get_row_size( db, t->colinfo, t->col_count, LONG_STR_BYTES );
|
||||
|
||||
/* if we can't read the table, just assume that it's empty */
|
||||
read_stream_data( stg, t->name, TRUE, &rawdata, &rawsize );
|
||||
|
@ -441,17 +449,19 @@ static UINT read_table_from_storage( MSIDATABASE *db, MSITABLE *t, IStorage *stg
|
|||
|
||||
/* transpose all the data */
|
||||
TRACE("Transposing data from %d rows\n", t->row_count );
|
||||
for( i=0; i<t->row_count; i++ )
|
||||
for (i = 0; i < t->row_count; i++)
|
||||
{
|
||||
t->data[i] = msi_alloc( row_size );
|
||||
UINT ofs = 0, ofs_mem = 0;
|
||||
|
||||
t->data[i] = msi_alloc( row_size_mem );
|
||||
if( !t->data[i] )
|
||||
goto err;
|
||||
t->data_persistent[i] = TRUE;
|
||||
|
||||
for( j=0; j<t->col_count; j++ )
|
||||
for (j = 0; j < t->col_count; j++)
|
||||
{
|
||||
UINT ofs = t->colinfo[j].offset;
|
||||
UINT n = bytes_per_column( db, &t->colinfo[j] );
|
||||
UINT m = bytes_per_column( db, &t->colinfo[j], LONG_STR_BYTES );
|
||||
UINT n = bytes_per_column( db, &t->colinfo[j], db->bytes_per_strref );
|
||||
UINT k;
|
||||
|
||||
if ( n != 2 && n != 3 && n != 4 )
|
||||
|
@ -459,9 +469,23 @@ static UINT read_table_from_storage( MSIDATABASE *db, MSITABLE *t, IStorage *stg
|
|||
ERR("oops - unknown column width %d\n", n);
|
||||
goto err;
|
||||
}
|
||||
|
||||
for ( k = 0; k < n; k++ )
|
||||
t->data[i][ofs + k] = rawdata[ofs*t->row_count + i * n + k];
|
||||
if (t->colinfo[j].type & MSITYPE_STRING && n < m)
|
||||
{
|
||||
for (k = 0; k < m; k++)
|
||||
{
|
||||
if (k < n)
|
||||
t->data[i][ofs_mem + k] = rawdata[ofs * t->row_count + i * n + k];
|
||||
else
|
||||
t->data[i][ofs_mem + k] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (k = 0; k < n; k++)
|
||||
t->data[i][ofs_mem + k] = rawdata[ofs * t->row_count + i * n + k];
|
||||
}
|
||||
ofs_mem += m;
|
||||
ofs += n;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -729,10 +753,20 @@ static UINT get_table( MSIDATABASE *db, LPCWSTR name, MSITABLE **table_ret )
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT save_table( MSIDATABASE *db, const MSITABLE *t )
|
||||
static UINT read_table_int(BYTE *const *data, UINT row, UINT col, UINT bytes)
|
||||
{
|
||||
BYTE *rawdata = NULL, *p;
|
||||
UINT rawsize, r, i, j, row_size;
|
||||
UINT ret = 0, i;
|
||||
|
||||
for (i = 0; i < bytes; i++)
|
||||
ret += data[row][col + i] << i * 8;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static UINT save_table( MSIDATABASE *db, const MSITABLE *t, UINT bytes_per_strref )
|
||||
{
|
||||
BYTE *rawdata = NULL;
|
||||
UINT rawsize, r, i, j, row_size, row_count;
|
||||
|
||||
/* Nothing to do for non-persistent tables */
|
||||
if( t->persistent == MSICONDITION_FALSE )
|
||||
|
@ -740,9 +774,17 @@ static UINT save_table( MSIDATABASE *db, const MSITABLE *t )
|
|||
|
||||
TRACE("Saving %s\n", debugstr_w( t->name ) );
|
||||
|
||||
row_size = msi_table_get_row_size( db, t->colinfo, t->col_count );
|
||||
|
||||
rawsize = t->row_count * row_size;
|
||||
row_size = msi_table_get_row_size( db, t->colinfo, t->col_count, bytes_per_strref );
|
||||
row_count = t->row_count;
|
||||
for (i = 0; i < t->row_count; i++)
|
||||
{
|
||||
if (!t->data_persistent[i])
|
||||
{
|
||||
row_count = 1; /* yes, this is bizarre */
|
||||
break;
|
||||
}
|
||||
}
|
||||
rawsize = row_count * row_size;
|
||||
rawdata = msi_alloc_zero( rawsize );
|
||||
if( !rawdata )
|
||||
{
|
||||
|
@ -751,25 +793,41 @@ static UINT save_table( MSIDATABASE *db, const MSITABLE *t )
|
|||
}
|
||||
|
||||
rawsize = 0;
|
||||
p = rawdata;
|
||||
for( i=0; i<t->col_count; i++ )
|
||||
for (i = 0; i < t->row_count; i++)
|
||||
{
|
||||
for( j=0; j<t->row_count; j++ )
|
||||
UINT ofs = 0, ofs_mem = 0;
|
||||
|
||||
if (!t->data_persistent[i]) break;
|
||||
|
||||
for (j = 0; j < t->col_count; j++)
|
||||
{
|
||||
UINT offset = t->colinfo[i].offset;
|
||||
UINT m = bytes_per_column( db, &t->colinfo[j], LONG_STR_BYTES );
|
||||
UINT n = bytes_per_column( db, &t->colinfo[j], bytes_per_strref );
|
||||
UINT k;
|
||||
|
||||
if (!t->data_persistent[j]) continue;
|
||||
if (i == 0)
|
||||
rawsize += row_size;
|
||||
|
||||
*p++ = t->data[j][offset];
|
||||
*p++ = t->data[j][offset + 1];
|
||||
if( 4 == bytes_per_column( db, &t->colinfo[i] ) )
|
||||
if (n != 2 && n != 3 && n != 4)
|
||||
{
|
||||
*p++ = t->data[j][offset + 2];
|
||||
*p++ = t->data[j][offset + 3];
|
||||
ERR("oops - unknown column width %d\n", n);
|
||||
goto err;
|
||||
}
|
||||
if (t->colinfo[j].type & MSITYPE_STRING && n < m)
|
||||
{
|
||||
UINT id = read_table_int( t->data, i, ofs_mem, LONG_STR_BYTES );
|
||||
if (id > 1 << bytes_per_strref * 8)
|
||||
{
|
||||
ERR("string id %u out of range\n", id);
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
for (k = 0; k < n; k++)
|
||||
{
|
||||
rawdata[ofs * row_count + i * n + k] = t->data[i][ofs_mem + k];
|
||||
}
|
||||
ofs_mem += m;
|
||||
ofs += n;
|
||||
}
|
||||
rawsize += row_size;
|
||||
}
|
||||
|
||||
TRACE("writing %d bytes\n", rawsize);
|
||||
|
@ -777,12 +835,10 @@ static UINT save_table( MSIDATABASE *db, const MSITABLE *t )
|
|||
|
||||
err:
|
||||
msi_free( rawdata );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void table_calc_column_offsets( MSIDATABASE *db, MSICOLUMNINFO *colinfo,
|
||||
DWORD count )
|
||||
static void table_calc_column_offsets( MSIDATABASE *db, MSICOLUMNINFO *colinfo, DWORD count )
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
|
@ -791,7 +847,7 @@ static void table_calc_column_offsets( MSIDATABASE *db, MSICOLUMNINFO *colinfo,
|
|||
assert( (i+1) == colinfo[ i ].number );
|
||||
if (i)
|
||||
colinfo[i].offset = colinfo[ i - 1 ].offset
|
||||
+ bytes_per_column( db, &colinfo[ i - 1 ] );
|
||||
+ bytes_per_column( db, &colinfo[ i - 1 ], LONG_STR_BYTES );
|
||||
else
|
||||
colinfo[i].offset = 0;
|
||||
TRACE("column %d is [%s] with type %08x ofs %d\n",
|
||||
|
@ -855,16 +911,6 @@ static LPWSTR msi_makestring( const MSIDATABASE *db, UINT stringid)
|
|||
return strdupW(msi_string_lookup_id( db->strings, stringid ));
|
||||
}
|
||||
|
||||
static UINT read_table_int(BYTE *const *data, UINT row, UINT col, UINT bytes)
|
||||
{
|
||||
UINT ret = 0, i;
|
||||
|
||||
for (i = 0; i < bytes; i++)
|
||||
ret += (data[row][col + i] << i * 8);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static UINT get_tablecolumns( MSIDATABASE *db,
|
||||
LPCWSTR szTableName, MSICOLUMNINFO *colinfo, UINT *sz)
|
||||
{
|
||||
|
@ -902,11 +948,11 @@ static UINT get_tablecolumns( MSIDATABASE *db,
|
|||
count = table->row_count;
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
if( read_table_int(table->data, i, 0, db->bytes_per_strref) != table_id )
|
||||
if( read_table_int(table->data, i, 0, LONG_STR_BYTES) != table_id )
|
||||
continue;
|
||||
if( colinfo )
|
||||
{
|
||||
UINT id = read_table_int(table->data, i, table->colinfo[2].offset, db->bytes_per_strref);
|
||||
UINT id = read_table_int(table->data, i, table->colinfo[2].offset, LONG_STR_BYTES);
|
||||
UINT col = read_table_int(table->data, i, table->colinfo[1].offset, sizeof(USHORT)) - (1<<15);
|
||||
|
||||
/* check the column number is in range */
|
||||
|
@ -971,7 +1017,7 @@ static void msi_update_table_columns( MSIDATABASE *db, LPCWSTR name )
|
|||
if (!table->col_count)
|
||||
goto done;
|
||||
|
||||
size = msi_table_get_row_size( db, table->colinfo, table->col_count );
|
||||
size = msi_table_get_row_size( db, table->colinfo, table->col_count, LONG_STR_BYTES );
|
||||
offset = table->colinfo[table->col_count - 1].offset;
|
||||
|
||||
for ( n = 0; n < table->row_count; n++ )
|
||||
|
@ -988,8 +1034,8 @@ done:
|
|||
/* try to find the table name in the _Tables table */
|
||||
BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name )
|
||||
{
|
||||
UINT r, table_id = 0, i, count;
|
||||
MSITABLE *table = NULL;
|
||||
UINT r, table_id, i;
|
||||
MSITABLE *table;
|
||||
|
||||
static const WCHAR szStreams[] = {'_','S','t','r','e','a','m','s',0};
|
||||
static const WCHAR szStorages[] = {'_','S','t','o','r','a','g','e','s',0};
|
||||
|
@ -1012,10 +1058,11 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name )
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
count = table->row_count;
|
||||
for( i=0; i<count; i++ )
|
||||
if( table->data[ i ][ 0 ] == table_id )
|
||||
for( i = 0; i < table->row_count; i++ )
|
||||
{
|
||||
if( read_table_int( table->data, i, 0, LONG_STR_BYTES ) == table_id )
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1059,7 +1106,7 @@ static UINT TABLE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *
|
|||
if (tv->order)
|
||||
row = tv->order->reorder[row];
|
||||
|
||||
n = bytes_per_column( tv->db, &tv->columns[col-1] );
|
||||
n = bytes_per_column( tv->db, &tv->columns[col - 1], LONG_STR_BYTES );
|
||||
if (n != 2 && n != 3 && n != 4)
|
||||
{
|
||||
ERR("oops! what is %d bytes per column?\n", n );
|
||||
|
@ -1116,7 +1163,7 @@ static UINT msi_stream_name( const MSITABLEVIEW *tv, UINT row, LPWSTR *pstname )
|
|||
{
|
||||
static const WCHAR fmt[] = { '%','d',0 };
|
||||
WCHAR number[0x20];
|
||||
UINT n = bytes_per_column( tv->db, &tv->columns[i] );
|
||||
UINT n = bytes_per_column( tv->db, &tv->columns[i], LONG_STR_BYTES );
|
||||
|
||||
switch( n )
|
||||
{
|
||||
|
@ -1213,7 +1260,7 @@ static UINT TABLE_set_int( MSITABLEVIEW *tv, UINT row, UINT col, UINT val )
|
|||
msi_free( tv->columns[col-1].hash_table );
|
||||
tv->columns[col-1].hash_table = NULL;
|
||||
|
||||
n = bytes_per_column( tv->db, &tv->columns[col-1] );
|
||||
n = bytes_per_column( tv->db, &tv->columns[col - 1], LONG_STR_BYTES );
|
||||
if ( n != 2 && n != 3 && n != 4 )
|
||||
{
|
||||
ERR("oops! what is %d bytes per column?\n", n );
|
||||
|
@ -1304,7 +1351,7 @@ static UINT get_table_value_from_record( MSITABLEVIEW *tv, MSIRECORD *rec, UINT
|
|||
if (r != ERROR_SUCCESS)
|
||||
return ERROR_NOT_FOUND;
|
||||
}
|
||||
else if ( 2 == bytes_per_column( tv->db, &columninfo ) )
|
||||
else if ( bytes_per_column( tv->db, &columninfo, LONG_STR_BYTES ) == 2 )
|
||||
{
|
||||
*pvalue = 0x8000 + MSI_RecordGetInteger( rec, iField );
|
||||
if ( *pvalue & 0xffff0000 )
|
||||
|
@ -1577,39 +1624,60 @@ static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec )
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT find_insert_index( MSITABLEVIEW *tv, MSIRECORD *rec, UINT *pidx )
|
||||
static int compare_record( MSITABLEVIEW *tv, UINT row, MSIRECORD *rec )
|
||||
{
|
||||
UINT r, idx, j, ivalue, x;
|
||||
UINT r, i, ivalue, x;
|
||||
|
||||
TRACE("%p %p %p\n", tv, rec, pidx);
|
||||
|
||||
for (idx = 0; idx < tv->table->row_count; idx++)
|
||||
for (i = 0; i < tv->num_cols; i++ )
|
||||
{
|
||||
for (j = 0; j < tv->num_cols; j++ )
|
||||
r = get_table_value_from_record( tv, rec, i + 1, &ivalue );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return 1;
|
||||
|
||||
r = TABLE_fetch_int( &tv->view, row, i + 1, &x );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
r = get_table_value_from_record (tv, rec, j+1, &ivalue);
|
||||
if (r != ERROR_SUCCESS)
|
||||
break;
|
||||
WARN("TABLE_fetch_int should not fail here %u\n", r);
|
||||
return -1;
|
||||
}
|
||||
if (ivalue > x)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (ivalue == x)
|
||||
{
|
||||
if (i < tv->num_cols - 1) continue;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = TABLE_fetch_int(&tv->view, idx, j + 1, &x);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
static int find_insert_index( MSITABLEVIEW *tv, MSIRECORD *rec )
|
||||
{
|
||||
int idx, c, low = 0, high = tv->table->row_count - 1;
|
||||
|
||||
if (ivalue > x)
|
||||
break;
|
||||
else if (ivalue == x)
|
||||
continue;
|
||||
else {
|
||||
TRACE("Found %d.\n", idx);
|
||||
*pidx = idx;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
TRACE("%p %p\n", tv, rec);
|
||||
|
||||
while (low <= high)
|
||||
{
|
||||
idx = (low + high) / 2;
|
||||
c = compare_record( tv, idx, rec );
|
||||
|
||||
if (c < 0)
|
||||
high = idx - 1;
|
||||
else if (c > 0)
|
||||
low = idx + 1;
|
||||
else
|
||||
{
|
||||
TRACE("found %u\n", idx);
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("Found %d.\n", idx);
|
||||
*pidx = idx;
|
||||
return ERROR_SUCCESS;
|
||||
TRACE("found %u\n", high + 1);
|
||||
return high + 1;
|
||||
}
|
||||
|
||||
static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary )
|
||||
|
@ -1625,11 +1693,7 @@ static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec, UINT row,
|
|||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
if (row == -1)
|
||||
{
|
||||
r = find_insert_index(tv, rec, &row);
|
||||
if( r != ERROR_SUCCESS )
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
row = find_insert_index( tv, rec );
|
||||
|
||||
r = table_create_new_row( view, &row, temporary );
|
||||
TRACE("insert_row returned %08x\n", r);
|
||||
|
@ -2306,7 +2370,7 @@ UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view )
|
|||
tv->db = db;
|
||||
tv->columns = tv->table->colinfo;
|
||||
tv->num_cols = tv->table->col_count;
|
||||
tv->row_size = msi_table_get_row_size( db, tv->table->colinfo, tv->table->col_count );
|
||||
tv->row_size = msi_table_get_row_size( db, tv->table->colinfo, tv->table->col_count, LONG_STR_BYTES );
|
||||
|
||||
TRACE("%s one row is %d bytes\n", debugstr_w(name), tv->row_size );
|
||||
|
||||
|
@ -2318,12 +2382,13 @@ UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view )
|
|||
|
||||
UINT MSI_CommitTables( MSIDATABASE *db )
|
||||
{
|
||||
UINT r;
|
||||
UINT r, bytes_per_strref;
|
||||
HRESULT hr;
|
||||
MSITABLE *table = NULL;
|
||||
|
||||
TRACE("%p\n",db);
|
||||
|
||||
r = msi_save_string_table( db->strings, db->storage );
|
||||
r = msi_save_string_table( db->strings, db->storage, &bytes_per_strref );
|
||||
if( r != ERROR_SUCCESS )
|
||||
{
|
||||
WARN("failed to save string table r=%08x\n",r);
|
||||
|
@ -2332,7 +2397,7 @@ UINT MSI_CommitTables( MSIDATABASE *db )
|
|||
|
||||
LIST_FOR_EACH_ENTRY( table, &db->tables, MSITABLE, entry )
|
||||
{
|
||||
r = save_table( db, table );
|
||||
r = save_table( db, table, bytes_per_strref );
|
||||
if( r != ERROR_SUCCESS )
|
||||
{
|
||||
WARN("failed to save table %s (r=%08x)\n",
|
||||
|
@ -2344,7 +2409,13 @@ UINT MSI_CommitTables( MSIDATABASE *db )
|
|||
/* force everything to reload next time */
|
||||
free_cached_tables( db );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
hr = IStorage_Commit( db->storage, 0 );
|
||||
if (FAILED( hr ))
|
||||
{
|
||||
WARN("failed to commit changes 0x%08x\n", hr);
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR table )
|
||||
|
@ -2463,7 +2534,7 @@ static MSIRECORD *msi_get_transform_record( const MSITABLEVIEW *tv, const string
|
|||
IStream *stm = NULL;
|
||||
UINT r;
|
||||
|
||||
ofs += bytes_per_column( tv->db, &columns[i] );
|
||||
ofs += bytes_per_column( tv->db, &columns[i], bytes_per_strref );
|
||||
|
||||
r = msi_record_encoded_stream_name( tv, rec, &encname );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
|
@ -2490,7 +2561,7 @@ static MSIRECORD *msi_get_transform_record( const MSITABLEVIEW *tv, const string
|
|||
}
|
||||
else
|
||||
{
|
||||
UINT n = bytes_per_column( tv->db, &columns[i] );
|
||||
UINT n = bytes_per_column( tv->db, &columns[i], bytes_per_strref );
|
||||
switch( n )
|
||||
{
|
||||
case 2:
|
||||
|
@ -2704,7 +2775,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
|
|||
! MSITYPE_IS_BINARY(tv->columns[i].type) )
|
||||
sz += bytes_per_strref;
|
||||
else
|
||||
sz += bytes_per_column( tv->db, &tv->columns[i] );
|
||||
sz += bytes_per_column( tv->db, &tv->columns[i], bytes_per_strref );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2726,7 +2797,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
|
|||
! MSITYPE_IS_BINARY(tv->columns[i].type) )
|
||||
sz += bytes_per_strref;
|
||||
else
|
||||
sz += bytes_per_column( tv->db, &tv->columns[i] );
|
||||
sz += bytes_per_column( tv->db, &tv->columns[i], bytes_per_strref );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
|
||||
#define WINE_FILEDESCRIPTION_STR "Wine MSI dll"
|
||||
#define WINE_FILENAME_STR "msi.dll"
|
||||
#define WINE_FILEVERSION 3,1,4000,2435
|
||||
#define WINE_FILEVERSION_STR "3.1.4000.2435"
|
||||
#define WINE_PRODUCTVERSION 3,1,4000,2435
|
||||
#define WINE_PRODUCTVERSION_STR "3.1.4000.2435"
|
||||
#define WINE_FILEVERSION 4,5,6001,22159
|
||||
#define WINE_FILEVERSION_STR "4.5.6001.22159"
|
||||
#define WINE_PRODUCTVERSION 4,5,6001,22159
|
||||
#define WINE_PRODUCTVERSION_STR "4.5.6001.22159"
|
||||
|
||||
#include "wine/wine_common_ver.rc"
|
||||
|
|
|
@ -19,14 +19,14 @@
|
|||
#ifndef __WINE_MSI_H
|
||||
#define __WINE_MSI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _MSI_NO_CRYPTO
|
||||
#include <wincrypt.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef ULONG MSIHANDLE;
|
||||
|
||||
typedef enum tagINSTALLSTATE
|
||||
|
@ -663,6 +663,12 @@ UINT WINAPI MsiApplyMultiplePatchesA(LPCSTR, LPCSTR, LPCSTR);
|
|||
UINT WINAPI MsiApplyMultiplePatchesW(LPCWSTR, LPCWSTR, LPCWSTR);
|
||||
#define MsiApplyMultiplePatches WINELIB_NAME_AW(MsiApplyMultiplePatches)
|
||||
|
||||
UINT WINAPI MsiBeginTransactionA(LPCSTR, DWORD, MSIHANDLE *, HANDLE *);
|
||||
UINT WINAPI MsiBeginTransactionW(LPCWSTR, DWORD, MSIHANDLE *, HANDLE *);
|
||||
#define MsiBeginTransaction WINELIB_NAME_AW(MsiBeginTransaction)
|
||||
|
||||
UINT WINAPI MsiEndTransaction(DWORD);
|
||||
|
||||
/* Non Unicode */
|
||||
UINT WINAPI MsiCloseHandle(MSIHANDLE);
|
||||
UINT WINAPI MsiCloseAllHandles(void);
|
||||
|
|
Loading…
Reference in a new issue