Index: dll/win32/msi/action.c =================================================================== --- dll/win32/msi/action.c (revision 58430) +++ dll/win32/msi/action.c (working copy) @@ -688,18 +688,6 @@ return NULL; } -MSIFILEPATCH *msi_get_loaded_filepatch( MSIPACKAGE *package, const WCHAR *key ) -{ - MSIFILEPATCH *patch; - - /* FIXME: There might be more than one patch */ - LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry ) - { - if (!strcmpW( key, patch->File->File )) return patch; - } - return NULL; -} - MSIFOLDER *msi_get_loaded_folder( MSIPACKAGE *package, const WCHAR *dir ) { MSIFOLDER *folder; @@ -1788,7 +1776,7 @@ ret |= process_state_property( package, level, szReinstall, INSTALLSTATE_UNKNOWN ); ret |= process_state_property( package, level, szAdvertise, INSTALLSTATE_ADVERTISED ); - if (ret) + if (ret && !package->full_reinstall) msi_set_property( package->db, szPreselected, szOne, -1 ); return ret; @@ -4856,12 +4844,12 @@ if (!msi_check_publish(package)) return ERROR_SUCCESS; - rc = MSIREG_OpenFeaturesKey(package->ProductCode, package->Context, + rc = MSIREG_OpenFeaturesKey(package->ProductCode, NULL, package->Context, &hkey, TRUE); if (rc != ERROR_SUCCESS) goto end; - rc = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, package->Context, + rc = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, NULL, package->Context, &userdata, TRUE); if (rc != ERROR_SUCCESS) goto end; @@ -4961,7 +4949,7 @@ TRACE("unpublishing feature %s\n", debugstr_w(feature->Feature)); - r = MSIREG_OpenFeaturesKey(package->ProductCode, package->Context, + r = MSIREG_OpenFeaturesKey(package->ProductCode, NULL, package->Context, &hkey, FALSE); if (r == ERROR_SUCCESS) { @@ -4969,7 +4957,7 @@ RegCloseKey(hkey); } - r = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, package->Context, + r = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, NULL, package->Context, &hkey, FALSE); if (r == ERROR_SUCCESS) { @@ -7264,12 +7252,14 @@ {'m','s','i','e','x','e','c',' ','/','i',' ','%','s',' ','R','E','M','O','V','E','=','%','s',0}; MSIPACKAGE *package = param; const WCHAR *property = MSI_RecordGetString( rec, 7 ); + int attrs = MSI_RecordGetInteger( rec, 5 ); UINT len = sizeof(fmtW)/sizeof(fmtW[0]); WCHAR *product, *features, *cmd; STARTUPINFOW si; PROCESS_INFORMATION info; BOOL ret; + if (attrs & msidbUpgradeAttributesOnlyDetect) return ERROR_SUCCESS; if (!(product = msi_dup_property( package->db, property ))) return ERROR_SUCCESS; deformat_string( package, MSI_RecordGetString( rec, 6 ), &features ); @@ -7789,10 +7779,12 @@ { TRACE("setting REINSTALL property to ALL\n"); msi_set_property( package->db, szReinstall, szAll, -1 ); + package->full_reinstall = 1; } /* properties may have been added by a transform */ msi_clone_properties( package ); + msi_set_original_database_property( package->db, szPackagePath ); msi_parse_command_line( package, szCommandLine, FALSE ); msi_adjust_privilege_properties( package ); Index: dll/win32/msi/automation.c =================================================================== --- dll/win32/msi/automation.c (revision 58430) +++ dll/win32/msi/automation.c (working copy) @@ -1620,7 +1620,7 @@ static void variant_from_registry_value(VARIANT *pVarResult, DWORD dwType, LPBYTE lpData, DWORD dwSize) { static const WCHAR szREG_BINARY[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 }; - static const WCHAR szREG_[] = { '(','R','E','G','_',']',0 }; + static const WCHAR szREG_[] = { '(','R','E','G','_','?','?',')',0 }; WCHAR *szString = (WCHAR *)lpData; LPWSTR szNewString = NULL; DWORD dwNewSize = 0; Index: dll/win32/msi/custom.c =================================================================== --- dll/win32/msi/custom.c (revision 58430) +++ dll/win32/msi/custom.c (working copy) @@ -622,43 +622,6 @@ return rc; } -static DWORD ACTION_CAInstallPackage(const GUID *guid) -{ - msi_custom_action_info *info; - UINT r = ERROR_FUNCTION_FAILED; - INSTALLUILEVEL old_level; - - info = find_action_by_guid(guid); - if (!info) - { - ERR("failed to find action %s\n", debugstr_guid(guid)); - return r; - } - - old_level = MsiSetInternalUI(INSTALLUILEVEL_BASIC, NULL); - r = MsiInstallProductW(info->source, info->target); - MsiSetInternalUI(old_level, NULL); - - release_custom_action_data(info); - - return r; -} - -static DWORD WINAPI ConcurrentInstallThread(LPVOID arg) -{ - LPGUID guid = arg; - DWORD rc; - - TRACE("concurrent installation (%x) started\n", GetCurrentThreadId()); - - rc = ACTION_CAInstallPackage(guid); - - TRACE("concurrent installation (%x) returned %i\n", GetCurrentThreadId(), rc); - - MsiCloseAllHandles(); - return rc; -} - static msi_custom_action_info *do_msidbCustomActionTypeDll( MSIPACKAGE *package, INT type, LPCWSTR source, LPCWSTR target, LPCWSTR action ) { @@ -693,62 +656,10 @@ return info; } -static msi_custom_action_info *do_msidbCAConcurrentInstall( - MSIPACKAGE *package, INT type, LPCWSTR source, LPCWSTR target, LPCWSTR action) +static UINT HANDLE_CustomType1( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { msi_custom_action_info *info; - - info = msi_alloc( sizeof *info ); - if (!info) - return NULL; - - msiobj_addref( &package->hdr ); - info->refs = 2; /* 1 for our caller and 1 for thread we created */ - info->package = package; - info->type = type; - info->target = strdupW( target ); - info->source = strdupW( source ); - info->action = strdupW( action ); - CoCreateGuid( &info->guid ); - - EnterCriticalSection( &msi_custom_action_cs ); - list_add_tail( &msi_pending_custom_actions, &info->entry ); - LeaveCriticalSection( &msi_custom_action_cs ); - - info->handle = CreateThread( NULL, 0, ConcurrentInstallThread, &info->guid, 0, NULL ); - if (!info->handle) - { - /* release both references */ - release_custom_action_data( info ); - release_custom_action_data( info ); - return NULL; - } - - return info; -} - -static UINT HANDLE_CustomType23(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) -{ - msi_custom_action_info *info; - WCHAR package_path[MAX_PATH]; - DWORD size; - - size = MAX_PATH; - msi_get_property(package->db, szSourceDir, package_path, &size); - lstrcatW(package_path, szBackSlash); - lstrcatW(package_path, source); - - TRACE("Installing package %s concurrently\n", debugstr_w(package_path)); - - info = do_msidbCAConcurrentInstall(package, type, package_path, target, action); - return wait_thread_handle(info); -} - -static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) -{ - msi_custom_action_info *info; MSIBINARY *binary; if (!(binary = get_temp_binary( package, source, TRUE ))) @@ -828,8 +739,8 @@ return info.hProcess; } -static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType2( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { MSIBINARY *binary; HANDLE handle; @@ -846,8 +757,8 @@ return wait_process_handle( package, type, handle, action ); } -static UINT HANDLE_CustomType17(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType17( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { msi_custom_action_info *info; MSIFILE *file; @@ -865,8 +776,8 @@ return wait_thread_handle( info ); } -static UINT HANDLE_CustomType18(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType18( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { MSIFILE *file; HANDLE handle; @@ -883,8 +794,8 @@ return wait_process_handle( package, type, handle, action ); } -static UINT HANDLE_CustomType19(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType19( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { static const WCHAR query[] = { 'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ', @@ -914,9 +825,53 @@ return ERROR_INSTALL_FAILURE; } -static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType23( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { + static const WCHAR msiexecW[] = {'m','s','i','e','x','e','c',0}; + static const WCHAR paramsW[] = {'/','q','b',' ','/','i',' '}; + WCHAR *dir, *arg, *p; + UINT len_src, len_dir, len_tgt, len = sizeof(paramsW)/sizeof(paramsW[0]); + HANDLE handle; + + if (!(dir = msi_dup_property( package->db, szOriginalDatabase ))) return ERROR_OUTOFMEMORY; + if (!(p = strrchrW( dir, '\\' )) && !(p = strrchrW( dir, '/' ))) + { + msi_free( dir ); + return ERROR_FUNCTION_FAILED; + } + *p = 0; + len_dir = p - dir; + len_src = strlenW( source ); + len_tgt = strlenW( target ); + if (!(arg = msi_alloc( (len + len_dir + len_src + len_tgt + 5) * sizeof(WCHAR) ))) + { + msi_free( dir ); + return ERROR_OUTOFMEMORY; + } + memcpy( arg, paramsW, sizeof(paramsW) ); + arg[len++] = '"'; + memcpy( arg + len, dir, len_dir * sizeof(WCHAR) ); + len += len_dir; + arg[len++] = '\\'; + memcpy( arg + len, source, len_src * sizeof(WCHAR) ); + len += len_src; + arg[len++] = '"'; + arg[len++] = ' '; + strcpyW( arg + len, target ); + + TRACE("installing %s concurrently\n", debugstr_w(source)); + + handle = execute_command( msiexecW, arg, dir ); + msi_free( dir ); + msi_free( arg ); + if (handle == INVALID_HANDLE_VALUE) return ERROR_SUCCESS; + return wait_process_handle( package, type, handle, action ); +} + +static UINT HANDLE_CustomType50( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) +{ WCHAR *exe, *arg; HANDLE handle; @@ -931,8 +886,8 @@ return wait_process_handle( package, type, handle, action ); } -static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType34( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { const WCHAR *workingdir = NULL; HANDLE handle; @@ -1032,8 +987,8 @@ return info; } -static UINT HANDLE_CustomType37_38(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType37_38( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { msi_custom_action_info *info; @@ -1043,8 +998,8 @@ return wait_thread_handle( info ); } -static UINT HANDLE_CustomType5_6(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType5_6( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { static const WCHAR query[] = { 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', @@ -1090,8 +1045,8 @@ return r; } -static UINT HANDLE_CustomType21_22(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType21_22( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { msi_custom_action_info *info; MSIFILE *file; @@ -1149,8 +1104,8 @@ return r; } -static UINT HANDLE_CustomType53_54(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType53_54( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { msi_custom_action_info *info; WCHAR *prop; Index: dll/win32/msi/dialog.c =================================================================== --- dll/win32/msi/dialog.c (revision 58430) +++ dll/win32/msi/dialog.c (working copy) @@ -696,7 +696,7 @@ else if ( !strcmpW( attribute, szProperty ) ) { MSIFEATURE *feature = msi_seltree_get_selected_feature( ctrl ); - msi_dialog_set_property( dialog->package, ctrl->property, feature->Directory ); + if (feature) msi_dialog_set_property( dialog->package, ctrl->property, feature->Directory ); } else if ( !strcmpW( attribute, szSelectionPath ) ) { @@ -1139,7 +1139,7 @@ msi_dialog_map_events(dialog, name); - control = msi_alloc( sizeof(*control) + strlenW(name) * sizeof(WCHAR) ); + control = msi_alloc( FIELD_OFFSET(msi_control, name[strlenW( name ) + 1] )); if (!control) return ERROR_OUTOFMEMORY; @@ -1808,7 +1808,6 @@ if( i == info->num_groups ) { TRACE("Set property %s to %s\n", debugstr_w(info->prop), debugstr_w(val)); - CharUpperBuffW( val, info->num_chars ); msi_dialog_set_property( info->dialog->package, info->prop, val ); msi_dialog_evaluate_control_conditions( info->dialog ); } @@ -3739,7 +3738,7 @@ msi_dialog_register_class(); /* allocate the structure for the dialog to use */ - dialog = msi_alloc_zero( sizeof *dialog + sizeof(WCHAR)*strlenW(szDialogName) ); + dialog = msi_alloc_zero( FIELD_OFFSET( msi_dialog, name[strlenW( szDialogName ) + 1] )); if( !dialog ) return NULL; strcpyW( dialog->name, szDialogName ); Index: dll/win32/msi/files.c =================================================================== --- dll/win32/msi/files.c (revision 58430) +++ dll/win32/msi/files.c (working copy) @@ -447,6 +447,17 @@ FreeLibrary(hmspatcha); } +static MSIFILEPATCH *get_next_filepatch( MSIPACKAGE *package, const WCHAR *key ) +{ + MSIFILEPATCH *patch; + + LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry ) + { + if (!patch->IsApplied && !strcmpW( key, patch->File->File )) return patch; + } + return NULL; +} + static BOOL patchfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action, LPWSTR *path, DWORD *attrs, PVOID user) { @@ -459,12 +470,9 @@ if (temp_folder[0] == '\0') GetTempPathW(MAX_PATH, temp_folder); - p = msi_get_loaded_filepatch(package, file); - if (!p) - { - TRACE("unknown file in cabinet (%s)\n", debugstr_w(file)); + if (!(p = get_next_filepatch(package, file)) || !p->File->Component->Enabled) return FALSE; - } + GetTempFileNameW(temp_folder, NULL, 0, patch_path); *path = strdupW(patch_path); Index: dll/win32/msi/msi.c =================================================================== --- dll/win32/msi/msi.c (revision 58430) +++ dll/win32/msi/msi.c (working copy) @@ -2922,6 +2922,123 @@ return r; } +static UINT query_feature_state( const WCHAR *product, const WCHAR *squashed, const WCHAR *usersid, + MSIINSTALLCONTEXT ctx, const WCHAR *feature, INSTALLSTATE *state ) +{ + UINT r; + HKEY hkey; + WCHAR *parent, *components, *path; + const WCHAR *p; + BOOL missing = FALSE, source = FALSE; + WCHAR comp[GUID_SIZE]; + GUID guid; + + if (ctx != MSIINSTALLCONTEXT_MACHINE) SetLastError( ERROR_SUCCESS ); + + if (MSIREG_OpenFeaturesKey( product, usersid, ctx, &hkey, FALSE )) return ERROR_UNKNOWN_PRODUCT; + + parent = msi_reg_get_val_str( hkey, feature ); + RegCloseKey( hkey ); + if (!parent) return ERROR_UNKNOWN_FEATURE; + + *state = (parent[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL; + msi_free( parent ); + if (*state == INSTALLSTATE_ABSENT) + return ERROR_SUCCESS; + + r = MSIREG_OpenUserDataFeaturesKey( product, usersid, ctx, &hkey, FALSE ); + if (r != ERROR_SUCCESS) + { + *state = INSTALLSTATE_ADVERTISED; + return ERROR_SUCCESS; + } + components = msi_reg_get_val_str( hkey, feature ); + RegCloseKey( hkey ); + + TRACE("buffer = %s\n", debugstr_w(components)); + + if (!components) + { + *state = INSTALLSTATE_ADVERTISED; + return ERROR_SUCCESS; + } + for (p = components; *p && *p != 2 ; p += 20) + { + if (!decode_base85_guid( p, &guid )) + { + if (p != components) break; + msi_free( components ); + *state = INSTALLSTATE_BADCONFIG; + return ERROR_BAD_CONFIGURATION; + } + StringFromGUID2( &guid, comp, GUID_SIZE ); + if (ctx == MSIINSTALLCONTEXT_MACHINE) + r = MSIREG_OpenUserDataComponentKey( comp, szLocalSid, &hkey, FALSE ); + else + r = MSIREG_OpenUserDataComponentKey( comp, usersid, &hkey, FALSE ); + + if (r != ERROR_SUCCESS) + { + msi_free( components ); + *state = INSTALLSTATE_ADVERTISED; + return ERROR_SUCCESS; + } + path = msi_reg_get_val_str( hkey, squashed ); + if (!path) missing = TRUE; + else if (strlenW( path ) > 2 && + path[0] >= '0' && path[0] <= '9' && + path[1] >= '0' && path[1] <= '9') + { + source = TRUE; + } + msi_free( path ); + } + msi_free( components ); + + if (missing) + *state = INSTALLSTATE_ADVERTISED; + else if (source) + *state = INSTALLSTATE_SOURCE; + else + *state = INSTALLSTATE_LOCAL; + + TRACE("returning state %d\n", *state); + return ERROR_SUCCESS; +} + +UINT WINAPI MsiQueryFeatureStateExW( LPCWSTR product, LPCWSTR usersid, MSIINSTALLCONTEXT ctx, + LPCWSTR feature, INSTALLSTATE *state ) +{ + WCHAR squashed[33]; + if (!squash_guid( product, squashed )) return ERROR_INVALID_PARAMETER; + return query_feature_state( product, squashed, usersid, ctx, feature, state ); +} + +UINT WINAPI MsiQueryFeatureStateExA( LPCSTR product, LPCSTR usersid, MSIINSTALLCONTEXT ctx, + LPCSTR feature, INSTALLSTATE *state ) +{ + UINT r; + WCHAR *productW = NULL, *usersidW = NULL, *featureW = NULL; + + if (product && !(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY; + if (usersid && !(usersidW = strdupAtoW( usersid ))) + { + msi_free( productW ); + return ERROR_OUTOFMEMORY; + } + if (feature && !(featureW = strdupAtoW( feature ))) + { + msi_free( productW ); + msi_free( usersidW ); + return ERROR_OUTOFMEMORY; + } + r = MsiQueryFeatureStateExW( productW, usersidW, ctx, featureW, state ); + msi_free( productW ); + msi_free( usersidW ); + msi_free( featureW ); + return r; +} + /****************************************************************** * MsiQueryFeatureStateA [MSI.@] */ @@ -2966,117 +3083,25 @@ */ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) { - WCHAR squishProduct[33], comp[GUID_SIZE]; - GUID guid; - LPWSTR components, p, parent_feature, path; - UINT rc; - HKEY hkey; - INSTALLSTATE r; - BOOL missing = FALSE; - BOOL machine = FALSE; - BOOL source = FALSE; + UINT r; + INSTALLSTATE state; + WCHAR squashed[33]; TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature)); - if (!szProduct || !szFeature) + if (!szProduct || !szFeature || !squash_guid( szProduct, squashed )) return INSTALLSTATE_INVALIDARG; - if (!squash_guid( szProduct, squishProduct )) - return INSTALLSTATE_INVALIDARG; + r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERMANAGED, szFeature, &state ); + if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state; - SetLastError( ERROR_SUCCESS ); + r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, szFeature, &state ); + if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state; - if (MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED, - &hkey, FALSE) != ERROR_SUCCESS && - MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, - &hkey, FALSE) != ERROR_SUCCESS) - { - rc = MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_MACHINE, - &hkey, FALSE); - if (rc != ERROR_SUCCESS) - return INSTALLSTATE_UNKNOWN; + r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_MACHINE, szFeature, &state ); + if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state; - machine = TRUE; - } - - parent_feature = msi_reg_get_val_str( hkey, szFeature ); - RegCloseKey(hkey); - - if (!parent_feature) - return INSTALLSTATE_UNKNOWN; - - r = (parent_feature[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL; - msi_free(parent_feature); - if (r == INSTALLSTATE_ABSENT) - return r; - - if (machine) - rc = MSIREG_OpenUserDataFeaturesKey(szProduct, - MSIINSTALLCONTEXT_MACHINE, - &hkey, FALSE); - else - rc = MSIREG_OpenUserDataFeaturesKey(szProduct, - MSIINSTALLCONTEXT_USERUNMANAGED, - &hkey, FALSE); - - if (rc != ERROR_SUCCESS) - return INSTALLSTATE_ADVERTISED; - - components = msi_reg_get_val_str( hkey, szFeature ); - RegCloseKey(hkey); - - TRACE("rc = %d buffer = %s\n", rc, debugstr_w(components)); - - if (!components) - return INSTALLSTATE_ADVERTISED; - - for( p = components; *p && *p != 2 ; p += 20) - { - if (!decode_base85_guid( p, &guid )) - { - if (p != components) - break; - - msi_free(components); - return INSTALLSTATE_BADCONFIG; - } - - StringFromGUID2(&guid, comp, GUID_SIZE); - - if (machine) - rc = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE); - else - rc = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE); - - if (rc != ERROR_SUCCESS) - { - msi_free(components); - return INSTALLSTATE_ADVERTISED; - } - - path = msi_reg_get_val_str(hkey, squishProduct); - if (!path) - missing = TRUE; - else if (lstrlenW(path) > 2 && - path[0] >= '0' && path[0] <= '9' && - path[1] >= '0' && path[1] <= '9') - { - source = TRUE; - } - - msi_free(path); - } - msi_free(components); - - if (missing) - r = INSTALLSTATE_ADVERTISED; - else if (source) - r = INSTALLSTATE_SOURCE; - else - r = INSTALLSTATE_LOCAL; - - TRACE("-> %d\n", r); - return r; + return INSTALLSTATE_UNKNOWN; } /****************************************************************** @@ -3137,7 +3162,7 @@ static const WCHAR szVersionResource[] = {'\\',0}; static const WCHAR szVersionFormat[] = {'%','d','.','%','d','.','%','d','.','%','d',0}; static const WCHAR szLangFormat[] = {'%','d',0}; - UINT ret = ERROR_SUCCESS; + UINT ret = ERROR_MORE_DATA; DWORD len, error; LPVOID version; VS_FIXEDFILEINFO *ffi; @@ -3148,6 +3173,7 @@ { error = GetLastError(); if (error == ERROR_BAD_PATHNAME) return ERROR_FILE_NOT_FOUND; + if (error == ERROR_RESOURCE_DATA_NOT_FOUND) return ERROR_FILE_INVALID; return error; } if (!(version = msi_alloc( len ))) return ERROR_OUTOFMEMORY; @@ -3156,6 +3182,11 @@ msi_free( version ); return GetLastError(); } + if (!verbuf && !verlen && !langbuf && !langlen) + { + msi_free( version ); + return ERROR_SUCCESS; + } if (verlen) { if (VerQueryValueW( version, szVersionResource, (LPVOID *)&ffi, &len ) && len > 0) @@ -3165,7 +3196,7 @@ HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS) ); if (verbuf) lstrcpynW( verbuf, tmp, *verlen ); len = strlenW( tmp ); - if (len >= *verlen) ret = ERROR_MORE_DATA; + if (*verlen > len) ret = ERROR_SUCCESS; *verlen = len; } else @@ -3181,7 +3212,7 @@ sprintfW( tmp, szLangFormat, *lang ); if (langbuf) lstrcpynW( langbuf, tmp, *langlen ); len = strlenW( tmp ); - if (len >= *langlen) ret = ERROR_MORE_DATA; + if (*langlen > len) ret = ERROR_SUCCESS; *langlen = len; } else @@ -3789,7 +3820,7 @@ lstrcatW(path, installerW); - if (!CreateDirectoryW(path, NULL)) + if (!CreateDirectoryW(path, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) return ERROR_FUNCTION_FAILED; return ERROR_SUCCESS; Index: dll/win32/msi/msi.spec =================================================================== --- dll/win32/msi/msi.spec (revision 58430) +++ dll/win32/msi/msi.spec (working copy) @@ -244,8 +244,8 @@ 248 stdcall MsiGetProductInfoExW(wstr wstr long wstr ptr ptr) 249 stdcall MsiQueryComponentStateA(str str long str ptr) 250 stdcall MsiQueryComponentStateW(wstr wstr long wstr ptr) -251 stub MsiQueryFeatureStateExA -252 stub MsiQueryFeatureStateExW +251 stdcall MsiQueryFeatureStateExA(str str long str ptr) +252 stdcall MsiQueryFeatureStateExW(wstr wstr long wstr ptr) 253 stdcall MsiDeterminePatchSequenceA(str str long long ptr) 254 stdcall MsiDeterminePatchSequenceW(wstr wstr long long ptr) 255 stdcall MsiSourceListAddSourceExA(str str long long str long) Index: dll/win32/msi/msipriv.h =================================================================== --- dll/win32/msi/msipriv.h (revision 58430) +++ dll/win32/msi/msipriv.h (working copy) @@ -338,6 +338,7 @@ enum platform { + PLATFORM_UNKNOWN, PLATFORM_INTEL, PLATFORM_INTEL64, PLATFORM_X64, @@ -414,6 +415,7 @@ unsigned char need_reboot_at_end : 1; unsigned char need_reboot_now : 1; unsigned char need_rollback : 1; + unsigned char full_reinstall : 1; } MSIPACKAGE; typedef struct tagMSIPREVIEW @@ -884,10 +886,10 @@ extern UINT MSIREG_DeleteUninstallKey(const WCHAR *, enum platform) DECLSPEC_HIDDEN; extern UINT MSIREG_OpenProductKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context, HKEY* key, BOOL create) DECLSPEC_HIDDEN; -extern UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context, +extern UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context, HKEY *key, BOOL create) DECLSPEC_HIDDEN; extern UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create) DECLSPEC_HIDDEN; -UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context, +UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context, HKEY *key, BOOL create) DECLSPEC_HIDDEN; extern UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create) DECLSPEC_HIDDEN; extern UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid, @@ -1016,7 +1018,6 @@ extern MSICOMPONENT *msi_get_loaded_component(MSIPACKAGE *package, const WCHAR *Component) DECLSPEC_HIDDEN; extern MSIFEATURE *msi_get_loaded_feature(MSIPACKAGE *package, const WCHAR *Feature) DECLSPEC_HIDDEN; extern MSIFILE *msi_get_loaded_file(MSIPACKAGE *package, const WCHAR *file) DECLSPEC_HIDDEN; -extern MSIFILEPATCH *msi_get_loaded_filepatch(MSIPACKAGE* package, const WCHAR *key) DECLSPEC_HIDDEN; extern MSIFOLDER *msi_get_loaded_folder(MSIPACKAGE *package, const WCHAR *dir) DECLSPEC_HIDDEN; extern int msi_track_tempfile(MSIPACKAGE *package, const WCHAR *path) DECLSPEC_HIDDEN; extern void msi_free_action_script(MSIPACKAGE *package, UINT script) DECLSPEC_HIDDEN; @@ -1040,6 +1041,7 @@ extern void msi_destroy_assembly_caches(MSIPACKAGE *) DECLSPEC_HIDDEN; extern WCHAR *msi_font_version_from_file(const WCHAR *) DECLSPEC_HIDDEN; extern WCHAR **msi_split_string(const WCHAR *, WCHAR) DECLSPEC_HIDDEN; +extern UINT msi_set_original_database_property(MSIDATABASE *, const WCHAR *) DECLSPEC_HIDDEN; /* media */ Index: dll/win32/msi/package.c =================================================================== --- dll/win32/msi/package.c (revision 58430) +++ dll/win32/msi/package.c (working copy) @@ -158,7 +158,6 @@ static void free_package_structures( MSIPACKAGE *package ) { - INT i; struct list *item, *cursor; LIST_FOR_EACH_SAFE( item, cursor, &package->features ) @@ -287,11 +286,14 @@ if (package->script) { + INT i; + UINT j; + for (i = 0; i < SCRIPT_MAX; i++) msi_free_action_script( package, i ); - for (i = 0; i < package->script->UniqueActionsCount; i++) - msi_free( package->script->UniqueActions[i] ); + for (j = 0; j < package->script->UniqueActionsCount; j++) + msi_free( package->script->UniqueActions[j] ); msi_free( package->script->UniqueActions ); msi_free( package->script ); @@ -753,6 +755,8 @@ static const WCHAR szPrintHoodFolder[] = {'P','r','i','n','t','H','o','o','d','F','o','l','d','e','r',0}; static const WCHAR szRecentFolder[] = {'R','e','c','e','n','t','F','o','l','d','e','r',0}; static const WCHAR szComputerName[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0}; + static const WCHAR szBrowseProperty[] = {'_','B','r','o','w','s','e','P','r','o','p','e','r','t','y',0}; + static const WCHAR szInstallDir[] = {'I','N','S','T','A','L','L','D','I','R',0}; /* * Other things that probably should be set: @@ -1024,6 +1028,7 @@ msi_free( computername ); } } + msi_set_property( package->db, szBrowseProperty, szInstallDir, -1 ); } static UINT msi_load_summary_properties( MSIPACKAGE *package ) @@ -1270,9 +1275,18 @@ return ERROR_SUCCESS; } +static enum platform parse_platform( WCHAR *str ) +{ + if (!str[0] || !strcmpW( str, szIntel )) return PLATFORM_INTEL; + else if (!strcmpW( str, szIntel64 )) return PLATFORM_INTEL64; + else if (!strcmpW( str, szX64 ) || !strcmpW( str, szAMD64 )) return PLATFORM_X64; + else if (!strcmpW( str, szARM )) return PLATFORM_ARM; + return PLATFORM_UNKNOWN; +} + static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package ) { - WCHAR *template, *p, *q; + WCHAR *template, *p, *q, *platform; DWORD i, count; package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT ); @@ -1292,17 +1306,17 @@ return ERROR_PATCH_PACKAGE_INVALID; } *p = 0; - if ((q = strchrW( template, ',' ))) *q = 0; - if (!template[0] || !strcmpW( template, szIntel )) - package->platform = PLATFORM_INTEL; - else if (!strcmpW( template, szIntel64 )) - package->platform = PLATFORM_INTEL64; - else if (!strcmpW( template, szX64 ) || !strcmpW( template, szAMD64 )) - package->platform = PLATFORM_X64; - else if (!strcmpW( template, szARM )) - package->platform = PLATFORM_ARM; - else + platform = template; + if ((q = strchrW( platform, ',' ))) *q = 0; + package->platform = parse_platform( platform ); + while (package->platform == PLATFORM_UNKNOWN && q) { + platform = q + 1; + if ((q = strchrW( platform, ',' ))) *q = 0; + package->platform = parse_platform( platform ); + } + if (package->platform == PLATFORM_UNKNOWN) + { WARN("unknown platform %s\n", debugstr_w(template)); msi_free( template ); return ERROR_INSTALL_PLATFORM_UNSUPPORTED; @@ -1514,6 +1528,28 @@ return r; } +UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package ) +{ + UINT r; + + if (UrlIsW( package, URLIS_URL )) + r = msi_set_property( db, szOriginalDatabase, package, -1 ); + else if (package[0] == '#') + r = msi_set_property( db, szOriginalDatabase, db->path, -1 ); + else + { + DWORD len; + WCHAR *path; + + if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError(); + if (!(path = msi_alloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY; + len = GetFullPathNameW( package, len, path, NULL ); + r = msi_set_property( db, szOriginalDatabase, path, len ); + msi_free( path ); + } + return r; +} + UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) { static const WCHAR dotmsi[] = {'.','m','s','i',0}; @@ -1623,17 +1659,6 @@ return r; } msi_set_property( package->db, szDatabase, db->path, -1 ); - - if( UrlIsW( szPackage, URLIS_URL ) ) - msi_set_property( package->db, szOriginalDatabase, szPackage, -1 ); - else if( szPackage[0] == '#' ) - msi_set_property( package->db, szOriginalDatabase, db->path, -1 ); - else - { - WCHAR fullpath[MAX_PATH]; - DWORD len = GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL ); - msi_set_property( package->db, szOriginalDatabase, fullpath, len ); - } msi_set_context( package ); while (1) @@ -1660,6 +1685,12 @@ msi_clone_properties( package ); msi_adjust_privilege_properties( package ); } + r = msi_set_original_database_property( package->db, szPackage ); + if (r != ERROR_SUCCESS) + { + msiobj_release( &package->hdr ); + return r; + } if (gszLogFile) package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); Index: dll/win32/msi/record.c =================================================================== --- dll/win32/msi/record.c (revision 58430) +++ dll/win32/msi/record.c (working copy) @@ -83,15 +83,14 @@ MSIRECORD *MSI_CreateRecord( UINT cParams ) { MSIRECORD *rec; - UINT len; TRACE("%d\n", cParams); if( cParams>65535 ) return NULL; - len = sizeof (MSIRECORD) + sizeof (MSIFIELD)*cParams; - rec = alloc_msiobject( MSIHANDLETYPE_RECORD, len, MSI_CloseRecord ); + rec = alloc_msiobject( MSIHANDLETYPE_RECORD, FIELD_OFFSET(MSIRECORD, fields[cParams + 1]), + MSI_CloseRecord ); if( rec ) rec->count = cParams; return rec; Index: dll/win32/msi/registry.c =================================================================== --- dll/win32/msi/registry.c (revision 58430) +++ dll/win32/msi/registry.c (working copy) @@ -566,12 +566,12 @@ return RegOpenKeyW(HKEY_CURRENT_USER, keypath, key); } -UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context, HKEY *key, BOOL create) +UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context, + HKEY *key, BOOL create) { - LPWSTR usersid; HKEY root = HKEY_LOCAL_MACHINE; REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS; - WCHAR squished_pc[GUID_SIZE], keypath[MAX_PATH]; + WCHAR squished_pc[GUID_SIZE], keypath[MAX_PATH], *usersid = NULL; if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED; TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc)); @@ -589,12 +589,16 @@ } else { - if (!(usersid = get_user_sid())) + if (!szUserSid) { - ERR("Failed to retrieve user SID\n"); - return ERROR_FUNCTION_FAILED; + if (!(usersid = get_user_sid())) + { + ERR("Failed to retrieve user SID\n"); + return ERROR_FUNCTION_FAILED; + } + szUserSid = usersid; } - sprintfW(keypath, szInstaller_LocalManagedFeat_fmt, usersid, squished_pc); + sprintfW(keypath, szInstaller_LocalManagedFeat_fmt, szUserSid, squished_pc); LocalFree(usersid); } if (create) return RegCreateKeyExW(root, keypath, 0, NULL, 0, access, NULL, key, NULL); @@ -628,11 +632,11 @@ return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key); } -UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context, HKEY *key, BOOL create) +UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context, + HKEY *key, BOOL create) { - LPWSTR usersid; REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS; - WCHAR squished_pc[GUID_SIZE], keypath[0x200]; + WCHAR squished_pc[GUID_SIZE], keypath[0x200], *usersid = NULL; if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED; TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc)); @@ -643,12 +647,16 @@ } else { - if (!(usersid = get_user_sid())) + if (!szUserSid) { - ERR("Failed to retrieve user SID\n"); - return ERROR_FUNCTION_FAILED; + if (!(usersid = get_user_sid())) + { + ERR("Failed to retrieve user SID\n"); + return ERROR_FUNCTION_FAILED; + } + szUserSid = usersid; } - sprintfW(keypath, szUserDataFeatures_fmt, usersid, squished_pc); + sprintfW(keypath, szUserDataFeatures_fmt, szUserSid, squished_pc); LocalFree(usersid); } if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL); Index: dll/win32/msi/where.c =================================================================== --- dll/win32/msi/where.c (revision 58430) +++ dll/win32/msi/where.c (working copy) @@ -774,7 +774,7 @@ JOINTABLE *table = wv->tables; UINT *rows; JOINTABLE **ordered_tables; - int i = 0; + UINT i = 0; TRACE("%p %p\n", wv, record); @@ -1056,7 +1056,7 @@ column_info *column = columns; MSIORDERINFO *orderinfo; UINT r, count = 0; - int i; + UINT i; TRACE("%p %p\n", view, columns); @@ -1072,7 +1072,7 @@ if (count == 0) return ERROR_SUCCESS; - orderinfo = msi_alloc(sizeof(MSIORDERINFO) + (count - 1) * sizeof(union ext_column)); + orderinfo = msi_alloc(FIELD_OFFSET(MSIORDERINFO, columns[count])); if (!orderinfo) return ERROR_OUTOFMEMORY;