[MSI] Sync with Wine Staging 1.7.55. CORE-10536

svn path=/trunk/; revision=69995
This commit is contained in:
Amine Khaldi 2015-11-21 16:44:38 +00:00
parent 02ab2bf42c
commit 9c595b7465
16 changed files with 536 additions and 138 deletions

View file

@ -65,7 +65,7 @@ set_module_type(msi win32dll)
target_link_libraries(msi uuid ${PSEH_LIB} wine) target_link_libraries(msi uuid ${PSEH_LIB} wine)
add_dependencies(msi msi_idlheader) add_dependencies(msi msi_idlheader)
add_delay_importlibs(msi odbccp32 crypt32 wintrust) 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 #FIXME : should be in delayed imports
imagehlp imagehlp
msvcrt msvcrt

View file

@ -239,8 +239,7 @@ static int parse_prop( const WCHAR *str, WCHAR *value, int *quotes )
len++; len++;
break; break;
default: default:
if (!count) in_quotes = FALSE; if (count) in_quotes = TRUE;
else in_quotes = TRUE;
len++; len++;
break; break;
} }
@ -261,8 +260,7 @@ static int parse_prop( const WCHAR *str, WCHAR *value, int *quotes )
break; break;
default: default:
state = state_token; state = state_token;
if (!count) in_quotes = FALSE; if (count) in_quotes = TRUE;
else in_quotes = TRUE;
len++; len++;
break; break;
} }
@ -271,6 +269,7 @@ static int parse_prop( const WCHAR *str, WCHAR *value, int *quotes )
default: break; default: break;
} }
if (!ignore) *out++ = *p; if (!ignore) *out++ = *p;
if (!count) in_quotes = FALSE;
} }
done: done:
@ -313,7 +312,7 @@ UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine,
ptr2 = strchrW( ptr, '=' ); ptr2 = strchrW( ptr, '=' );
if (!ptr2) return ERROR_INVALID_COMMAND_LINE; if (!ptr2) return ERROR_INVALID_COMMAND_LINE;
len = ptr2 - ptr; len = ptr2 - ptr;
if (!len) return ERROR_INVALID_COMMAND_LINE; if (!len) return ERROR_INVALID_COMMAND_LINE;
@ -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)); 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 UINT ACTION_CostFinalize(MSIPACKAGE *package)
{ {
static const WCHAR query[] = static const WCHAR query[] =
@ -2376,6 +2387,12 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
static const WCHAR szPrimaryVolumeSpaceAvailable[] = static const WCHAR szPrimaryVolumeSpaceAvailable[] =
{'P','r','i','m','a','r','y','V','o','l','u','m','e','S','p','a','c','e', {'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}; '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[] = static const WCHAR szOutOfNoRbDiskSpace[] =
{'O','u','t','O','f','N','o','R','b','D','i','s','k','S','p','a','c','e',0}; {'O','u','t','O','f','N','o','R','b','D','i','s','k','S','p','a','c','e',0};
MSICOMPONENT *comp; MSICOMPONENT *comp;
@ -2426,6 +2443,8 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
if (!level) msi_set_property( package->db, szInstallLevel, szOne, -1 ); if (!level) msi_set_property( package->db, szInstallLevel, szOne, -1 );
msi_free(level); msi_free(level);
if ((rc = MSI_SetFeatureStates( package ))) return rc;
if ((primary_key = msi_dup_property( package->db, szPrimaryFolder ))) if ((primary_key = msi_dup_property( package->db, szPrimaryFolder )))
{ {
if ((primary_folder = msi_dup_property( package->db, primary_key ))) 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') || if (((primary_folder[0] >= 'A' && primary_folder[0] <= 'Z') ||
(primary_folder[0] >= 'a' && primary_folder[0] <= 'z')) && primary_folder[1] == ':') (primary_folder[0] >= 'a' && primary_folder[0] <= 'z')) && primary_folder[1] == ':')
{ {
static const WCHAR fmtW[] = {'%','l','u',0};
ULARGE_INTEGER free; ULARGE_INTEGER free;
ULONGLONG required;
WCHAR buf[21];
primary_folder[2] = 0; primary_folder[2] = 0;
if (GetDiskFreeSpaceExW( primary_folder, &free, NULL, NULL )) if (GetDiskFreeSpaceExW( primary_folder, &free, NULL, NULL ))
{ {
static const WCHAR fmtW[] = {'%','l','u',0};
WCHAR buf[21];
sprintfW( buf, fmtW, free.QuadPart / 512 ); sprintfW( buf, fmtW, free.QuadPart / 512 );
msi_set_property( package->db, szPrimaryVolumeSpaceAvailable, buf, -1 ); 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_set_property( package->db, szPrimaryVolumePath, primary_folder, 2 );
} }
msi_free( primary_folder ); 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, szOutOfDiskSpace, szZero, -1 );
msi_set_property( package->db, szOutOfNoRbDiskSpace, 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 ) 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; 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; WCHAR *subkey, *p, *q;
HKEY hkey, ret = NULL; HKEY hkey, ret = NULL;
LONG res; LONG res;
@ -2641,7 +2665,7 @@ static HKEY open_key( const MSICOMPONENT *comp, HKEY root, const WCHAR *path, BO
} }
if (q && q[1]) if (q && q[1])
{ {
ret = open_key( comp, hkey, q + 1, create ); ret = open_key( comp, hkey, q + 1, create, access );
RegCloseKey( hkey ); RegCloseKey( hkey );
} }
else ret = hkey; else ret = hkey;
@ -2866,7 +2890,7 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
strcpyW(uikey,szRoot); strcpyW(uikey,szRoot);
strcatW(uikey,deformated); 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)); ERR("Could not create key %s\n", debugstr_w(deformated));
msi_free(uikey); msi_free(uikey);
@ -2957,13 +2981,17 @@ static void delete_key( const MSICOMPONENT *comp, HKEY root, const WCHAR *path )
access |= get_registry_view( comp ); access |= get_registry_view( comp );
if (!(subkey = strdupW( path ))) return; if (!(subkey = strdupW( path ))) return;
for (;;) do
{ {
if ((p = strrchrW( subkey, '\\' ))) *p = 0; if ((p = strrchrW( subkey, '\\' )))
hkey = open_key( comp, root, subkey, FALSE ); {
if (!hkey) break; *p = 0;
if (p && p[1]) if (!p[1]) continue; /* trailing backslash */
hkey = open_key( comp, root, subkey, FALSE, access );
if (!hkey) break;
res = RegDeleteKeyExW( hkey, p + 1, access, 0 ); res = RegDeleteKeyExW( hkey, p + 1, access, 0 );
RegCloseKey( hkey );
}
else else
res = RegDeleteKeyExW( root, subkey, access, 0 ); res = RegDeleteKeyExW( root, subkey, access, 0 );
if (res) 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); TRACE("failed to delete key %s (%d)\n", debugstr_w(subkey), res);
break; break;
} }
if (p && p[1]) RegCloseKey( hkey ); } while (p);
else break;
}
msi_free( subkey ); msi_free( subkey );
} }
@ -2983,7 +3009,7 @@ static void delete_value( const MSICOMPONENT *comp, HKEY root, const WCHAR *path
HKEY hkey; HKEY hkey;
DWORD num_subkeys, num_values; 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 ))) if ((res = RegDeleteValueW( hkey, value )))
TRACE("failed to delete value %s (%d)\n", debugstr_w(value), res); 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; LONG res;
HKEY hkey; HKEY hkey;
if (!(hkey = open_key( comp, root, path, FALSE ))) return; if (!(hkey = open_key( comp, root, path, FALSE, KEY_ALL_ACCESS ))) return;
res = SHDeleteKeyW( hkey, NULL ); res = RegDeleteTreeW( hkey, NULL );
if (res) TRACE("failed to delete subtree of %s (%d)\n", debugstr_w(path), res); if (res) TRACE("failed to delete subtree of %s (%d)\n", debugstr_w(path), res);
delete_key( comp, root, path ); delete_key( comp, root, path );
RegCloseKey( hkey ); RegCloseKey( hkey );
@ -3537,7 +3563,9 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
if (!comp->KeyPath || !(file = msi_get_loaded_file(package, comp->KeyPath))) if (!comp->KeyPath || !(file = msi_get_loaded_file(package, comp->KeyPath)))
continue; 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)); sprintfW(source, fmt, MSI_RecordGetInteger(row, 1));
ptr2 = strrchrW(source, '\\') + 1; ptr2 = strrchrW(source, '\\') + 1;
msiobj_release(&row->hdr); 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); if (image_path != file->TargetPath) msi_free(image_path);
done: done:
CloseServiceHandle(service); if (service) CloseServiceHandle(service);
CloseServiceHandle(hscm); if (hscm) CloseServiceHandle(hscm);
msi_free(name); msi_free(name);
msi_free(disp); msi_free(disp);
msi_free(sd.lpDescription); msi_free(sd.lpDescription);
@ -6032,8 +6060,8 @@ done:
msi_ui_actiondata( package, szStartServices, uirow ); msi_ui_actiondata( package, szStartServices, uirow );
msiobj_release( &uirow->hdr ); msiobj_release( &uirow->hdr );
CloseServiceHandle(service); if (service) CloseServiceHandle(service);
CloseServiceHandle(scm); if (scm) CloseServiceHandle(scm);
msi_free(name); msi_free(name);
msi_free(args); 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()); WARN("Failed to stop service (%s): %d\n", debugstr_w(name), GetLastError());
done: done:
CloseServiceHandle(service); if (service) CloseServiceHandle(service);
CloseServiceHandle(scm); if (scm) CloseServiceHandle(scm);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -6280,8 +6308,8 @@ done:
msi_ui_actiondata( package, szDeleteServices, uirow ); msi_ui_actiondata( package, szDeleteServices, uirow );
msiobj_release( &uirow->hdr ); msiobj_release( &uirow->hdr );
CloseServiceHandle( service ); if (service) CloseServiceHandle( service );
CloseServiceHandle( scm ); if (scm) CloseServiceHandle( scm );
msi_free( name ); msi_free( name );
msi_free( display_name ); msi_free( display_name );
@ -6903,13 +6931,13 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
{ {
MSIPACKAGE *package = param; MSIPACKAGE *package = param;
LPCWSTR name, value, component; LPCWSTR name, value, component;
LPWSTR data = NULL, newval = NULL, deformatted = NULL, ptr; WCHAR *data = NULL, *newval = NULL, *deformatted = NULL, *p, *q;
DWORD flags, type, size; DWORD flags, type, size, len, len_value = 0;
UINT res; UINT res;
HKEY env = NULL; HKEY env = NULL;
MSICOMPONENT *comp; MSICOMPONENT *comp;
MSIRECORD *uirow; MSIRECORD *uirow;
int action = 0; int action = 0, found = 0;
component = MSI_RecordGetString(rec, 4); component = MSI_RecordGetString(rec, 4);
comp = msi_get_loaded_component(package, component); comp = msi_get_loaded_component(package, component);
@ -6937,7 +6965,20 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
goto done; 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 ); res = open_env_key( flags, &env );
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS)
@ -6963,10 +7004,6 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
res = ERROR_SUCCESS; res = ERROR_SUCCESS;
goto done; 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); size = (lstrlenW(value) + 1) * sizeof(WCHAR);
newval = strdupW(value); newval = strdupW(value);
if (!newval) if (!newval)
@ -6986,15 +7023,14 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
goto done; goto done;
} }
data = msi_alloc(size); if (!(p = q = data = msi_alloc( size )))
if (!data)
{ {
msi_free(deformatted); msi_free(deformatted);
RegCloseKey(env); RegCloseKey(env);
return ERROR_OUTOFMEMORY; 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) if (res != ERROR_SUCCESS)
goto done; goto done;
@ -7007,20 +7043,28 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
goto done; goto done;
} }
size = (lstrlenW(data) + 1) * sizeof(WCHAR); for (;;)
if (flags & ENV_MOD_MASK)
{ {
DWORD mod_size; while (*q && *q != ';') q++;
int multiplier = 0; len = q - p;
if (flags & ENV_MOD_APPEND) multiplier++; if (value && len == len_value && !memcmp( value, p, len * sizeof(WCHAR) ) &&
if (flags & ENV_MOD_PREFIX) multiplier++; (!p[len] || p[len] == ';'))
mod_size = lstrlenW(value) * multiplier; {
size += mod_size * sizeof(WCHAR); found = 1;
break;
}
if (!*q) break;
p = ++q;
} }
newval = msi_alloc(size); if (found)
ptr = newval; {
if (!newval) 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; res = ERROR_OUTOFMEMORY;
goto done; goto done;
@ -7028,21 +7072,24 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
if (flags & ENV_MOD_PREFIX) if (flags & ENV_MOD_PREFIX)
{ {
lstrcpyW(newval, value); memcpy( newval, value, len_value * sizeof(WCHAR) );
ptr = newval + lstrlenW(value); newval[len_value] = ';';
p = newval + len_value + 1;
action |= 0x80000000; action |= 0x80000000;
} }
lstrcpyW(ptr, data); strcpyW( p, data );
if (flags & ENV_MOD_APPEND) if (flags & ENV_MOD_APPEND)
{ {
lstrcatW(newval, value); p += strlenW( data );
*p++ = ';';
memcpy( p, value, (len_value + 1) * sizeof(WCHAR) );
action |= 0x40000000; action |= 0x40000000;
} }
} }
TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval)); 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) if (res)
{ {
WARN("Failed to set %s to %s (%d)\n", debugstr_w(name), debugstr_w(newval), 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; MSIPACKAGE *package = param;
LPCWSTR name, value, component; LPCWSTR name, value, component;
LPWSTR deformatted = NULL; WCHAR *p, *q, *deformatted = NULL, *new_value = NULL;
DWORD flags; DWORD flags, type, size, len, len_value = 0, len_new_value;
HKEY env; HKEY env;
MSICOMPONENT *comp; MSICOMPONENT *comp;
MSIRECORD *uirow; MSIRECORD *uirow;
@ -7122,7 +7169,20 @@ static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param )
if (value && !deformat_string( package, value, &deformatted )) if (value && !deformat_string( package, value, &deformatted ))
return ERROR_OUTOFMEMORY; 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 ); r = open_env_key( flags, &env );
if (r != ERROR_SUCCESS) if (r != ERROR_SUCCESS)
@ -7134,13 +7194,48 @@ static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param )
if (flags & ENV_MOD_MACHINE) if (flags & ENV_MOD_MACHINE)
action |= 0x20000000; 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;
res = RegDeleteValueW( env, name ); if (!(new_value = msi_alloc( size ))) goto done;
res = RegQueryValueExW( env, name, NULL, &type, (BYTE *)new_value, &size );
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS)
goto done;
len_new_value = size / sizeof(WCHAR) - 1;
p = q = new_value;
for (;;)
{ {
WARN("Failed to delete value %s (%d)\n", debugstr_w(name), res); while (*q && *q != ';') q++;
r = ERROR_SUCCESS; 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
{
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: done:
@ -7153,6 +7248,7 @@ done:
if (env) RegCloseKey( env ); if (env) RegCloseKey( env );
msi_free( deformatted ); msi_free( deformatted );
msi_free( new_value );
return r; return r;
} }

View file

@ -1421,7 +1421,7 @@ static HRESULT session_invoke(
hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
V_VT(pVarResult) = VT_BOOL; 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) { } else if (wFlags & DISPATCH_PROPERTYPUT) {
hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
@ -1816,12 +1816,36 @@ static HRESULT InstallerImpl_SummaryInformation(WORD wFlags,
EXCEPINFO* pExcepInfo, EXCEPINFO* pExcepInfo,
UINT* puArgErr) 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; 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; return S_OK;
} }
@ -2013,7 +2037,7 @@ static HRESULT InstallerImpl_RegistryValue(WORD wFlags,
/* Return VT_BOOL clarifying whether registry key exists or not. */ /* Return VT_BOOL clarifying whether registry key exists or not. */
case VT_EMPTY: case VT_EMPTY:
V_VT(pVarResult) = VT_BOOL; V_VT(pVarResult) = VT_BOOL;
V_BOOL(pVarResult) = (ret == ERROR_SUCCESS); V_BOOL(pVarResult) = (ret == ERROR_SUCCESS) ? VARIANT_TRUE : VARIANT_FALSE;
break; break;
/* Return the value of specified key if it exists. */ /* Return the value of specified key if it exists. */

View file

@ -953,7 +953,7 @@ UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package )
cls->action = INSTALLSTATE_ABSENT; cls->action = INSTALLSTATE_ABSENT;
res = SHDeleteKeyW( hkey, cls->clsid ); res = RegDeleteTreeW( hkey, cls->clsid );
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS)
WARN("Failed to delete class key %d\n", res); WARN("Failed to delete class key %d\n", res);
@ -975,7 +975,7 @@ UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package )
{ {
strcpyW( filetype, szFileType ); strcpyW( filetype, szFileType );
strcatW( filetype, cls->clsid ); strcatW( filetype, cls->clsid );
res = SHDeleteKeyW( HKEY_CLASSES_ROOT, filetype ); res = RegDeleteTreeW( HKEY_CLASSES_ROOT, filetype );
msi_free( filetype ); msi_free( filetype );
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS)
@ -1148,7 +1148,7 @@ UINT ACTION_UnregisterProgIdInfo( MSIPACKAGE *package )
} }
TRACE("Unregistering progid %s\n", debugstr_w(progid->ProgID)); 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) if (res != ERROR_SUCCESS)
TRACE("Failed to delete progid key %d\n", res); TRACE("Failed to delete progid key %d\n", res);
@ -1392,7 +1392,7 @@ UINT ACTION_UnregisterExtensionInfo( MSIPACKAGE *package )
{ {
extension[0] = '.'; extension[0] = '.';
strcpyW( extension + 1, ext->Extension ); strcpyW( extension + 1, ext->Extension );
res = SHDeleteKeyW( HKEY_CLASSES_ROOT, extension ); res = RegDeleteTreeW( HKEY_CLASSES_ROOT, extension );
msi_free( extension ); msi_free( extension );
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS)
WARN("Failed to delete extension key %d\n", res); WARN("Failed to delete extension key %d\n", res);
@ -1414,7 +1414,7 @@ UINT ACTION_UnregisterExtensionInfo( MSIPACKAGE *package )
{ {
strcpyW( progid_shell, progid ); strcpyW( progid_shell, progid );
strcatW( progid_shell, shellW ); strcatW( progid_shell, shellW );
res = SHDeleteKeyW( HKEY_CLASSES_ROOT, progid_shell ); res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid_shell );
msi_free( progid_shell ); msi_free( progid_shell );
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS)
WARN("Failed to delete shell key %d\n", res); WARN("Failed to delete shell key %d\n", res);

View file

@ -36,6 +36,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
#define IS_INTMSIDBOPEN(x) (((ULONG_PTR)(x) >> 16) == 0) #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 ) static void free_transforms( MSIDATABASE *db )
{ {
while( !list_empty( &db->transforms ) ) while( !list_empty( &db->transforms ) )
@ -763,6 +770,8 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
lstrcatW( path, file ); lstrcatW( path, file );
data = msi_read_text_archive( path, &len ); data = msi_read_text_archive( path, &len );
if (data == NULL)
return ERROR_BAD_PATHNAME;
ptr = data; ptr = data;
msi_parse_line( &ptr, &columns, &num_columns, &len ); msi_parse_line( &ptr, &columns, &num_columns, &len );
@ -901,50 +910,131 @@ end:
return r; 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; char *buffer;
BOOL bret;
DWORD sz; DWORD sz;
UINT r;
len = 0x100; sz = 0x100;
buffer = msi_alloc( len ); buffer = msi_alloc( sz );
if ( !buffer ) if (!buffer)
return ERROR_OUTOFMEMORY; return ERROR_OUTOFMEMORY;
count = MSI_RecordGetFieldCount( row ); r = MSI_RecordGetStringA( row, field, buffer, &sz );
for ( i=start; i<=count; i++ ) if (r == ERROR_MORE_DATA)
{ {
sz = len; char *p;
r = MSI_RecordGetStringA( row, i, buffer, &sz );
if (r == ERROR_MORE_DATA)
{
char *p = msi_realloc( buffer, sz + 1 );
if (!p)
break;
len = sz + 1;
buffer = p;
}
sz = len;
r = MSI_RecordGetStringA( row, i, buffer, &sz );
if (r != ERROR_SUCCESS)
break;
if (!WriteFile( handle, buffer, sz, &sz, NULL )) sz++; /* leave room for NULL terminator */
p = msi_realloc( buffer, sz );
if (!p)
{ {
r = ERROR_FUNCTION_FAILED; msi_free( buffer );
break; 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++)
{
r = msi_export_field( handle, row, i );
if (r == ERROR_INVALID_PARAMETER)
{
r = msi_export_stream( row_export_info->folder, row_export_info->table, row, i, start );
if (r != ERROR_SUCCESS)
return r;
/* 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"; sep = (i < count) ? "\t" : "\r\n";
if (!WriteFile( handle, sep, strlen(sep), &sz, NULL )) if (!WriteFile( handle, sep, strlen(sep), &sz, NULL ))
{ return ERROR_FUNCTION_FAILED;
r = ERROR_FUNCTION_FAILED;
break;
}
} }
msi_free( buffer );
return r; return r;
} }
@ -968,9 +1058,25 @@ static UINT msi_export_forcecodepage( HANDLE handle, UINT codepage )
return ERROR_SUCCESS; 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, static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
LPCWSTR folder, LPCWSTR file ) 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[] = { static const WCHAR query[] = {
's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','%','s',0 }; 's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','%','s',0 };
static const WCHAR forcecodepage[] = { static const WCHAR forcecodepage[] = {
@ -1009,14 +1115,22 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
goto done; goto done;
} }
if (!strcmpW( table, summaryinformation ))
{
r = msi_export_summaryinformation( db, handle );
goto done;
}
r = MSI_OpenQuery( db, &view, query, table ); r = MSI_OpenQuery( db, &view, query, table );
if (r == ERROR_SUCCESS) if (r == ERROR_SUCCESS)
{ {
struct row_export_info row_export_info = { handle, folder, table };
/* write out row 1, the column names */ /* write out row 1, the column names */
r = MSI_ViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); r = MSI_ViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
if (r == ERROR_SUCCESS) if (r == ERROR_SUCCESS)
{ {
msi_export_record( handle, rec, 1 ); msi_export_record( &row_export_info, rec, 1 );
msiobj_release( &rec->hdr ); msiobj_release( &rec->hdr );
} }
@ -1024,7 +1138,7 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
r = MSI_ViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); r = MSI_ViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
if (r == ERROR_SUCCESS) if (r == ERROR_SUCCESS)
{ {
msi_export_record( handle, rec, 1 ); msi_export_record( &row_export_info, rec, 1 );
msiobj_release( &rec->hdr ); msiobj_release( &rec->hdr );
} }
@ -1033,12 +1147,12 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
if (r == ERROR_SUCCESS) if (r == ERROR_SUCCESS)
{ {
MSI_RecordSetStringW( rec, 0, table ); MSI_RecordSetStringW( rec, 0, table );
msi_export_record( handle, rec, 0 ); msi_export_record( &row_export_info, rec, 0 );
msiobj_release( &rec->hdr ); msiobj_release( &rec->hdr );
} }
/* write out row 4 onwards, the data */ /* 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 ); msiobj_release( &view->hdr );
} }

View file

@ -2672,7 +2672,7 @@ static UINT msi_dialog_selection_tree( msi_dialog *dialog, MSIRECORD *rec )
/* create the treeview control */ /* create the treeview control */
style = TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT; 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 ); control = msi_dialog_add_control( dialog, rec, WC_TREEVIEWW, style );
if (!control) if (!control)
{ {
@ -3645,8 +3645,11 @@ static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs )
if (!dialog->default_font) if (!dialog->default_font)
{ {
dialog->default_font = strdupW(dfv); dialog->default_font = strdupW(dfv);
msiobj_release( &rec->hdr ); if (!dialog->default_font)
if (!dialog->default_font) return -1; {
msiobj_release( &rec->hdr );
return -1;
}
} }
title = msi_get_deformatted_field( dialog->package, rec, 7 ); title = msi_get_deformatted_field( dialog->package, rec, 7 );

View file

@ -4291,6 +4291,17 @@ UINT WINAPI MsiBeginTransactionW( LPCWSTR name, DWORD attrs, MSIHANDLE *id, HAND
return ERROR_SUCCESS; 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.@] * MsiEndTransaction [MSI.@]
*/ */

View file

@ -280,7 +280,7 @@
284 stdcall MsiBeginTransactionA(str long ptr ptr) 284 stdcall MsiBeginTransactionA(str long ptr ptr)
285 stdcall MsiBeginTransactionW(wstr long ptr ptr) 285 stdcall MsiBeginTransactionW(wstr long ptr ptr)
286 stdcall MsiEndTransaction(long) 286 stdcall MsiEndTransaction(long)
287 stub MsiJoinTransaction 287 stdcall MsiJoinTransaction(long long ptr)
288 stub MsiSetOfflineContextW 288 stub MsiSetOfflineContextW
289 stdcall MsiEnumComponentsExA(str long long ptr ptr ptr ptr) 289 stdcall MsiEnumComponentsExA(str long long ptr ptr ptr ptr)
290 stdcall MsiEnumComponentsExW(wstr long long ptr ptr ptr ptr) 290 stdcall MsiEnumComponentsExW(wstr long long ptr ptr ptr ptr)

View file

@ -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 INT msi_suminfo_get_int32( MSISUMMARYINFO *si, UINT uiProperty ) DECLSPEC_HIDDEN;
extern LPWSTR msi_get_suminfo_product( IStorage *stg ) 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_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 enum platform parse_platform( const WCHAR *str ) DECLSPEC_HIDDEN;
extern UINT msi_load_suminfo_properties( MSIPACKAGE *package ) DECLSPEC_HIDDEN; extern UINT msi_load_suminfo_properties( MSIPACKAGE *package ) DECLSPEC_HIDDEN;

View file

@ -335,7 +335,7 @@ UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec)
if ((type & MSI_DATASIZEMASK) == 2) if ((type & MSI_DATASIZEMASK) == 2)
MSI_RecordSetInteger(*rec, i, ival - (1<<15)); MSI_RecordSetInteger(*rec, i, ival - (1<<15));
else else
MSI_RecordSetInteger(*rec, i, ival - (1<<31)); MSI_RecordSetInteger(*rec, i, ival - (1u<<31));
} }
} }

View file

@ -2100,6 +2100,8 @@ UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName,
MSIRECORD *row; MSIRECORD *row;
UINT rc = ERROR_FUNCTION_FAILED; UINT rc = ERROR_FUNCTION_FAILED;
TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf);
row = msi_get_property_row( db, szName ); row = msi_get_property_row( db, szName );
if (*pchValueBuf > 0) if (*pchValueBuf > 0)

