diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 8fe122197c5..4671f3e1402 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -878,7 +878,7 @@ static UINT ITERATE_CreateFolders(MSIRECORD *row, LPVOID param) folder = msi_get_loaded_folder( package, dir ); if (folder->State == FOLDER_STATE_UNINITIALIZED) msi_create_full_path( full_path ); - folder->State = FOLDER_STATE_CREATED_PERSISTENT; + folder->State = FOLDER_STATE_CREATED; return ERROR_SUCCESS; } @@ -1438,6 +1438,32 @@ static UINT load_all_patches(MSIPACKAGE *package) return ERROR_SUCCESS; } +static UINT load_folder_persistence( MSIPACKAGE *package, MSIFOLDER *folder ) +{ + static const WCHAR query[] = { + 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + '`','C','r','e','a','t','e','F','o','l','d','e','r','`',' ','W','H','E','R','E',' ', + '`','D','i','r','e','c','t','o','r','y','_','`',' ','=','\'','%','s','\'',0}; + MSIQUERY *view; + + folder->persistent = FALSE; + if (!MSI_OpenQuery( package->db, &view, query, folder->Directory )) + { + if (!MSI_ViewExecute( view, NULL )) + { + MSIRECORD *rec; + if (!MSI_ViewFetch( view, &rec )) + { + TRACE("directory %s is persistent\n", debugstr_w(folder->Directory)); + folder->persistent = TRUE; + msiobj_release( &rec->hdr ); + } + } + msiobj_release( &view->hdr ); + } + return ERROR_SUCCESS; +} + static UINT load_folder( MSIRECORD *row, LPVOID param ) { MSIPACKAGE *package = param; @@ -1488,6 +1514,8 @@ static UINT load_folder( MSIRECORD *row, LPVOID param ) TRACE("SourceLong = %s\n", debugstr_w( folder->SourceLongPath )); TRACE("SourceShort = %s\n", debugstr_w( folder->SourceShortPath )); + load_folder_persistence( package, folder ); + list_add_tail( &package->folders, &folder->entry ); return ERROR_SUCCESS; } diff --git a/dlls/msi/files.c b/dlls/msi/files.c index 69f6b68483c..5749c69029e 100644 --- a/dlls/msi/files.c +++ b/dlls/msi/files.c @@ -1212,43 +1212,30 @@ done: return ret; } -static BOOL has_persistent_dir( MSIPACKAGE *package, MSICOMPONENT *comp ) +static void remove_folder( MSIFOLDER *folder ) { - MSIQUERY *view; - UINT r = ERROR_FUNCTION_FAILED; + FolderList *fl; - static const WCHAR query[] = { - 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', - '`','C','r','e','a','t','e','F','o','l','d','e','r','`',' ','W','H','E','R','E',' ', - '`','C','o','m','p','o','n','e','n','t','_','`',' ','=','\'','%','s','\'',' ','A','N','D',' ', - '`','D','i','r','e','c','t','o','r','y','_','`',' ','=','\'','%','s','\'',0}; - - if (!MSI_OpenQuery( package->db, &view, query, comp->Component, comp->Directory )) + LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry ) { - if (!MSI_ViewExecute( view, NULL )) - { - MSIRECORD *rec; - if (!(r = MSI_ViewFetch( view, &rec ))) - { - TRACE("directory %s is persistent\n", debugstr_w(comp->Directory)); - msiobj_release( &rec->hdr ); - } - } - msiobj_release( &view->hdr ); + remove_folder( fl->folder ); + } + if (!folder->persistent && folder->State != FOLDER_STATE_REMOVED) + { + if (RemoveDirectoryW( folder->ResolvedTarget )) folder->State = FOLDER_STATE_REMOVED; } - return (r == ERROR_SUCCESS); } UINT ACTION_RemoveFiles( MSIPACKAGE *package ) { + static const WCHAR query[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + '`','R','e','m','o','v','e','F','i','l','e','`',0}; MSIQUERY *view; + MSICOMPONENT *comp; MSIFILE *file; UINT r; - static const WCHAR query[] = { - 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', - '`','R','e','m','o','v','e','F','i','l','e','`',0}; - r = MSI_DatabaseOpenViewW(package->db, query, &view); if (r == ERROR_SUCCESS) { @@ -1259,10 +1246,9 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package ) LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry ) { MSIRECORD *uirow; - LPWSTR dir, p; VS_FIXEDFILEINFO *ver; - MSICOMPONENT *comp = file->Component; + comp = file->Component; msi_file_update_ui( package, file, szRemoveFiles ); comp->Action = msi_get_component_action( package, comp ); @@ -1300,15 +1286,6 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package ) { WARN("failed to delete %s (%u)\n", debugstr_w(file->TargetPath), GetLastError()); } - else if (!has_persistent_dir( package, comp )) - { - if ((dir = strdupW( file->TargetPath ))) - { - if ((p = strrchrW( dir, '\\' ))) *p = 0; - RemoveDirectoryW( dir ); - msi_free( dir ); - } - } file->state = msifs_missing; uirow = MSI_CreateRecord( 9 ); @@ -1317,5 +1294,22 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package ) msi_ui_actiondata( package, szRemoveFiles, uirow ); msiobj_release( &uirow->hdr ); } + LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry ) + { + MSIFOLDER *folder; + + comp->Action = msi_get_component_action( package, comp ); + if (comp->Action != INSTALLSTATE_ABSENT) continue; + + if (comp->assembly && !comp->assembly->application) continue; + + if (comp->Attributes & msidbComponentAttributesPermanent) + { + TRACE("permanent component, not removing directory\n"); + continue; + } + folder = msi_get_loaded_folder( package, comp->Directory ); + remove_folder( folder ); + } return ERROR_SUCCESS; } diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 09468c4bfe3..e2fb03e99f0 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -508,10 +508,10 @@ typedef struct tagMSIFOLDER LPWSTR TargetDefault; LPWSTR SourceLongPath; LPWSTR SourceShortPath; - LPWSTR ResolvedTarget; LPWSTR ResolvedSource; enum folder_state State; + BOOL persistent; INT Cost; INT Space; } MSIFOLDER;