mirror of
https://github.com/reactos/reactos.git
synced 2024-06-30 09:50:07 +00:00
[MSI] Sync with Wine Staging 1.7.55. CORE-10536
svn path=/trunk/; revision=69995
This commit is contained in:
parent
02ab2bf42c
commit
9c595b7465
|
@ -65,7 +65,7 @@ set_module_type(msi win32dll)
|
|||
target_link_libraries(msi uuid ${PSEH_LIB} wine)
|
||||
add_dependencies(msi msi_idlheader)
|
||||
add_delay_importlibs(msi odbccp32 crypt32 wintrust)
|
||||
add_importlibs(msi advapi32 cabinet comctl32 gdi32 ole32 oleaut32 shell32 shlwapi urlmon user32 version wininet mspatcha
|
||||
add_importlibs(msi advapi32 advapi32_vista cabinet comctl32 gdi32 ole32 oleaut32 shell32 shlwapi urlmon user32 version wininet mspatcha
|
||||
#FIXME : should be in delayed imports
|
||||
imagehlp
|
||||
msvcrt
|
||||
|
|
|
@ -239,8 +239,7 @@ static int parse_prop( const WCHAR *str, WCHAR *value, int *quotes )
|
|||
len++;
|
||||
break;
|
||||
default:
|
||||
if (!count) in_quotes = FALSE;
|
||||
else in_quotes = TRUE;
|
||||
if (count) in_quotes = TRUE;
|
||||
len++;
|
||||
break;
|
||||
}
|
||||
|
@ -261,8 +260,7 @@ static int parse_prop( const WCHAR *str, WCHAR *value, int *quotes )
|
|||
break;
|
||||
default:
|
||||
state = state_token;
|
||||
if (!count) in_quotes = FALSE;
|
||||
else in_quotes = TRUE;
|
||||
if (count) in_quotes = TRUE;
|
||||
len++;
|
||||
break;
|
||||
}
|
||||
|
@ -271,6 +269,7 @@ static int parse_prop( const WCHAR *str, WCHAR *value, int *quotes )
|
|||
default: break;
|
||||
}
|
||||
if (!ignore) *out++ = *p;
|
||||
if (!count) in_quotes = FALSE;
|
||||
}
|
||||
|
||||
done:
|
||||
|
@ -2362,6 +2361,18 @@ void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL loa
|
|||
TRACE("%s resolves to %s\n", debugstr_w(name), debugstr_w(folder->ResolvedTarget));
|
||||
}
|
||||
|
||||
static ULONGLONG get_volume_space_required( MSIPACKAGE *package )
|
||||
{
|
||||
MSICOMPONENT *comp;
|
||||
ULONGLONG ret = 0;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
|
||||
{
|
||||
if (comp->Action == INSTALLSTATE_LOCAL) ret += comp->Cost;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static UINT ACTION_CostFinalize(MSIPACKAGE *package)
|
||||
{
|
||||
static const WCHAR query[] =
|
||||
|
@ -2376,6 +2387,12 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
|
|||
static const WCHAR szPrimaryVolumeSpaceAvailable[] =
|
||||
{'P','r','i','m','a','r','y','V','o','l','u','m','e','S','p','a','c','e',
|
||||
'A','v','a','i','l','a','b','l','e',0};
|
||||
static const WCHAR szPrimaryVolumeSpaceRequired[] =
|
||||
{'P','r','i','m','a','r','y','V','o','l','u','m','e','S','p','a','c','e',
|
||||
'R','e','q','u','i','r','e','d',0};
|
||||
static const WCHAR szPrimaryVolumeSpaceRemaining[] =
|
||||
{'P','r','i','m','a','r','y','V','o','l','u','m','e','S','p','a','c','e',
|
||||
'R','e','m','a','i','n','i','n','g',0};
|
||||
static const WCHAR szOutOfNoRbDiskSpace[] =
|
||||
{'O','u','t','O','f','N','o','R','b','D','i','s','k','S','p','a','c','e',0};
|
||||
MSICOMPONENT *comp;
|
||||
|
@ -2426,6 +2443,8 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
|
|||
if (!level) msi_set_property( package->db, szInstallLevel, szOne, -1 );
|
||||
msi_free(level);
|
||||
|
||||
if ((rc = MSI_SetFeatureStates( package ))) return rc;
|
||||
|
||||
if ((primary_key = msi_dup_property( package->db, szPrimaryFolder )))
|
||||
{
|
||||
if ((primary_folder = msi_dup_property( package->db, primary_key )))
|
||||
|
@ -2433,17 +2452,23 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
|
|||
if (((primary_folder[0] >= 'A' && primary_folder[0] <= 'Z') ||
|
||||
(primary_folder[0] >= 'a' && primary_folder[0] <= 'z')) && primary_folder[1] == ':')
|
||||
{
|
||||
static const WCHAR fmtW[] = {'%','l','u',0};
|
||||
ULARGE_INTEGER free;
|
||||
ULONGLONG required;
|
||||
WCHAR buf[21];
|
||||
|
||||
primary_folder[2] = 0;
|
||||
if (GetDiskFreeSpaceExW( primary_folder, &free, NULL, NULL ))
|
||||
{
|
||||
static const WCHAR fmtW[] = {'%','l','u',0};
|
||||
WCHAR buf[21];
|
||||
|
||||
sprintfW( buf, fmtW, free.QuadPart / 512 );
|
||||
msi_set_property( package->db, szPrimaryVolumeSpaceAvailable, buf, -1 );
|
||||
}
|
||||
required = get_volume_space_required( package );
|
||||
sprintfW( buf, fmtW, required / 512 );
|
||||
msi_set_property( package->db, szPrimaryVolumeSpaceRequired, buf, -1 );
|
||||
|
||||
sprintfW( buf, fmtW, (free.QuadPart - required) / 512 );
|
||||
msi_set_property( package->db, szPrimaryVolumeSpaceRemaining, buf, -1 );
|
||||
msi_set_property( package->db, szPrimaryVolumePath, primary_folder, 2 );
|
||||
}
|
||||
msi_free( primary_folder );
|
||||
|
@ -2455,7 +2480,7 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
|
|||
msi_set_property( package->db, szOutOfDiskSpace, szZero, -1 );
|
||||
msi_set_property( package->db, szOutOfNoRbDiskSpace, szZero, -1 );
|
||||
|
||||
return MSI_SetFeatureStates(package);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static BYTE *parse_value( MSIPACKAGE *package, const WCHAR *value, DWORD len, DWORD *type, DWORD *size )
|
||||
|
@ -2617,9 +2642,8 @@ static inline REGSAM get_registry_view( const MSICOMPONENT *comp )
|
|||
return view;
|
||||
}
|
||||
|
||||
static HKEY open_key( const MSICOMPONENT *comp, HKEY root, const WCHAR *path, BOOL create )
|
||||
static HKEY open_key( const MSICOMPONENT *comp, HKEY root, const WCHAR *path, BOOL create, REGSAM access )
|
||||
{
|
||||
REGSAM access = KEY_ALL_ACCESS;
|
||||
WCHAR *subkey, *p, *q;
|
||||
HKEY hkey, ret = NULL;
|
||||
LONG res;
|
||||
|
@ -2641,7 +2665,7 @@ static HKEY open_key( const MSICOMPONENT *comp, HKEY root, const WCHAR *path, BO
|
|||
}
|
||||
if (q && q[1])
|
||||
{
|
||||
ret = open_key( comp, hkey, q + 1, create );
|
||||
ret = open_key( comp, hkey, q + 1, create, access );
|
||||
RegCloseKey( hkey );
|
||||
}
|
||||
else ret = hkey;
|
||||
|
@ -2866,7 +2890,7 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
|
|||
strcpyW(uikey,szRoot);
|
||||
strcatW(uikey,deformated);
|
||||
|
||||
if (!(hkey = open_key( comp, root_key, deformated, TRUE )))
|
||||
if (!(hkey = open_key( comp, root_key, deformated, TRUE, KEY_QUERY_VALUE | KEY_SET_VALUE )))
|
||||
{
|
||||
ERR("Could not create key %s\n", debugstr_w(deformated));
|
||||
msi_free(uikey);
|
||||
|
@ -2957,13 +2981,17 @@ static void delete_key( const MSICOMPONENT *comp, HKEY root, const WCHAR *path )
|
|||
access |= get_registry_view( comp );
|
||||
|
||||
if (!(subkey = strdupW( path ))) return;
|
||||
for (;;)
|
||||
do
|
||||
{
|
||||
if ((p = strrchrW( subkey, '\\' ))) *p = 0;
|
||||
hkey = open_key( comp, root, subkey, FALSE );
|
||||
if ((p = strrchrW( subkey, '\\' )))
|
||||
{
|
||||
*p = 0;
|
||||
if (!p[1]) continue; /* trailing backslash */
|
||||
hkey = open_key( comp, root, subkey, FALSE, access );
|
||||
if (!hkey) break;
|
||||
if (p && p[1])
|
||||
res = RegDeleteKeyExW( hkey, p + 1, access, 0 );
|
||||
RegCloseKey( hkey );
|
||||
}
|
||||
else
|
||||
res = RegDeleteKeyExW( root, subkey, access, 0 );
|
||||
if (res)
|
||||
|
@ -2971,9 +2999,7 @@ static void delete_key( const MSICOMPONENT *comp, HKEY root, const WCHAR *path )
|
|||
TRACE("failed to delete key %s (%d)\n", debugstr_w(subkey), res);
|
||||
break;
|
||||
}
|
||||
if (p && p[1]) RegCloseKey( hkey );
|
||||
else break;
|
||||
}
|
||||
} while (p);
|
||||
msi_free( subkey );
|
||||
}
|
||||
|
||||
|
@ -2983,7 +3009,7 @@ static void delete_value( const MSICOMPONENT *comp, HKEY root, const WCHAR *path
|
|||
HKEY hkey;
|
||||
DWORD num_subkeys, num_values;
|
||||
|
||||
if ((hkey = open_key( comp, root, path, FALSE )))
|
||||
if ((hkey = open_key( comp, root, path, FALSE, KEY_SET_VALUE | KEY_QUERY_VALUE )))
|
||||
{
|
||||
if ((res = RegDeleteValueW( hkey, value )))
|
||||
TRACE("failed to delete value %s (%d)\n", debugstr_w(value), res);
|
||||
|
@ -3004,8 +3030,8 @@ static void delete_tree( const MSICOMPONENT *comp, HKEY root, const WCHAR *path
|
|||
LONG res;
|
||||
HKEY hkey;
|
||||
|
||||
if (!(hkey = open_key( comp, root, path, FALSE ))) return;
|
||||
res = SHDeleteKeyW( hkey, NULL );
|
||||
if (!(hkey = open_key( comp, root, path, FALSE, KEY_ALL_ACCESS ))) return;
|
||||
res = RegDeleteTreeW( hkey, NULL );
|
||||
if (res) TRACE("failed to delete subtree of %s (%d)\n", debugstr_w(path), res);
|
||||
delete_key( comp, root, path );
|
||||
RegCloseKey( hkey );
|
||||
|
@ -3537,7 +3563,9 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
|
|||
if (!comp->KeyPath || !(file = msi_get_loaded_file(package, comp->KeyPath)))
|
||||
continue;
|
||||
|
||||
row = MSI_QueryGetRecord(package->db, query, file->Sequence);
|
||||
if (!(row = MSI_QueryGetRecord(package->db, query, file->Sequence)))
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
sprintfW(source, fmt, MSI_RecordGetInteger(row, 1));
|
||||
ptr2 = strrchrW(source, '\\') + 1;
|
||||
msiobj_release(&row->hdr);
|
||||
|
@ -5857,8 +5885,8 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
|
|||
|
||||
if (image_path != file->TargetPath) msi_free(image_path);
|
||||
done:
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(hscm);
|
||||
if (service) CloseServiceHandle(service);
|
||||
if (hscm) CloseServiceHandle(hscm);
|
||||
msi_free(name);
|
||||
msi_free(disp);
|
||||
msi_free(sd.lpDescription);
|
||||
|
@ -6032,8 +6060,8 @@ done:
|
|||
msi_ui_actiondata( package, szStartServices, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(scm);
|
||||
if (service) CloseServiceHandle(service);
|
||||
if (scm) CloseServiceHandle(scm);
|
||||
|
||||
msi_free(name);
|
||||
msi_free(args);
|
||||
|
@ -6142,8 +6170,8 @@ static UINT stop_service( LPCWSTR name )
|
|||
WARN("Failed to stop service (%s): %d\n", debugstr_w(name), GetLastError());
|
||||
|
||||
done:
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(scm);
|
||||
if (service) CloseServiceHandle(service);
|
||||
if (scm) CloseServiceHandle(scm);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -6280,8 +6308,8 @@ done:
|
|||
msi_ui_actiondata( package, szDeleteServices, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
|
||||
CloseServiceHandle( service );
|
||||
CloseServiceHandle( scm );
|
||||
if (service) CloseServiceHandle( service );
|
||||
if (scm) CloseServiceHandle( scm );
|
||||
msi_free( name );
|
||||
msi_free( display_name );
|
||||
|
||||
|
@ -6903,13 +6931,13 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
|
|||
{
|
||||
MSIPACKAGE *package = param;
|
||||
LPCWSTR name, value, component;
|
||||
LPWSTR data = NULL, newval = NULL, deformatted = NULL, ptr;
|
||||
DWORD flags, type, size;
|
||||
WCHAR *data = NULL, *newval = NULL, *deformatted = NULL, *p, *q;
|
||||
DWORD flags, type, size, len, len_value = 0;
|
||||
UINT res;
|
||||
HKEY env = NULL;
|
||||
MSICOMPONENT *comp;
|
||||
MSIRECORD *uirow;
|
||||
int action = 0;
|
||||
int action = 0, found = 0;
|
||||
|
||||
component = MSI_RecordGetString(rec, 4);
|
||||
comp = msi_get_loaded_component(package, component);
|
||||
|
@ -6937,7 +6965,20 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
|
|||
goto done;
|
||||
}
|
||||
|
||||
value = deformatted;
|
||||
if ((value = deformatted))
|
||||
{
|
||||
if (flags & ENV_MOD_PREFIX)
|
||||
{
|
||||
p = strrchrW( value, ';' );
|
||||
len_value = p - value;
|
||||
}
|
||||
else if (flags & ENV_MOD_APPEND)
|
||||
{
|
||||
value = strchrW( value, ';' ) + 1;
|
||||
len_value = strlenW( value );
|
||||
}
|
||||
else len_value = strlenW( value );
|
||||
}
|
||||
|
||||
res = open_env_key( flags, &env );
|
||||
if (res != ERROR_SUCCESS)
|
||||
|
@ -6963,10 +7004,6 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
|
|||
res = ERROR_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* If we are appending but the string was empty, strip ; */
|
||||
if ((flags & ENV_MOD_APPEND) && (value[0] == szSemiColon[0])) value++;
|
||||
|
||||
size = (lstrlenW(value) + 1) * sizeof(WCHAR);
|
||||
newval = strdupW(value);
|
||||
if (!newval)
|
||||
|
@ -6986,15 +7023,14 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
|
|||
goto done;
|
||||
}
|
||||
|
||||
data = msi_alloc(size);
|
||||
if (!data)
|
||||
if (!(p = q = data = msi_alloc( size )))
|
||||
{
|
||||
msi_free(deformatted);
|
||||
RegCloseKey(env);
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
res = RegQueryValueExW(env, name, NULL, &type, (LPVOID)data, &size);
|
||||
res = RegQueryValueExW( env, name, NULL, &type, (BYTE *)data, &size );
|
||||
if (res != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
|
@ -7007,20 +7043,28 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
|
|||
goto done;
|
||||
}
|
||||
|
||||
size = (lstrlenW(data) + 1) * sizeof(WCHAR);
|
||||
if (flags & ENV_MOD_MASK)
|
||||
for (;;)
|
||||
{
|
||||
DWORD mod_size;
|
||||
int multiplier = 0;
|
||||
if (flags & ENV_MOD_APPEND) multiplier++;
|
||||
if (flags & ENV_MOD_PREFIX) multiplier++;
|
||||
mod_size = lstrlenW(value) * multiplier;
|
||||
size += mod_size * sizeof(WCHAR);
|
||||
while (*q && *q != ';') q++;
|
||||
len = q - p;
|
||||
if (value && len == len_value && !memcmp( value, p, len * sizeof(WCHAR) ) &&
|
||||
(!p[len] || p[len] == ';'))
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
if (!*q) break;
|
||||
p = ++q;
|
||||
}
|
||||
|
||||
newval = msi_alloc(size);
|
||||
ptr = newval;
|
||||
if (!newval)
|
||||
if (found)
|
||||
{
|
||||
TRACE("string already set\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
size = (len_value + 1 + strlenW( data ) + 1) * sizeof(WCHAR);
|
||||
if (!(p = newval = msi_alloc( size )))
|
||||
{
|
||||
res = ERROR_OUTOFMEMORY;
|
||||
goto done;
|
||||
|
@ -7028,21 +7072,24 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
|
|||
|
||||
if (flags & ENV_MOD_PREFIX)
|
||||
{
|
||||
lstrcpyW(newval, value);
|
||||
ptr = newval + lstrlenW(value);
|
||||
memcpy( newval, value, len_value * sizeof(WCHAR) );
|
||||
newval[len_value] = ';';
|
||||
p = newval + len_value + 1;
|
||||
action |= 0x80000000;
|
||||
}
|
||||
|
||||
lstrcpyW(ptr, data);
|
||||
strcpyW( p, data );
|
||||
|
||||
if (flags & ENV_MOD_APPEND)
|
||||
{
|
||||
lstrcatW(newval, value);
|
||||
p += strlenW( data );
|
||||
*p++ = ';';
|
||||
memcpy( p, value, (len_value + 1) * sizeof(WCHAR) );
|
||||
action |= 0x40000000;
|
||||
}
|
||||
}
|
||||
TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval));
|
||||
res = RegSetValueExW(env, name, 0, type, (LPVOID)newval, size);
|
||||
res = RegSetValueExW( env, name, 0, type, (BYTE *)newval, size );
|
||||
if (res)
|
||||
{
|
||||
WARN("Failed to set %s to %s (%d)\n", debugstr_w(name), debugstr_w(newval), res);
|
||||
|
@ -7084,8 +7131,8 @@ static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param )
|
|||
{
|
||||
MSIPACKAGE *package = param;
|
||||
LPCWSTR name, value, component;
|
||||
LPWSTR deformatted = NULL;
|
||||
DWORD flags;
|
||||
WCHAR *p, *q, *deformatted = NULL, *new_value = NULL;
|
||||
DWORD flags, type, size, len, len_value = 0, len_new_value;
|
||||
HKEY env;
|
||||
MSICOMPONENT *comp;
|
||||
MSIRECORD *uirow;
|
||||
|
@ -7122,7 +7169,20 @@ static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param )
|
|||
if (value && !deformat_string( package, value, &deformatted ))
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
value = deformatted;
|
||||
if ((value = deformatted))
|
||||
{
|
||||
if (flags & ENV_MOD_PREFIX)
|
||||
{
|
||||
p = strchrW( value, ';' );
|
||||
len_value = p - value;
|
||||
}
|
||||
else if (flags & ENV_MOD_APPEND)
|
||||
{
|
||||
value = strchrW( value, ';' ) + 1;
|
||||
len_value = strlenW( value );
|
||||
}
|
||||
else len_value = strlenW( value );
|
||||
}
|
||||
|
||||
r = open_env_key( flags, &env );
|
||||
if (r != ERROR_SUCCESS)
|
||||
|
@ -7134,13 +7194,48 @@ static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param )
|
|||
if (flags & ENV_MOD_MACHINE)
|
||||
action |= 0x20000000;
|
||||
|
||||
TRACE("Removing %s\n", debugstr_w(name));
|
||||
size = 0;
|
||||
type = REG_SZ;
|
||||
res = RegQueryValueExW( env, name, NULL, &type, NULL, &size );
|
||||
if (res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ))
|
||||
goto done;
|
||||
|
||||
if (!(new_value = msi_alloc( size ))) goto done;
|
||||
|
||||
res = RegQueryValueExW( env, name, NULL, &type, (BYTE *)new_value, &size );
|
||||
if (res != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
len_new_value = size / sizeof(WCHAR) - 1;
|
||||
p = q = new_value;
|
||||
for (;;)
|
||||
{
|
||||
while (*q && *q != ';') q++;
|
||||
len = q - p;
|
||||
if (value && len == len_value && !memcmp( value, p, len * sizeof(WCHAR) ))
|
||||
{
|
||||
if (*q == ';') q++;
|
||||
memmove( p, q, (len_new_value - (q - new_value) + 1) * sizeof(WCHAR) );
|
||||
break;
|
||||
}
|
||||
if (!*q) break;
|
||||
p = ++q;
|
||||
}
|
||||
|
||||
if (!new_value[0] || !value)
|
||||
{
|
||||
TRACE("removing %s\n", debugstr_w(name));
|
||||
res = RegDeleteValueW( env, name );
|
||||
if (res != ERROR_SUCCESS)
|
||||
WARN("failed to delete value %s (%d)\n", debugstr_w(name), res);
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("Failed to delete value %s (%d)\n", debugstr_w(name), res);
|
||||
r = ERROR_SUCCESS;
|
||||
TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(new_value));
|
||||
size = (strlenW( new_value ) + 1) * sizeof(WCHAR);
|
||||
res = RegSetValueExW( env, name, 0, type, (BYTE *)new_value, size );
|
||||
if (res != ERROR_SUCCESS)
|
||||
WARN("failed to set %s to %s (%d)\n", debugstr_w(name), debugstr_w(new_value), res);
|
||||
}
|
||||
|
||||
done:
|
||||
|
@ -7153,6 +7248,7 @@ done:
|
|||
|
||||
if (env) RegCloseKey( env );
|
||||
msi_free( deformatted );
|
||||
msi_free( new_value );
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -1421,7 +1421,7 @@ static HRESULT session_invoke(
|
|||
hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
|
||||
if (FAILED(hr)) return hr;
|
||||
V_VT(pVarResult) = VT_BOOL;
|
||||
V_BOOL(pVarResult) = MsiGetMode(This->msiHandle, V_I4(&varg0));
|
||||
V_BOOL(pVarResult) = MsiGetMode(This->msiHandle, V_I4(&varg0)) ? VARIANT_TRUE : VARIANT_FALSE;
|
||||
} else if (wFlags & DISPATCH_PROPERTYPUT) {
|
||||
hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
@ -1816,12 +1816,36 @@ static HRESULT InstallerImpl_SummaryInformation(WORD wFlags,
|
|||
EXCEPINFO* pExcepInfo,
|
||||
UINT* puArgErr)
|
||||
{
|
||||
if (!(wFlags & DISPATCH_METHOD))
|
||||
UINT ret;
|
||||
HRESULT hr;
|
||||
MSIHANDLE hsuminfo;
|
||||
IDispatch *dispatch;
|
||||
VARIANTARG varg0, varg1;
|
||||
|
||||
if (!(wFlags & DISPATCH_PROPERTYGET))
|
||||
return DISP_E_MEMBERNOTFOUND;
|
||||
|
||||
FIXME("\n");
|
||||
VariantInit(&varg1);
|
||||
hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
VariantInit(pVarResult);
|
||||
VariantInit(&varg0);
|
||||
hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
ret = MsiGetSummaryInformationW(0, V_BSTR(&varg0), V_I4(&varg1), &hsuminfo);
|
||||
VariantClear(&varg0);
|
||||
if (ret != ERROR_SUCCESS)
|
||||
return DISP_E_EXCEPTION;
|
||||
|
||||
hr = create_summaryinfo(hsuminfo, &dispatch);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
V_VT(pVarResult) = VT_DISPATCH;
|
||||
V_DISPATCH(pVarResult) = dispatch;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -2013,7 +2037,7 @@ static HRESULT InstallerImpl_RegistryValue(WORD wFlags,
|
|||
/* Return VT_BOOL clarifying whether registry key exists or not. */
|
||||
case VT_EMPTY:
|
||||
V_VT(pVarResult) = VT_BOOL;
|
||||
V_BOOL(pVarResult) = (ret == ERROR_SUCCESS);
|
||||
V_BOOL(pVarResult) = (ret == ERROR_SUCCESS) ? VARIANT_TRUE : VARIANT_FALSE;
|
||||
break;
|
||||
|
||||
/* Return the value of specified key if it exists. */
|
||||
|
|
|
@ -953,7 +953,7 @@ UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package )
|
|||
|
||||
cls->action = INSTALLSTATE_ABSENT;
|
||||
|
||||
res = SHDeleteKeyW( hkey, cls->clsid );
|
||||
res = RegDeleteTreeW( hkey, cls->clsid );
|
||||
if (res != ERROR_SUCCESS)
|
||||
WARN("Failed to delete class key %d\n", res);
|
||||
|
||||
|
@ -975,7 +975,7 @@ UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package )
|
|||
{
|
||||
strcpyW( filetype, szFileType );
|
||||
strcatW( filetype, cls->clsid );
|
||||
res = SHDeleteKeyW( HKEY_CLASSES_ROOT, filetype );
|
||||
res = RegDeleteTreeW( HKEY_CLASSES_ROOT, filetype );
|
||||
msi_free( filetype );
|
||||
|
||||
if (res != ERROR_SUCCESS)
|
||||
|
@ -1148,7 +1148,7 @@ UINT ACTION_UnregisterProgIdInfo( MSIPACKAGE *package )
|
|||
}
|
||||
TRACE("Unregistering progid %s\n", debugstr_w(progid->ProgID));
|
||||
|
||||
res = SHDeleteKeyW( HKEY_CLASSES_ROOT, progid->ProgID );
|
||||
res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid->ProgID );
|
||||
if (res != ERROR_SUCCESS)
|
||||
TRACE("Failed to delete progid key %d\n", res);
|
||||
|
||||
|
@ -1392,7 +1392,7 @@ UINT ACTION_UnregisterExtensionInfo( MSIPACKAGE *package )
|
|||
{
|
||||
extension[0] = '.';
|
||||
strcpyW( extension + 1, ext->Extension );
|
||||
res = SHDeleteKeyW( HKEY_CLASSES_ROOT, extension );
|
||||
res = RegDeleteTreeW( HKEY_CLASSES_ROOT, extension );
|
||||
msi_free( extension );
|
||||
if (res != ERROR_SUCCESS)
|
||||
WARN("Failed to delete extension key %d\n", res);
|
||||
|
@ -1414,7 +1414,7 @@ UINT ACTION_UnregisterExtensionInfo( MSIPACKAGE *package )
|
|||
{
|
||||
strcpyW( progid_shell, progid );
|
||||
strcatW( progid_shell, shellW );
|
||||
res = SHDeleteKeyW( HKEY_CLASSES_ROOT, progid_shell );
|
||||
res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid_shell );
|
||||
msi_free( progid_shell );
|
||||
if (res != ERROR_SUCCESS)
|
||||
WARN("Failed to delete shell key %d\n", res);
|
||||
|
|
|
@ -36,6 +36,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
|||
|
||||
#define IS_INTMSIDBOPEN(x) (((ULONG_PTR)(x) >> 16) == 0)
|
||||
|
||||
struct row_export_info
|
||||
{
|
||||
HANDLE handle;
|
||||
LPCWSTR folder;
|
||||
LPCWSTR table;
|
||||
};
|
||||
|
||||
static void free_transforms( MSIDATABASE *db )
|
||||
{
|
||||
while( !list_empty( &db->transforms ) )
|
||||
|
@ -763,6 +770,8 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
|||
lstrcatW( path, file );
|
||||
|
||||
data = msi_read_text_archive( path, &len );
|
||||
if (data == NULL)
|
||||
return ERROR_BAD_PATHNAME;
|
||||
|
||||
ptr = data;
|
||||
msi_parse_line( &ptr, &columns, &num_columns, &len );
|
||||
|
@ -901,50 +910,131 @@ end:
|
|||
return r;
|
||||
}
|
||||
|
||||
static UINT msi_export_record( HANDLE handle, MSIRECORD *row, UINT start )
|
||||
static UINT msi_export_field( HANDLE handle, MSIRECORD *row, UINT field )
|
||||
{
|
||||
UINT i, count, len, r = ERROR_SUCCESS;
|
||||
const char *sep;
|
||||
char *buffer;
|
||||
BOOL bret;
|
||||
DWORD sz;
|
||||
UINT r;
|
||||
|
||||
len = 0x100;
|
||||
buffer = msi_alloc( len );
|
||||
sz = 0x100;
|
||||
buffer = msi_alloc( sz );
|
||||
if (!buffer)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
r = MSI_RecordGetStringA( row, field, buffer, &sz );
|
||||
if (r == ERROR_MORE_DATA)
|
||||
{
|
||||
char *p;
|
||||
|
||||
sz++; /* leave room for NULL terminator */
|
||||
p = msi_realloc( buffer, sz );
|
||||
if (!p)
|
||||
{
|
||||
msi_free( buffer );
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
buffer = p;
|
||||
|
||||
r = MSI_RecordGetStringA( row, field, buffer, &sz );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
msi_free( buffer );
|
||||
return r;
|
||||
}
|
||||
}
|
||||
else if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
bret = WriteFile( handle, buffer, sz, &sz, NULL );
|
||||
msi_free( buffer );
|
||||
if (!bret)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static UINT msi_export_stream( LPCWSTR folder, LPCWSTR table, MSIRECORD *row, UINT field,
|
||||
UINT start )
|
||||
{
|
||||
static const WCHAR fmt_file[] = { '%','s','/','%','s','/','%','s',0 };
|
||||
static const WCHAR fmt_folder[] = { '%','s','/','%','s',0 };
|
||||
WCHAR stream_name[256], stream_filename[MAX_PATH];
|
||||
DWORD sz, read_size, write_size;
|
||||
char buffer[1024];
|
||||
HANDLE file;
|
||||
UINT r;
|
||||
|
||||
/* get the name of the file */
|
||||
sz = sizeof(stream_name)/sizeof(WCHAR);
|
||||
r = MSI_RecordGetStringW( row, start, stream_name, &sz );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
/* if the destination folder does not exist then create it (folder name = table name) */
|
||||
snprintfW( stream_filename, sizeof(stream_filename), fmt_folder, folder, table );
|
||||
if (GetFileAttributesW( stream_filename ) == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
if (!CreateDirectoryW( stream_filename, NULL ))
|
||||
return ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* actually create the file */
|
||||
snprintfW( stream_filename, sizeof(stream_filename), fmt_file, folder, table, stream_name );
|
||||
file = CreateFileW( stream_filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
return ERROR_FILE_NOT_FOUND;
|
||||
|
||||
/* copy the stream to the file */
|
||||
read_size = sizeof(buffer);
|
||||
while (read_size == sizeof(buffer))
|
||||
{
|
||||
r = MSI_RecordReadStream( row, field, buffer, &read_size );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
CloseHandle( file );
|
||||
return r;
|
||||
}
|
||||
if (!WriteFile( file, buffer, read_size, &write_size, NULL ) || read_size != write_size)
|
||||
{
|
||||
CloseHandle( file );
|
||||
return ERROR_WRITE_FAULT;
|
||||
}
|
||||
}
|
||||
CloseHandle( file );
|
||||
return r;
|
||||
}
|
||||
|
||||
static UINT msi_export_record( struct row_export_info *row_export_info, MSIRECORD *row, UINT start )
|
||||
{
|
||||
HANDLE handle = row_export_info->handle;
|
||||
UINT i, count, r = ERROR_SUCCESS;
|
||||
const char *sep;
|
||||
DWORD sz;
|
||||
|
||||
count = MSI_RecordGetFieldCount( row );
|
||||
for (i = start; i <= count; i++)
|
||||
{
|
||||
sz = len;
|
||||
r = MSI_RecordGetStringA( row, i, buffer, &sz );
|
||||
if (r == ERROR_MORE_DATA)
|
||||
r = msi_export_field( handle, row, i );
|
||||
if (r == ERROR_INVALID_PARAMETER)
|
||||
{
|
||||
char *p = msi_realloc( buffer, sz + 1 );
|
||||
if (!p)
|
||||
break;
|
||||
len = sz + 1;
|
||||
buffer = p;
|
||||
}
|
||||
sz = len;
|
||||
r = MSI_RecordGetStringA( row, i, buffer, &sz );
|
||||
r = msi_export_stream( row_export_info->folder, row_export_info->table, row, i, start );
|
||||
if (r != ERROR_SUCCESS)
|
||||
break;
|
||||
return r;
|
||||
|
||||
if (!WriteFile( handle, buffer, sz, &sz, NULL ))
|
||||
{
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
break;
|
||||
/* exporting a binary stream, repeat the "Name" field */
|
||||
r = msi_export_field( handle, row, start );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
}
|
||||
else if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
sep = (i < count) ? "\t" : "\r\n";
|
||||
if (!WriteFile( handle, sep, strlen(sep), &sz, NULL ))
|
||||
{
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
break;
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
}
|
||||
msi_free( buffer );
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -968,9 +1058,25 @@ static UINT msi_export_forcecodepage( HANDLE handle, UINT codepage )
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_export_summaryinformation( MSIDATABASE *db, HANDLE handle )
|
||||
{
|
||||
static const char header[] = "PropertyId\tValue\r\n"
|
||||
"i2\tl255\r\n"
|
||||
"_SummaryInformation\tPropertyId\r\n";
|
||||
DWORD sz;
|
||||
|
||||
sz = lstrlenA(header);
|
||||
if (!WriteFile(handle, header, sz, &sz, NULL))
|
||||
return ERROR_WRITE_FAULT;
|
||||
|
||||
return msi_export_suminfo( db, handle );
|
||||
}
|
||||
|
||||
static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
||||
LPCWSTR folder, LPCWSTR file )
|
||||
{
|
||||
static const WCHAR summaryinformation[] = {
|
||||
'_','S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',0 };
|
||||
static const WCHAR query[] = {
|
||||
's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','%','s',0 };
|
||||
static const WCHAR forcecodepage[] = {
|
||||
|
@ -1009,14 +1115,22 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (!strcmpW( table, summaryinformation ))
|
||||
{
|
||||
r = msi_export_summaryinformation( db, handle );
|
||||
goto done;
|
||||
}
|
||||
|
||||
r = MSI_OpenQuery( db, &view, query, table );
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
struct row_export_info row_export_info = { handle, folder, table };
|
||||
|
||||
/* write out row 1, the column names */
|
||||
r = MSI_ViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
msi_export_record( handle, rec, 1 );
|
||||
msi_export_record( &row_export_info, rec, 1 );
|
||||
msiobj_release( &rec->hdr );
|
||||
}
|
||||
|
||||
|
@ -1024,7 +1138,7 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
|||
r = MSI_ViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
msi_export_record( handle, rec, 1 );
|
||||
msi_export_record( &row_export_info, rec, 1 );
|
||||
msiobj_release( &rec->hdr );
|
||||
}
|
||||
|
||||
|
@ -1033,12 +1147,12 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
|||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
MSI_RecordSetStringW( rec, 0, table );
|
||||
msi_export_record( handle, rec, 0 );
|
||||
msi_export_record( &row_export_info, rec, 0 );
|
||||
msiobj_release( &rec->hdr );
|
||||
}
|
||||
|
||||
/* write out row 4 onwards, the data */
|
||||
r = MSI_IterateRecords( view, 0, msi_export_row, handle );
|
||||
r = MSI_IterateRecords( view, 0, msi_export_row, &row_export_info );
|
||||
msiobj_release( &view->hdr );
|
||||
}
|
||||
|
||||
|
|
|
@ -2672,7 +2672,7 @@ static UINT msi_dialog_selection_tree( msi_dialog *dialog, MSIRECORD *rec )
|
|||
|
||||
/* create the treeview control */
|
||||
style = TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT;
|
||||
style |= WS_GROUP | WS_VSCROLL;
|
||||
style |= WS_GROUP | WS_VSCROLL | WS_TABSTOP;
|
||||
control = msi_dialog_add_control( dialog, rec, WC_TREEVIEWW, style );
|
||||
if (!control)
|
||||
{
|
||||
|
@ -3645,8 +3645,11 @@ static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs )
|
|||
if (!dialog->default_font)
|
||||
{
|
||||
dialog->default_font = strdupW(dfv);
|
||||
if (!dialog->default_font)
|
||||
{
|
||||
msiobj_release( &rec->hdr );
|
||||
if (!dialog->default_font) return -1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
title = msi_get_deformatted_field( dialog->package, rec, 7 );
|
||||
|
|
|
@ -4291,6 +4291,17 @@ UINT WINAPI MsiBeginTransactionW( LPCWSTR name, DWORD attrs, MSIHANDLE *id, HAND
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MsiJoinTransaction [MSI.@]
|
||||
*/
|
||||
UINT WINAPI MsiJoinTransaction( MSIHANDLE handle, DWORD attrs, HANDLE *event )
|
||||
{
|
||||
FIXME("%u %08x %p\n", handle, attrs, event);
|
||||
|
||||
*event = (HANDLE)0xdeadbeef;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MsiEndTransaction [MSI.@]
|
||||
*/
|
||||
|
|
|
@ -280,7 +280,7 @@
|
|||
284 stdcall MsiBeginTransactionA(str long ptr ptr)
|
||||
285 stdcall MsiBeginTransactionW(wstr long ptr ptr)
|
||||
286 stdcall MsiEndTransaction(long)
|
||||
287 stub MsiJoinTransaction
|
||||
287 stdcall MsiJoinTransaction(long long ptr)
|
||||
288 stub MsiSetOfflineContextW
|
||||
289 stdcall MsiEnumComponentsExA(str long long ptr ptr ptr ptr)
|
||||
290 stdcall MsiEnumComponentsExW(wstr long long ptr ptr ptr ptr)
|
||||
|
|
|
@ -968,6 +968,7 @@ extern LPWSTR msi_suminfo_dup_string( MSISUMMARYINFO *si, UINT uiProperty ) DECL
|
|||
extern INT msi_suminfo_get_int32( MSISUMMARYINFO *si, UINT uiProperty ) DECLSPEC_HIDDEN;
|
||||
extern LPWSTR msi_get_suminfo_product( IStorage *stg ) DECLSPEC_HIDDEN;
|
||||
extern UINT msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns ) DECLSPEC_HIDDEN;
|
||||
extern UINT msi_export_suminfo( MSIDATABASE *db, HANDLE handle ) DECLSPEC_HIDDEN;
|
||||
extern enum platform parse_platform( const WCHAR *str ) DECLSPEC_HIDDEN;
|
||||
extern UINT msi_load_suminfo_properties( MSIPACKAGE *package ) DECLSPEC_HIDDEN;
|
||||
|
||||
|
|
|
@ -335,7 +335,7 @@ UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec)
|
|||
if ((type & MSI_DATASIZEMASK) == 2)
|
||||
MSI_RecordSetInteger(*rec, i, ival - (1<<15));
|
||||
else
|
||||
MSI_RecordSetInteger(*rec, i, ival - (1<<31));
|
||||
MSI_RecordSetInteger(*rec, i, ival - (1u<<31));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2100,6 +2100,8 @@ UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName,
|
|||
MSIRECORD *row;
|
||||
UINT rc = ERROR_FUNCTION_FAILED;
|
||||
|
||||
TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf);
|
||||
|
||||
row = msi_get_property_row( db, szName );
|
||||
|
||||
if (*pchValueBuf > 0)
|
||||
|
|
|
@ -157,6 +157,10 @@ static const WCHAR szUserComponents[] = {
|
|||
'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
|
||||
'I','n','s','t','a','l','l','e','r','\\','C','o','m','p','o','n','e','n','t','s','\\',0};
|
||||
|
||||
static const WCHAR szInstaller_Components[] = {
|
||||
'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s','\\',
|
||||
'I','n','s','t','a','l','l','e','r','\\','C','o','m','p','o','n','e','n','t','s','\\',0};
|
||||
|
||||
static const WCHAR szUserFeatures[] = {
|
||||
'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
|
||||
'I','n','s','t','a','l','l','e','r','\\','F','e','a','t','u','r','e','s','\\',0};
|
||||
|
@ -466,7 +470,7 @@ UINT MSIREG_DeleteUninstallKey(const WCHAR *product, enum platform platform)
|
|||
strcpyW(keypath, szUninstall);
|
||||
strcatW(keypath, product);
|
||||
}
|
||||
return SHDeleteKeyW(HKEY_LOCAL_MACHINE, keypath);
|
||||
return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
|
||||
}
|
||||
|
||||
UINT MSIREG_OpenProductKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context, HKEY *key, BOOL create)
|
||||
|
@ -517,7 +521,7 @@ UINT MSIREG_DeleteUserProductKey(LPCWSTR szProduct)
|
|||
|
||||
strcpyW(keypath, szUserProducts);
|
||||
strcatW(keypath, squished_pc);
|
||||
return SHDeleteKeyW(HKEY_CURRENT_USER, keypath);
|
||||
return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
|
||||
}
|
||||
|
||||
UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY *key, BOOL create)
|
||||
|
@ -582,7 +586,7 @@ UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct)
|
|||
|
||||
strcpyW(keypath, szUserFeatures);
|
||||
strcatW(keypath, squished_pc);
|
||||
return SHDeleteKeyW(HKEY_CURRENT_USER, keypath);
|
||||
return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
|
||||
}
|
||||
|
||||
static UINT MSIREG_OpenInstallerFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create)
|
||||
|
@ -634,6 +638,7 @@ UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINS
|
|||
UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY *key, BOOL create)
|
||||
{
|
||||
WCHAR squished_cc[GUID_SIZE], keypath[0x200];
|
||||
UINT ret;
|
||||
|
||||
if (!squash_guid(szComponent, squished_cc)) return ERROR_FUNCTION_FAILED;
|
||||
TRACE("%s squished %s\n", debugstr_w(szComponent), debugstr_w(squished_cc));
|
||||
|
@ -642,7 +647,12 @@ UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY *key, BOOL create)
|
|||
strcatW(keypath, squished_cc);
|
||||
|
||||
if (create) return RegCreateKeyW(HKEY_CURRENT_USER, keypath, key);
|
||||
return RegOpenKeyW(HKEY_CURRENT_USER, keypath, key);
|
||||
ret = RegOpenKeyW(HKEY_CURRENT_USER, keypath, key);
|
||||
if (ret != ERROR_FILE_NOT_FOUND) return ret;
|
||||
|
||||
strcpyW(keypath, szInstaller_Components);
|
||||
strcatW(keypath, squished_cc);
|
||||
return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
|
||||
}
|
||||
|
||||
UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid, HKEY *key, BOOL create)
|
||||
|
@ -696,7 +706,7 @@ UINT MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid)
|
|||
sprintfW(keypath, szUserDataComponents_fmt, szUserSid);
|
||||
|
||||
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS;
|
||||
r = SHDeleteKeyW(hkey, comp);
|
||||
r = RegDeleteTreeW(hkey, comp);
|
||||
RegCloseKey(hkey);
|
||||
return r;
|
||||
}
|
||||
|
@ -777,7 +787,7 @@ UINT MSIREG_DeleteUserDataPatchKey(LPCWSTR patch, MSIINSTALLCONTEXT context)
|
|||
LocalFree(usersid);
|
||||
}
|
||||
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS;
|
||||
r = SHDeleteKeyW(hkey, squished_patch);
|
||||
r = RegDeleteTreeW(hkey, squished_patch);
|
||||
RegCloseKey(hkey);
|
||||
return r;
|
||||
}
|
||||
|
@ -854,7 +864,7 @@ UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct)
|
|||
LocalFree(usersid);
|
||||
|
||||
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS;
|
||||
r = SHDeleteKeyW(hkey, squished_pc);
|
||||
r = RegDeleteTreeW(hkey, squished_pc);
|
||||
RegCloseKey(hkey);
|
||||
return r;
|
||||
}
|
||||
|
@ -870,7 +880,7 @@ UINT MSIREG_DeleteProductKey(LPCWSTR szProduct)
|
|||
TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc));
|
||||
|
||||
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szInstaller_Products, 0, access, &hkey)) return ERROR_SUCCESS;
|
||||
r = SHDeleteKeyW(hkey, squished_pc);
|
||||
r = RegDeleteTreeW(hkey, squished_pc);
|
||||
RegCloseKey(hkey);
|
||||
return r;
|
||||
}
|
||||
|
@ -927,7 +937,7 @@ UINT MSIREG_DeleteUserUpgradeCodesKey(LPCWSTR szUpgradeCode)
|
|||
|
||||
strcpyW(keypath, szInstaller_UserUpgradeCodes);
|
||||
strcatW(keypath, squished_pc);
|
||||
return SHDeleteKeyW(HKEY_CURRENT_USER, keypath);
|
||||
return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
|
||||
}
|
||||
|
||||
UINT MSIREG_DeleteLocalClassesProductKey(LPCWSTR szProductCode)
|
||||
|
@ -941,7 +951,7 @@ UINT MSIREG_DeleteLocalClassesProductKey(LPCWSTR szProductCode)
|
|||
TRACE("%s squished %s\n", debugstr_w(szProductCode), debugstr_w(squished_pc));
|
||||
|
||||
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szInstaller_LocalClassesProducts, 0, access, &hkey)) return ERROR_SUCCESS;
|
||||
r = SHDeleteKeyW(hkey, squished_pc);
|
||||
r = RegDeleteTreeW(hkey, squished_pc);
|
||||
RegCloseKey(hkey);
|
||||
return r;
|
||||
}
|
||||
|
@ -957,7 +967,7 @@ UINT MSIREG_DeleteLocalClassesFeaturesKey(LPCWSTR szProductCode)
|
|||
TRACE("%s squished %s\n", debugstr_w(szProductCode), debugstr_w(squished_pc));
|
||||
|
||||
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szInstaller_LocalClassesFeatures, 0, access, &hkey)) return ERROR_SUCCESS;
|
||||
r = SHDeleteKeyW(hkey, squished_pc);
|
||||
r = RegDeleteTreeW(hkey, squished_pc);
|
||||
RegCloseKey(hkey);
|
||||
return r;
|
||||
}
|
||||
|
@ -988,7 +998,7 @@ UINT MSIREG_DeleteClassesUpgradeCodesKey(LPCWSTR szUpgradeCode)
|
|||
TRACE("%s squished %s\n", debugstr_w(szUpgradeCode), debugstr_w(squished_pc));
|
||||
|
||||
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szInstaller_ClassesUpgradeCodes, 0, access, &hkey)) return ERROR_SUCCESS;
|
||||
r = SHDeleteKeyW(hkey, squished_pc);
|
||||
r = RegDeleteTreeW(hkey, squished_pc);
|
||||
RegCloseKey(hkey);
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -194,7 +194,28 @@ static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row
|
|||
|
||||
static UINT STREAMS_delete_row(struct tagMSIVIEW *view, UINT row)
|
||||
{
|
||||
FIXME("(%p %d): stub!\n", view, row);
|
||||
MSIDATABASE *db = ((MSISTREAMSVIEW *)view)->db;
|
||||
UINT i, num_rows = db->num_streams - 1;
|
||||
const WCHAR *name;
|
||||
WCHAR *encname;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p %d)!\n", view, row);
|
||||
|
||||
name = msi_string_lookup( db->strings, db->streams[row].str_index, NULL );
|
||||
if (!(encname = encode_streamname( FALSE, name ))) return ERROR_OUTOFMEMORY;
|
||||
hr = IStorage_DestroyElement( db->storage, encname );
|
||||
msi_free( encname );
|
||||
if (FAILED( hr ))
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
hr = IStream_Release( db->streams[row].stream );
|
||||
if (FAILED( hr ))
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
for (i = row; i < num_rows; i++)
|
||||
db->streams[i] = db->streams[i + 1];
|
||||
db->num_streams = num_rows;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -293,12 +314,15 @@ static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRE
|
|||
r = streams_modify_update(view, rec);
|
||||
break;
|
||||
|
||||
case MSIMODIFY_DELETE:
|
||||
r = STREAMS_delete_row(view, row - 1);
|
||||
break;
|
||||
|
||||
case MSIMODIFY_VALIDATE_NEW:
|
||||
case MSIMODIFY_INSERT_TEMPORARY:
|
||||
case MSIMODIFY_REFRESH:
|
||||
case MSIMODIFY_REPLACE:
|
||||
case MSIMODIFY_MERGE:
|
||||
case MSIMODIFY_DELETE:
|
||||
case MSIMODIFY_VALIDATE:
|
||||
case MSIMODIFY_VALIDATE_FIELD:
|
||||
case MSIMODIFY_VALIDATE_DELETE:
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "msipriv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <propvarutil.h>
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||
|
@ -999,6 +1000,117 @@ end:
|
|||
return r;
|
||||
}
|
||||
|
||||
static UINT save_prop( MSISUMMARYINFO *si, HANDLE handle, UINT row )
|
||||
{
|
||||
static const char fmt_systemtime[] = "%d/%02d/%02d %02d:%02d:%02d";
|
||||
char data[20]; /* largest string: YYYY/MM/DD hh:mm:ss */
|
||||
static const char fmt_begin[] = "%u\t";
|
||||
static const char data_end[] = "\r\n";
|
||||
static const char fmt_int[] = "%u";
|
||||
UINT r, data_type, len;
|
||||
SYSTEMTIME system_time;
|
||||
FILETIME file_time;
|
||||
INT int_value;
|
||||
awstring str;
|
||||
DWORD sz;
|
||||
|
||||
str.unicode = FALSE;
|
||||
str.str.a = NULL;
|
||||
len = 0;
|
||||
r = get_prop( si, row, &data_type, &int_value, &file_time, &str, &len );
|
||||
if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
|
||||
return r;
|
||||
if (data_type == VT_EMPTY)
|
||||
return ERROR_SUCCESS; /* property not set */
|
||||
snprintf( data, sizeof(data), fmt_begin, row );
|
||||
sz = lstrlenA( data );
|
||||
if (!WriteFile( handle, data, sz, &sz, NULL ))
|
||||
return ERROR_WRITE_FAULT;
|
||||
|
||||
switch (data_type)
|
||||
{
|
||||
case VT_I2:
|
||||
case VT_I4:
|
||||
snprintf( data, sizeof(data), fmt_int, int_value );
|
||||
sz = lstrlenA( data );
|
||||
if (!WriteFile( handle, data, sz, &sz, NULL ))
|
||||
return ERROR_WRITE_FAULT;
|
||||
break;
|
||||
case VT_LPSTR:
|
||||
len++;
|
||||
if (!(str.str.a = msi_alloc( len )))
|
||||
return ERROR_OUTOFMEMORY;
|
||||
r = get_prop( si, row, NULL, NULL, NULL, &str, &len );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
msi_free( str.str.a );
|
||||
return r;
|
||||
}
|
||||
sz = lstrlenA( str.str.a );
|
||||
if (!WriteFile( handle, str.str.a, sz, &sz, NULL ))
|
||||
{
|
||||
msi_free( str.str.a );
|
||||
return ERROR_WRITE_FAULT;
|
||||
}
|
||||
msi_free( str.str.a );
|
||||
break;
|
||||
case VT_FILETIME:
|
||||
if (!FileTimeToSystemTime( &file_time, &system_time ))
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
snprintf( data, sizeof(data), fmt_systemtime, system_time.wYear, system_time.wMonth,
|
||||
system_time.wDay, system_time.wHour, system_time.wMinute,
|
||||
system_time.wSecond );
|
||||
sz = lstrlenA( data );
|
||||
if (!WriteFile( handle, data, sz, &sz, NULL ))
|
||||
return ERROR_WRITE_FAULT;
|
||||
break;
|
||||
case VT_EMPTY:
|
||||
/* cannot reach here, property not set */
|
||||
break;
|
||||
default:
|
||||
FIXME( "Unknown property variant type\n" );
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
sz = lstrlenA( data_end );
|
||||
if (!WriteFile( handle, data_end, sz, &sz, NULL ))
|
||||
return ERROR_WRITE_FAULT;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT msi_export_suminfo( MSIDATABASE *db, HANDLE handle )
|
||||
{
|
||||
UINT i, r, num_rows;
|
||||
MSISUMMARYINFO *si;
|
||||
|
||||
r = msi_get_suminfo( db->storage, 0, &si );
|
||||
if (r != ERROR_SUCCESS)
|
||||
r = msi_get_db_suminfo( db, 0, &si );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
num_rows = get_property_count( si->property );
|
||||
if (!num_rows)
|
||||
{
|
||||
msiobj_release( &si->hdr );
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_rows; i++)
|
||||
{
|
||||
r = save_prop( si, handle, i );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
msiobj_release( &si->hdr );
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
msiobj_release( &si->hdr );
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE handle )
|
||||
{
|
||||
MSISUMMARYINFO *si;
|
||||
|
|
|
@ -792,7 +792,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
|
|||
/* add each column to the _Columns table */
|
||||
r = TABLE_CreateView( db, szColumns, &tv );
|
||||
if( r )
|
||||
return r;
|
||||
goto err;
|
||||
|
||||
r = tv->ops->execute( tv, 0 );
|
||||
TRACE("tv execute returned %x\n", r);
|
||||
|
@ -2308,8 +2308,7 @@ err:
|
|||
}
|
||||
|
||||
static MSIRECORD *msi_get_transform_record( const MSITABLEVIEW *tv, const string_table *st,
|
||||
IStorage *stg,
|
||||
const BYTE *rawdata, UINT bytes_per_strref )
|
||||
IStorage *stg, const BYTE *rawdata, UINT bytes_per_strref )
|
||||
{
|
||||
UINT i, val, ofs = 0;
|
||||
USHORT mask;
|
||||
|
@ -2342,12 +2341,14 @@ static MSIRECORD *msi_get_transform_record( const MSITABLEVIEW *tv, const string
|
|||
|
||||
r = msi_record_encoded_stream_name( tv, rec, &encname );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
{
|
||||
msiobj_release( &rec->hdr );
|
||||
return NULL;
|
||||
|
||||
r = IStorage_OpenStream( stg, encname, NULL,
|
||||
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm );
|
||||
}
|
||||
r = IStorage_OpenStream( stg, encname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
{
|
||||
msiobj_release( &rec->hdr );
|
||||
msi_free( encname );
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ reactos/dll/win32/msg711.acm # Synced to WineStaging-1.7.47
|
|||
reactos/dll/win32/msgsm32.acm # Synced to WineStaging-1.7.47
|
||||
reactos/dll/win32/mshtml # Synced to WineStaging-1.7.37
|
||||
reactos/dll/win32/mshtml.tlb # Synced to WineStaging-1.7.47
|
||||
reactos/dll/win32/msi # Synced to WineStaging-1.7.47
|
||||
reactos/dll/win32/msi # Synced to WineStaging-1.7.55
|
||||
reactos/dll/win32/msimg32 # Synced to WineStaging-1.7.47
|
||||
reactos/dll/win32/msimtf # Synced to WineStaging-1.7.47
|
||||
reactos/dll/win32/msisip # Synced to WineStaging-1.7.47
|
||||
|
|
Loading…
Reference in a new issue