Author: akhaldi Date: Sat Nov 21 16:44:38 2015 New Revision: 69995
URL: http://svn.reactos.org/svn/reactos?rev=69995&view=rev Log: [MSI] Sync with Wine Staging 1.7.55. CORE-10536
Modified: trunk/reactos/dll/win32/msi/CMakeLists.txt trunk/reactos/dll/win32/msi/action.c trunk/reactos/dll/win32/msi/automation.c trunk/reactos/dll/win32/msi/classes.c trunk/reactos/dll/win32/msi/database.c trunk/reactos/dll/win32/msi/dialog.c trunk/reactos/dll/win32/msi/msi.c trunk/reactos/dll/win32/msi/msi.spec trunk/reactos/dll/win32/msi/msipriv.h trunk/reactos/dll/win32/msi/msiquery.c trunk/reactos/dll/win32/msi/package.c trunk/reactos/dll/win32/msi/registry.c trunk/reactos/dll/win32/msi/streams.c trunk/reactos/dll/win32/msi/suminfo.c trunk/reactos/dll/win32/msi/table.c trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/dll/win32/msi/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/CMakeLists.tx... ============================================================================== --- trunk/reactos/dll/win32/msi/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/CMakeLists.txt [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -65,7 +65,7 @@ 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
Modified: trunk/reactos/dll/win32/msi/action.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/action.c?rev=... ============================================================================== --- trunk/reactos/dll/win32/msi/action.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/action.c [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -239,8 +239,7 @@ len++; break; default: - if (!count) in_quotes = FALSE; - else in_quotes = TRUE; + if (count) in_quotes = TRUE; len++; break; } @@ -261,8 +260,7 @@ 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 @@ default: break; } if (!ignore) *out++ = *p; + if (!count) in_quotes = FALSE; }
done: @@ -313,7 +312,7 @@
ptr2 = strchrW( ptr, '=' ); if (!ptr2) return ERROR_INVALID_COMMAND_LINE; - + len = ptr2 - ptr; if (!len) return ERROR_INVALID_COMMAND_LINE;
@@ -2362,6 +2361,18 @@ 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 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 @@ 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 @@ 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 @@ 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 @@ return view; }
-static HKEY open_key( const MSICOMPONENT *comp, HKEY root, const WCHAR *path, BOOL create ) -{ - REGSAM access = KEY_ALL_ACCESS; +static HKEY open_key( const MSICOMPONENT *comp, HKEY root, const WCHAR *path, BOOL create, REGSAM access ) +{ WCHAR *subkey, *p, *q; HKEY hkey, ret = NULL; LONG res; @@ -2641,7 +2665,7 @@ } 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 @@ 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 @@ access |= get_registry_view( comp );
if (!(subkey = strdupW( path ))) return; - for (;;) - { - if ((p = strrchrW( subkey, '\' ))) *p = 0; - hkey = open_key( comp, root, subkey, FALSE ); - if (!hkey) break; - if (p && p[1]) + do + { + if ((p = strrchrW( subkey, '\' ))) + { + *p = 0; + if (!p[1]) continue; /* trailing backslash */ + hkey = open_key( comp, root, subkey, FALSE, access ); + if (!hkey) break; res = RegDeleteKeyExW( hkey, p + 1, access, 0 ); + RegCloseKey( hkey ); + } else res = RegDeleteKeyExW( root, subkey, access, 0 ); if (res) @@ -2971,9 +2999,7 @@ 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 @@ 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 @@ 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 @@ 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 @@
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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ goto done; }
- size = (lstrlenW(data) + 1) * sizeof(WCHAR); - if (flags & ENV_MOD_MASK) - { - 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); - } - - newval = msi_alloc(size); - ptr = newval; - if (!newval) + for (;;) + { + 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; + } + + 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 @@
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 @@ { 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 @@ 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 @@ if (flags & ENV_MOD_MACHINE) action |= 0x20000000;
- TRACE("Removing %s\n", debugstr_w(name)); - - res = RegDeleteValueW( env, 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) - { - WARN("Failed to delete value %s (%d)\n", debugstr_w(name), res); - r = 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 + { + 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 @@
if (env) RegCloseKey( env ); msi_free( deformatted ); + msi_free( new_value ); return r; }
Modified: trunk/reactos/dll/win32/msi/automation.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/automation.c?... ============================================================================== --- trunk/reactos/dll/win32/msi/automation.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/automation.c [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -1421,7 +1421,7 @@ 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 @@ 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(pVarResult); + VariantInit(&varg1); + hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr); + if (FAILED(hr)) + return hr; + + 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 @@ /* 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. */
Modified: trunk/reactos/dll/win32/msi/classes.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/classes.c?rev... ============================================================================== --- trunk/reactos/dll/win32/msi/classes.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/classes.c [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -953,7 +953,7 @@
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 @@ { 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 @@ } 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 @@ { 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 @@ { 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);
Modified: trunk/reactos/dll/win32/msi/database.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/database.c?re... ============================================================================== --- trunk/reactos/dll/win32/msi/database.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/database.c [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -35,6 +35,13 @@ */
#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 ) { @@ -763,6 +770,8 @@ 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 @@ return r; }
-static UINT msi_export_record( HANDLE handle, MSIRECORD *row, UINT start ) -{ - UINT i, count, len, r = ERROR_SUCCESS; +static UINT msi_export_field( HANDLE handle, MSIRECORD *row, UINT field ) +{ + char *buffer; + BOOL bret; + DWORD sz; + UINT r; + + 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; - char *buffer; DWORD sz;
- len = 0x100; - buffer = msi_alloc( len ); - if ( !buffer ) - return ERROR_OUTOFMEMORY; - count = MSI_RecordGetFieldCount( row ); - for ( i=start; i<=count; i++ ) - { - sz = len; - 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 )) - { - r = ERROR_FUNCTION_FAILED; - break; - } + 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"; if (!WriteFile( handle, sep, strlen(sep), &sz, NULL )) - { - r = ERROR_FUNCTION_FAILED; - break; - } - } - msi_free( buffer ); + return ERROR_FUNCTION_FAILED; + } return r; }
@@ -968,9 +1058,25 @@ 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 @@ 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 @@ 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 @@ 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 ); }
Modified: trunk/reactos/dll/win32/msi/dialog.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/dialog.c?rev=... ============================================================================== --- trunk/reactos/dll/win32/msi/dialog.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/dialog.c [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -2672,7 +2672,7 @@
/* 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 @@ if (!dialog->default_font) { dialog->default_font = strdupW(dfv); - msiobj_release( &rec->hdr ); - if (!dialog->default_font) return -1; + if (!dialog->default_font) + { + msiobj_release( &rec->hdr ); + return -1; + } }
title = msi_get_deformatted_field( dialog->package, rec, 7 );
Modified: trunk/reactos/dll/win32/msi/msi.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msi.c?rev=699... ============================================================================== --- trunk/reactos/dll/win32/msi/msi.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/msi.c [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -4292,6 +4292,17 @@ }
/*********************************************************************** + * 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.@] */ UINT WINAPI MsiEndTransaction( DWORD state )
Modified: trunk/reactos/dll/win32/msi/msi.spec URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msi.spec?rev=... ============================================================================== --- trunk/reactos/dll/win32/msi/msi.spec [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/msi.spec [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -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)
Modified: trunk/reactos/dll/win32/msi/msipriv.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msipriv.h?rev... ============================================================================== --- trunk/reactos/dll/win32/msi/msipriv.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/msipriv.h [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -968,6 +968,7 @@ 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;
Modified: trunk/reactos/dll/win32/msi/msiquery.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msiquery.c?re... ============================================================================== --- trunk/reactos/dll/win32/msi/msiquery.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/msiquery.c [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -335,7 +335,7 @@ 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)); } }
Modified: trunk/reactos/dll/win32/msi/package.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/package.c?rev... ============================================================================== --- trunk/reactos/dll/win32/msi/package.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/package.c [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -2100,6 +2100,8 @@ 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)
Modified: trunk/reactos/dll/win32/msi/registry.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/registry.c?re... ============================================================================== --- trunk/reactos/dll/win32/msi/registry.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/registry.c [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -157,6 +157,10 @@ '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 @@ 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 @@
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 @@
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_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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@
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 @@ 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 @@ 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 @@ 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; }
Modified: trunk/reactos/dll/win32/msi/streams.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/streams.c?rev... ============================================================================== --- trunk/reactos/dll/win32/msi/streams.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/streams.c [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -194,7 +194,28 @@
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; }
@@ -291,6 +312,10 @@
case MSIMODIFY_UPDATE: r = streams_modify_update(view, rec); + break; + + case MSIMODIFY_DELETE: + r = STREAMS_delete_row(view, row - 1); break;
case MSIMODIFY_VALIDATE_NEW: @@ -298,7 +323,6 @@ case MSIMODIFY_REFRESH: case MSIMODIFY_REPLACE: case MSIMODIFY_MERGE: - case MSIMODIFY_DELETE: case MSIMODIFY_VALIDATE: case MSIMODIFY_VALIDATE_FIELD: case MSIMODIFY_VALIDATE_DELETE:
Modified: trunk/reactos/dll/win32/msi/suminfo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/suminfo.c?rev... ============================================================================== --- trunk/reactos/dll/win32/msi/suminfo.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/suminfo.c [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -20,6 +20,7 @@
#include "msipriv.h"
+#include <stdio.h> #include <propvarutil.h>
WINE_DEFAULT_DEBUG_CHANNEL(msi); @@ -999,6 +1000,117 @@ 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;
Modified: trunk/reactos/dll/win32/msi/table.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/table.c?rev=6... ============================================================================== --- trunk/reactos/dll/win32/msi/table.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msi/table.c [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -792,7 +792,7 @@ /* 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 @@ }
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 @@
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; }
Modified: trunk/reactos/media/doc/README.WINE URL: http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=6... ============================================================================== --- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original) +++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Sat Nov 21 16:44:38 2015 @@ -115,7 +115,7 @@ 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