View file

@ -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','\\', '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}; '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[] = { static const WCHAR szUserFeatures[] = {
'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', '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}; '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); strcpyW(keypath, szUninstall);
strcatW(keypath, product); 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) 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); strcpyW(keypath, szUserProducts);
strcatW(keypath, squished_pc); 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) UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY *key, BOOL create)
@ -582,7 +586,7 @@ UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct)
strcpyW(keypath, szUserFeatures); strcpyW(keypath, szUserFeatures);
strcatW(keypath, squished_pc); 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) 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) UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY *key, BOOL create)
{ {
WCHAR squished_cc[GUID_SIZE], keypath[0x200]; WCHAR squished_cc[GUID_SIZE], keypath[0x200];
UINT ret;
if (!squash_guid(szComponent, squished_cc)) return ERROR_FUNCTION_FAILED; if (!squash_guid(szComponent, squished_cc)) return ERROR_FUNCTION_FAILED;
TRACE("%s squished %s\n", debugstr_w(szComponent), debugstr_w(squished_cc)); 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); strcatW(keypath, squished_cc);
if (create) return RegCreateKeyW(HKEY_CURRENT_USER, keypath, key); 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) 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); sprintfW(keypath, szUserDataComponents_fmt, szUserSid);
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS; if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS;
r = SHDeleteKeyW(hkey, comp); r = RegDeleteTreeW(hkey, comp);
RegCloseKey(hkey); RegCloseKey(hkey);
return r; return r;
} }
@ -777,7 +787,7 @@ UINT MSIREG_DeleteUserDataPatchKey(LPCWSTR patch, MSIINSTALLCONTEXT context)
LocalFree(usersid); LocalFree(usersid);
} }
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS; if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS;
r = SHDeleteKeyW(hkey, squished_patch); r = RegDeleteTreeW(hkey, squished_patch);
RegCloseKey(hkey); RegCloseKey(hkey);
return r; return r;
} }
@ -854,7 +864,7 @@ UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct)
LocalFree(usersid); LocalFree(usersid);
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS; if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS;
r = SHDeleteKeyW(hkey, squished_pc); r = RegDeleteTreeW(hkey, squished_pc);
RegCloseKey(hkey); RegCloseKey(hkey);
return r; return r;
} }
@ -870,7 +880,7 @@ UINT MSIREG_DeleteProductKey(LPCWSTR szProduct)
TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc)); 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; 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); RegCloseKey(hkey);
return r; return r;
} }
@ -927,7 +937,7 @@ UINT MSIREG_DeleteUserUpgradeCodesKey(LPCWSTR szUpgradeCode)
strcpyW(keypath, szInstaller_UserUpgradeCodes); strcpyW(keypath, szInstaller_UserUpgradeCodes);
strcatW(keypath, squished_pc); strcatW(keypath, squished_pc);
return SHDeleteKeyW(HKEY_CURRENT_USER, keypath); return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
} }
UINT MSIREG_DeleteLocalClassesProductKey(LPCWSTR szProductCode) 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)); 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; 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); RegCloseKey(hkey);
return r; return r;
} }
@ -957,7 +967,7 @@ UINT MSIREG_DeleteLocalClassesFeaturesKey(LPCWSTR szProductCode)
TRACE("%s squished %s\n", debugstr_w(szProductCode), debugstr_w(squished_pc)); 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; 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); RegCloseKey(hkey);
return r; return r;
} }
@ -988,7 +998,7 @@ UINT MSIREG_DeleteClassesUpgradeCodesKey(LPCWSTR szUpgradeCode)
TRACE("%s squished %s\n", debugstr_w(szUpgradeCode), debugstr_w(squished_pc)); 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; 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); RegCloseKey(hkey);
return r; return r;
} }

