From 13d789dd5020fc5897665076af442b788225d37b Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sun, 9 Dec 2012 19:43:59 +0000 Subject: [PATCH] [MSI]: Sync to Wine 1.5.19. svn path=/trunk/; revision=57851 --- reactos/dll/win32/msi/action.c | 448 +++++++++++++++++++++-------- reactos/dll/win32/msi/appsearch.c | 4 +- reactos/dll/win32/msi/automation.c | 264 ++++++++++------- reactos/dll/win32/msi/custom.c | 36 +-- reactos/dll/win32/msi/database.c | 2 +- reactos/dll/win32/msi/dialog.c | 8 +- reactos/dll/win32/msi/events.c | 10 +- reactos/dll/win32/msi/files.c | 13 +- reactos/dll/win32/msi/format.c | 298 +++++++++---------- reactos/dll/win32/msi/install.c | 46 ++- reactos/dll/win32/msi/msi.c | 36 ++- reactos/dll/win32/msi/msi_main.c | 1 + reactos/dll/win32/msi/msipriv.h | 28 +- reactos/dll/win32/msi/msiquery.c | 7 +- reactos/dll/win32/msi/package.c | 232 +++++++-------- reactos/dll/win32/msi/patch.c | 2 +- reactos/dll/win32/msi/record.c | 130 +++++---- reactos/dll/win32/msi/registry.c | 7 +- reactos/dll/win32/msi/script.c | 373 ++++++++++++------------ reactos/dll/win32/msi/select.c | 7 +- reactos/dll/win32/msi/source.c | 3 + reactos/dll/win32/msi/storages.c | 2 +- reactos/dll/win32/msi/streams.c | 2 +- reactos/dll/win32/msi/string.c | 92 +++--- reactos/dll/win32/msi/table.c | 69 +++-- reactos/dll/win32/msi/tokenize.c | 169 +++++------ reactos/dll/win32/msi/upgrade.c | 2 +- reactos/dll/win32/msi/where.c | 6 +- reactos/media/doc/README.WINE | 2 +- 29 files changed, 1315 insertions(+), 984 deletions(-) diff --git a/reactos/dll/win32/msi/action.c b/reactos/dll/win32/msi/action.c index 1ad3bc2b26e..076d1b3775d 100644 --- a/reactos/dll/win32/msi/action.c +++ b/reactos/dll/win32/msi/action.c @@ -353,7 +353,7 @@ UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine, remove_quotes( val ); TRACE("Found commandline property %s = %s\n", debugstr_w(prop), debugstr_w(val)); - r = msi_set_property( package->db, prop, val ); + r = msi_set_property( package->db, prop, val, -1 ); if (r == ERROR_SUCCESS && !strcmpW( prop, szSourceDir )) msi_reset_folders( package, TRUE ); @@ -462,7 +462,7 @@ UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace) check = msi_dup_property( package->db, szSourceDir ); if (!check || replace) { - UINT r = msi_set_property( package->db, szSourceDir, source ); + UINT r = msi_set_property( package->db, szSourceDir, source, -1 ); if (r == ERROR_SUCCESS) msi_reset_folders( package, TRUE ); } @@ -470,7 +470,7 @@ UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace) check = msi_dup_property( package->db, szSOURCEDIR ); if (!check || replace) - msi_set_property( package->db, szSOURCEDIR, source ); + msi_set_property( package->db, szSOURCEDIR, source, -1 ); msi_free( check ); msi_free( source ); @@ -605,7 +605,7 @@ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran) { TRACE("Running the actions\n"); - msi_set_property(package->db, szSourceDir, NULL); + msi_set_property( package->db, szSourceDir, NULL, -1 ); rc = MSI_IterateRecords(view, NULL, ITERATE_Actions, package); msiobj_release(&view->hdr); } @@ -809,6 +809,11 @@ INSTALLSTATE msi_get_component_action( MSIPACKAGE *package, MSICOMPONENT *comp ) return INSTALLSTATE_UNKNOWN; } if (package->need_rollback) return comp->Installed; + if (comp->num_clients > 0 && comp->ActionRequest == INSTALLSTATE_ABSENT) + { + TRACE("%s has %u clients left\n", debugstr_w(comp->Component), comp->num_clients); + return INSTALLSTATE_UNKNOWN; + } return comp->ActionRequest; } @@ -1563,8 +1568,8 @@ static UINT load_all_folders( MSIPACKAGE *package ) static UINT ACTION_CostInitialize(MSIPACKAGE *package) { - msi_set_property( package->db, szCostingComplete, szZero ); - msi_set_property( package->db, szRootDrive, szCRoot ); + msi_set_property( package->db, szCostingComplete, szZero, -1 ); + msi_set_property( package->db, szRootDrive, szCRoot, -1 ); load_all_folders( package ); msi_load_all_components( package ); @@ -1620,6 +1625,27 @@ static UINT ACTION_FileCost(MSIPACKAGE *package) return ERROR_SUCCESS; } +static void get_client_counts( MSIPACKAGE *package ) +{ + MSICOMPONENT *comp; + HKEY hkey; + + LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry ) + { + if (!comp->ComponentId) continue; + + if (MSIREG_OpenUserDataComponentKey( comp->ComponentId, szLocalSid, &hkey, FALSE ) && + MSIREG_OpenUserDataComponentKey( comp->ComponentId, NULL, &hkey, FALSE )) + { + comp->num_clients = 0; + continue; + } + RegQueryInfoKeyW( hkey, NULL, NULL, NULL, NULL, NULL, NULL, (DWORD *)&comp->num_clients, + NULL, NULL, NULL, NULL ); + RegCloseKey( hkey ); + } +} + static void ACTION_GetComponentInstallStates(MSIPACKAGE *package) { MSICOMPONENT *comp; @@ -1759,7 +1785,7 @@ static BOOL process_overrides( MSIPACKAGE *package, int level ) ret |= process_state_property( package, level, szAdvertise, INSTALLSTATE_ADVERTISED ); if (ret) - msi_set_property( package->db, szPreselected, szOne ); + msi_set_property( package->db, szPreselected, szOne, -1 ); return ret; } @@ -1956,8 +1982,7 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package) continue; } TRACE("nobody wants component %s\n", debugstr_w(component->Component)); - if (component->anyAbsent && - (component->Installed == INSTALLSTATE_LOCAL || component->Installed == INSTALLSTATE_SOURCE)) + if (component->anyAbsent && component->ComponentId) { component->Action = INSTALLSTATE_ABSENT; component->ActionRequest = INSTALLSTATE_ABSENT; @@ -1983,6 +2008,11 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package) TRACE("component %s (installed %d request %d action %d)\n", debugstr_w(component->Component), component->Installed, component->ActionRequest, component->Action); + + if (component->Action == INSTALLSTATE_LOCAL || component->Action == INSTALLSTATE_SOURCE) + component->num_clients++; + else if (component->Action == INSTALLSTATE_ABSENT) + component->num_clients--; } return ERROR_SUCCESS; @@ -2154,7 +2184,7 @@ WCHAR *msi_build_directory_name( DWORD count, ... ) const WCHAR *str = va_arg( va, const WCHAR * ); if (!str) continue; strcatW( dir, str ); - if ( i + 1 != count && dir[strlenW( dir ) - 1] != '\\') strcatW( dir, szBackSlash ); + if ( i + 1 != count && dir[0] && dir[strlenW( dir ) - 1] != '\\') strcatW( dir, szBackSlash ); } va_end( va ); return dir; @@ -2281,6 +2311,19 @@ WCHAR *msi_normalize_path( const WCHAR *in ) return ret; } +static WCHAR *get_install_location( MSIPACKAGE *package ) +{ + HKEY hkey; + WCHAR *path; + + if (!package->ProductCode) return NULL; + if (MSIREG_OpenInstallProps( package->ProductCode, package->Context, NULL, &hkey, FALSE )) + return NULL; + path = msi_reg_get_val_str( hkey, szInstallLocation ); + RegCloseKey( hkey ); + return path; +} + void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL load_prop ) { FolderList *fl; @@ -2293,7 +2336,8 @@ void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL loa if (!strcmpW( folder->Directory, szTargetDir )) /* special resolving for target root dir */ { - if (!load_prop || !(path = msi_dup_property( package->db, szTargetDir ))) + if (!(path = get_install_location( package )) && + (!load_prop || !(path = msi_dup_property( package->db, szTargetDir )))) { path = msi_dup_property( package->db, szRootDrive ); } @@ -2316,7 +2360,7 @@ void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL loa msi_free( normalized_path ); return; } - msi_set_property( package->db, folder->Directory, normalized_path ); + msi_set_property( package->db, folder->Directory, normalized_path, -1 ); msi_free( folder->ResolvedTarget ); folder->ResolvedTarget = normalized_path; @@ -2354,6 +2398,7 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package) else comp->Enabled = TRUE; } + get_client_counts( package ); /* read components states from the registry */ ACTION_GetComponentInstallStates(package); @@ -2376,28 +2421,28 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package) TRACE("Calculating file cost\n"); calculate_file_cost( package ); - msi_set_property( package->db, szCostingComplete, szOne ); + msi_set_property( package->db, szCostingComplete, szOne, -1 ); /* set default run level if not set */ level = msi_dup_property( package->db, szInstallLevel ); if (!level) - msi_set_property( package->db, szInstallLevel, szOne ); + msi_set_property( package->db, szInstallLevel, szOne, -1 ); msi_free(level); /* FIXME: check volume disk space */ - msi_set_property( package->db, szOutOfDiskSpace, szZero ); + msi_set_property( package->db, szOutOfDiskSpace, szZero, -1 ); return MSI_SetFeatureStates(package); } -static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type, DWORD *size) +static BYTE *parse_value( MSIPACKAGE *package, const WCHAR *value, DWORD *type, DWORD *size ) { - LPSTR data = NULL; + BYTE *data = NULL; if (!value) { - data = (LPSTR)strdupW(szEmpty); - *size = sizeof(szEmpty); + *size = sizeof(WCHAR); *type = REG_SZ; + if ((data = msi_alloc( *size ))) *(WCHAR *)data = 0; return data; } if (value[0]=='#' && value[1]!='#' && value[1]!='%') @@ -2479,38 +2524,22 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type, DWORD } else { - static const WCHAR szMulti[] = {'[','~',']',0}; - LPCWSTR ptr; - *type=REG_SZ; + const WCHAR *ptr = value; + DWORD len; - if (value[0]=='#') + *type = REG_SZ; + if (value[0] == '#') { - if (value[1]=='%') + ptr++; + if (value[1] == '%') { - ptr = &value[2]; - *type=REG_EXPAND_SZ; + ptr++; + *type = REG_EXPAND_SZ; } - else - ptr = &value[1]; - } - else - ptr=value; - - if (strstrW(value, szMulti)) - *type = REG_MULTI_SZ; - - /* remove initial delimiter */ - if (!strncmpW(value, szMulti, 3)) - ptr = value + 3; - - *size = deformat_string(package, ptr,(LPWSTR*)&data); - - /* add double NULL terminator */ - if (*type == REG_MULTI_SZ) - { - *size += 2 * sizeof(WCHAR); /* two NULL terminators */ - data = msi_realloc_zero(data, *size); } + len = deformat_string( package, ptr, (WCHAR **)&data ); + if (len > strlenW( (const WCHAR *)data )) *type = REG_MULTI_SZ; + *size = (len + 1) * sizeof(WCHAR); } return data; } @@ -2618,19 +2647,181 @@ static BOOL is_special_entry( const WCHAR *name ) return (name && (name[0] == '*' || name[0] == '+') && !name[1]); } +static WCHAR **split_multi_string_values( const WCHAR *str, DWORD len, DWORD *count ) +{ + const WCHAR *p = str; + WCHAR **ret; + int i = 0; + + *count = 0; + if (!str) return NULL; + while ((p - str) < len) + { + p += strlenW( p ) + 1; + (*count)++; + } + if (!(ret = msi_alloc( *count * sizeof(WCHAR *) ))) return NULL; + p = str; + while ((p - str) < len) + { + if (!(ret[i] = strdupW( p ))) + { + for (; i >= 0; i--) msi_free( ret[i] ); + msi_free( ret ); + return NULL; + } + p += strlenW( p ) + 1; + i++; + } + return ret; +} + +static WCHAR *flatten_multi_string_values( WCHAR **left, DWORD left_count, + WCHAR **right, DWORD right_count, DWORD *size ) +{ + WCHAR *ret, *p; + unsigned int i; + + *size = sizeof(WCHAR); + for (i = 0; i < left_count; i++) *size += (strlenW( left[i] ) + 1) * sizeof(WCHAR); + for (i = 0; i < right_count; i++) *size += (strlenW( right[i] ) + 1) * sizeof(WCHAR); + + if (!(ret = p = msi_alloc( *size ))) return NULL; + + for (i = 0; i < left_count; i++) + { + strcpyW( p, left[i] ); + p += strlenW( p ) + 1; + } + for (i = 0; i < right_count; i++) + { + strcpyW( p, right[i] ); + p += strlenW( p ) + 1; + } + *p = 0; + return ret; +} + +static DWORD remove_duplicate_values( WCHAR **old, DWORD old_count, + WCHAR **new, DWORD new_count ) +{ + DWORD ret = old_count; + unsigned int i, j, k; + + for (i = 0; i < new_count; i++) + { + for (j = 0; j < old_count; j++) + { + if (old[j] && !strcmpW( new[i], old[j] )) + { + msi_free( old[j] ); + for (k = j; k < old_count - 1; k++) { old[k] = old[k + 1]; } + old[k] = NULL; + ret--; + } + } + } + return ret; +} + +enum join_op +{ + JOIN_OP_APPEND, + JOIN_OP_PREPEND, + JOIN_OP_REPLACE +}; + +static WCHAR *join_multi_string_values( enum join_op op, WCHAR **old, DWORD old_count, + WCHAR **new, DWORD new_count, DWORD *size ) +{ + switch (op) + { + case JOIN_OP_APPEND: + old_count = remove_duplicate_values( old, old_count, new, new_count ); + return flatten_multi_string_values( old, old_count, new, new_count, size ); + + case JOIN_OP_PREPEND: + old_count = remove_duplicate_values( old, old_count, new, new_count ); + return flatten_multi_string_values( new, new_count, old, old_count, size ); + + case JOIN_OP_REPLACE: + return flatten_multi_string_values( new, new_count, NULL, 0, size ); + + default: + ERR("unhandled join op %u\n", op); + return NULL; + } +} + +static BYTE *build_multi_string_value( BYTE *old_value, DWORD old_size, + BYTE *new_value, DWORD new_size, DWORD *size ) +{ + DWORD i, old_len = 0, new_len = 0, old_count = 0, new_count = 0; + const WCHAR *new_ptr = NULL, *old_ptr = NULL; + enum join_op op = JOIN_OP_REPLACE; + WCHAR **old = NULL, **new = NULL; + BYTE *ret; + + if (new_size / sizeof(WCHAR) - 1 > 1) + { + new_ptr = (const WCHAR *)new_value; + new_len = new_size / sizeof(WCHAR) - 1; + + if (!new_ptr[0] && new_ptr[new_len - 1]) + { + op = JOIN_OP_APPEND; + new_len--; + new_ptr++; + } + else if (new_ptr[0] && !new_ptr[new_len - 1]) + { + op = JOIN_OP_PREPEND; + new_len--; + } + else if (new_len > 2 && !new_ptr[0] && !new_ptr[new_len - 1]) + { + op = JOIN_OP_REPLACE; + new_len -= 2; + new_ptr++; + } + new = split_multi_string_values( new_ptr, new_len, &new_count ); + } + if (old_size / sizeof(WCHAR) - 1 > 1) + { + old_ptr = (const WCHAR *)old_value; + old_len = old_size / sizeof(WCHAR) - 1; + old = split_multi_string_values( old_ptr, old_len, &old_count ); + } + ret = (BYTE *)join_multi_string_values( op, old, old_count, new, new_count, size ); + for (i = 0; i < old_count; i++) msi_free( old[i] ); + for (i = 0; i < new_count; i++) msi_free( new[i] ); + msi_free( old ); + msi_free( new ); + return ret; +} + +static BYTE *reg_get_value( HKEY hkey, const WCHAR *name, DWORD *type, DWORD *size ) +{ + BYTE *ret; + if (RegQueryValueExW( hkey, name, NULL, NULL, NULL, size )) return NULL; + if (!(ret = msi_alloc( *size ))) return NULL; + RegQueryValueExW( hkey, name, NULL, type, ret, size ); + return ret; +} + static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param) { MSIPACKAGE *package = param; - LPSTR value; + BYTE *new_value, *old_value = NULL; HKEY root_key, hkey; - DWORD type,size; + DWORD type, old_type, new_size, old_size = 0; LPWSTR deformated, uikey, keypath; - LPCWSTR szRoot, component, name, key; + const WCHAR *szRoot, *component, *name, *key, *str; MSICOMPONENT *comp; MSIRECORD * uirow; INT root; BOOL check_first = FALSE; - UINT rc; + int len; msi_ui_progress( package, 2, REG_PROGRESS_VALUE, 0, 0 ); @@ -2664,8 +2855,7 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param) return ERROR_SUCCESS; deformat_string(package, key , &deformated); - size = strlenW(deformated) + strlenW(szRoot) + 1; - uikey = msi_alloc(size*sizeof(WCHAR)); + uikey = msi_alloc( (strlenW(deformated) + strlenW(szRoot) + 1) * sizeof(WCHAR) ); strcpyW(uikey,szRoot); strcatW(uikey,deformated); @@ -2678,34 +2868,46 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param) msi_free(keypath); return ERROR_FUNCTION_FAILED; } - value = parse_value(package, MSI_RecordGetString(row, 5), &type, &size); + str = msi_record_get_string( row, 5, &len ); + if (str && len > strlenW( str )) + { + type = REG_MULTI_SZ; + new_size = (len + 1) * sizeof(WCHAR); + new_value = (BYTE *)msi_strdupW( str, len ); + } + else new_value = parse_value( package, str, &type, &new_size ); deformat_string(package, name, &deformated); if (!is_special_entry( name )) { + old_value = reg_get_value( hkey, deformated, &old_type, &old_size ); + if (type == REG_MULTI_SZ) + { + BYTE *new; + if (old_value && old_type != REG_MULTI_SZ) + { + msi_free( old_value ); + old_value = NULL; + old_size = 0; + } + new = build_multi_string_value( old_value, old_size, new_value, new_size, &new_size ); + msi_free( new_value ); + new_value = new; + } if (!check_first) { - TRACE("Setting value %s of %s\n", debugstr_w(deformated), - debugstr_w(uikey)); - RegSetValueExW(hkey, deformated, 0, type, (LPBYTE)value, size); + TRACE("setting value %s of %s type %u\n", debugstr_w(deformated), debugstr_w(uikey), type); + RegSetValueExW( hkey, deformated, 0, type, new_value, new_size ); } - else + else if (!old_value) { - DWORD sz = 0; - rc = RegQueryValueExW(hkey, deformated, NULL, NULL, NULL, &sz); - if (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA) + if (deformated || new_size) { - TRACE("value %s of %s checked already exists\n", debugstr_w(deformated), - debugstr_w(uikey)); - } - else - { - TRACE("Checked and setting value %s of %s\n", debugstr_w(deformated), - debugstr_w(uikey)); - if (deformated || size) - RegSetValueExW(hkey, deformated, 0, type, (LPBYTE)value, size); + TRACE("setting value %s of %s type %u\n", debugstr_w(deformated), debugstr_w(uikey), type); + RegSetValueExW( hkey, deformated, 0, type, new_value, new_size ); } } + else TRACE("not overwriting existing value %s of %s\n", debugstr_w(deformated), debugstr_w(uikey)); } RegCloseKey(hkey); @@ -2713,11 +2915,12 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param) MSI_RecordSetStringW(uirow,2,deformated); MSI_RecordSetStringW(uirow,1,uikey); if (type == REG_SZ || type == REG_EXPAND_SZ) - MSI_RecordSetStringW(uirow, 3, (LPWSTR)value); + MSI_RecordSetStringW(uirow, 3, (LPWSTR)new_value); msi_ui_actiondata( package, szWriteRegistryValues, uirow ); msiobj_release( &uirow->hdr ); - msi_free(value); + msi_free(new_value); + msi_free(old_value); msi_free(deformated); msi_free(uikey); msi_free(keypath); @@ -3293,9 +3496,9 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package) if (package->need_rollback) action = comp->Installed; else action = comp->ActionRequest; - TRACE("Component %s (%s), Keypath=%s, RefCount=%u Action=%u\n", + TRACE("Component %s (%s) Keypath=%s RefCount=%u Clients=%u Action=%u\n", debugstr_w(comp->Component), debugstr_w(squished_cc), - debugstr_w(comp->FullKeypath), comp->RefCount, action); + debugstr_w(comp->FullKeypath), comp->RefCount, comp->num_clients, action); if (action == INSTALLSTATE_LOCAL || action == INSTALLSTATE_SOURCE) { @@ -3358,10 +3561,13 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package) } else if (action == INSTALLSTATE_ABSENT) { - if (package->Context == MSIINSTALLCONTEXT_MACHINE) - MSIREG_DeleteUserDataComponentKey(comp->ComponentId, szLocalSid); - else - MSIREG_DeleteUserDataComponentKey(comp->ComponentId, NULL); + if (comp->num_clients <= 0) + { + if (package->Context == MSIINSTALLCONTEXT_MACHINE) + MSIREG_DeleteUserDataComponentKey( comp->ComponentId, szLocalSid ); + else + MSIREG_DeleteUserDataComponentKey( comp->ComponentId, NULL ); + } } /* UI stuff */ @@ -4514,27 +4720,27 @@ static UINT ACTION_RemoveIniValues( MSIPACKAGE *package ) static void register_dll( const WCHAR *dll, BOOL unregister ) { - HMODULE hmod; + static const WCHAR regW[] = + {'r','e','g','s','v','r','3','2','.','e','x','e',' ','\"','%','s','\"',0}; + static const WCHAR unregW[] = + {'r','e','g','s','v','r','3','2','.','e','x','e',' ','/','u',' ','\"','%','s','\"',0}; + PROCESS_INFORMATION pi; + STARTUPINFOW si; + WCHAR *cmd; - hmod = LoadLibraryExW( dll, 0, LOAD_WITH_ALTERED_SEARCH_PATH ); - if (hmod) - { - HRESULT (WINAPI *func_ptr)( void ); - const char *func = unregister ? "DllUnregisterServer" : "DllRegisterServer"; + if (!(cmd = msi_alloc( strlenW(dll) * sizeof(WCHAR) + sizeof(unregW) ))) return; - func_ptr = (void *)GetProcAddress( hmod, func ); - if (func_ptr) - { - HRESULT hr = func_ptr(); - if (FAILED( hr )) - WARN("failed to register dll 0x%08x\n", hr); - } - else - WARN("entry point %s not found\n", func); - FreeLibrary( hmod ); - return; + if (unregister) sprintfW( cmd, unregW, dll ); + else sprintfW( cmd, regW, dll ); + + memset( &si, 0, sizeof(STARTUPINFOW) ); + if (CreateProcessW( NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi )) + { + CloseHandle( pi.hThread ); + msi_dialog_check_messages( pi.hProcess ); + CloseHandle( pi.hProcess ); } - WARN("failed to load library %u\n", GetLastError()); + msi_free( cmd ); } static UINT ITERATE_SelfRegModules(MSIRECORD *row, LPVOID param) @@ -4837,8 +5043,6 @@ static UINT msi_publish_install_properties(MSIPACKAGE *package, HKEY hkey) {'H','e','l','p','T','e','l','e','p','h','o','n','e',0}; static const WCHAR szARPINSTALLLOCATION[] = {'A','R','P','I','N','S','T','A','L','L','L','O','C','A','T','I','O','N',0}; - static const WCHAR szInstallLocation[] = - {'I','n','s','t','a','l','l','L','o','c','a','t','i','o','n',0}; static const WCHAR szManufacturer[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0}; static const WCHAR szPublisher[] = @@ -4896,7 +5100,7 @@ static UINT msi_publish_install_properties(MSIPACKAGE *package, HKEY hkey) { msi_reg_set_val_dword( hkey, szSystemComponent, 1 ); } - size = deformat_string(package, modpath_fmt, &buffer); + size = deformat_string(package, modpath_fmt, &buffer) * sizeof(WCHAR); RegSetValueExW(hkey, szModifyPath, 0, REG_EXPAND_SZ, (LPBYTE)buffer, size); RegSetValueExW(hkey, szUninstallString, 0, REG_EXPAND_SZ, (LPBYTE)buffer, size); msi_free(buffer); @@ -5548,6 +5752,7 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param) LPWSTR depends = NULL, pass = NULL, args = NULL, image_path = NULL; DWORD serv_type, start_type, err_control; SERVICE_DESCRIPTIONW sd = {NULL}; + UINT ret = ERROR_SUCCESS; comp = MSI_RecordGetString( rec, 12 ); component = msi_get_loaded_component( package, comp ); @@ -5605,7 +5810,10 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param) { int len = strlenW(file->TargetPath) + strlenW(args) + 2; if (!(image_path = msi_alloc(len * sizeof(WCHAR)))) - return ERROR_OUTOFMEMORY; + { + ret = ERROR_OUTOFMEMORY; + goto done; + } strcpyW(image_path, file->TargetPath); strcatW(image_path, szSpace); @@ -5639,7 +5847,7 @@ done: msi_free(depends); msi_free(args); - return ERROR_SUCCESS; + return ret; } static UINT ACTION_InstallServices( MSIPACKAGE *package ) @@ -5839,6 +6047,7 @@ static BOOL stop_service_dependents(SC_HANDLE scm, SC_HANDLE service) ENUM_SERVICE_STATUSW *dependencies; SERVICE_STATUS ss; SC_HANDLE depserv; + BOOL stopped, ret = FALSE; if (EnumDependentServicesW(service, SERVICE_ACTIVE, NULL, 0, &needed, &count)) @@ -5853,24 +6062,26 @@ static BOOL stop_service_dependents(SC_HANDLE scm, SC_HANDLE service) if (!EnumDependentServicesW(service, SERVICE_ACTIVE, dependencies, needed, &needed, &count)) - goto error; + goto done; for (i = 0; i < count; i++) { depserv = OpenServiceW(scm, dependencies[i].lpServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS); if (!depserv) - goto error; + goto done; - if (!ControlService(depserv, SERVICE_CONTROL_STOP, &ss)) - goto error; + stopped = ControlService(depserv, SERVICE_CONTROL_STOP, &ss); + CloseServiceHandle(depserv); + if (!stopped) + goto done; } - return TRUE; + ret = TRUE; -error: +done: msi_free(dependencies); - return FALSE; + return ret; } static UINT stop_service( LPCWSTR name ) @@ -6959,7 +7170,7 @@ UINT msi_validate_product_id( MSIPACKAGE *package ) if (key && template) { FIXME( "partial stub: template %s key %s\n", debugstr_w(template), debugstr_w(key) ); - r = msi_set_property( package->db, szProductID, key ); + r = msi_set_property( package->db, szProductID, key, -1 ); } msi_free( template ); msi_free( key ); @@ -6999,7 +7210,7 @@ static UINT ACTION_DisableRollback( MSIPACKAGE *package ) { TRACE("%p\n", package); - msi_set_property( package->db, szRollbackDisabled, szOne ); + msi_set_property( package->db, szRollbackDisabled, szOne, -1 ); return ERROR_SUCCESS; } @@ -7516,11 +7727,11 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath, static const WCHAR szDisableRollback[] = {'D','I','S','A','B','L','E','R','O','L','L','B','A','C','K',0}; static const WCHAR szAction[] = {'A','C','T','I','O','N',0}; static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0}; - WCHAR *reinstall = NULL; + WCHAR *reinstall, *remove, *patch; BOOL ui_exists; UINT rc; - msi_set_property( package->db, szAction, szInstall ); + msi_set_property( package->db, szAction, szInstall, -1 ); package->script->InWhatSequence = SEQUENCE_INSTALL; @@ -7567,10 +7778,13 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath, msi_apply_transforms( package ); msi_apply_patches( package ); - if (!szCommandLine && msi_get_property_int( package->db, szInstalled, 0 )) + patch = msi_dup_property( package->db, szPatch ); + remove = msi_dup_property( package->db, szRemove ); + reinstall = msi_dup_property( package->db, szReinstall ); + if (msi_get_property_int( package->db, szInstalled, 0 ) && !remove && !reinstall && !patch) { - TRACE("setting reinstall property\n"); - msi_set_property( package->db, szReinstall, szAll ); + TRACE("setting REINSTALL property to ALL\n"); + msi_set_property( package->db, szReinstall, szAll, -1 ); } /* properties may have been added by a transform */ @@ -7583,7 +7797,7 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath, if (msi_get_property_int( package->db, szDisableRollback, 0 )) { TRACE("disabling rollback\n"); - msi_set_property( package->db, szRollbackDisabled, szOne ); + msi_set_property( package->db, szRollbackDisabled, szOne, -1 ); } if (needs_ui_sequence( package)) @@ -7621,12 +7835,14 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath, /* finish up running custom actions */ ACTION_FinishCustomActions(package); - if (package->need_rollback && !(reinstall = msi_dup_property( package->db, szReinstall ))) + if (package->need_rollback && !reinstall) { WARN("installation failed, running rollback script\n"); execute_script( package, SCRIPT_ROLLBACK ); } msi_free( reinstall ); + msi_free( remove ); + msi_free( patch ); if (rc == ERROR_SUCCESS && package->need_reboot_at_end) return ERROR_SUCCESS_REBOOT_REQUIRED; diff --git a/reactos/dll/win32/msi/appsearch.c b/reactos/dll/win32/msi/appsearch.c index 21daf43f334..0d9c3022f09 100644 --- a/reactos/dll/win32/msi/appsearch.c +++ b/reactos/dll/win32/msi/appsearch.c @@ -1093,7 +1093,7 @@ static UINT iterate_appsearch(MSIRECORD *row, LPVOID param) r = ACTION_AppSearchSigName(package, sigName, &sig, &value); if (value) { - r = msi_set_property( package->db, propName, value ); + r = msi_set_property( package->db, propName, value, -1 ); if (r == ERROR_SUCCESS && !strcmpW( propName, szSourceDir )) msi_reset_folders( package, TRUE ); @@ -1153,7 +1153,7 @@ static UINT ITERATE_CCPSearch(MSIRECORD *row, LPVOID param) if (value) { TRACE("Found signature %s\n", debugstr_w(signature)); - msi_set_property(package->db, success, szOne); + msi_set_property( package->db, success, szOne, -1 ); msi_free(value); r = ERROR_NO_MORE_ITEMS; } diff --git a/reactos/dll/win32/msi/automation.c b/reactos/dll/win32/msi/automation.c index e55717af7f1..8164463a581 100644 --- a/reactos/dll/win32/msi/automation.c +++ b/reactos/dll/win32/msi/automation.c @@ -42,36 +42,116 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi); #define REG_INDEX_CLASSES_ROOT 0 #define REG_INDEX_DYN_DATA 6 -/* - * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function - * called from AutomationObject::Invoke. - */ - typedef struct AutomationObject AutomationObject; -typedef HRESULT (*autoInvokeFunc)(AutomationObject* This, +/* function that is called from AutomationObject::Invoke, specific to this type of object */ +typedef HRESULT (*auto_invoke_func)(AutomationObject* This, DISPID dispIdMember, REFIID riid, LCID lcid, WORD flags, DISPPARAMS* pDispParams, VARIANT* result, EXCEPINFO* ei, UINT* arg_err); +/* function that is called from AutomationObject::Release when the object is being freed + to free any private data structures (or NULL) */ +typedef void (*auto_free_func)(AutomationObject* This); + +typedef struct { + REFIID riid; + auto_invoke_func fn_invoke; + auto_free_func fn_free; +} tid_id_t; + + +static HRESULT database_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*); +static HRESULT installer_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*); +static HRESULT record_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*); +static HRESULT session_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*); +static HRESULT list_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*); +static void list_free(AutomationObject*); +static HRESULT summaryinfo_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*); +static HRESULT view_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*); + +static tid_id_t tid_ids[] = { + { &DIID_Database, database_invoke }, + { &DIID_Installer, installer_invoke }, + { &DIID_Record, record_invoke }, + { &DIID_Session, session_invoke }, + { &DIID_StringList, list_invoke, list_free }, + { &DIID_SummaryInfo, summaryinfo_invoke }, + { &DIID_View, view_invoke } +}; + +static ITypeLib *typelib; +static ITypeInfo *typeinfos[LAST_tid]; + +static const IID *get_riid_from_tid(tid_t tid) +{ + return tid_ids[tid].riid; +} + +HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo) +{ + HRESULT hr; + + if (!typelib) + { + ITypeLib *lib; + + hr = LoadRegTypeLib(&LIBID_WindowsInstaller, 1, 0, LOCALE_NEUTRAL, &lib); + if (FAILED(hr)) { + static const WCHAR msiserverW[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0}; + hr = LoadTypeLib(msiserverW, &lib); + if (FAILED(hr)) { + ERR("Could not load msiserver.tlb\n"); + return hr; + } + } + + if (InterlockedCompareExchangePointer((void**)&typelib, lib, NULL)) + ITypeLib_Release(lib); + } + + if (!typeinfos[tid]) + { + ITypeInfo *ti; + + hr = ITypeLib_GetTypeInfoOfGuid(typelib, get_riid_from_tid(tid), &ti); + if (FAILED(hr)) { + ERR("Could not load ITypeInfo for %s\n", debugstr_guid(get_riid_from_tid(tid))); + return hr; + } + + if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL)) + ITypeInfo_Release(ti); + } + + *typeinfo = typeinfos[tid]; + return S_OK; +} + +void release_typelib(void) +{ + unsigned i; -typedef void (*autoFreeFunc)(AutomationObject* This); + for (i = 0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++) + if (typeinfos[i]) + ITypeInfo_Release(typeinfos[i]); + if (typelib) + ITypeLib_Release(typelib); +} + +/* + * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function + * called from AutomationObject::Invoke. + */ struct AutomationObject { IDispatch IDispatch_iface; IProvideMultipleClassInfo IProvideMultipleClassInfo_iface; LONG ref; - /* Clsid for this class and it's appropriate ITypeInfo object */ - LPCLSID clsid; - ITypeInfo *iTypeInfo; + /* type id for this class */ + tid_t tid; /* The MSI handle of the current object */ MSIHANDLE msiHandle; - - /* A function that is called from AutomationObject::Invoke, specific to this type of object. */ - autoInvokeFunc funcInvoke; - /* A function that is called from AutomationObject::Release when the object is being freed to free any private - * data structures (or NULL) */ - autoFreeFunc funcFree; }; typedef struct { @@ -110,37 +190,6 @@ static inline AutomationObject *impl_from_IDispatch( IDispatch *iface ) return CONTAINING_RECORD(iface, AutomationObject, IDispatch_iface); } -/* Load type info so we don't have to process GetIDsOfNames */ -HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID lcid) -{ - static const WCHAR msiserverW[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0}; - ITypeInfo *ti = NULL; - ITypeLib *lib = NULL; - HRESULT hr; - - TRACE("(%p)->(%s, %d)\n", iface, debugstr_guid(clsid), lcid); - - /* Load registered type library */ - hr = LoadRegTypeLib(&LIBID_WindowsInstaller, 1, 0, lcid, &lib); - if (FAILED(hr)) { - hr = LoadTypeLib(msiserverW, &lib); - if (FAILED(hr)) { - ERR("Could not load msiserver.tlb\n"); - return hr; - } - } - - /* Get type information for object */ - hr = ITypeLib_GetTypeInfoOfGuid(lib, clsid, &ti); - ITypeLib_Release(lib); - if (FAILED(hr)) { - ERR("Could not load ITypeInfo for %s\n", debugstr_guid(clsid)); - return hr; - } - *pptinfo = ti; - return S_OK; -} - /* AutomationObject methods */ static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID riid, void** ppvObject) { @@ -155,7 +204,7 @@ static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID r if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDispatch) || - IsEqualGUID(riid, This->clsid)) + IsEqualGUID(riid, get_riid_from_tid(This->tid))) *ppvObject = &This->IDispatch_iface; else if (IsEqualGUID(riid, &IID_IProvideClassInfo) || IsEqualGUID(riid, &IID_IProvideClassInfo2) || @@ -190,8 +239,7 @@ static ULONG WINAPI AutomationObject_Release(IDispatch* iface) if (!ref) { - if (This->funcFree) This->funcFree(This); - ITypeInfo_Release(This->iTypeInfo); + if (tid_ids[This->tid].fn_free) tid_ids[This->tid].fn_free(This); MsiCloseHandle(This->msiHandle); msi_free(This); } @@ -217,11 +265,16 @@ static HRESULT WINAPI AutomationObject_GetTypeInfo( ITypeInfo** ppTInfo) { AutomationObject *This = impl_from_IDispatch(iface); + HRESULT hr; + TRACE("(%p/%p)->(%d,%d,%p)\n", iface, This, iTInfo, lcid, ppTInfo); - ITypeInfo_AddRef(This->iTypeInfo); - *ppTInfo = This->iTypeInfo; - return S_OK; + hr = get_typeinfo(This->tid, ppTInfo); + if (FAILED(hr)) + return hr; + + ITypeInfo_AddRef(*ppTInfo); + return hr; } static HRESULT WINAPI AutomationObject_GetIDsOfNames( @@ -233,18 +286,25 @@ static HRESULT WINAPI AutomationObject_GetIDsOfNames( DISPID* rgDispId) { AutomationObject *This = impl_from_IDispatch(iface); + ITypeInfo *ti; HRESULT hr; + TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface, This, riid, rgszNames, cNames, lcid, rgDispId); if (!IsEqualGUID(riid, &IID_NULL)) return E_INVALIDARG; - hr = ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId); + + hr = get_typeinfo(This->tid, &ti); + if (FAILED(hr)) + return hr; + + hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId); if (hr == DISP_E_UNKNOWNNAME) { UINT idx; for (idx=0; idxclsid)); + FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames[idx]), debugstr_guid(get_riid_from_tid(This->tid))); } } return hr; @@ -270,6 +330,7 @@ static HRESULT WINAPI AutomationObject_Invoke( unsigned int uArgErr; VARIANT varResultDummy; BSTR bstrName = NULL; + ITypeInfo *ti; TRACE("(%p/%p)->(%d,%p,%d,%d,%p,%p,%p,%p)\n", iface, This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); @@ -289,21 +350,26 @@ static HRESULT WINAPI AutomationObject_Invoke( if (puArgErr == NULL) puArgErr = &uArgErr; if (pVarResult == NULL) pVarResult = &varResultDummy; + hr = get_typeinfo(This->tid, &ti); + if (FAILED(hr)) + return hr; + /* Assume return type is void unless determined otherwise */ VariantInit(pVarResult); /* If we are tracing, we want to see the name of the member we are invoking */ if (TRACE_ON(msi)) { - ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL); + ITypeInfo_GetDocumentation(ti, dispIdMember, &bstrName, NULL, NULL, NULL); TRACE("Method %d, %s\n", dispIdMember, debugstr_w(bstrName)); } - hr = This->funcInvoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr); + hr = tid_ids[This->tid].fn_invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr); if (hr == DISP_E_MEMBERNOTFOUND) { - if (bstrName == NULL) ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL); - FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember, debugstr_w(bstrName), wFlags, debugstr_guid(This->clsid)); + if (bstrName == NULL) ITypeInfo_GetDocumentation(ti, dispIdMember, &bstrName, NULL, NULL, NULL); + FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember, debugstr_w(bstrName), wFlags, + debugstr_guid(get_riid_from_tid(This->tid))); } else if (pExcepInfo && (hr == DISP_E_PARAMNOTFOUND || @@ -315,7 +381,7 @@ static HRESULT WINAPI AutomationObject_Invoke( unsigned namesNo, i; BOOL bFirst = TRUE; - if (FAILED(ITypeInfo_GetNames(This->iTypeInfo, dispIdMember, bstrParamNames, + if (FAILED(ITypeInfo_GetNames(ti, dispIdMember, bstrParamNames, MAX_FUNC_PARAMS, &namesNo))) { TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember); @@ -391,8 +457,15 @@ static ULONG WINAPI ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo* static HRESULT WINAPI ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo* iface, ITypeInfo** ppTI) { AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface); + HRESULT hr; + TRACE("(%p/%p)->(%p)\n", iface, This, ppTI); - return load_type_info(&This->IDispatch_iface, ppTI, This->clsid, 0); + + hr = get_typeinfo(This->tid, ppTI); + if (SUCCEEDED(hr)) + ITypeInfo_AddRef(*ppTI); + + return hr; } static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo* iface, DWORD dwGuidKind, GUID* pGUID) @@ -403,7 +476,7 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID) return E_INVALIDARG; else { - *pGUID = *This->clsid; + *pGUID = *get_riid_from_tid(This->tid); return S_OK; } } @@ -420,7 +493,7 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMul static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo* iface, ULONG iti, DWORD dwFlags, - ITypeInfo** pptiCoClass, + ITypeInfo** ti, DWORD* pdwTIFlags, ULONG* pcdispidReserved, IID* piidPrimary, @@ -428,13 +501,19 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleCl { AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface); - TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface, This, iti, dwFlags, pptiCoClass, pdwTIFlags, pcdispidReserved, piidPrimary, piidSource); + TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface, This, iti, dwFlags, ti, pdwTIFlags, pcdispidReserved, piidPrimary, piidSource); if (iti != 0) return E_INVALIDARG; if (dwFlags & MULTICLASSINFO_GETTYPEINFO) - load_type_info(&This->IDispatch_iface, pptiCoClass, This->clsid, 0); + { + HRESULT hr = get_typeinfo(This->tid, ti); + if (FAILED(hr)) + return hr; + + ITypeInfo_AddRef(*ti); + } if (dwFlags & MULTICLASSINFO_GETNUMRESERVEDDISPIDS) { @@ -442,13 +521,11 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleCl *pcdispidReserved = 0; } - if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY){ - *piidPrimary = *This->clsid; - } + if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY) + *piidPrimary = *get_riid_from_tid(This->tid); - if (dwFlags & MULTICLASSINFO_GETIIDSOURCE){ - *piidSource = *This->clsid; - } + if (dwFlags & MULTICLASSINFO_GETIIDSOURCE) + *piidSource = *get_riid_from_tid(This->tid); return S_OK; } @@ -464,23 +541,18 @@ static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl = ProvideMultipleClassInfo_GetInfoOfIndex }; -static HRESULT init_automation_object(AutomationObject *This, MSIHANDLE msiHandle, REFIID clsid, - autoInvokeFunc invokeFunc, autoFreeFunc freeFunc) +static HRESULT init_automation_object(AutomationObject *This, MSIHANDLE msiHandle, tid_t tid) { - TRACE("(%p, %d, %s, %p, %p)\n", This, msiHandle, debugstr_guid(clsid), invokeFunc, freeFunc); + TRACE("(%p, %d, %s)\n", This, msiHandle, debugstr_guid(get_riid_from_tid(tid))); This->IDispatch_iface.lpVtbl = &AutomationObjectVtbl; This->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl; This->ref = 1; This->msiHandle = msiHandle; - This->clsid = (LPCLSID)clsid; - This->funcInvoke = invokeFunc; - This->funcFree = freeFunc; + This->tid = tid; - /* Load our TypeInfo so we don't have to process GetIDsOfNames */ - This->iTypeInfo = NULL; - return load_type_info(&This->IDispatch_iface, &This->iTypeInfo, clsid, 0); + return S_OK; } /* @@ -682,7 +754,7 @@ static HRESULT DispGetParam_CopyOnly( &pdispparams->rgvarg[pos]); } -static HRESULT SummaryInfoImpl_Invoke( +static HRESULT summaryinfo_invoke( AutomationObject* This, DISPID dispIdMember, REFIID riid, @@ -834,7 +906,7 @@ static HRESULT SummaryInfoImpl_Invoke( return S_OK; } -static HRESULT RecordImpl_Invoke( +static HRESULT record_invoke( AutomationObject* This, DISPID dispIdMember, REFIID riid, @@ -846,7 +918,7 @@ static HRESULT RecordImpl_Invoke( UINT* puArgErr) { WCHAR *szString; - DWORD dwLen; + DWORD dwLen = 0; UINT ret; VARIANTARG varg0, varg1; HRESULT hr; @@ -933,7 +1005,7 @@ static HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp) record = msi_alloc(sizeof(*record)); if (!record) return E_OUTOFMEMORY; - hr = init_automation_object(record, msiHandle, &DIID_Record, RecordImpl_Invoke, NULL); + hr = init_automation_object(record, msiHandle, Record_tid); if (hr != S_OK) { msi_free(record); @@ -945,7 +1017,7 @@ static HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp) return hr; } -static HRESULT ListImpl_Invoke( +static HRESULT list_invoke( AutomationObject* This, DISPID dispIdMember, REFIID riid, @@ -1002,7 +1074,7 @@ static HRESULT ListImpl_Invoke( return S_OK; } -static void ListImpl_Free(AutomationObject *This) +static void list_free(AutomationObject *This) { ListObject *list = (ListObject*)This; int i; @@ -1049,7 +1121,7 @@ static HRESULT create_list(const WCHAR *product, IDispatch **dispatch) list = msi_alloc_zero(sizeof(ListObject)); if (!list) return E_OUTOFMEMORY; - hr = init_automation_object(&list->autoobj, 0, &DIID_StringList, ListImpl_Invoke, ListImpl_Free); + hr = init_automation_object(&list->autoobj, 0, StringList_tid); if (hr != S_OK) { msi_free(list); @@ -1092,7 +1164,7 @@ static HRESULT create_list(const WCHAR *product, IDispatch **dispatch) return S_OK; } -static HRESULT ViewImpl_Invoke( +static HRESULT view_invoke( AutomationObject* This, DISPID dispIdMember, REFIID riid, @@ -1200,7 +1272,7 @@ static HRESULT DatabaseImpl_LastErrorRecord(WORD wFlags, return S_OK; } -static HRESULT DatabaseImpl_Invoke( +HRESULT database_invoke( AutomationObject* This, DISPID dispIdMember, REFIID riid, @@ -1285,7 +1357,7 @@ static HRESULT DatabaseImpl_Invoke( return S_OK; } -static HRESULT SessionImpl_Invoke( +static HRESULT session_invoke( AutomationObject* This, DISPID dispIdMember, REFIID riid, @@ -2250,7 +2322,7 @@ static HRESULT InstallerImpl_RelatedProducts(WORD flags, return hr; } -static HRESULT InstallerImpl_Invoke( +static HRESULT installer_invoke( AutomationObject* This, DISPID dispIdMember, REFIID riid, @@ -2363,7 +2435,7 @@ HRESULT create_msiserver(IUnknown *outer, void **ppObj) installer = msi_alloc(sizeof(AutomationObject)); if (!installer) return E_OUTOFMEMORY; - hr = init_automation_object(installer, 0, &DIID_Installer, InstallerImpl_Invoke, NULL); + hr = init_automation_object(installer, 0, Installer_tid); if (hr != S_OK) { msi_free(installer); @@ -2383,7 +2455,7 @@ HRESULT create_session(MSIHANDLE msiHandle, IDispatch *installer, IDispatch **di session = msi_alloc(sizeof(SessionObject)); if (!session) return E_OUTOFMEMORY; - hr = init_automation_object(&session->autoobj, msiHandle, &DIID_Session, SessionImpl_Invoke, NULL); + hr = init_automation_object(&session->autoobj, msiHandle, Session_tid); if (hr != S_OK) { msi_free(session); @@ -2406,7 +2478,7 @@ static HRESULT create_database(MSIHANDLE msiHandle, IDispatch **dispatch) database = msi_alloc(sizeof(AutomationObject)); if (!database) return E_OUTOFMEMORY; - hr = init_automation_object(database, msiHandle, &DIID_Database, DatabaseImpl_Invoke, NULL); + hr = init_automation_object(database, msiHandle, Database_tid); if (hr != S_OK) { msi_free(database); @@ -2428,7 +2500,7 @@ static HRESULT create_view(MSIHANDLE msiHandle, IDispatch **dispatch) view = msi_alloc(sizeof(AutomationObject)); if (!view) return E_OUTOFMEMORY; - hr = init_automation_object(view, msiHandle, &DIID_View, ViewImpl_Invoke, NULL); + hr = init_automation_object(view, msiHandle, View_tid); if (hr != S_OK) { msi_free(view); @@ -2448,7 +2520,7 @@ static HRESULT create_summaryinfo(MSIHANDLE msiHandle, IDispatch **disp) info = msi_alloc(sizeof(*info)); if (!info) return E_OUTOFMEMORY; - hr = init_automation_object(info, msiHandle, &DIID_SummaryInfo, SummaryInfoImpl_Invoke, NULL); + hr = init_automation_object(info, msiHandle, SummaryInfo_tid); if (hr != S_OK) { msi_free(info); diff --git a/reactos/dll/win32/msi/custom.c b/reactos/dll/win32/msi/custom.c index 8f32e590300..a33f19d3512 100644 --- a/reactos/dll/win32/msi/custom.c +++ b/reactos/dll/win32/msi/custom.c @@ -184,25 +184,21 @@ static LPWSTR msi_get_deferred_action(LPCWSTR action, LPCWSTR actiondata, return deferred; } -static void set_deferred_action_props(MSIPACKAGE *package, LPWSTR deferred_data) +static void set_deferred_action_props( MSIPACKAGE *package, const WCHAR *deferred_data ) { - LPWSTR end, beg = deferred_data + 1; - static const WCHAR sep[] = {'<','=','>',0}; + const WCHAR *end, *beg = deferred_data + 1; end = strstrW(beg, sep); - *end = '\0'; - msi_set_property(package->db, szCustomActionData, beg); + msi_set_property( package->db, szCustomActionData, beg, end - beg ); beg = end + 3; end = strstrW(beg, sep); - *end = '\0'; - msi_set_property(package->db, szUserSID, beg); + msi_set_property( package->db, szUserSID, beg, end - beg ); beg = end + 3; end = strchrW(beg, ']'); - *end = '\0'; - msi_set_property(package->db, szProductCode, beg); + msi_set_property( package->db, szProductCode, beg, end - beg ); } static MSIBINARY *create_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL dll ) @@ -1229,23 +1225,20 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL UINT rc = ERROR_SUCCESS; MSIRECORD *row; UINT type; - LPCWSTR source, target; - LPWSTR ptr, deferred_data = NULL; - LPWSTR deformated = NULL, action_copy = strdupW(action); + const WCHAR *source, *target, *ptr, *deferred_data = NULL; + WCHAR *deformated = NULL; + int len; /* deferred action: [properties]Action */ - if ((ptr = strrchrW(action_copy, ']'))) + if ((ptr = strrchrW(action, ']'))) { - deferred_data = action_copy; + deferred_data = action; action = ptr + 1; } row = MSI_QueryGetRecord( package->db, query, action ); if (!row) - { - msi_free(action_copy); return ERROR_CALL_NOT_IMPLEMENTED; - } type = MSI_RecordGetInteger(row,2); source = MSI_RecordGetString(row,3); @@ -1284,9 +1277,9 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL if (deferred_data) set_deferred_action_props(package, deferred_data); else if (actiondata) - msi_set_property(package->db, szCustomActionData, actiondata); + msi_set_property( package->db, szCustomActionData, actiondata, -1 ); else - msi_set_property(package->db, szCustomActionData, szEmpty); + msi_set_property( package->db, szCustomActionData, szEmpty, -1 ); msi_free(actiondata); } @@ -1334,8 +1327,8 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL if (!source) break; - deformat_string(package,target,&deformated); - rc = msi_set_property( package->db, source, deformated ); + len = deformat_string( package, target, &deformated ); + rc = msi_set_property( package->db, source, deformated, len ); if (rc == ERROR_SUCCESS && !strcmpW( source, szSourceDir )) msi_reset_folders( package, TRUE ); msi_free(deformated); @@ -1365,7 +1358,6 @@ end: package->scheduled_action_running = FALSE; package->commit_action_running = FALSE; package->rollback_action_running = FALSE; - msi_free(action_copy); msiobj_release(&row->hdr); return rc; } diff --git a/reactos/dll/win32/msi/database.c b/reactos/dll/win32/msi/database.c index 944cf8f66e8..9c0d3466aba 100644 --- a/reactos/dll/win32/msi/database.c +++ b/reactos/dll/win32/msi/database.c @@ -130,7 +130,7 @@ UINT msi_clone_open_stream( MSIDATABASE *db, IStorage *stg, LPCWSTR name, IStrea UINT msi_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm ) { HRESULT r; - IStorage *stg = 0; + IStorage *stg; WCHAR decoded[MAX_STREAM_NAME_LEN]; decode_streamname( stname, decoded ); diff --git a/reactos/dll/win32/msi/dialog.c b/reactos/dll/win32/msi/dialog.c index 66d87864c52..c0ff2043a5e 100644 --- a/reactos/dll/win32/msi/dialog.c +++ b/reactos/dll/win32/msi/dialog.c @@ -309,7 +309,7 @@ static UINT msi_dialog_add_font( MSIRECORD *rec, LPVOID param ) /* create a font and add it to the list */ name = MSI_RecordGetString( rec, 1 ); - font = msi_alloc( sizeof *font + strlenW( name )*sizeof (WCHAR) ); + font = msi_alloc( FIELD_OFFSET( msi_font, name[strlenW( name ) + 1] )); strcpyW( font->name, name ); list_add_head( &dialog->fonts, &font->entry ); @@ -414,7 +414,7 @@ static msi_control *msi_dialog_create_window( msi_dialog *dialog, style |= WS_CHILD; - control = msi_alloc( sizeof *control + strlenW(name)*sizeof(WCHAR) ); + control = msi_alloc( FIELD_OFFSET( msi_control, name[strlenW( name ) + 1] )); if (!control) return NULL; @@ -583,7 +583,7 @@ static void msi_dialog_update_controls( msi_dialog *dialog, LPCWSTR property ) static void msi_dialog_set_property( MSIPACKAGE *package, LPCWSTR property, LPCWSTR value ) { - UINT r = msi_set_property( package->db, property, value ); + UINT r = msi_set_property( package->db, property, value, -1 ); if (r == ERROR_SUCCESS && !strcmpW( property, szSourceDir )) msi_reset_folders( package, TRUE ); } @@ -3939,7 +3939,7 @@ static UINT error_dialog_handler(MSIPACKAGE *package, LPCWSTR event, if ( !strcmpW( argument, error_abort ) || !strcmpW( argument, error_cancel ) || !strcmpW( argument, error_no ) ) { - msi_set_property( package->db, result_prop, error_abort ); + msi_set_property( package->db, result_prop, error_abort, -1 ); } ControlEvent_CleanupSubscriptions(package); diff --git a/reactos/dll/win32/msi/events.c b/reactos/dll/win32/msi/events.c index d42ac5b4e99..707a4a235fd 100644 --- a/reactos/dll/win32/msi/events.c +++ b/reactos/dll/win32/msi/events.c @@ -173,7 +173,7 @@ static UINT ControlEvent_AddLocal( MSIPACKAGE *package, LPCWSTR argument, msi_di if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) { if (feature->ActionRequest != INSTALLSTATE_LOCAL) - msi_set_property( package->db, szPreselected, szOne ); + msi_set_property( package->db, szPreselected, szOne, -1 ); MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_LOCAL ); } } @@ -189,7 +189,7 @@ static UINT ControlEvent_Remove( MSIPACKAGE *package, LPCWSTR argument, msi_dial if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) { if (feature->ActionRequest != INSTALLSTATE_ABSENT) - msi_set_property( package->db, szPreselected, szOne ); + msi_set_property( package->db, szPreselected, szOne, -1 ); MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_ABSENT ); } } @@ -205,7 +205,7 @@ static UINT ControlEvent_AddSource( MSIPACKAGE *package, LPCWSTR argument, msi_d if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) { if (feature->ActionRequest != INSTALLSTATE_SOURCE) - msi_set_property( package->db, szPreselected, szOne ); + msi_set_property( package->db, szPreselected, szOne, -1 ); MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_SOURCE ); } } @@ -377,13 +377,13 @@ static UINT ControlEvent_DirectoryListUp(MSIPACKAGE *package, LPCWSTR argument, static UINT ControlEvent_ReinstallMode(MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog) { - return msi_set_property( package->db, szReinstallMode, argument ); + return msi_set_property( package->db, szReinstallMode, argument, -1 ); } static UINT ControlEvent_Reinstall( MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog ) { - return msi_set_property( package->db, szReinstall, argument ); + return msi_set_property( package->db, szReinstall, argument, -1 ); } static UINT ControlEvent_ValidateProductID(MSIPACKAGE *package, LPCWSTR argument, diff --git a/reactos/dll/win32/msi/files.c b/reactos/dll/win32/msi/files.c index 11913efd618..7202fb637cd 100644 --- a/reactos/dll/win32/msi/files.c +++ b/reactos/dll/win32/msi/files.c @@ -69,7 +69,6 @@ static msi_file_state calculate_install_state( MSIPACKAGE *package, MSIFILE *fil VS_FIXEDFILEINFO *file_version; WCHAR *font_version; msi_file_state state; - DWORD file_size; comp->Action = msi_get_component_action( package, comp ); if (comp->Action != INSTALLSTATE_LOCAL || (comp->assembly && comp->assembly->installed)) @@ -118,7 +117,7 @@ static msi_file_state calculate_install_state( MSIPACKAGE *package, MSIFILE *fil return state; } } - if ((file_size = msi_get_disk_file_size( file->TargetPath )) != file->FileSize) + if (msi_get_disk_file_size( file->TargetPath ) != file->FileSize) { return msifs_overwrite; } @@ -336,7 +335,8 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package) if (rc != ERROR_SUCCESS) { ERR("Unable to load media info for %s (%u)\n", debugstr_w(file->File), rc); - return ERROR_FUNCTION_FAILED; + rc = ERROR_FUNCTION_FAILED; + goto done; } if (!file->Component->Enabled) continue; @@ -513,7 +513,8 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package ) if (rc != ERROR_SUCCESS) { ERR("Unable to load media info for %s (%u)\n", debugstr_w(file->File), rc); - return ERROR_FUNCTION_FAILED; + rc = ERROR_FUNCTION_FAILED; + goto done; } comp->Action = msi_get_component_action( package, comp ); if (!comp->Enabled || comp->Action != INSTALLSTATE_LOCAL) continue; @@ -779,7 +780,7 @@ static UINT ITERATE_MoveFiles( MSIRECORD *rec, LPVOID param ) LPWSTR sourcedir, destname = NULL, destdir = NULL, source = NULL, dest = NULL; int options; DWORD size; - BOOL ret, wildcards; + BOOL wildcards; component = MSI_RecordGetString(rec, 2); comp = msi_get_loaded_component(package, component); @@ -861,7 +862,7 @@ static UINT ITERATE_MoveFiles( MSIRECORD *rec, LPVOID param ) if (GetFileAttributesW(destdir) == INVALID_FILE_ATTRIBUTES) { - if (!(ret = msi_create_full_path(destdir))) + if (!msi_create_full_path(destdir)) { WARN("failed to create directory %u\n", GetLastError()); goto done; diff --git a/reactos/dll/win32/msi/format.c b/reactos/dll/win32/msi/format.c index 8188f132497..756c4d1bd4b 100644 --- a/reactos/dll/win32/msi/format.c +++ b/reactos/dll/win32/msi/format.c @@ -140,130 +140,146 @@ static LPCWSTR get_formstr_data(FORMAT *format, FORMSTR *str) return &format->deformatted[str->n]; } -static LPWSTR dup_formstr(FORMAT *format, FORMSTR *str) +static WCHAR *dup_formstr( FORMAT *format, FORMSTR *str, int *ret_len ) { - LPWSTR val; - LPCWSTR data; - - if (str->len == 0) - return NULL; - - val = msi_alloc((str->len + 1) * sizeof(WCHAR)); - data = get_formstr_data(format, str); - lstrcpynW(val, data, str->len + 1); + WCHAR *val; + if (!str->len) return NULL; + if ((val = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) + { + memcpy( val, get_formstr_data(format, str), str->len * sizeof(WCHAR) ); + val[str->len] = 0; + *ret_len = str->len; + } return val; } -static LPWSTR deformat_index(FORMAT *format, FORMSTR *str) +static WCHAR *deformat_index( FORMAT *format, FORMSTR *str, int *ret_len ) { - LPWSTR val, ret; + WCHAR *val, *ret; + DWORD len; + int field; - val = msi_alloc((str->len + 1) * sizeof(WCHAR)); + if (!(val = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL; lstrcpynW(val, get_formstr_data(format, str), str->len + 1); + field = atoiW( val ); + msi_free( val ); - ret = msi_dup_record_field(format->record, atoiW(val)); + if (MSI_RecordIsNull( format->record, field ) || + MSI_RecordGetStringW( format->record, field, NULL, &len )) return NULL; - msi_free(val); + len++; + if (!(ret = msi_alloc( len * sizeof(WCHAR) ))) return NULL; + ret[0] = 0; + if (MSI_RecordGetStringW( format->record, field, ret, &len )) + { + msi_free( ret ); + return NULL; + } + *ret_len = len; return ret; } -static LPWSTR deformat_property(FORMAT *format, FORMSTR *str) +static WCHAR *deformat_property( FORMAT *format, FORMSTR *str, int *ret_len ) { - LPWSTR val, ret; - - val = msi_alloc((str->len + 1) * sizeof(WCHAR)); - lstrcpynW(val, get_formstr_data(format, str), str->len + 1); + WCHAR *prop, *ret; + DWORD len = 0; + UINT r; - ret = msi_dup_property(format->package->db, val); + if (!(prop = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL; + lstrcpynW( prop, get_formstr_data(format, str), str->len + 1 ); - msi_free(val); + r = msi_get_property( format->package->db, prop, NULL, &len ); + if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) + { + msi_free( prop ); + return NULL; + } + len++; + if ((ret = msi_alloc( len * sizeof(WCHAR) ))) + msi_get_property( format->package->db, prop, ret, &len ); + msi_free( prop ); + *ret_len = len; return ret; } -static LPWSTR deformat_component(FORMAT *format, FORMSTR *str) +static WCHAR *deformat_component( FORMAT *format, FORMSTR *str, int *ret_len ) { - LPWSTR key, ret = NULL; + WCHAR *key, *ret; MSICOMPONENT *comp; - key = msi_alloc((str->len + 1) * sizeof(WCHAR)); + if (!(key = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL; lstrcpynW(key, get_formstr_data(format, str), str->len + 1); - comp = msi_get_loaded_component(format->package, key); - if (!comp) - goto done; - + if (!(comp = msi_get_loaded_component( format->package, key ))) + { + msi_free( key ); + return NULL; + } if (comp->Action == INSTALLSTATE_SOURCE) ret = msi_resolve_source_folder( format->package, comp->Directory, NULL ); else ret = strdupW( msi_get_target_folder( format->package, comp->Directory ) ); -done: - msi_free(key); + if (ret) *ret_len = strlenW( ret ); + else *ret_len = 0; + msi_free( key ); return ret; } -static LPWSTR deformat_file(FORMAT *format, FORMSTR *str, BOOL shortname) +static WCHAR *deformat_file( FORMAT *format, FORMSTR *str, BOOL shortname, int *ret_len ) { - LPWSTR key, ret = NULL; - MSIFILE *file; - DWORD size; + WCHAR *key, *ret = NULL; + const MSIFILE *file; + DWORD len = 0; - key = msi_alloc((str->len + 1) * sizeof(WCHAR)); + if (!(key = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL; lstrcpynW(key, get_formstr_data(format, str), str->len + 1); - file = msi_get_loaded_file(format->package, key); - if (!file) - goto done; - + if (!(file = msi_get_loaded_file( format->package, key ))) goto done; if (!shortname) { - ret = strdupW(file->TargetPath); + if ((ret = strdupW( file->TargetPath ))) len = strlenW( ret ); goto done; } - - size = GetShortPathNameW(file->TargetPath, NULL, 0); - if (size <= 0) + if ((len = GetShortPathNameW(file->TargetPath, NULL, 0)) <= 0) { - ret = strdupW(file->TargetPath); + if ((ret = strdupW( file->TargetPath ))) len = strlenW( ret ); goto done; } - - size++; - ret = msi_alloc(size * sizeof(WCHAR)); - GetShortPathNameW(file->TargetPath, ret, size); + len++; + if ((ret = msi_alloc( len * sizeof(WCHAR) ))) + len = GetShortPathNameW( file->TargetPath, ret, len ); done: - msi_free(key); + msi_free( key ); + *ret_len = len; return ret; } -static LPWSTR deformat_environment(FORMAT *format, FORMSTR *str) +static WCHAR *deformat_environment( FORMAT *format, FORMSTR *str, int *ret_len ) { - LPWSTR key, ret = NULL; - DWORD sz; + WCHAR *key, *ret = NULL; + DWORD len; - key = msi_alloc((str->len + 1) * sizeof(WCHAR)); + if (!(key = msi_alloc((str->len + 1) * sizeof(WCHAR)))) return NULL; lstrcpynW(key, get_formstr_data(format, str), str->len + 1); - sz = GetEnvironmentVariableW(key, NULL ,0); - if (sz <= 0) - goto done; - - sz++; - ret = msi_alloc(sz * sizeof(WCHAR)); - GetEnvironmentVariableW(key, ret, sz); - -done: - msi_free(key); + if ((len = GetEnvironmentVariableW( key, NULL, 0 ))) + { + len++; + if ((ret = msi_alloc( len * sizeof(WCHAR) ))) + *ret_len = GetEnvironmentVariableW( key, ret, len ); + } + msi_free( key ); return ret; } -static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound, - BOOL *nonprop, int *type) +static WCHAR *deformat_literal( FORMAT *format, FORMSTR *str, BOOL *propfound, + BOOL *nonprop, int *type, int *len ) { LPCWSTR data = get_formstr_data(format, str); - LPWSTR replaced = NULL; + WCHAR *replaced = NULL; char ch = data[0]; if (ch == '\\') @@ -277,17 +293,17 @@ static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound, else { str->len = 1; - replaced = dup_formstr(format, str); + replaced = dup_formstr( format, str, len ); } } else if (ch == '~') { if (str->len != 1) replaced = NULL; - else + else if ((replaced = msi_alloc( sizeof(WCHAR) ))) { - replaced = msi_alloc(sizeof(WCHAR)); - *replaced = '\0'; + *replaced = 0; + *len = 0; } } else if (ch == '%' || ch == '#' || ch == '!' || ch == '$') @@ -298,20 +314,20 @@ static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound, switch (ch) { case '%': - replaced = deformat_environment(format, str); break; + replaced = deformat_environment( format, str, len ); break; case '#': - replaced = deformat_file(format, str, FALSE); break; + replaced = deformat_file( format, str, FALSE, len ); break; case '!': - replaced = deformat_file(format, str, TRUE); break; + replaced = deformat_file( format, str, TRUE, len ); break; case '$': - replaced = deformat_component(format, str); break; + replaced = deformat_component( format, str, len ); break; } *type = FORMAT_LITERAL; } else { - replaced = deformat_property(format, str); + replaced = deformat_property( format, str, len ); *type = FORMAT_LITERAL; if (replaced) @@ -489,8 +505,8 @@ static int format_lex(FORMAT *format, FORMSTR **out) return type; } -static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, - int oldsize, int type, LPWSTR replace) +static FORMSTR *format_replace( FORMAT *format, BOOL propfound, BOOL nonprop, + int oldsize, int type, WCHAR *replace, int len ) { FORMSTR *ret; LPWSTR str, ptr; @@ -499,10 +515,10 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, if (replace) { - if (!*replace) + if (!len) size = 1; else - size = lstrlenW(replace); + size = len; } size -= oldsize; @@ -526,15 +542,12 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, if (replace) { - if (!*replace) - { - str[n] = '\0'; - n++; - } + if (!len) str[n++] = 0; else { - lstrcpyW(&str[n], replace); - n += lstrlenW(replace); + memcpy( str + n, replace, len * sizeof(WCHAR) ); + n += len; + str[n] = 0; } } @@ -546,7 +559,7 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, format->len = size - 1; /* don't reformat the NULL */ - if (replace && !*replace) + if (replace && !len) format->n++; if (!replace) @@ -556,7 +569,7 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, if (!ret) return NULL; - ret->len = lstrlenW(replace); + ret->len = len; ret->type = type; ret->n = format->n; ret->propfound = propfound; @@ -565,13 +578,12 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, return ret; } -static LPWSTR replace_stack_group(FORMAT *format, STACK *values, - BOOL *propfound, BOOL *nonprop, - int *oldsize, int *type) +static WCHAR *replace_stack_group( FORMAT *format, STACK *values, + BOOL *propfound, BOOL *nonprop, + int *oldsize, int *type, int *len ) { - LPWSTR replaced = NULL; - FORMSTR *content; - FORMSTR *node; + WCHAR *replaced; + FORMSTR *content, *node; int n; *nonprop = FALSE; @@ -626,7 +638,7 @@ static LPWSTR replace_stack_group(FORMAT *format, STACK *values, *nonprop = TRUE; } - replaced = dup_formstr(format, content); + replaced = dup_formstr( format, content, len ); *type = content->type; msi_free(content); @@ -636,13 +648,12 @@ static LPWSTR replace_stack_group(FORMAT *format, STACK *values, return replaced; } -static LPWSTR replace_stack_prop(FORMAT *format, STACK *values, - BOOL *propfound, BOOL *nonprop, - int *oldsize, int *type) +static WCHAR *replace_stack_prop( FORMAT *format, STACK *values, + BOOL *propfound, BOOL *nonprop, + int *oldsize, int *type, int *len ) { - LPWSTR replaced = NULL; - FORMSTR *content; - FORMSTR *node; + WCHAR *replaced; + FORMSTR *content, *node; int n; *propfound = FALSE; @@ -672,7 +683,7 @@ static LPWSTR replace_stack_prop(FORMAT *format, STACK *values, if (*type == FORMAT_NUMBER) { - replaced = deformat_index(format, content); + replaced = deformat_index( format, content, len ); if (replaced) *propfound = TRUE; else @@ -684,48 +695,42 @@ static LPWSTR replace_stack_prop(FORMAT *format, STACK *values, } else if (format->package) { - replaced = deformat_literal(format, content, propfound, nonprop, type); + replaced = deformat_literal( format, content, propfound, nonprop, type, len ); } else { *nonprop = TRUE; content->n--; content->len += 2; - replaced = dup_formstr(format, content); + replaced = dup_formstr( format, content, len ); } - msi_free(content); return replaced; } static UINT replace_stack(FORMAT *format, STACK *stack, STACK *values) { - LPWSTR replaced = NULL; - FORMSTR *beg; - FORMSTR *top; - FORMSTR *node; - BOOL propfound = FALSE; - BOOL nonprop = FALSE; - BOOL group = FALSE; - int oldsize = 0; - int type, n; + WCHAR *replaced = NULL; + FORMSTR *beg, *top, *node; + BOOL propfound = FALSE, nonprop = FALSE, group = FALSE; + int type, n, len = 0, oldsize = 0; node = stack_peek(values); type = node->type; n = node->n; if (type == FORMAT_LBRACK) - replaced = replace_stack_prop(format, values, &propfound, - &nonprop, &oldsize, &type); + replaced = replace_stack_prop( format, values, &propfound, + &nonprop, &oldsize, &type, &len ); else if (type == FORMAT_LBRACE) { - replaced = replace_stack_group(format, values, &propfound, - &nonprop, &oldsize, &type); + replaced = replace_stack_group( format, values, &propfound, + &nonprop, &oldsize, &type, &len ); group = TRUE; } format->n = n; - beg = format_replace(format, propfound, nonprop, oldsize, type, replaced); + beg = format_replace( format, propfound, nonprop, oldsize, type, replaced, len ); if (!beg) return ERROR_SUCCESS; @@ -865,20 +870,18 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer, LPDWORD size ) { - LPWSTR deformated; - LPWSTR rec; - DWORD len; + WCHAR *format, *deformated; UINT rc = ERROR_INVALID_PARAMETER; + DWORD len; TRACE("%p %p %p %p\n", package, record, buffer, size); - rec = msi_dup_record_field(record,0); - if (!rec) - rec = build_default_format(record); + if (!(format = msi_dup_record_field( record, 0 ))) + format = build_default_format( record ); - TRACE("(%s)\n",debugstr_w(rec)); + TRACE("%s\n", debugstr_w(format)); - deformat_string_internal(package, rec, &deformated, &len, record, NULL); + deformat_string_internal( package, format, &deformated, &len, record, NULL ); if (buffer) { if (*size>len) @@ -897,13 +900,11 @@ UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer, rc = ERROR_MORE_DATA; } } - else - rc = ERROR_SUCCESS; + else rc = ERROR_SUCCESS; *size = len; - - msi_free(rec); - msi_free(deformated); + msi_free( format ); + msi_free( deformated ); return rc; } @@ -934,7 +935,7 @@ UINT WINAPI MsiFormatRecordW( MSIHANDLE hInstall, MSIHANDLE hRecord, wstr.unicode = TRUE; wstr.str.w = szResult; - r = msi_strcpy_to_awstring( value, &wstr, sz ); + r = msi_strcpy_to_awstring( value, SysStringLen(value), &wstr, sz ); done: IWineMsiRemotePackage_Release( remote_package ); @@ -1022,24 +1023,23 @@ done: } /* wrapper to resist a need for a full rewrite right now */ -DWORD deformat_string( MSIPACKAGE *package, const WCHAR *ptr, WCHAR **data ) +DWORD deformat_string( MSIPACKAGE *package, const WCHAR *fmt, WCHAR **data ) { - if (ptr) - { - DWORD size = 0; - MSIRECORD *rec = MSI_CreateRecord( 1 ); - - MSI_RecordSetStringW( rec, 0, ptr ); - MSI_FormatRecordW( package, rec, NULL, &size ); + DWORD len; + MSIRECORD *rec; - size++; - *data = msi_alloc( size * sizeof(WCHAR) ); - if (size > 1) MSI_FormatRecordW( package, rec, *data, &size ); - else *data[0] = 0; + *data = NULL; + if (!fmt) return 0; + if (!(rec = MSI_CreateRecord( 1 ))) return 0; + MSI_RecordSetStringW( rec, 0, fmt ); + MSI_FormatRecordW( package, rec, NULL, &len ); + if (!(*data = msi_alloc( ++len * sizeof(WCHAR) ))) + { msiobj_release( &rec->hdr ); - return size * sizeof(WCHAR); + return 0; } - *data = NULL; - return 0; + MSI_FormatRecordW( package, rec, *data, &len ); + msiobj_release( &rec->hdr ); + return len; } diff --git a/reactos/dll/win32/msi/install.c b/reactos/dll/win32/msi/install.c index a6c832a94eb..5810a1ebfdb 100644 --- a/reactos/dll/win32/msi/install.c +++ b/reactos/dll/win32/msi/install.c @@ -178,32 +178,28 @@ UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode return ret; } -UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz ) +UINT msi_strcpy_to_awstring( const WCHAR *str, int len, awstring *awbuf, DWORD *sz ) { - UINT len, r = ERROR_SUCCESS; + UINT r = ERROR_SUCCESS; - if (awbuf->str.w && !sz ) + if (awbuf->str.w && !sz) return ERROR_INVALID_PARAMETER; - if (!sz) - return r; + return ERROR_SUCCESS; + + if (len < 0) len = strlenW( str ); - if (awbuf->unicode) - { - len = lstrlenW( str ); - if (awbuf->str.w) - lstrcpynW( awbuf->str.w, str, *sz ); - } + if (awbuf->unicode && awbuf->str.w) + memcpy( awbuf->str.w, str, min(len + 1, *sz) * sizeof(WCHAR) ); else { - len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL ); - if (len) - len--; - WideCharToMultiByte( CP_ACP, 0, str, -1, awbuf->str.a, *sz, NULL, NULL ); - if ( awbuf->str.a && *sz && (len >= *sz) ) + int lenA = WideCharToMultiByte( CP_ACP, 0, str, len + 1, NULL, 0, NULL, NULL ); + if (lenA) lenA--; + WideCharToMultiByte( CP_ACP, 0, str, len + 1, awbuf->str.a, *sz, NULL, NULL ); + if (awbuf->str.a && *sz && lenA >= *sz) awbuf->str.a[*sz - 1] = 0; + len = lenA; } - if (awbuf->str.w && len >= *sz) r = ERROR_MORE_DATA; *sz = len; @@ -277,7 +273,7 @@ static UINT MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder, if (FAILED(hr)) goto done; - r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf ); + r = msi_strcpy_to_awstring( value, len, szPathBuf, pcchPathBuf ); done: IWineMsiRemotePackage_Release( remote_package ); @@ -301,8 +297,7 @@ done: if (!path) return ERROR_DIRECTORY; - r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf ); - return r; + return msi_strcpy_to_awstring( path, -1, szPathBuf, pcchPathBuf ); } /*********************************************************************** @@ -447,7 +442,7 @@ static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder, if (FAILED(hr)) goto done; - r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf ); + r = msi_strcpy_to_awstring( value, len, szPathBuf, pcchPathBuf ); done: IWineMsiRemotePackage_Release( remote_package ); @@ -478,7 +473,7 @@ done: if (!path) return ERROR_DIRECTORY; - r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf ); + r = msi_strcpy_to_awstring( path, -1, szPathBuf, pcchPathBuf ); msi_free( path ); return r; } @@ -558,7 +553,7 @@ static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR { msi_free( folder->ResolvedTarget ); folder->ResolvedTarget = target_path; - msi_set_property( package->db, folder->Directory, folder->ResolvedTarget ); + msi_set_property( package->db, folder->Directory, folder->ResolvedTarget, -1 ); LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry ) { @@ -1650,6 +1645,7 @@ UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel ) { static const WCHAR fmt[] = { '%','d',0 }; WCHAR level[6]; + int len; UINT r; TRACE("%p %i\n", package, iInstallLevel); @@ -1660,8 +1656,8 @@ UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel ) if (iInstallLevel < 1) return MSI_SetFeatureStates( package ); - sprintfW( level, fmt, iInstallLevel ); - r = msi_set_property( package->db, szInstallLevel, level ); + len = sprintfW( level, fmt, iInstallLevel ); + r = msi_set_property( package->db, szInstallLevel, level, len ); if ( r == ERROR_SUCCESS ) r = MSI_SetFeatureStates( package ); diff --git a/reactos/dll/win32/msi/msi.c b/reactos/dll/win32/msi/msi.c index 68e9f8154e7..92ef52cbc15 100644 --- a/reactos/dll/win32/msi/msi.c +++ b/reactos/dll/win32/msi/msi.c @@ -1101,6 +1101,11 @@ static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type) static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, awstring *szValue, LPDWORD pcchValueBuf) { + static WCHAR empty[] = {0}; + static const WCHAR sourcelist[] = {'S','o','u','r','c','e','L','i','s','t',0}; + static const WCHAR display_name[] = {'D','i','s','p','l','a','y','N','a','m','e',0}; + static const WCHAR display_version[] = {'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0}; + static const WCHAR assignment[] = {'A','s','s','i','g','n','m','e','n','t',0}; MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED; UINT r = ERROR_UNKNOWN_PROPERTY; HKEY prodkey, userdata, source; @@ -1111,16 +1116,6 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, LONG res; DWORD type = REG_NONE; - static WCHAR empty[] = {0}; - static const WCHAR sourcelist[] = { - 'S','o','u','r','c','e','L','i','s','t',0}; - static const WCHAR display_name[] = { - 'D','i','s','p','l','a','y','N','a','m','e',0}; - static const WCHAR display_version[] = { - 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0}; - static const WCHAR assignment[] = { - 'A','s','s','i','g','n','m','e','n','t',0}; - TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute), szValue, pcchValueBuf); @@ -1244,6 +1239,8 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, if (pcchValueBuf) { + int len = strlenW( val ); + /* If szBuffer (szValue->str) is NULL, there's no need to copy the value * out. Also, *pcchValueBuf may be uninitialized in this case, so we * can't rely on its value. @@ -1251,16 +1248,14 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, if (szValue->str.a || szValue->str.w) { DWORD size = *pcchValueBuf; - if (strlenW(val) < size) - r = msi_strcpy_to_awstring(val, szValue, &size); + if (len < size) + r = msi_strcpy_to_awstring( val, len, szValue, &size ); else - { r = ERROR_MORE_DATA; - } } if (!badconfig) - *pcchValueBuf = lstrlenW(val); + *pcchValueBuf = len; } if (badconfig) @@ -2220,7 +2215,10 @@ UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode, if (!(val = msi_alloc( sz ))) return ERROR_OUTOFMEMORY; if ((r = msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz))) + { + msi_free(val); return r; + } if (lstrlenW(val) > 2 && val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9' && val[2] != ':') @@ -2867,7 +2865,7 @@ static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent, if (state == INSTALLSTATE_LOCAL && !*path) state = INSTALLSTATE_NOTUSED; - msi_strcpy_to_awstring(path, lpPathBuf, pcchBuf); + msi_strcpy_to_awstring(path, -1, lpPathBuf, pcchBuf); msi_free(path); return state; } @@ -3521,7 +3519,7 @@ static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct, goto done; } - r = msi_strcpy_to_awstring(user, lpUserNameBuf, pcchUserNameBuf); + r = msi_strcpy_to_awstring(user, -1, lpUserNameBuf, pcchUserNameBuf); if (r == ERROR_MORE_DATA) { state = USERINFOSTATE_MOREDATA; @@ -3534,7 +3532,7 @@ static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct, orgptr = org; if (!orgptr) orgptr = szEmpty; - r = msi_strcpy_to_awstring(orgptr, lpOrgNameBuf, pcchOrgNameBuf); + r = msi_strcpy_to_awstring(orgptr, -1, lpOrgNameBuf, pcchOrgNameBuf); if (r == ERROR_MORE_DATA) { state = USERINFOSTATE_MOREDATA; @@ -3550,7 +3548,7 @@ static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct, goto done; } - r = msi_strcpy_to_awstring(serial, lpSerialBuf, pcchSerialBuf); + r = msi_strcpy_to_awstring(serial, -1, lpSerialBuf, pcchSerialBuf); if (r == ERROR_MORE_DATA) state = USERINFOSTATE_MOREDATA; } diff --git a/reactos/dll/win32/msi/msi_main.c b/reactos/dll/win32/msi/msi_main.c index de0534af131..46f9ed8db11 100644 --- a/reactos/dll/win32/msi/msi_main.c +++ b/reactos/dll/win32/msi/msi_main.c @@ -79,6 +79,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) msi_dialog_unregister_class(); msi_free_handle_table(); msi_free( gszLogFile ); + release_typelib(); break; } return TRUE; diff --git a/reactos/dll/win32/msi/msipriv.h b/reactos/dll/win32/msi/msipriv.h index a0657f4ce90..4110ec6166a 100644 --- a/reactos/dll/win32/msi/msipriv.h +++ b/reactos/dll/win32/msi/msipriv.h @@ -118,6 +118,7 @@ typedef struct tagMSIFIELD LPWSTR szwVal; IStream *stream; } u; + int len; } MSIFIELD; typedef struct tagMSIRECORD @@ -481,6 +482,7 @@ typedef struct tagMSICOMPONENT LPWSTR FullKeypath; LPWSTR AdvertiseString; MSIASSEMBLY *assembly; + int num_clients; unsigned int anyAbsent:1; unsigned int hasAdvertiseFeature:1; @@ -722,7 +724,7 @@ typedef struct { } str; } awcstring; -UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz ) DECLSPEC_HIDDEN; +UINT msi_strcpy_to_awstring(const WCHAR *, int, awstring *, DWORD *) DECLSPEC_HIDDEN; /* msi server interface */ extern HRESULT create_msi_custom_remote( IUnknown *pOuter, LPVOID *ppObj ) DECLSPEC_HIDDEN; @@ -753,14 +755,15 @@ enum StringPersistence }; extern BOOL msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcount, enum StringPersistence persistence ) DECLSPEC_HIDDEN; -extern UINT msi_string2idW( const string_table *st, LPCWSTR buffer, UINT *id ) DECLSPEC_HIDDEN; +extern UINT msi_string2id( const string_table *st, const WCHAR *data, int len, UINT *id ) DECLSPEC_HIDDEN; extern VOID msi_destroy_stringtable( string_table *st ) DECLSPEC_HIDDEN; -extern const WCHAR *msi_string_lookup_id( const string_table *st, UINT id ) DECLSPEC_HIDDEN; +extern const WCHAR *msi_string_lookup( const string_table *st, UINT id, int *len ) DECLSPEC_HIDDEN; extern HRESULT msi_init_string_table( IStorage *stg ) DECLSPEC_HIDDEN; extern string_table *msi_load_string_table( IStorage *stg, UINT *bytes_per_strref ) DECLSPEC_HIDDEN; extern UINT msi_save_string_table( const string_table *st, IStorage *storage, UINT *bytes_per_strref ) DECLSPEC_HIDDEN; extern UINT msi_get_string_table_codepage( const string_table *st ) DECLSPEC_HIDDEN; extern UINT msi_set_string_table_codepage( string_table *st, UINT codepage ) DECLSPEC_HIDDEN; +extern WCHAR *msi_strdupW( const WCHAR *value, int len ) DECLSPEC_HIDDEN; extern BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name ) DECLSPEC_HIDDEN; extern MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR table ) DECLSPEC_HIDDEN; @@ -820,6 +823,8 @@ extern UINT MSI_RecordCopyField( MSIRECORD *, UINT, MSIRECORD *, UINT ) DECLSPEC extern MSIRECORD *MSI_CloneRecord( MSIRECORD * ) DECLSPEC_HIDDEN; extern BOOL MSI_RecordsAreEqual( MSIRECORD *, MSIRECORD * ) DECLSPEC_HIDDEN; extern BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field) DECLSPEC_HIDDEN; +extern UINT msi_record_set_string(MSIRECORD *, UINT, const WCHAR *, int) DECLSPEC_HIDDEN; +extern const WCHAR *msi_record_get_string(const MSIRECORD *, UINT, int *) DECLSPEC_HIDDEN; /* stream internals */ extern void enum_stream_names( IStorage *stg ) DECLSPEC_HIDDEN; @@ -999,7 +1004,7 @@ extern UINT ACTION_MsiUnpublishAssemblies(MSIPACKAGE *package) DECLSPEC_HIDDEN; extern DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data ) DECLSPEC_HIDDEN; extern WCHAR *msi_dup_record_field(MSIRECORD *row, INT index) DECLSPEC_HIDDEN; extern LPWSTR msi_dup_property( MSIDATABASE *db, LPCWSTR prop ) DECLSPEC_HIDDEN; -extern UINT msi_set_property( MSIDATABASE *, LPCWSTR, LPCWSTR ) DECLSPEC_HIDDEN; +extern UINT msi_set_property( MSIDATABASE *, const WCHAR *, const WCHAR *, int ) DECLSPEC_HIDDEN; extern UINT msi_get_property( MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD ) DECLSPEC_HIDDEN; extern int msi_get_property_int( MSIDATABASE *package, LPCWSTR prop, int def ) DECLSPEC_HIDDEN; extern WCHAR *msi_resolve_source_folder(MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder) DECLSPEC_HIDDEN; @@ -1067,9 +1072,21 @@ extern VOID ControlEvent_SubscribeToEvent(MSIPACKAGE *package, msi_dialog *dialo LPCWSTR event, LPCWSTR control, LPCWSTR attribute) DECLSPEC_HIDDEN; /* OLE automation */ +typedef enum tid_t { + Database_tid, + Installer_tid, + Record_tid, + Session_tid, + StringList_tid, + SummaryInfo_tid, + View_tid, + LAST_tid +} tid_t; + extern HRESULT create_msiserver(IUnknown *pOuter, LPVOID *ppObj) DECLSPEC_HIDDEN; extern HRESULT create_session(MSIHANDLE msiHandle, IDispatch *pInstaller, IDispatch **pDispatch) DECLSPEC_HIDDEN; -extern HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID lcid) DECLSPEC_HIDDEN; +extern HRESULT get_typeinfo(tid_t tid, ITypeInfo **ti) DECLSPEC_HIDDEN; +extern void release_typelib(void) DECLSPEC_HIDDEN; /* Scripting */ extern DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action) DECLSPEC_HIDDEN; @@ -1177,6 +1194,7 @@ static const WCHAR szRollbackDisabled[] = {'R','o','l','l','b','a','c','k','D',' static const WCHAR szName[] = {'N','a','m','e',0}; static const WCHAR szData[] = {'D','a','t','a',0}; static const WCHAR szLangResource[] = {'\\','V','a','r','F','i','l','e','I','n','f','o','\\','T','r','a','n','s','l','a','t','i','o','n',0}; +static const WCHAR szInstallLocation[] = {'I','n','s','t','a','l','l','L','o','c','a','t','i','o','n',0}; /* memory allocation macro functions */ static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1); diff --git a/reactos/dll/win32/msi/msiquery.c b/reactos/dll/win32/msi/msiquery.c index 433b3c772f6..451fdddbbb0 100644 --- a/reactos/dll/win32/msi/msiquery.c +++ b/reactos/dll/win32/msi/msiquery.c @@ -345,10 +345,9 @@ UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec) if (type & MSITYPE_STRING) { - LPCWSTR sval; - - sval = msi_string_lookup_id(db->strings, ival); - MSI_RecordSetStringW(*rec, i, sval); + int len; + const WCHAR *sval = msi_string_lookup( db->strings, ival, &len ); + msi_record_set_string( *rec, i, sval, len ); } else { diff --git a/reactos/dll/win32/msi/package.c b/reactos/dll/win32/msi/package.c index a050b2eb54b..3055175773b 100644 --- a/reactos/dll/win32/msi/package.c +++ b/reactos/dll/win32/msi/package.c @@ -483,7 +483,7 @@ static UINT set_installed_prop( MSIPACKAGE *package ) if (r == ERROR_SUCCESS) { RegCloseKey( hkey ); - msi_set_property( package->db, szInstalled, szOne ); + msi_set_property( package->db, szInstalled, szOne, -1 ); } return r; } @@ -525,7 +525,7 @@ static UINT set_user_sid_prop( MSIPACKAGE *package ) if (!ConvertSidToStringSidW( psid, &sid_str )) goto done; - r = msi_set_property( package->db, szUserSID, sid_str ); + r = msi_set_property( package->db, szUserSID, sid_str, -1 ); done: LocalFree( sid_str ); @@ -638,10 +638,12 @@ static void set_msi_assembly_prop(MSIPACKAGE *package) return; size = GetFileVersionInfoSizeW(fusion, &handle); - if (!size) return; + if (!size) + goto done; version = msi_alloc(size); - if (!version) return; + if (!version) + goto done; if (!GetFileVersionInfoW(fusion, handle, size, version)) goto done; @@ -657,7 +659,7 @@ static void set_msi_assembly_prop(MSIPACKAGE *package) if (!val_len || !verstr) goto done; - msi_set_property(package->db, netasm, verstr); + msi_set_property( package->db, netasm, verstr, -1 ); done: msi_free(fusion); @@ -757,182 +759,182 @@ static VOID set_installer_properties(MSIPACKAGE *package) SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szCommonAppDataFolder, pth); + msi_set_property( package->db, szCommonAppDataFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szFavoritesFolder, pth); + msi_set_property( package->db, szFavoritesFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szFontsFolder, pth); + msi_set_property( package->db, szFontsFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szSendToFolder, pth); + msi_set_property( package->db, szSendToFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szStartMenuFolder, pth); + msi_set_property( package->db, szStartMenuFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szStartupFolder, pth); + msi_set_property( package->db, szStartupFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szTemplateFolder, pth); + msi_set_property( package->db, szTemplateFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szDesktopFolder, pth); + msi_set_property( package->db, szDesktopFolder, pth, -1 ); /* FIXME: set to AllUsers profile path if ALLUSERS is set */ SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szProgramMenuFolder, pth); + msi_set_property( package->db, szProgramMenuFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szAdminToolsFolder, pth); + msi_set_property( package->db, szAdminToolsFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szAppDataFolder, pth); + msi_set_property( package->db, szAppDataFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szSystemFolder, pth); - msi_set_property(package->db, szSystem16Folder, pth); + msi_set_property( package->db, szSystemFolder, pth, -1 ); + msi_set_property( package->db, szSystem16Folder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szLocalAppDataFolder, pth); + msi_set_property( package->db, szLocalAppDataFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szMyPicturesFolder, pth); + msi_set_property( package->db, szMyPicturesFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szPersonalFolder, pth); + msi_set_property( package->db, szPersonalFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szWindowsFolder, pth); + msi_set_property( package->db, szWindowsFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szPrintHoodFolder, pth); + msi_set_property( package->db, szPrintHoodFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szNetHoodFolder, pth); + msi_set_property( package->db, szNetHoodFolder, pth, -1 ); SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth); strcatW(pth, szBackSlash); - msi_set_property(package->db, szRecentFolder, pth); + msi_set_property( package->db, szRecentFolder, pth, -1 ); /* Physical Memory is specified in MB. Using total amount. */ msex.dwLength = sizeof(msex); GlobalMemoryStatusEx( &msex ); - sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) ); - msi_set_property(package->db, szPhysicalMemory, bufstr); + len = sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) ); + msi_set_property( package->db, szPhysicalMemory, bufstr, len ); SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); ptr = strchrW(pth,'\\'); if (ptr) *(ptr + 1) = 0; - msi_set_property(package->db, szWindowsVolume, pth); + msi_set_property( package->db, szWindowsVolume, pth, -1 ); - GetTempPathW(MAX_PATH,pth); - msi_set_property(package->db, szTempFolder, pth); + len = GetTempPathW(MAX_PATH, pth); + msi_set_property( package->db, szTempFolder, pth, len ); /* in a wine environment the user is always admin and privileged */ - msi_set_property(package->db, szAdminUser, szOne); - msi_set_property(package->db, szPrivileged, szOne); + msi_set_property( package->db, szAdminUser, szOne, -1 ); + msi_set_property( package->db, szPrivileged, szOne, -1 ); /* set the os things */ OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); GetVersionExW((OSVERSIONINFOW *)&OSVersion); verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100; - sprintfW(verstr, szFormat, verval); + len = sprintfW( verstr, szFormat, verval ); switch (OSVersion.dwPlatformId) { case VER_PLATFORM_WIN32_WINDOWS: - msi_set_property(package->db, szVersion9x, verstr); + msi_set_property( package->db, szVersion9x, verstr, len ); break; case VER_PLATFORM_WIN32_NT: - msi_set_property(package->db, szVersionNT, verstr); - sprintfW(verstr, szFormat,OSVersion.wProductType); - msi_set_property(package->db, szMsiNTProductType, verstr); + msi_set_property( package->db, szVersionNT, verstr, len ); + len = sprintfW( verstr, szFormat,OSVersion.wProductType ); + msi_set_property( package->db, szMsiNTProductType, verstr, len ); break; } - sprintfW(verstr, szFormat, OSVersion.dwBuildNumber); - msi_set_property(package->db, szWindowsBuild, verstr); - sprintfW(verstr, szFormat, OSVersion.wServicePackMajor); - msi_set_property(package->db, szServicePackLevel, verstr); + len = sprintfW( verstr, szFormat, OSVersion.dwBuildNumber ); + msi_set_property( package->db, szWindowsBuild, verstr, len ); + len = sprintfW( verstr, szFormat, OSVersion.wServicePackMajor ); + msi_set_property( package->db, szServicePackLevel, verstr, len ); - sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION); - msi_set_property( package->db, szVersionMsi, bufstr ); - sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100); - msi_set_property( package->db, szVersionDatabase, bufstr ); + len = sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION ); + msi_set_property( package->db, szVersionMsi, bufstr, len ); + len = sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100 ); + msi_set_property( package->db, szVersionDatabase, bufstr, len ); GetNativeSystemInfo( &sys_info ); - sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel ); - msi_set_property( package->db, szIntel, bufstr ); + len = sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel ); + msi_set_property( package->db, szIntel, bufstr, len ); if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) { GetSystemDirectoryW( pth, MAX_PATH ); PathAddBackslashW( pth ); - msi_set_property( package->db, szSystemFolder, pth ); + msi_set_property( package->db, szSystemFolder, pth, -1 ); SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth ); PathAddBackslashW( pth ); - msi_set_property( package->db, szProgramFilesFolder, pth ); + msi_set_property( package->db, szProgramFilesFolder, pth, -1 ); SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth ); PathAddBackslashW( pth ); - msi_set_property( package->db, szCommonFilesFolder, pth ); + msi_set_property( package->db, szCommonFilesFolder, pth, -1 ); } else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) { - msi_set_property( package->db, szMsiAMD64, bufstr ); - msi_set_property( package->db, szMsix64, bufstr ); - msi_set_property( package->db, szVersionNT64, verstr ); + msi_set_property( package->db, szMsiAMD64, bufstr, -1 ); + msi_set_property( package->db, szMsix64, bufstr, -1 ); + msi_set_property( package->db, szVersionNT64, verstr, -1 ); GetSystemDirectoryW( pth, MAX_PATH ); PathAddBackslashW( pth ); - msi_set_property( package->db, szSystem64Folder, pth ); + msi_set_property( package->db, szSystem64Folder, pth, -1 ); GetSystemWow64DirectoryW( pth, MAX_PATH ); PathAddBackslashW( pth ); - msi_set_property( package->db, szSystemFolder, pth ); + msi_set_property( package->db, szSystemFolder, pth, -1 ); SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth ); PathAddBackslashW( pth ); - msi_set_property( package->db, szProgramFiles64Folder, pth ); + msi_set_property( package->db, szProgramFiles64Folder, pth, -1 ); SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, pth ); PathAddBackslashW( pth ); - msi_set_property( package->db, szProgramFilesFolder, pth ); + msi_set_property( package->db, szProgramFilesFolder, pth, -1 ); SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth ); PathAddBackslashW( pth ); - msi_set_property( package->db, szCommonFiles64Folder, pth ); + msi_set_property( package->db, szCommonFiles64Folder, pth, -1 ); SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, pth ); PathAddBackslashW( pth ); - msi_set_property( package->db, szCommonFilesFolder, pth ); + msi_set_property( package->db, szCommonFilesFolder, pth, -1 ); } /* Screen properties. */ dc = GetDC(0); - sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, HORZRES ) ); - msi_set_property( package->db, szScreenX, bufstr ); - sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, VERTRES )); - msi_set_property( package->db, szScreenY, bufstr ); - sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, BITSPIXEL )); - msi_set_property( package->db, szColorBits, bufstr ); + len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, HORZRES) ); + msi_set_property( package->db, szScreenX, bufstr, len ); + len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, VERTRES) ); + msi_set_property( package->db, szScreenY, bufstr, len ); + len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, BITSPIXEL) ); + msi_set_property( package->db, szColorBits, bufstr, len ); ReleaseDC(0, dc); /* USERNAME and COMPANYNAME */ @@ -944,10 +946,10 @@ static VOID set_installer_properties(MSIPACKAGE *package) { if (!username && (username = msi_reg_get_val_str( hkey, szDefName ))) - msi_set_property( package->db, szUSERNAME, username ); + msi_set_property( package->db, szUSERNAME, username, -1 ); if (!companyname && (companyname = msi_reg_get_val_str( hkey, szDefCompany ))) - msi_set_property( package->db, szCOMPANYNAME, companyname ); + msi_set_property( package->db, szCOMPANYNAME, companyname, -1 ); CloseHandle( hkey ); } if ((!username || !companyname) && @@ -955,10 +957,10 @@ static VOID set_installer_properties(MSIPACKAGE *package) { if (!username && (username = msi_reg_get_val_str( hkey, szRegisteredUser ))) - msi_set_property( package->db, szUSERNAME, username ); + msi_set_property( package->db, szUSERNAME, username, -1 ); if (!companyname && (companyname = msi_reg_get_val_str( hkey, szRegisteredOrganization ))) - msi_set_property( package->db, szCOMPANYNAME, companyname ); + msi_set_property( package->db, szCOMPANYNAME, companyname, -1 ); CloseHandle( hkey ); } msi_free( username ); @@ -971,7 +973,7 @@ static VOID set_installer_properties(MSIPACKAGE *package) GetSystemTime( &systemtime ); if (GetDateFormatW( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemtime, NULL, bufstr, sizeof(bufstr)/sizeof(bufstr[0]) )) - msi_set_property( package->db, szDate, bufstr ); + msi_set_property( package->db, szDate, bufstr, -1 ); else ERR("Couldn't set Date property: GetDateFormat failed with error %d\n", GetLastError()); @@ -979,22 +981,22 @@ static VOID set_installer_properties(MSIPACKAGE *package) TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &systemtime, NULL, bufstr, sizeof(bufstr)/sizeof(bufstr[0]) )) - msi_set_property( package->db, szTime, bufstr ); + msi_set_property( package->db, szTime, bufstr, -1 ); else ERR("Couldn't set Time property: GetTimeFormat failed with error %d\n", GetLastError()); set_msi_assembly_prop( package ); langid = GetUserDefaultLangID(); - sprintfW(bufstr, szIntFormat, langid); - msi_set_property( package->db, szUserLanguageID, bufstr ); + len = sprintfW( bufstr, szIntFormat, langid ); + msi_set_property( package->db, szUserLanguageID, bufstr, len ); langid = GetSystemDefaultLangID(); - sprintfW(bufstr, szIntFormat, langid); - msi_set_property( package->db, szSystemLangID, bufstr ); + len = sprintfW( bufstr, szIntFormat, langid ); + msi_set_property( package->db, szSystemLangID, bufstr, len ); - sprintfW(bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode)); - msi_set_property( package->db, szProductState, bufstr ); + len = sprintfW( bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode) ); + msi_set_property( package->db, szProductState, bufstr, len ); len = 0; if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) @@ -1003,7 +1005,7 @@ static VOID set_installer_properties(MSIPACKAGE *package) if ((username = msi_alloc( len * sizeof(WCHAR) ))) { if (GetUserNameW( username, &len )) - msi_set_property( package->db, szLogonUser, username ); + msi_set_property( package->db, szLogonUser, username, len - 1 ); msi_free( username ); } } @@ -1014,7 +1016,7 @@ static VOID set_installer_properties(MSIPACKAGE *package) if ((computername = msi_alloc( len * sizeof(WCHAR) ))) { if (GetComputerNameW( computername, &len )) - msi_set_property( package->db, szComputerName, computername ); + msi_set_property( package->db, szComputerName, computername, len - 1 ); msi_free( computername ); } } @@ -1073,7 +1075,7 @@ static UINT msi_load_summary_properties( MSIPACKAGE *package ) goto done; } - msi_set_property( package->db, szPackageCode, package_code ); + msi_set_property( package->db, szPackageCode, package_code, len ); msi_free( package_code ); /* load package attributes */ @@ -1141,9 +1143,9 @@ void msi_adjust_privilege_properties( MSIPACKAGE *package ) if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2) { TRACE("resetting ALLUSERS property from 2 to 1\n"); - msi_set_property( package->db, szAllUsers, szOne ); + msi_set_property( package->db, szAllUsers, szOne, -1 ); } - msi_set_property( package->db, szAdminUser, szOne ); + msi_set_property( package->db, szAdminUser, szOne, -1 ); } MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) @@ -1151,6 +1153,7 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) static const WCHAR fmtW[] = {'%','u',0}; MSIPACKAGE *package; WCHAR uilevel[11]; + int len; UINT r; TRACE("%p\n", db); @@ -1176,8 +1179,8 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) set_installer_properties( package ); package->ui_level = gUILevel; - sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK ); - msi_set_property(package->db, szUILevel, uilevel); + len = sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK ); + msi_set_property( package->db, szUILevel, uilevel, len ); r = msi_load_summary_properties( package ); if (r != ERROR_SUCCESS) @@ -1564,13 +1567,17 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) { r = msi_create_empty_local_file( localfile, dotmsi ); if (r != ERROR_SUCCESS) + { + msi_free ( base_url ); return r; + } if (!CopyFileW( file, localfile, FALSE )) { r = GetLastError(); WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r); DeleteFileW( localfile ); + msi_free ( base_url ); return r; } delete_on_close = TRUE; @@ -1578,7 +1585,10 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) TRACE("opening package %s\n", debugstr_w( localfile )); r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db ); if (r != ERROR_SUCCESS) + { + msi_free ( base_url ); return r; + } } package = MSI_CreatePackage( db, base_url ); msi_free( base_url ); @@ -1608,18 +1618,17 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) msiobj_release( &package->hdr ); return r; } - msi_set_property( package->db, szDatabase, db->path ); + msi_set_property( package->db, szDatabase, db->path, -1 ); if( UrlIsW( szPackage, URLIS_URL ) ) - msi_set_property( package->db, szOriginalDatabase, szPackage ); + msi_set_property( package->db, szOriginalDatabase, szPackage, -1 ); else if( szPackage[0] == '#' ) - msi_set_property( package->db, szOriginalDatabase, db->path ); + msi_set_property( package->db, szOriginalDatabase, db->path, -1 ); else { WCHAR fullpath[MAX_PATH]; - - GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL ); - msi_set_property( package->db, szOriginalDatabase, fullpath ); + DWORD len = GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL ); + msi_set_property( package->db, szOriginalDatabase, fullpath, len ); } msi_set_context( package ); @@ -2018,7 +2027,7 @@ void msi_reset_folders( MSIPACKAGE *package, BOOL source ) } } -UINT msi_set_property( MSIDATABASE *db, LPCWSTR szName, LPCWSTR szValue ) +UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len ) { static const WCHAR insert_query[] = { 'I','N','S','E','R','T',' ','I','N','T','O',' ', @@ -2039,34 +2048,34 @@ UINT msi_set_property( MSIDATABASE *db, LPCWSTR szName, LPCWSTR szValue ) WCHAR query[1024]; UINT rc; - TRACE("%p %s %s\n", db, debugstr_w(szName), debugstr_w(szValue)); + TRACE("%p %s %s %d\n", db, debugstr_w(name), debugstr_wn(value, len), len); - if (!szName) + if (!name) return ERROR_INVALID_PARAMETER; /* this one is weird... */ - if (!szName[0]) - return szValue ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS; + if (!name[0]) + return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS; + + if (value && len < 0) len = strlenW( value ); - rc = msi_get_property(db, szName, 0, &sz); - if (!szValue || !*szValue) + rc = msi_get_property( db, name, 0, &sz ); + if (!value || (!*value && !len)) { - sprintfW(query, delete_query, szName); + sprintfW( query, delete_query, name ); } else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS) { - sprintfW(query, update_query, szName); - + sprintfW( query, update_query, name ); row = MSI_CreateRecord(1); - MSI_RecordSetStringW(row, 1, szValue); + msi_record_set_string( row, 1, value, len ); } else { - strcpyW(query, insert_query); - + strcpyW( query, insert_query ); row = MSI_CreateRecord(2); - MSI_RecordSetStringW(row, 1, szName); - MSI_RecordSetStringW(row, 2, szValue); + msi_record_set_string( row, 1, name, -1 ); + msi_record_set_string( row, 2, value, len ); } rc = MSI_DatabaseOpenViewW(db, query, &view); @@ -2123,7 +2132,7 @@ UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue return ERROR_SUCCESS; } - ret = msi_set_property( package->db, szName, szValue ); + ret = msi_set_property( package->db, szName, szValue, -1 ); if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir )) msi_reset_folders( package, TRUE ); @@ -2181,7 +2190,7 @@ UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName, } if (rc == ERROR_SUCCESS) - TRACE("returning %s for property %s\n", debugstr_w(szValueBuf), + TRACE("returning %s for property %s\n", debugstr_wn(szValueBuf, *pchValueBuf), debugstr_w(szName)); else if (rc == ERROR_MORE_DATA) TRACE("need %d sized buffer for %s\n", *pchValueBuf, @@ -2232,6 +2241,7 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name, MSIRECORD *row = NULL; UINT r = ERROR_FUNCTION_FAILED; LPCWSTR val = NULL; + DWORD len = 0; TRACE("%u %s %p %p\n", handle, debugstr_w(name), szValueBuf->str.w, pchValueBuf ); @@ -2246,7 +2256,6 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name, IWineMsiRemotePackage *remote_package; LPWSTR value = NULL; BSTR bname; - DWORD len; remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle ); if (!remote_package) @@ -2259,7 +2268,6 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name, return ERROR_OUTOFMEMORY; } - len = 0; hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, NULL, &len ); if (FAILED(hr)) goto done; @@ -2276,7 +2284,7 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name, if (FAILED(hr)) goto done; - r = msi_strcpy_to_awstring( value, szValueBuf, pchValueBuf ); + r = msi_strcpy_to_awstring( value, len, szValueBuf, pchValueBuf ); /* Bug required by Adobe installers */ if (!szValueBuf->unicode && !szValueBuf->str.a) @@ -2300,12 +2308,12 @@ done: row = msi_get_property_row( package->db, name ); if (row) - val = MSI_RecordGetString( row, 1 ); + val = msi_record_get_string( row, 1, (int *)&len ); if (!val) val = szEmpty; - r = msi_strcpy_to_awstring( val, szValueBuf, pchValueBuf ); + r = msi_strcpy_to_awstring( val, len, szValueBuf, pchValueBuf ); if (row) msiobj_release( &row->hdr ); diff --git a/reactos/dll/win32/msi/patch.c b/reactos/dll/win32/msi/patch.c index 4801872b32b..59785a690f2 100644 --- a/reactos/dll/win32/msi/patch.c +++ b/reactos/dll/win32/msi/patch.c @@ -225,7 +225,7 @@ static UINT patch_set_media_source_prop( MSIPACKAGE *package ) { property = MSI_RecordGetString( rec, 1 ); patch = msi_dup_property( package->db, szPatch ); - msi_set_property( package->db, property, patch ); + msi_set_property( package->db, property, patch, -1 ); msi_free( patch ); msiobj_release( &rec->hdr ); } diff --git a/reactos/dll/win32/msi/record.c b/reactos/dll/win32/msi/record.c index 1dace787906..dd097ea46e8 100644 --- a/reactos/dll/win32/msi/record.c +++ b/reactos/dll/win32/msi/record.c @@ -156,6 +156,17 @@ static BOOL string2intW( LPCWSTR str, int *out ) return TRUE; } +WCHAR *msi_strdupW( const WCHAR *value, int len ) +{ + WCHAR *ret; + + if (!value) return NULL; + if (!(ret = msi_alloc( (len + 1) * sizeof(WCHAR) ))) return NULL; + memcpy( ret, value, len * sizeof(WCHAR) ); + ret[len] = 0; + return ret; +} + UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n, MSIRECORD *out_rec, UINT out_n ) { @@ -184,11 +195,12 @@ UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n, out->u.pVal = in->u.pVal; break; case MSIFIELD_WSTR: - str = strdupW( in->u.szwVal ); - if ( !str ) - r = ERROR_OUTOFMEMORY; - else + if ((str = msi_strdupW( in->u.szwVal, in->len ))) + { out->u.szwVal = str; + out->len = in->len; + } + else r = ERROR_OUTOFMEMORY; break; case MSIFIELD_STREAM: IStream_AddRef( in->u.stream ); @@ -202,7 +214,6 @@ UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n, } msiobj_unlock( &in_rec->hdr ); - return r; } @@ -380,7 +391,7 @@ BOOL WINAPI MsiRecordIsNull( MSIHANDLE handle, UINT iField ) UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField, LPSTR szValue, LPDWORD pcchValue) { - UINT len=0, ret; + UINT len = 0, ret = ERROR_SUCCESS; CHAR buffer[16]; TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue); @@ -394,7 +405,6 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField, return ERROR_SUCCESS; } - ret = ERROR_SUCCESS; switch( rec->fields[iField].type ) { case MSIFIELD_INT: @@ -404,11 +414,11 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField, lstrcpynA(szValue, buffer, *pcchValue); break; case MSIFIELD_WSTR: - len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1, - NULL, 0 , NULL, NULL); + len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, + rec->fields[iField].len + 1, NULL, 0 , NULL, NULL ); if (szValue) - WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1, - szValue, *pcchValue, NULL, NULL); + WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, + rec->fields[iField].len + 1, szValue, *pcchValue, NULL, NULL ); if( szValue && *pcchValue && len>*pcchValue ) szValue[*pcchValue-1] = 0; if( len ) @@ -448,23 +458,30 @@ UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, UINT iField, return ret; } -const WCHAR *MSI_RecordGetString( const MSIRECORD *rec, UINT iField ) +const WCHAR *msi_record_get_string( const MSIRECORD *rec, UINT field, int *len ) { - if( iField > rec->count ) + if (field > rec->count) return NULL; - if( rec->fields[iField].type != MSIFIELD_WSTR ) + if (rec->fields[field].type != MSIFIELD_WSTR) return NULL; - return rec->fields[iField].u.szwVal; + if (len) *len = rec->fields[field].len; + + return rec->fields[field].u.szwVal; +} + +const WCHAR *MSI_RecordGetString( const MSIRECORD *rec, UINT iField ) +{ + return msi_record_get_string( rec, iField, NULL ); } UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField, LPWSTR szValue, LPDWORD pcchValue) { - UINT len=0, ret; + static const WCHAR szFormat[] = {'%','d',0}; + UINT len = 0, ret = ERROR_SUCCESS; WCHAR buffer[16]; - static const WCHAR szFormat[] = { '%','d',0 }; TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue); @@ -477,7 +494,6 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField, return ERROR_SUCCESS; } - ret = ERROR_SUCCESS; switch( rec->fields[iField].type ) { case MSIFIELD_INT: @@ -487,9 +503,9 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField, lstrcpynW(szValue, buffer, *pcchValue); break; case MSIFIELD_WSTR: - len = lstrlenW( rec->fields[iField].u.szwVal ); + len = rec->fields[iField].len; if (szValue) - lstrcpynW(szValue, rec->fields[iField].u.szwVal, *pcchValue); + memcpy( szValue, rec->fields[iField].u.szwVal, min(len + 1, *pcchValue) * sizeof(WCHAR) ); break; case MSIFIELD_NULL: if( szValue && *pcchValue > 0 ) @@ -548,7 +564,7 @@ static UINT MSI_RecordDataSize(MSIRECORD *rec, UINT iField) case MSIFIELD_INT: return sizeof (INT); case MSIFIELD_WSTR: - return lstrlenW( rec->fields[iField].u.szwVal ); + return rec->fields[iField].len; case MSIFIELD_NULL: break; case MSIFIELD_STREAM: @@ -574,74 +590,61 @@ UINT WINAPI MsiRecordDataSize(MSIHANDLE handle, UINT iField) return ret; } -static UINT MSI_RecordSetStringA( MSIRECORD *rec, UINT iField, LPCSTR szValue ) -{ - LPWSTR str; - - TRACE("%p %d %s\n", rec, iField, debugstr_a(szValue)); - - if( iField > rec->count ) - return ERROR_INVALID_FIELD; - - MSI_FreeField( &rec->fields[iField] ); - if( szValue && szValue[0] ) - { - str = strdupAtoW( szValue ); - rec->fields[iField].type = MSIFIELD_WSTR; - rec->fields[iField].u.szwVal = str; - } - else - { - rec->fields[iField].type = MSIFIELD_NULL; - rec->fields[iField].u.szwVal = NULL; - } - - return 0; -} - UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, UINT iField, LPCSTR szValue ) { + WCHAR *valueW = NULL; MSIRECORD *rec; UINT ret; TRACE("%d %d %s\n", handle, iField, debugstr_a(szValue)); + if (szValue && !(valueW = strdupAtoW( szValue ))) return ERROR_OUTOFMEMORY; + rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); if( !rec ) + { + msi_free( valueW ); return ERROR_INVALID_HANDLE; + } msiobj_lock( &rec->hdr ); - ret = MSI_RecordSetStringA( rec, iField, szValue ); + ret = MSI_RecordSetStringW( rec, iField, valueW ); msiobj_unlock( &rec->hdr ); msiobj_release( &rec->hdr ); + msi_free( valueW ); return ret; } -UINT MSI_RecordSetStringW( MSIRECORD *rec, UINT iField, LPCWSTR szValue ) +UINT msi_record_set_string( MSIRECORD *rec, UINT field, const WCHAR *value, int len ) { - LPWSTR str; - - TRACE("%p %d %s\n", rec, iField, debugstr_w(szValue)); - - if( iField > rec->count ) + if (field > rec->count) return ERROR_INVALID_FIELD; - MSI_FreeField( &rec->fields[iField] ); + MSI_FreeField( &rec->fields[field] ); - if( szValue && szValue[0] ) + if (value && len < 0) len = strlenW( value ); + + if (value && len) { - str = strdupW( szValue ); - rec->fields[iField].type = MSIFIELD_WSTR; - rec->fields[iField].u.szwVal = str; + rec->fields[field].type = MSIFIELD_WSTR; + rec->fields[field].u.szwVal = msi_strdupW( value, len ); + rec->fields[field].len = len; } else { - rec->fields[iField].type = MSIFIELD_NULL; - rec->fields[iField].u.szwVal = NULL; + rec->fields[field].type = MSIFIELD_NULL; + rec->fields[field].u.szwVal = NULL; + rec->fields[field].len = 0; } - return 0; } +UINT MSI_RecordSetStringW( MSIRECORD *rec, UINT iField, LPCWSTR szValue ) +{ + TRACE("%p %d %s\n", rec, iField, debugstr_w(szValue)); + + return msi_record_set_string( rec, iField, szValue, -1 ); +} + UINT WINAPI MsiRecordSetStringW( MSIHANDLE handle, UINT iField, LPCWSTR szValue ) { MSIRECORD *rec; @@ -1011,8 +1014,9 @@ BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field) break; case MSIFIELD_WSTR: - if (strcmpW(a->fields[field].u.szwVal, b->fields[field].u.szwVal)) - return FALSE; + if (a->fields[field].len != b->fields[field].len) return FALSE; + if (memcmp( a->fields[field].u.szwVal, b->fields[field].u.szwVal, + a->fields[field].len * sizeof(WCHAR) )) return FALSE; break; case MSIFIELD_STREAM: diff --git a/reactos/dll/win32/msi/registry.c b/reactos/dll/win32/msi/registry.c index 4143a791e84..388c0772808 100644 --- a/reactos/dll/win32/msi/registry.c +++ b/reactos/dll/win32/msi/registry.c @@ -1557,7 +1557,7 @@ static UINT MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex, } r = ERROR_OUTOFMEMORY; - if ((name_sz+1) >= name_max) + if (name_sz + 1 >= name_max) { name_max *= 2; msi_free( name ); @@ -1586,8 +1586,8 @@ static UINT MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex, TRACE("Providing %s and %s\n", debugstr_w(name), debugstr_w(val+ofs)); - r = msi_strcpy_to_awstring( name, lpQualBuf, pcchQual ); - r2 = msi_strcpy_to_awstring( val+ofs, lpAppBuf, pcchAppBuf ); + r = msi_strcpy_to_awstring( name, -1, lpQualBuf, pcchQual ); + r2 = msi_strcpy_to_awstring( val+ofs, -1, lpAppBuf, pcchAppBuf ); if (r2 != ERROR_SUCCESS) r = r2; @@ -1596,7 +1596,6 @@ end: msi_free(val); msi_free(name); RegCloseKey(key); - return r; } diff --git a/reactos/dll/win32/msi/script.c b/reactos/dll/win32/msi/script.c index 94577bae058..8d48a9411ae 100644 --- a/reactos/dll/win32/msi/script.c +++ b/reactos/dll/win32/msi/script.c @@ -36,6 +36,20 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi); +#ifdef _WIN64 + +#define IActiveScriptParse_Release IActiveScriptParse64_Release +#define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText + +#else + +#define IActiveScriptParse_Release IActiveScriptParse32_Release +#define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText + +#endif + static const WCHAR szJScript[] = { 'J','S','c','r','i','p','t',0}; static const WCHAR szVBScript[] = { 'V','B','S','c','r','i','p','t',0}; static const WCHAR szSession[] = {'S','e','s','s','i','o','n',0}; @@ -43,207 +57,54 @@ static const WCHAR szSession[] = {'S','e','s','s','i','o','n',0}; /* * MsiActiveScriptSite - Our IActiveScriptSite implementation. */ - typedef struct { - IActiveScriptSite lpVtbl; - IDispatch *pInstaller; - IDispatch *pSession; + IActiveScriptSite IActiveScriptSite_iface; + IDispatch *installer; + IDispatch *session; LONG ref; } MsiActiveScriptSite; -static const struct IActiveScriptSiteVtbl ASS_Vtbl; - -static HRESULT create_ActiveScriptSite(IUnknown *pUnkOuter, LPVOID *ppObj) +static inline MsiActiveScriptSite *impl_from_IActiveScriptSite( IActiveScriptSite *iface ) { - MsiActiveScriptSite* object; - - TRACE("(%p,%p)\n", pUnkOuter, ppObj); - - if( pUnkOuter ) - return CLASS_E_NOAGGREGATION; - - object = msi_alloc_zero( sizeof(MsiActiveScriptSite) ); - - object->lpVtbl.lpVtbl = &ASS_Vtbl; - object->ref = 1; - object->pInstaller = NULL; - object->pSession = NULL; - - *ppObj = object; - - return S_OK; -} - -/* - * Call a script. - */ -DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action) -{ - HRESULT hr; - IActiveScript *pActiveScript = NULL; - IActiveScriptParse32 *pActiveScriptParse32 = NULL; - IActiveScriptParse64 *pActiveScriptParse64 = NULL; - MsiActiveScriptSite *pActiveScriptSite = NULL; - IDispatch *pDispatch = NULL; - DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; - DISPID dispid; - CLSID clsid; - VARIANT var; - DWORD ret = ERROR_INSTALL_FAILURE; - - CoInitialize(NULL); - - /* Create MsiActiveScriptSite object */ - hr = create_ActiveScriptSite(NULL, (void **)&pActiveScriptSite); - if (hr != S_OK) goto done; - - /* Create an installer object */ - hr = create_msiserver(NULL, (LPVOID *)&pActiveScriptSite->pInstaller); - if (hr != S_OK) goto done; - - /* Create a session object */ - hr = create_session(hPackage, pActiveScriptSite->pInstaller, &pActiveScriptSite->pSession); - if (hr != S_OK) goto done; - - /* Create the scripting engine */ - if ((type & 7) == msidbCustomActionTypeJScript) - hr = CLSIDFromProgID(szJScript, &clsid); - else if ((type & 7) == msidbCustomActionTypeVBScript) - hr = CLSIDFromProgID(szVBScript, &clsid); - else { - ERR("Unknown script type %d\n", type); - goto done; - } - if (FAILED(hr)) { - ERR("Could not find CLSID for Windows Script\n"); - goto done; - } - hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IActiveScript, (void **)&pActiveScript); - if (FAILED(hr)) { - ERR("Could not instantiate class for Windows Script\n"); - goto done; - } - - if (type & msidbCustomActionType64BitScript) - { - hr = IActiveScript_QueryInterface(pActiveScript, &IID_IActiveScriptParse64, (void **)&pActiveScriptParse64); - if (FAILED(hr)) goto done; - - hr = IActiveScript_SetScriptSite(pActiveScript, (IActiveScriptSite *)pActiveScriptSite); - if (FAILED(hr)) goto done; - - hr = IActiveScriptParse64_InitNew(pActiveScriptParse64); - if (FAILED(hr)) goto done; - - hr = IActiveScript_AddNamedItem(pActiveScript, szSession, SCRIPTITEM_GLOBALMEMBERS); - if (FAILED(hr)) goto done; - - hr = IActiveScriptParse64_ParseScriptText(pActiveScriptParse64, script, NULL, NULL, NULL, 0, 0, 0L, NULL, NULL); - if (FAILED(hr)) goto done; - } - else - { - hr = IActiveScript_QueryInterface(pActiveScript, &IID_IActiveScriptParse32, (void **)&pActiveScriptParse32); - if (FAILED(hr)) goto done; - - hr = IActiveScript_SetScriptSite(pActiveScript, (IActiveScriptSite *)pActiveScriptSite); - if (FAILED(hr)) goto done; - - hr = IActiveScriptParse32_InitNew(pActiveScriptParse32); - if (FAILED(hr)) goto done; - - hr = IActiveScript_AddNamedItem(pActiveScript, szSession, SCRIPTITEM_GLOBALMEMBERS); - if (FAILED(hr)) goto done; - - hr = IActiveScriptParse32_ParseScriptText(pActiveScriptParse32, script, NULL, NULL, NULL, 0, 0, 0L, NULL, NULL); - if (FAILED(hr)) goto done; - } - - hr = IActiveScript_SetScriptState(pActiveScript, SCRIPTSTATE_CONNECTED); - if (FAILED(hr)) goto done; - - /* Call a function if necessary through the IDispatch interface */ - if (function != NULL && strlenW(function) > 0) { - TRACE("Calling function %s\n", debugstr_w(function)); - - hr = IActiveScript_GetScriptDispatch(pActiveScript, NULL, &pDispatch); - if (FAILED(hr)) goto done; - - hr = IDispatch_GetIDsOfNames(pDispatch, &IID_NULL, (WCHAR **)&function, 1,LOCALE_USER_DEFAULT, &dispid); - if (FAILED(hr)) goto done; - - hr = IDispatch_Invoke(pDispatch, dispid, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparamsNoArgs, &var, NULL, NULL); - if (FAILED(hr)) goto done; - - /* Check return value, if it's not IDOK we failed */ - hr = VariantChangeType(&var, &var, 0, VT_I4); - if (FAILED(hr)) goto done; - - if (V_I4(&var) == IDOK) - ret = ERROR_SUCCESS; - else ret = ERROR_INSTALL_FAILURE; - - VariantClear(&var); - } else { - /* If no function to be called, MSI behavior is to succeed */ - ret = ERROR_SUCCESS; - } - -done: - - if (pDispatch) IDispatch_Release(pDispatch); - if (pActiveScript) IActiveScript_Release(pActiveScript); - if (pActiveScriptParse32) IActiveScriptParse32_Release(pActiveScriptParse32); - if (pActiveScriptParse64) IActiveScriptParse64_Release(pActiveScriptParse64); - if (pActiveScriptSite) - { - if (pActiveScriptSite->pSession) IDispatch_Release(pActiveScriptSite->pSession); - if (pActiveScriptSite->pInstaller) IDispatch_Release(pActiveScriptSite->pInstaller); - IActiveScriptSite_Release((IActiveScriptSite *)pActiveScriptSite); - } - CoUninitialize(); /* must call even if CoInitialize failed */ - return ret; + return CONTAINING_RECORD(iface, MsiActiveScriptSite, IActiveScriptSite_iface); } /* * MsiActiveScriptSite */ - -/*** IUnknown methods ***/ -static HRESULT WINAPI MsiActiveScriptSite_QueryInterface(IActiveScriptSite* iface, REFIID riid, void** ppvObject) +static HRESULT WINAPI MsiActiveScriptSite_QueryInterface(IActiveScriptSite* iface, REFIID riid, void** obj) { - MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; + MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface); - TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject); + TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj); if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IActiveScriptSite)) { IActiveScriptSite_AddRef(iface); - *ppvObject = This; + *obj = iface; return S_OK; } - TRACE("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); + *obj = NULL; return E_NOINTERFACE; } static ULONG WINAPI MsiActiveScriptSite_AddRef(IActiveScriptSite* iface) { - MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; - - TRACE("(%p/%p)\n", iface, This); - - return InterlockedIncrement(&This->ref); + MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface); + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p)->(%d)\n", This, ref); + return ref; } static ULONG WINAPI MsiActiveScriptSite_Release(IActiveScriptSite* iface) { - MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; + MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p)->(%d)\n", This, ref); if (!ref) msi_free(This); @@ -251,18 +112,18 @@ static ULONG WINAPI MsiActiveScriptSite_Release(IActiveScriptSite* iface) return ref; } -/*** IActiveScriptSite methods **/ static HRESULT WINAPI MsiActiveScriptSite_GetLCID(IActiveScriptSite* iface, LCID* plcid) { - MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; - TRACE("(%p/%p)->(%p)\n", This, iface, plcid); + MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface); + TRACE("(%p)->(%p)\n", This, plcid); return E_NOTIMPL; /* Script will use system-defined locale */ } static HRESULT WINAPI MsiActiveScriptSite_GetItemInfo(IActiveScriptSite* iface, LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown** ppiunkItem, ITypeInfo** ppti) { - MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; - TRACE("(%p/%p)->(%p,%d,%p,%p)\n", This, iface, pstrName, dwReturnMask, ppiunkItem, ppti); + MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface); + + TRACE("(%p)->(%p, %d, %p, %p)\n", This, pstrName, dwReturnMask, ppiunkItem, ppti); /* Determine the kind of pointer that is requested, and make sure placeholder is valid */ if (dwReturnMask & SCRIPTINFO_ITYPEINFO) { @@ -276,10 +137,14 @@ static HRESULT WINAPI MsiActiveScriptSite_GetItemInfo(IActiveScriptSite* iface, /* Are we looking for the session object? */ if (!strcmpW(szSession, pstrName)) { - if (dwReturnMask & SCRIPTINFO_ITYPEINFO) - return load_type_info(This->pSession, ppti, &DIID_Session, 0); + if (dwReturnMask & SCRIPTINFO_ITYPEINFO) { + HRESULT hr = get_typeinfo(Session_tid, ppti); + if (SUCCEEDED(hr)) + ITypeInfo_AddRef(*ppti); + return hr; + } else if (dwReturnMask & SCRIPTINFO_IUNKNOWN) { - IDispatch_QueryInterface(This->pSession, &IID_IUnknown, (void **)ppiunkItem); + IDispatch_QueryInterface(This->session, &IID_IUnknown, (void **)ppiunkItem); return S_OK; } } @@ -289,15 +154,15 @@ static HRESULT WINAPI MsiActiveScriptSite_GetItemInfo(IActiveScriptSite* iface, static HRESULT WINAPI MsiActiveScriptSite_GetDocVersionString(IActiveScriptSite* iface, BSTR* pbstrVersion) { - MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; - TRACE("(%p/%p)->(%p)\n", This, iface, pbstrVersion); + MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface); + TRACE("(%p)->(%p)\n", This, pbstrVersion); return E_NOTIMPL; } static HRESULT WINAPI MsiActiveScriptSite_OnScriptTerminate(IActiveScriptSite* iface, const VARIANT* pvarResult, const EXCEPINFO* pexcepinfo) { - MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; - TRACE("(%p/%p)->(%p,%p)\n", This, iface, pvarResult, pexcepinfo); + MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface); + TRACE("(%p)->(%p, %p)\n", This, pvarResult, pexcepinfo); return S_OK; } @@ -338,11 +203,11 @@ static HRESULT WINAPI MsiActiveScriptSite_OnStateChange(IActiveScriptSite* iface static HRESULT WINAPI MsiActiveScriptSite_OnScriptError(IActiveScriptSite* iface, IActiveScriptError* pscripterror) { - MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; + MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface); EXCEPINFO exception; HRESULT hr; - TRACE("(%p/%p)->(%p)\n", This, iface, pscripterror); + TRACE("(%p)->(%p)\n", This, pscripterror); memset(&exception, 0, sizeof(EXCEPINFO)); hr = IActiveScriptError_GetExceptionInfo(pscripterror, &exception); @@ -359,19 +224,19 @@ static HRESULT WINAPI MsiActiveScriptSite_OnScriptError(IActiveScriptSite* iface static HRESULT WINAPI MsiActiveScriptSite_OnEnterScript(IActiveScriptSite* iface) { - MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; - TRACE("(%p/%p)\n", This, iface); + MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface); + TRACE("(%p)\n", This); return S_OK; } static HRESULT WINAPI MsiActiveScriptSite_OnLeaveScript(IActiveScriptSite* iface) { - MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; - TRACE("(%p/%p)\n", This, iface); + MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface); + TRACE("(%p)\n", This); return S_OK; } -static const struct IActiveScriptSiteVtbl ASS_Vtbl = +static const struct IActiveScriptSiteVtbl activescriptsitevtbl = { MsiActiveScriptSite_QueryInterface, MsiActiveScriptSite_AddRef, @@ -385,3 +250,135 @@ static const struct IActiveScriptSiteVtbl ASS_Vtbl = MsiActiveScriptSite_OnEnterScript, MsiActiveScriptSite_OnLeaveScript }; + +static HRESULT create_activescriptsite(MsiActiveScriptSite **obj) +{ + MsiActiveScriptSite* object; + + TRACE("(%p)\n", obj); + + *obj = NULL; + + object = msi_alloc( sizeof(MsiActiveScriptSite) ); + if (!object) + return E_OUTOFMEMORY; + + object->IActiveScriptSite_iface.lpVtbl = &activescriptsitevtbl; + object->ref = 1; + object->installer = NULL; + object->session = NULL; + + *obj = object; + + return S_OK; +} + +/* + * Call a script. + */ +DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action) +{ + HRESULT hr; + IActiveScript *pActiveScript = NULL; + IActiveScriptParse *pActiveScriptParse = NULL; + MsiActiveScriptSite *scriptsite; + IDispatch *pDispatch = NULL; + DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; + DISPID dispid; + CLSID clsid; + VARIANT var; + DWORD ret = ERROR_INSTALL_FAILURE; + + CoInitialize(NULL); + + /* Create MsiActiveScriptSite object */ + hr = create_activescriptsite(&scriptsite); + if (hr != S_OK) goto done; + + /* Create an installer object */ + hr = create_msiserver(NULL, (void**)&scriptsite->installer); + if (hr != S_OK) goto done; + + /* Create a session object */ + hr = create_session(hPackage, scriptsite->installer, &scriptsite->session); + if (hr != S_OK) goto done; + + /* Create the scripting engine */ + type &= msidbCustomActionTypeJScript|msidbCustomActionTypeVBScript; + if (type == msidbCustomActionTypeJScript) + hr = CLSIDFromProgID(szJScript, &clsid); + else if (type == msidbCustomActionTypeVBScript) + hr = CLSIDFromProgID(szVBScript, &clsid); + else { + ERR("Unknown script type %d\n", type); + goto done; + } + if (FAILED(hr)) { + ERR("Could not find CLSID for Windows Script\n"); + goto done; + } + hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IActiveScript, (void **)&pActiveScript); + if (FAILED(hr)) { + ERR("Could not instantiate class for Windows Script\n"); + goto done; + } + + hr = IActiveScript_QueryInterface(pActiveScript, &IID_IActiveScriptParse, (void **)&pActiveScriptParse); + if (FAILED(hr)) goto done; + + hr = IActiveScript_SetScriptSite(pActiveScript, &scriptsite->IActiveScriptSite_iface); + if (FAILED(hr)) goto done; + + hr = IActiveScriptParse_InitNew(pActiveScriptParse); + if (FAILED(hr)) goto done; + + hr = IActiveScript_AddNamedItem(pActiveScript, szSession, SCRIPTITEM_GLOBALMEMBERS|SCRIPTITEM_ISVISIBLE); + if (FAILED(hr)) goto done; + + hr = IActiveScriptParse_ParseScriptText(pActiveScriptParse, script, NULL, NULL, NULL, 0, 0, 0L, NULL, NULL); + if (FAILED(hr)) goto done; + + hr = IActiveScript_SetScriptState(pActiveScript, SCRIPTSTATE_CONNECTED); + if (FAILED(hr)) goto done; + + /* Call a function if necessary through the IDispatch interface */ + if (function != NULL && strlenW(function) > 0) { + TRACE("Calling function %s\n", debugstr_w(function)); + + hr = IActiveScript_GetScriptDispatch(pActiveScript, NULL, &pDispatch); + if (FAILED(hr)) goto done; + + hr = IDispatch_GetIDsOfNames(pDispatch, &IID_NULL, (WCHAR **)&function, 1,LOCALE_USER_DEFAULT, &dispid); + if (FAILED(hr)) goto done; + + hr = IDispatch_Invoke(pDispatch, dispid, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparamsNoArgs, &var, NULL, NULL); + if (FAILED(hr)) goto done; + + /* Check return value, if it's not IDOK we failed */ + hr = VariantChangeType(&var, &var, 0, VT_I4); + if (FAILED(hr)) goto done; + + if (V_I4(&var) == IDOK) + ret = ERROR_SUCCESS; + else ret = ERROR_INSTALL_FAILURE; + + VariantClear(&var); + } else { + /* If no function to be called, MSI behavior is to succeed */ + ret = ERROR_SUCCESS; + } + +done: + + if (pDispatch) IDispatch_Release(pDispatch); + if (pActiveScript) IActiveScript_Release(pActiveScript); + if (pActiveScriptParse) IActiveScriptParse_Release(pActiveScriptParse); + if (scriptsite) + { + if (scriptsite->session) IDispatch_Release(scriptsite->session); + if (scriptsite->installer) IDispatch_Release(scriptsite->installer); + IActiveScriptSite_Release(&scriptsite->IActiveScriptSite_iface); + } + CoUninitialize(); /* must call even if CoInitialize failed */ + return ret; +} diff --git a/reactos/dll/win32/msi/select.c b/reactos/dll/win32/msi/select.c index 982cf6a9369..e8f38855a86 100644 --- a/reactos/dll/win32/msi/select.c +++ b/reactos/dll/win32/msi/select.c @@ -276,8 +276,9 @@ static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row) } else if (type & MSITYPE_STRING) { - str = MSI_RecordGetString(rec, i + 1); - r = MSI_RecordSetStringW(mod, col, str); + int len; + str = msi_record_get_string( rec, i + 1, &len ); + r = msi_record_set_string( mod, col, str, len ); } else { @@ -430,7 +431,7 @@ UINT SELECT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table, count = select_count_columns( columns ); - sv = msi_alloc_zero( sizeof *sv + count*sizeof (UINT) ); + sv = msi_alloc_zero( FIELD_OFFSET( MSISELECTVIEW, cols[count] )); if( !sv ) return ERROR_FUNCTION_FAILED; diff --git a/reactos/dll/win32/msi/source.c b/reactos/dll/win32/msi/source.c index 881f3d26bf2..ab8541c170c 100644 --- a/reactos/dll/win32/msi/source.c +++ b/reactos/dll/win32/msi/source.c @@ -763,7 +763,10 @@ UINT msi_set_last_used_source(LPCWSTR product, LPCWSTR usersid, r = OpenSourceKey(product, &source, MSICODE_PRODUCT, context, FALSE); if (r != ERROR_SUCCESS) + { + msi_free(buffer); return r; + } sprintfW(buffer, format, typechar, index, value); diff --git a/reactos/dll/win32/msi/storages.c b/reactos/dll/win32/msi/storages.c index c980df8aa32..35c1de5903d 100644 --- a/reactos/dll/win32/msi/storages.c +++ b/reactos/dll/win32/msi/storages.c @@ -312,7 +312,7 @@ static UINT storages_find_row(MSISTORAGESVIEW *sv, MSIRECORD *rec, UINT *row) UINT r, i, id, data; str = MSI_RecordGetString(rec, 1); - r = msi_string2idW(sv->db->strings, str, &id); + r = msi_string2id(sv->db->strings, str, -1, &id); if (r != ERROR_SUCCESS) return r; diff --git a/reactos/dll/win32/msi/streams.c b/reactos/dll/win32/msi/streams.c index 71616e93eb0..d9d632fafbc 100644 --- a/reactos/dll/win32/msi/streams.c +++ b/reactos/dll/win32/msi/streams.c @@ -299,7 +299,7 @@ static UINT streams_find_row(MSISTREAMSVIEW *sv, MSIRECORD *rec, UINT *row) UINT r, i, id, data; str = MSI_RecordGetString(rec, 1); - r = msi_string2idW(sv->db->strings, str, &id); + r = msi_string2id(sv->db->strings, str, -1, &id); if (r != ERROR_SUCCESS) return r; diff --git a/reactos/dll/win32/msi/string.c b/reactos/dll/win32/msi/string.c index 065c04a3720..8e3e575f502 100644 --- a/reactos/dll/win32/msi/string.c +++ b/reactos/dll/win32/msi/string.c @@ -45,7 +45,8 @@ struct msistring { USHORT persistent_refcount; USHORT nonpersistent_refcount; - LPWSTR str; + WCHAR *data; + int len; }; struct string_table @@ -112,7 +113,7 @@ VOID msi_destroy_stringtable( string_table *st ) { if( st->strings[i].persistent_refcount || st->strings[i].nonpersistent_refcount ) - msi_free( st->strings[i].str ); + msi_free( st->strings[i].data ); } msi_free( st->strings ); msi_free( st->sorted ); @@ -162,6 +163,19 @@ static int st_find_free_entry( string_table *st ) return st->freeslot; } +static inline int cmp_string( const WCHAR *str1, int len1, const WCHAR *str2, int len2 ) +{ + if (len1 < len2) return -1; + else if (len1 > len2) return 1; + while (len1) + { + if (*str1 == *str2) { str1++; str2++; } + else return *str1 - *str2; + len1--; + } + return 0; +} + static int find_insert_index( const string_table *st, UINT string_id ) { int i, c, low = 0, high = st->sortcount - 1; @@ -169,8 +183,8 @@ static int find_insert_index( const string_table *st, UINT string_id ) while (low <= high) { i = (low + high) / 2; - c = strcmpW( st->strings[string_id].str, st->strings[st->sorted[i]].str ); - + c = cmp_string( st->strings[string_id].data, st->strings[string_id].len, + st->strings[st->sorted[i]].data, st->strings[st->sorted[i]].len ); if (c < 0) high = i - 1; else if (c > 0) @@ -194,7 +208,8 @@ static void insert_string_sorted( string_table *st, UINT string_id ) st->sortcount++; } -static void set_st_entry( string_table *st, UINT n, LPWSTR str, USHORT refcount, enum StringPersistence persistence ) +static void set_st_entry( string_table *st, UINT n, WCHAR *str, int len, USHORT refcount, + enum StringPersistence persistence ) { if (persistence == StringPersistent) { @@ -207,7 +222,8 @@ static void set_st_entry( string_table *st, UINT n, LPWSTR str, USHORT refcount, st->strings[n].nonpersistent_refcount = refcount; } - st->strings[n].str = str; + st->strings[n].data = str; + st->strings[n].len = len; insert_string_sorted( st, n ); @@ -237,20 +253,17 @@ static UINT msi_string2idA( const string_table *st, LPCSTR buffer, UINT *id ) return ERROR_NOT_ENOUGH_MEMORY; MultiByteToWideChar( st->codepage, 0, buffer, -1, str, sz ); - r = msi_string2idW( st, str, id ); + r = msi_string2id( st, str, sz - 1, id ); msi_free( str ); - return r; } -static int msi_addstring( string_table *st, UINT n, const CHAR *data, int len, USHORT refcount, enum StringPersistence persistence ) +static int msi_addstring( string_table *st, UINT n, const char *data, UINT len, USHORT refcount, enum StringPersistence persistence ) { LPWSTR str; int sz; - if( !data ) - return 0; - if( !data[0] ) + if( !data || !len ) return 0; if( n > 0 ) { @@ -280,8 +293,6 @@ static int msi_addstring( string_table *st, UINT n, const CHAR *data, int len, U } /* allocate a new string */ - if( len < 0 ) - len = strlen(data); sz = MultiByteToWideChar( st->codepage, 0, data, len, NULL, 0 ); str = msi_alloc( (sz+1)*sizeof(WCHAR) ); if( !str ) @@ -289,8 +300,7 @@ static int msi_addstring( string_table *st, UINT n, const CHAR *data, int len, U MultiByteToWideChar( st->codepage, 0, data, len, str, sz ); str[sz] = 0; - set_st_entry( st, n, str, refcount, persistence ); - + set_st_entry( st, n, str, sz, refcount, persistence ); return n; } @@ -301,10 +311,13 @@ int msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcoun if( !data ) return 0; - if( !data[0] ) + + if (len < 0) len = strlenW( data ); + + if( !data[0] && !len ) return 0; - if( msi_string2idW( st, data, &n ) == ERROR_SUCCESS ) + if (msi_string2id( st, data, len, &n) == ERROR_SUCCESS ) { if (persistence == StringPersistent) st->strings[n].persistent_refcount += refcount; @@ -318,9 +331,7 @@ int msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcoun return -1; /* allocate a new string */ - if(len<0) - len = strlenW(data); - TRACE("%s, n = %d len = %d\n", debugstr_w(data), n, len ); + TRACE( "%s, n = %d len = %d\n", debugstr_wn(data, len), n, len ); str = msi_alloc( (len+1)*sizeof(WCHAR) ); if( !str ) @@ -328,24 +339,27 @@ int msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcoun memcpy( str, data, len*sizeof(WCHAR) ); str[len] = 0; - set_st_entry( st, n, str, refcount, persistence ); - + set_st_entry( st, n, str, len, refcount, persistence ); return n; } /* find the string identified by an id - return null if there's none */ -const WCHAR *msi_string_lookup_id( const string_table *st, UINT id ) +const WCHAR *msi_string_lookup( const string_table *st, UINT id, int *len ) { if( id == 0 ) + { + if (len) *len = 0; return szEmpty; - + } if( id >= st->maxcount ) return NULL; if( id && !st->strings[id].persistent_refcount && !st->strings[id].nonpersistent_refcount) return NULL; - return st->strings[id].str; + if (len) *len = st->strings[id].len; + + return st->strings[id].data; } /* @@ -361,16 +375,15 @@ const WCHAR *msi_string_lookup_id( const string_table *st, UINT id ) */ static UINT msi_id2stringA( const string_table *st, UINT id, LPSTR buffer, UINT *sz ) { - UINT len, lenW; + int len, lenW; const WCHAR *str; TRACE("Finding string %d of %d\n", id, st->maxcount); - str = msi_string_lookup_id( st, id ); + str = msi_string_lookup( st, id, &lenW ); if( !str ) return ERROR_FUNCTION_FAILED; - lenW = strlenW( str ); len = WideCharToMultiByte( st->codepage, 0, str, lenW, NULL, 0, NULL, NULL ); if( *sz < len ) { @@ -382,20 +395,22 @@ static UINT msi_id2stringA( const string_table *st, UINT id, LPSTR buffer, UINT } /* - * msi_string2idW + * msi_string2id * * [in] st - pointer to the string table * [in] str - string to find in the string table * [out] id - id of the string, if found */ -UINT msi_string2idW( const string_table *st, LPCWSTR str, UINT *id ) +UINT msi_string2id( const string_table *st, const WCHAR *str, int len, UINT *id ) { int i, c, low = 0, high = st->sortcount - 1; + if (len < 0) len = strlenW( str ); + while (low <= high) { i = (low + high) / 2; - c = strcmpW( str, st->strings[st->sorted[i]].str ); + c = cmp_string( str, len, st->strings[st->sorted[i]].data, st->strings[st->sorted[i]].len ); if (c < 0) high = i - 1; @@ -407,7 +422,6 @@ UINT msi_string2idW( const string_table *st, LPCWSTR str, UINT *id ) return ERROR_SUCCESS; } } - return ERROR_INVALID_PARAMETER; } @@ -415,7 +429,7 @@ static void string_totalsize( const string_table *st, UINT *datasize, UINT *pool { UINT i, len, holesize; - if( st->strings[0].str || st->strings[0].persistent_refcount || st->strings[0].nonpersistent_refcount) + if( st->strings[0].data || st->strings[0].persistent_refcount || st->strings[0].nonpersistent_refcount) ERR("oops. element 0 has a string\n"); *poolsize = 4; @@ -425,14 +439,14 @@ static void string_totalsize( const string_table *st, UINT *datasize, UINT *pool { if( !st->strings[i].persistent_refcount ) { - TRACE("[%u] nonpersistent = %s\n", i, debugstr_w(st->strings[i].str)); + TRACE("[%u] nonpersistent = %s\n", i, debugstr_wn(st->strings[i].data, st->strings[i].len)); (*poolsize) += 4; } - else if( st->strings[i].str ) + else if( st->strings[i].data ) { - TRACE("[%u] = %s\n", i, debugstr_w(st->strings[i].str)); - len = WideCharToMultiByte( st->codepage, 0, - st->strings[i].str, -1, NULL, 0, NULL, NULL); + TRACE("[%u] = %s\n", i, debugstr_wn(st->strings[i].data, st->strings[i].len)); + len = WideCharToMultiByte( st->codepage, 0, st->strings[i].data, st->strings[i].len + 1, + NULL, 0, NULL, NULL); if( len ) len--; (*datasize) += len; diff --git a/reactos/dll/win32/msi/table.c b/reactos/dll/win32/msi/table.c index dd25fbb2cde..e2186fcb3cf 100644 --- a/reactos/dll/win32/msi/table.c +++ b/reactos/dll/win32/msi/table.c @@ -660,7 +660,7 @@ static UINT get_tablecolumns( MSIDATABASE *db, LPCWSTR szTableName, MSICOLUMNINF } /* convert table and column names to IDs from the string table */ - r = msi_string2idW( db->strings, szTableName, &table_id ); + r = msi_string2id( db->strings, szTableName, -1, &table_id ); if (r != ERROR_SUCCESS) { WARN("Couldn't find id for %s\n", debugstr_w(szTableName)); @@ -693,9 +693,9 @@ static UINT get_tablecolumns( MSIDATABASE *db, LPCWSTR szTableName, MSICOLUMNINF ERR("duplicate column %d\n", col); continue; } - colinfo[col - 1].tablename = msi_string_lookup_id( db->strings, table_id ); + colinfo[col - 1].tablename = msi_string_lookup( db->strings, table_id, NULL ); colinfo[col - 1].number = col; - colinfo[col - 1].colname = msi_string_lookup_id( db->strings, id ); + colinfo[col - 1].colname = msi_string_lookup( db->strings, id, NULL ); colinfo[col - 1].type = read_table_int( table->data, i, table->colinfo[3].offset, sizeof(USHORT) ) - (1 << 15); colinfo[col - 1].offset = 0; @@ -763,9 +763,9 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info, UINT table_id = msi_addstringW( db->strings, col->table, -1, 1, string_persistence ); UINT col_id = msi_addstringW( db->strings, col->column, -1, 1, string_persistence ); - table->colinfo[ i ].tablename = msi_string_lookup_id( db->strings, table_id ); + table->colinfo[ i ].tablename = msi_string_lookup( db->strings, table_id, NULL ); table->colinfo[ i ].number = i + 1; - table->colinfo[ i ].colname = msi_string_lookup_id( db->strings, col_id ); + table->colinfo[ i ].colname = msi_string_lookup( db->strings, col_id, NULL ); table->colinfo[ i ].type = col->type; table->colinfo[ i ].offset = 0; table->colinfo[ i ].ref_count = 0; @@ -981,7 +981,7 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name ) !strcmpW( name, szStreams ) || !strcmpW( name, szStorages ) ) return TRUE; - r = msi_string2idW( db->strings, name, &table_id ); + r = msi_string2id( db->strings, name, -1, &table_id ); if( r != ERROR_SUCCESS ) { TRACE("Couldn't find id for %s\n", debugstr_w(name)); @@ -1087,7 +1087,7 @@ static UINT msi_stream_name( const MSITABLEVIEW *tv, UINT row, LPWSTR *pstname ) if ( tv->columns[i].type & MSITYPE_STRING ) { - sval = msi_string_lookup_id( tv->db->strings, ival ); + sval = msi_string_lookup( tv->db->strings, ival, NULL ); if ( !sval ) { r = ERROR_INVALID_PARAMETER; @@ -1273,10 +1273,11 @@ static UINT get_table_value_from_record( MSITABLEVIEW *tv, MSIRECORD *rec, UINT } else if ( columninfo.type & MSITYPE_STRING ) { - LPCWSTR sval = MSI_RecordGetString( rec, iField ); + int len; + const WCHAR *sval = msi_record_get_string( rec, iField, &len ); if (sval) { - r = msi_string2idW(tv->db->strings, sval, pvalue); + r = msi_string2id( tv->db->strings, sval, len, pvalue ); if (r != ERROR_SUCCESS) return ERROR_NOT_FOUND; } @@ -1360,8 +1361,9 @@ static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UI if ( r != ERROR_SUCCESS ) { - LPCWSTR sval = MSI_RecordGetString( rec, i + 1 ); - val = msi_addstringW( tv->db->strings, sval, -1, 1, + int len; + const WCHAR *sval = msi_record_get_string( rec, i + 1, &len ); + val = msi_addstringW( tv->db->strings, sval, len, 1, persistent ? StringPersistent : StringNonPersistent ); } else @@ -1530,10 +1532,10 @@ static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec, UINT *column ) TRACE("skipping binary column\n"); else if ( tv->columns[i].type & MSITYPE_STRING ) { - LPCWSTR str; + int len; + const WCHAR *str = msi_record_get_string( rec, i+1, &len ); - str = MSI_RecordGetString( rec, i+1 ); - if (str == NULL || str[0] == 0) + if (!str || (!str[0] && !len)) { if (column) *column = i; return ERROR_INVALID_DATA; @@ -2139,7 +2141,7 @@ UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view ) else if ( !strcmpW( name, szStorages ) ) return STORAGES_CreateView( db, view ); - sz = sizeof *tv + lstrlenW(name)*sizeof name[0] ; + sz = FIELD_OFFSET( MSITABLEVIEW, name[lstrlenW( name ) + 1] ); tv = msi_alloc_zero( sz ); if( !tv ) return ERROR_FUNCTION_FAILED; @@ -2265,6 +2267,7 @@ static UINT msi_record_encoded_stream_name( const MSITABLEVIEW *tv, MSIRECORD *r if ( !p ) { r = ERROR_OUTOFMEMORY; + msi_free(sval); goto err; } stname = p; @@ -2328,21 +2331,25 @@ static MSIRECORD *msi_get_transform_record( const MSITABLEVIEW *tv, const string r = IStorage_OpenStream( stg, encname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm ); - msi_free( encname ); if ( r != ERROR_SUCCESS ) + { + msi_free( encname ); return NULL; + } MSI_RecordSetStream( rec, i+1, stm ); TRACE(" field %d [%s]\n", i+1, debugstr_w(encname)); + msi_free( encname ); } else if( columns[i].type & MSITYPE_STRING ) { - LPCWSTR sval; + int len; + const WCHAR *sval; val = read_raw_int(rawdata, ofs, bytes_per_strref); - sval = msi_string_lookup_id( st, val ); - MSI_RecordSetStringW( rec, i+1, sval ); - TRACE(" field %d [%s]\n", i+1, debugstr_w(sval)); + sval = msi_string_lookup( st, val, &len ); + msi_record_set_string( rec, i+1, sval, len ); + TRACE(" field %d [%s]\n", i+1, debugstr_wn(sval, len)); ofs += bytes_per_strref; } else @@ -2379,12 +2386,13 @@ static void dump_record( MSIRECORD *rec ) n = MSI_RecordGetFieldCount( rec ); for( i=1; i<=n; i++ ) { - LPCWSTR sval; + int len; + const WCHAR *sval; if( MSI_RecordIsNull( rec, i ) ) TRACE("row -> []\n"); - else if( (sval = MSI_RecordGetString( rec, i )) ) - TRACE("row -> [%s]\n", debugstr_w(sval)); + else if( (sval = msi_record_get_string( rec, i, &len )) ) + TRACE("row -> [%s]\n", debugstr_wn(sval, len)); else TRACE("row -> [0x%08x]\n", MSI_RecordGetInteger( rec, i ) ); } @@ -2392,19 +2400,17 @@ static void dump_record( MSIRECORD *rec ) static void dump_table( const string_table *st, const USHORT *rawdata, UINT rawsize ) { - LPCWSTR sval; UINT i; - - for( i=0; i<(rawsize/2); i++ ) + for (i = 0; i < rawsize / 2; i++) { - sval = msi_string_lookup_id( st, rawdata[i] ); - MESSAGE(" %04x %s\n", rawdata[i], debugstr_w(sval) ); + int len; + const WCHAR *sval = msi_string_lookup( st, rawdata[i], &len ); + MESSAGE(" %04x %s\n", rawdata[i], debugstr_wn(sval, len) ); } } static UINT* msi_record_to_row( const MSITABLEVIEW *tv, MSIRECORD *rec ) { - LPCWSTR str; UINT i, r, *data; data = msi_alloc( tv->num_cols *sizeof (UINT) ); @@ -2419,10 +2425,11 @@ static UINT* msi_record_to_row( const MSITABLEVIEW *tv, MSIRECORD *rec ) if ( ( tv->columns[i].type & MSITYPE_STRING ) && ! MSITYPE_IS_BINARY(tv->columns[i].type) ) { - str = MSI_RecordGetString( rec, i+1 ); + int len; + const WCHAR *str = msi_record_get_string( rec, i+1, &len ); if (str) { - r = msi_string2idW( tv->db->strings, str, &data[i] ); + r = msi_string2id( tv->db->strings, str, len, &data[i] ); /* if there's no matching string in the string table, these keys can't match any record, so fail now. */ diff --git a/reactos/dll/win32/msi/tokenize.c b/reactos/dll/win32/msi/tokenize.c index 47989175b08..441a54aff3d 100644 --- a/reactos/dll/win32/msi/tokenize.c +++ b/reactos/dll/win32/msi/tokenize.c @@ -32,103 +32,108 @@ */ typedef struct Keyword Keyword; struct Keyword { - const WCHAR *zName; /* The keyword name */ + const WCHAR *name; /* The keyword name */ + unsigned int len; int tokenType; /* The token value for this keyword */ }; #define MAX_TOKEN_LEN 11 -static const WCHAR ADD_W[] = { 'A','D','D',0 }; -static const WCHAR ALTER_W[] = { 'A','L','T','E','R',0 }; -static const WCHAR AND_W[] = { 'A','N','D',0 }; -static const WCHAR BY_W[] = { 'B','Y',0 }; -static const WCHAR CHAR_W[] = { 'C','H','A','R',0 }; -static const WCHAR CHARACTER_W[] = { 'C','H','A','R','A','C','T','E','R',0 }; -static const WCHAR CREATE_W[] = { 'C','R','E','A','T','E',0 }; -static const WCHAR DELETE_W[] = { 'D','E','L','E','T','E',0 }; -static const WCHAR DISTINCT_W[] = { 'D','I','S','T','I','N','C','T',0 }; -static const WCHAR DROP_W[] = { 'D','R','O','P',0 }; -static const WCHAR FREE_W[] = { 'F','R','E','E',0 }; -static const WCHAR FROM_W[] = { 'F','R','O','M',0 }; -static const WCHAR HOLD_W[] = { 'H','O','L','D',0 }; -static const WCHAR INSERT_W[] = { 'I','N','S','E','R','T',0 }; -static const WCHAR INT_W[] = { 'I','N','T',0 }; -static const WCHAR INTEGER_W[] = { 'I','N','T','E','G','E','R',0 }; -static const WCHAR INTO_W[] = { 'I','N','T','O',0 }; -static const WCHAR IS_W[] = { 'I','S',0 }; -static const WCHAR KEY_W[] = { 'K','E','Y',0 }; -static const WCHAR LIKE_W[] = { 'L','I','K','E',0 }; -static const WCHAR LOCALIZABLE_W[] = { 'L','O','C','A','L','I','Z','A','B','L','E',0 }; -static const WCHAR LONG_W[] = { 'L','O','N','G',0 }; -static const WCHAR LONGCHAR_W[] = { 'L','O','N','G','C','H','A','R',0 }; -static const WCHAR NOT_W[] = { 'N','O','T',0 }; -static const WCHAR NULL_W[] = { 'N','U','L','L',0 }; -static const WCHAR OBJECT_W[] = { 'O','B','J','E','C','T',0 }; -static const WCHAR OR_W[] = { 'O','R',0 }; -static const WCHAR ORDER_W[] = { 'O','R','D','E','R',0 }; -static const WCHAR PRIMARY_W[] = { 'P','R','I','M','A','R','Y',0 }; -static const WCHAR SELECT_W[] = { 'S','E','L','E','C','T',0 }; -static const WCHAR SET_W[] = { 'S','E','T',0 }; -static const WCHAR SHORT_W[] = { 'S','H','O','R','T',0 }; -static const WCHAR TABLE_W[] = { 'T','A','B','L','E',0 }; -static const WCHAR TEMPORARY_W[] = { 'T','E','M','P','O','R','A','R','Y',0 }; -static const WCHAR UPDATE_W[] = { 'U','P','D','A','T','E',0 }; -static const WCHAR VALUES_W[] = { 'V','A','L','U','E','S',0 }; -static const WCHAR WHERE_W[] = { 'W','H','E','R','E',0 }; +static const WCHAR addW[] = {'A','D','D'}; +static const WCHAR alterW[] = {'A','L','T','E','R'}; +static const WCHAR andW[] = {'A','N','D'}; +static const WCHAR byW[] = {'B','Y'}; +static const WCHAR charW[] = {'C','H','A','R'}; +static const WCHAR characterW[] = {'C','H','A','R','A','C','T','E','R'}; +static const WCHAR createW[] = {'C','R','E','A','T','E'}; +static const WCHAR deleteW[] = {'D','E','L','E','T','E'}; +static const WCHAR distinctW[] = {'D','I','S','T','I','N','C','T'}; +static const WCHAR dropW[] = {'D','R','O','P'}; +static const WCHAR freeW[] = {'F','R','E','E'}; +static const WCHAR fromW[] = {'F','R','O','M'}; +static const WCHAR holdW[] = {'H','O','L','D'}; +static const WCHAR insertW[] = {'I','N','S','E','R','T'}; +static const WCHAR intW[] = {'I','N','T'}; +static const WCHAR integerW[] = {'I','N','T','E','G','E','R'}; +static const WCHAR intoW[] = {'I','N','T','O'}; +static const WCHAR isW[] = {'I','S'}; +static const WCHAR keyW[] = {'K','E','Y'}; +static const WCHAR likeW[] = {'L','I','K','E'}; +static const WCHAR localizableW[] = {'L','O','C','A','L','I','Z','A','B','L','E'}; +static const WCHAR longW[] = {'L','O','N','G'}; +static const WCHAR longcharW[] = {'L','O','N','G','C','H','A','R'}; +static const WCHAR notW[] = {'N','O','T'}; +static const WCHAR nullW[] = {'N','U','L','L'}; +static const WCHAR objectW[] = {'O','B','J','E','C','T'}; +static const WCHAR orW[] = {'O','R'}; +static const WCHAR orderW[] = {'O','R','D','E','R'}; +static const WCHAR primaryW[] = {'P','R','I','M','A','R','Y'}; +static const WCHAR selectW[] = {'S','E','L','E','C','T'}; +static const WCHAR setW[] = {'S','E','T'}; +static const WCHAR shortW[] = {'S','H','O','R','T'}; +static const WCHAR tableW[] = {'T','A','B','L','E'}; +static const WCHAR temporaryW[] = {'T','E','M','P','O','R','A','R','Y'}; +static const WCHAR updateW[] = {'U','P','D','A','T','E'}; +static const WCHAR valuesW[] = {'V','A','L','U','E','S'}; +static const WCHAR whereW[] = {'W','H','E','R','E'}; + +#define ARRAY_SIZE(array) (sizeof(array)/sizeof((array)[0])) /* ** These are the keywords ** They MUST be in alphabetical order */ static const Keyword aKeywordTable[] = { - { ADD_W, TK_ADD }, - { ALTER_W, TK_ALTER }, - { AND_W, TK_AND }, - { BY_W, TK_BY }, - { CHAR_W, TK_CHAR }, - { CHARACTER_W, TK_CHAR }, - { CREATE_W, TK_CREATE }, - { DELETE_W, TK_DELETE }, - { DISTINCT_W, TK_DISTINCT }, - { DROP_W, TK_DROP }, - { FREE_W, TK_FREE }, - { FROM_W, TK_FROM }, - { HOLD_W, TK_HOLD }, - { INSERT_W, TK_INSERT }, - { INT_W, TK_INT }, - { INTEGER_W, TK_INT }, - { INTO_W, TK_INTO }, - { IS_W, TK_IS }, - { KEY_W, TK_KEY }, - { LIKE_W, TK_LIKE }, - { LOCALIZABLE_W, TK_LOCALIZABLE }, - { LONG_W, TK_LONG }, - { LONGCHAR_W, TK_LONGCHAR }, - { NOT_W, TK_NOT }, - { NULL_W, TK_NULL }, - { OBJECT_W, TK_OBJECT }, - { OR_W, TK_OR }, - { ORDER_W, TK_ORDER }, - { PRIMARY_W, TK_PRIMARY }, - { SELECT_W, TK_SELECT }, - { SET_W, TK_SET }, - { SHORT_W, TK_SHORT }, - { TABLE_W, TK_TABLE }, - { TEMPORARY_W, TK_TEMPORARY }, - { UPDATE_W, TK_UPDATE }, - { VALUES_W, TK_VALUES }, - { WHERE_W, TK_WHERE }, + { addW, ARRAY_SIZE(addW), TK_ADD }, + { alterW, ARRAY_SIZE(alterW), TK_ALTER }, + { andW, ARRAY_SIZE(andW), TK_AND }, + { byW, ARRAY_SIZE(byW), TK_BY }, + { charW, ARRAY_SIZE(charW), TK_CHAR }, + { characterW, ARRAY_SIZE(characterW), TK_CHAR }, + { createW, ARRAY_SIZE(createW), TK_CREATE }, + { deleteW, ARRAY_SIZE(deleteW), TK_DELETE }, + { distinctW, ARRAY_SIZE(distinctW), TK_DISTINCT }, + { dropW, ARRAY_SIZE(dropW), TK_DROP }, + { freeW, ARRAY_SIZE(freeW), TK_FREE }, + { fromW, ARRAY_SIZE(fromW), TK_FROM }, + { holdW, ARRAY_SIZE(holdW), TK_HOLD }, + { insertW, ARRAY_SIZE(insertW), TK_INSERT }, + { intW, ARRAY_SIZE(intW), TK_INT }, + { integerW, ARRAY_SIZE(integerW), TK_INT }, + { intoW, ARRAY_SIZE(intoW), TK_INTO }, + { isW, ARRAY_SIZE(isW), TK_IS }, + { keyW, ARRAY_SIZE(keyW), TK_KEY }, + { likeW, ARRAY_SIZE(likeW), TK_LIKE }, + { localizableW, ARRAY_SIZE(localizableW), TK_LOCALIZABLE }, + { longW, ARRAY_SIZE(longW), TK_LONG }, + { longcharW, ARRAY_SIZE(longcharW), TK_LONGCHAR }, + { notW, ARRAY_SIZE(notW), TK_NOT }, + { nullW, ARRAY_SIZE(nullW), TK_NULL }, + { objectW, ARRAY_SIZE(objectW), TK_OBJECT }, + { orW, ARRAY_SIZE(orW), TK_OR }, + { orderW, ARRAY_SIZE(orderW), TK_ORDER }, + { primaryW, ARRAY_SIZE(primaryW), TK_PRIMARY }, + { selectW, ARRAY_SIZE(selectW), TK_SELECT }, + { setW, ARRAY_SIZE(setW), TK_SET }, + { shortW, ARRAY_SIZE(shortW), TK_SHORT }, + { tableW, ARRAY_SIZE(tableW), TK_TABLE }, + { temporaryW, ARRAY_SIZE(temporaryW), TK_TEMPORARY }, + { updateW, ARRAY_SIZE(updateW), TK_UPDATE }, + { valuesW, ARRAY_SIZE(valuesW), TK_VALUES }, + { whereW, ARRAY_SIZE(whereW), TK_WHERE }, }; -#define KEYWORD_COUNT ( sizeof aKeywordTable/sizeof (Keyword) ) - /* ** Comparison function for binary search. */ static int compKeyword(const void *m1, const void *m2){ const Keyword *k1 = m1, *k2 = m2; + int ret, len = min( k1->len, k2->len ); - return strcmpiW( k1->zName, k2->zName ); + if ((ret = memicmpW( k1->name, k2->name, len ))) return ret; + if (k1->len < k2->len) return -1; + else if (k1->len > k2->len) return 1; + return 0; } /* @@ -137,17 +142,15 @@ static int compKeyword(const void *m1, const void *m2){ ** returned. If the input is not a keyword, TK_ID is returned. */ static int sqliteKeywordCode(const WCHAR *z, int n){ - WCHAR str[MAX_TOKEN_LEN+1]; Keyword key, *r; if( n>MAX_TOKEN_LEN ) return TK_ID; - memcpy( str, z, n*sizeof (WCHAR) ); - str[n] = 0; key.tokenType = 0; - key.zName = str; - r = bsearch( &key, aKeywordTable, KEYWORD_COUNT, sizeof (Keyword), compKeyword ); + key.name = z; + key.len = n; + r = bsearch( &key, aKeywordTable, ARRAY_SIZE(aKeywordTable), sizeof(Keyword), compKeyword ); if( r ) return r->tokenType; return TK_ID; diff --git a/reactos/dll/win32/msi/upgrade.c b/reactos/dll/win32/msi/upgrade.c index 94806610045..cd0ec06e6e2 100644 --- a/reactos/dll/win32/msi/upgrade.c +++ b/reactos/dll/win32/msi/upgrade.c @@ -88,7 +88,7 @@ static void append_productcode(MSIPACKAGE* package, LPCWSTR action_property, newprop[0] = 0; strcatW(newprop,productid); - r = msi_set_property( package->db, action_property, newprop ); + r = msi_set_property( package->db, action_property, newprop, -1 ); if (r == ERROR_SUCCESS && !strcmpW( action_property, szSourceDir )) msi_reset_folders( package, TRUE ); diff --git a/reactos/dll/win32/msi/where.c b/reactos/dll/win32/msi/where.c index 36c8ec83e01..1bf77889580 100644 --- a/reactos/dll/win32/msi/where.c +++ b/reactos/dll/win32/msi/where.c @@ -494,7 +494,7 @@ static UINT STRING_evaluate( MSIWHEREVIEW *wv, const UINT rows[], case EXPR_COL_NUMBER_STRING: r = expr_fetch_value(&expr->u.column, rows, &val); if (r == ERROR_SUCCESS) - *str = msi_string_lookup_id(wv->db->strings, val); + *str = msi_string_lookup(wv->db->strings, val, NULL); else *str = NULL; break; @@ -883,7 +883,7 @@ static UINT join_find_row( MSIWHEREVIEW *wv, MSIRECORD *rec, UINT *row ) UINT r, i, id, data; str = MSI_RecordGetString( rec, 1 ); - r = msi_string2idW( wv->db->strings, str, &id ); + r = msi_string2id( wv->db->strings, str, -1, &id ); if (r != ERROR_SUCCESS) return r; @@ -1253,6 +1253,8 @@ UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables, if (r != ERROR_SUCCESS) { ERR("can't get table dimensions\n"); + table->view->ops->delete(table->view); + msi_free(table); goto end; } diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index f99e2ddc018..102df897458 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -103,7 +103,7 @@ reactos/dll/win32/msg711.acm # Synced to Wine-1.5.4 reactos/dll/win32/msgsm32.acm # Synced to Wine-1.5.4 reactos/dll/win32/mshtml # Autosync reactos/dll/win32/mshtml.tlb # Autosync -reactos/dll/win32/msi # Synced to Wine-1.5.10 +reactos/dll/win32/msi # Synced to Wine-1.5.19 reactos/dll/win32/msimg32 # Synced to Wine-1.5.4 reactos/dll/win32/msimtf # Synced to Wine-1.5.4 reactos/dll/win32/msisip # Synced to Wine-1.5.4 -- 2.17.1