View file

@ -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) 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; return ERROR_SUCCESS;
} }
@ -293,12 +314,15 @@ static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRE
r = streams_modify_update(view, rec); r = streams_modify_update(view, rec);
break; break;
case MSIMODIFY_DELETE:
r = STREAMS_delete_row(view, row - 1);
break;
case MSIMODIFY_VALIDATE_NEW: case MSIMODIFY_VALIDATE_NEW:
case MSIMODIFY_INSERT_TEMPORARY: case MSIMODIFY_INSERT_TEMPORARY:
case MSIMODIFY_REFRESH: case MSIMODIFY_REFRESH:
case MSIMODIFY_REPLACE: case MSIMODIFY_REPLACE:
case MSIMODIFY_MERGE: case MSIMODIFY_MERGE:
case MSIMODIFY_DELETE:
case MSIMODIFY_VALIDATE: case MSIMODIFY_VALIDATE:
case MSIMODIFY_VALIDATE_FIELD: case MSIMODIFY_VALIDATE_FIELD:
case MSIMODIFY_VALIDATE_DELETE: case MSIMODIFY_VALIDATE_DELETE:

View file

@ -20,6 +20,7 @@
#include "msipriv.h" #include "msipriv.h"
#include <stdio.h>
#include <propvarutil.h> #include <propvarutil.h>
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -999,6 +1000,117 @@ end:
return r; 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 ) UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE handle )
{ {
MSISUMMARYINFO *si; MSISUMMARYINFO *si;

View file

@ -792,7 +792,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
/* add each column to the _Columns table */ /* add each column to the _Columns table */
r = TABLE_CreateView( db, szColumns, &tv ); r = TABLE_CreateView( db, szColumns, &tv );
if( r ) if( r )
return r; goto err;
r = tv->ops->execute( tv, 0 ); r = tv->ops->execute( tv, 0 );
TRACE("tv execute returned %x\n", r); 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, static MSIRECORD *msi_get_transform_record( const MSITABLEVIEW *tv, const string_table *st,
IStorage *stg, IStorage *stg, const BYTE *rawdata, UINT bytes_per_strref )
const BYTE *rawdata, UINT bytes_per_strref )
{ {
UINT i, val, ofs = 0; UINT i, val, ofs = 0;
USHORT mask; 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 ); r = msi_record_encoded_stream_name( tv, rec, &encname );
if ( r != ERROR_SUCCESS ) if ( r != ERROR_SUCCESS )
{
msiobj_release( &rec->hdr );
return NULL; return NULL;
}
r = IStorage_OpenStream( stg, encname, NULL, r = IStorage_OpenStream( stg, encname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm );
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm );
if ( r != ERROR_SUCCESS ) if ( r != ERROR_SUCCESS )
{ {
msiobj_release( &rec->hdr );
msi_free( encname ); msi_free( encname );
return NULL; return NULL;
} }

View file

@ -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/msgsm32.acm # Synced to WineStaging-1.7.47
reactos/dll/win32/mshtml # Synced to WineStaging-1.7.37 reactos/dll/win32/mshtml # Synced to WineStaging-1.7.37
reactos/dll/win32/mshtml.tlb # Synced to WineStaging-1.7.47 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/msimg32 # Synced to WineStaging-1.7.47
reactos/dll/win32/msimtf # 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 reactos/dll/win32/msisip # Synced to WineStaging-1.7.47