msi: Clean up handling of temporary files.
This commit is contained in:
parent
20ef12a762
commit
17b05316a5
|
@ -2107,18 +2107,38 @@ BOOL msi_file_hash_matches( MSIFILE *file )
|
|||
return !memcmp( &hash, &file->hash, sizeof(MSIFILEHASHINFO) );
|
||||
}
|
||||
|
||||
static WCHAR *get_temp_dir( void )
|
||||
static WCHAR *create_temp_dir( MSIDATABASE *db )
|
||||
{
|
||||
static UINT id;
|
||||
WCHAR tmp[MAX_PATH], dir[MAX_PATH];
|
||||
WCHAR *ret;
|
||||
|
||||
if (!db->tempfolder)
|
||||
{
|
||||
WCHAR tmp[MAX_PATH];
|
||||
UINT len = sizeof(tmp)/sizeof(tmp[0]);
|
||||
|
||||
if (msi_get_property( db, szTempFolder, tmp, &len ) ||
|
||||
GetFileAttributesW( tmp ) != FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
GetTempPathW( MAX_PATH, tmp );
|
||||
}
|
||||
if (!(db->tempfolder = strdupW( tmp ))) return NULL;
|
||||
}
|
||||
|
||||
if ((ret = msi_alloc( (strlenW( db->tempfolder ) + 20) * sizeof(WCHAR) )))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (!GetTempFileNameW( tmp, szMsi, ++id, dir )) return NULL;
|
||||
if (CreateDirectoryW( dir, NULL )) break;
|
||||
if (!GetTempFileNameW( db->tempfolder, szMsi, ++id, ret ))
|
||||
{
|
||||
msi_free( ret );
|
||||
return NULL;
|
||||
}
|
||||
return strdupW( dir );
|
||||
if (CreateDirectoryW( ret, NULL )) break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2181,9 +2201,8 @@ static void set_target_path( MSIPACKAGE *package, MSIFILE *file )
|
|||
{
|
||||
MSIASSEMBLY *assembly = file->Component->assembly;
|
||||
|
||||
if (!assembly->tempdir) assembly->tempdir = get_temp_dir();
|
||||
if (!assembly->tempdir) assembly->tempdir = create_temp_dir( package->db );
|
||||
file->TargetPath = msi_build_directory_name( 2, assembly->tempdir, file->FileName );
|
||||
msi_track_tempfile( package, file->TargetPath );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -201,6 +201,35 @@ static void set_deferred_action_props( MSIPACKAGE *package, const WCHAR *deferre
|
|||
msi_set_property( package->db, szProductCode, beg, end - beg );
|
||||
}
|
||||
|
||||
WCHAR *msi_create_temp_file( MSIDATABASE *db )
|
||||
{
|
||||
WCHAR *ret;
|
||||
|
||||
if (!db->tempfolder)
|
||||
{
|
||||
WCHAR tmp[MAX_PATH];
|
||||
UINT len = sizeof(tmp)/sizeof(tmp[0]);
|
||||
|
||||
if (msi_get_property( db, szTempFolder, tmp, &len ) ||
|
||||
GetFileAttributesW( tmp ) != FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
GetTempPathW( MAX_PATH, tmp );
|
||||
}
|
||||
if (!(db->tempfolder = strdupW( tmp ))) return NULL;
|
||||
}
|
||||
|
||||
if ((ret = msi_alloc( (strlenW( db->tempfolder ) + 20) * sizeof(WCHAR) )))
|
||||
{
|
||||
if (!GetTempFileNameW( db->tempfolder, szMsi, 0, ret ))
|
||||
{
|
||||
msi_free( ret );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static MSIBINARY *create_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL dll )
|
||||
{
|
||||
static const WCHAR query[] = {
|
||||
|
@ -208,38 +237,21 @@ static MSIBINARY *create_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL
|
|||
'`','B','i' ,'n','a','r','y','`',' ','W','H','E','R','E',' ',
|
||||
'`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0};
|
||||
MSIRECORD *row;
|
||||
MSIBINARY *binary;
|
||||
MSIBINARY *binary = NULL;
|
||||
HANDLE file;
|
||||
CHAR buffer[1024];
|
||||
WCHAR fmt[MAX_PATH], tmpfile[MAX_PATH];
|
||||
DWORD sz = MAX_PATH, write;
|
||||
WCHAR *tmpfile;
|
||||
DWORD sz, write;
|
||||
UINT r;
|
||||
|
||||
if (msi_get_property(package->db, szTempFolder, fmt, &sz) != ERROR_SUCCESS ||
|
||||
GetFileAttributesW(fmt) == INVALID_FILE_ATTRIBUTES) GetTempPathW(MAX_PATH, fmt);
|
||||
if (!(tmpfile = msi_create_temp_file( package->db ))) return NULL;
|
||||
|
||||
if (!GetTempFileNameW( fmt, szMsi, 0, tmpfile ))
|
||||
{
|
||||
TRACE("unable to create temp file %s (%u)\n", debugstr_w(tmpfile), GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
if (!(row = MSI_QueryGetRecord( package->db, query, source ))) goto error;
|
||||
if (!(binary = msi_alloc_zero( sizeof(MSIBINARY) ))) goto error;
|
||||
|
||||
row = MSI_QueryGetRecord(package->db, query, source);
|
||||
if (!row)
|
||||
return NULL;
|
||||
file = CreateFileW( tmpfile, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
if (file == INVALID_HANDLE_VALUE) goto error;
|
||||
|
||||
if (!(binary = msi_alloc_zero( sizeof(MSIBINARY) )))
|
||||
{
|
||||
msiobj_release( &row->hdr );
|
||||
return NULL;
|
||||
}
|
||||
file = CreateFileW( tmpfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
msiobj_release( &row->hdr );
|
||||
msi_free( binary );
|
||||
return NULL;
|
||||
}
|
||||
do
|
||||
{
|
||||
sz = sizeof(buffer);
|
||||
|
@ -253,13 +265,7 @@ static MSIBINARY *create_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL
|
|||
} while (sz == sizeof buffer);
|
||||
|
||||
CloseHandle( file );
|
||||
msiobj_release( &row->hdr );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
DeleteFileW( tmpfile );
|
||||
msi_free( binary );
|
||||
return NULL;
|
||||
}
|
||||
if (r != ERROR_SUCCESS) goto error;
|
||||
|
||||
/* keep a reference to prevent the dll from being unloaded */
|
||||
if (dll && !(binary->module = LoadLibraryW( tmpfile )))
|
||||
|
@ -267,9 +273,18 @@ static MSIBINARY *create_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL
|
|||
WARN( "failed to load dll %s (%u)\n", debugstr_w( tmpfile ), GetLastError() );
|
||||
}
|
||||
binary->source = strdupW( source );
|
||||
binary->tmpfile = strdupW( tmpfile );
|
||||
binary->tmpfile = tmpfile;
|
||||
list_add_tail( &package->binaries, &binary->entry );
|
||||
|
||||
msiobj_release( &row->hdr );
|
||||
return binary;
|
||||
|
||||
error:
|
||||
if (row) msiobj_release( &row->hdr );
|
||||
DeleteFileW( tmpfile );
|
||||
msi_free( tmpfile );
|
||||
msi_free( binary );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static MSIBINARY *get_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL dll )
|
||||
|
|
|
@ -99,6 +99,7 @@ static VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
|
|||
DeleteFileW( db->deletefile );
|
||||
msi_free( db->deletefile );
|
||||
}
|
||||
msi_free( db->tempfolder );
|
||||
}
|
||||
|
||||
static HRESULT db_initialize( IStorage *stg, const GUID *clsid )
|
||||
|
|
|
@ -495,42 +495,17 @@ static MSIRECORD *msi_get_binary_record( MSIDATABASE *db, LPCWSTR name )
|
|||
return MSI_QueryGetRecord( db, query, name );
|
||||
}
|
||||
|
||||
static LPWSTR msi_create_tmp_path(void)
|
||||
{
|
||||
WCHAR tmp[MAX_PATH];
|
||||
LPWSTR path = NULL;
|
||||
DWORD len, r;
|
||||
|
||||
r = GetTempPathW( MAX_PATH, tmp );
|
||||
if( !r )
|
||||
return path;
|
||||
len = lstrlenW( tmp ) + 20;
|
||||
path = msi_alloc( len * sizeof (WCHAR) );
|
||||
if( path )
|
||||
{
|
||||
r = GetTempFileNameW( tmp, szMsi, 0, path );
|
||||
if (!r)
|
||||
{
|
||||
msi_free( path );
|
||||
path = NULL;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
static HANDLE msi_load_image( MSIDATABASE *db, LPCWSTR name, UINT type,
|
||||
UINT cx, UINT cy, UINT flags )
|
||||
{
|
||||
MSIRECORD *rec = NULL;
|
||||
MSIRECORD *rec;
|
||||
HANDLE himage = NULL;
|
||||
LPWSTR tmp;
|
||||
UINT r;
|
||||
|
||||
TRACE("%p %s %u %u %08x\n", db, debugstr_w(name), cx, cy, flags);
|
||||
|
||||
tmp = msi_create_tmp_path();
|
||||
if( !tmp )
|
||||
return himage;
|
||||
if (!(tmp = msi_create_temp_file( db ))) return NULL;
|
||||
|
||||
rec = msi_get_binary_record( db, name );
|
||||
if( rec )
|
||||
|
|
|
@ -275,33 +275,33 @@ static MSIFILE *find_file( MSIPACKAGE *package, UINT disk_id, const WCHAR *filen
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
|
||||
static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR filename, DWORD action,
|
||||
LPWSTR *path, DWORD *attrs, PVOID user)
|
||||
{
|
||||
static MSIFILE *f = NULL;
|
||||
static MSIFILE *file = NULL;
|
||||
UINT_PTR disk_id = (UINT_PTR)user;
|
||||
|
||||
if (action == MSICABEXTRACT_BEGINEXTRACT)
|
||||
{
|
||||
if (!(f = find_file( package, disk_id, file )))
|
||||
if (!(file = find_file( package, disk_id, filename )))
|
||||
{
|
||||
TRACE("unknown file in cabinet (%s)\n", debugstr_w(file));
|
||||
TRACE("unknown file in cabinet (%s)\n", debugstr_w(filename));
|
||||
return FALSE;
|
||||
}
|
||||
if (f->disk_id != disk_id || (f->state != msifs_missing && f->state != msifs_overwrite))
|
||||
if (file->state != msifs_missing && file->state != msifs_overwrite)
|
||||
return FALSE;
|
||||
|
||||
if (!msi_is_global_assembly( f->Component ))
|
||||
if (!msi_is_global_assembly( file->Component ))
|
||||
{
|
||||
msi_create_directory(package, f->Component->Directory);
|
||||
msi_create_directory( package, file->Component->Directory );
|
||||
}
|
||||
*path = strdupW(f->TargetPath);
|
||||
*attrs = f->Attributes;
|
||||
*path = strdupW( file->TargetPath );
|
||||
*attrs = file->Attributes;
|
||||
}
|
||||
else if (action == MSICABEXTRACT_FILEEXTRACTED)
|
||||
{
|
||||
if (!msi_is_global_assembly( f->Component )) f->state = msifs_installed;
|
||||
f = NULL;
|
||||
if (!msi_is_global_assembly( file->Component )) file->state = msifs_installed;
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -378,8 +378,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
|||
data.cb = installfiles_cb;
|
||||
data.user = (PVOID)(UINT_PTR)mi->disk_id;
|
||||
|
||||
if (file->IsCompressed &&
|
||||
!msi_cabextract(package, mi, &data))
|
||||
if (file->IsCompressed && !msi_cabextract(package, mi, &data))
|
||||
{
|
||||
ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
|
||||
rc = ERROR_INSTALL_FAILURE;
|
||||
|
@ -419,8 +418,8 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
|||
{
|
||||
MSICOMPONENT *comp = file->Component;
|
||||
|
||||
if (!msi_is_global_assembly( comp ) || (file->state != msifs_missing && file->state != msifs_overwrite))
|
||||
continue;
|
||||
if (!msi_is_global_assembly( comp ) || comp->assembly->installed ||
|
||||
(file->state != msifs_missing && file->state != msifs_overwrite)) continue;
|
||||
|
||||
rc = msi_install_assembly( package, comp );
|
||||
if (rc != ERROR_SUCCESS)
|
||||
|
@ -453,22 +452,18 @@ static BOOL patchfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
|
|||
LPWSTR *path, DWORD *attrs, PVOID user)
|
||||
{
|
||||
static MSIFILEPATCH *patch;
|
||||
static WCHAR tmpfile[MAX_PATH], tmpdir[MAX_PATH];
|
||||
UINT_PTR disk_id = (UINT_PTR)user;
|
||||
|
||||
if (!tmpdir[0]) GetTempPathW( MAX_PATH, tmpdir );
|
||||
|
||||
if (action == MSICABEXTRACT_BEGINEXTRACT)
|
||||
{
|
||||
if (!(patch = find_filepatch( package, disk_id, file ))) return FALSE;
|
||||
|
||||
GetTempFileNameW( tmpdir, NULL, 0, tmpfile );
|
||||
*path = strdupW( tmpfile );
|
||||
patch->path = msi_create_temp_file( package->db );
|
||||
*path = strdupW( patch->path );
|
||||
*attrs = patch->File->Attributes;
|
||||
}
|
||||
else if (action == MSICABEXTRACT_FILEEXTRACTED)
|
||||
{
|
||||
patch->path = strdupW( tmpfile );
|
||||
patch->extracted = TRUE;
|
||||
patch = NULL;
|
||||
}
|
||||
|
@ -531,14 +526,16 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package )
|
|||
|
||||
LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry )
|
||||
{
|
||||
WCHAR tmpdir[MAX_PATH], tmpfile[MAX_PATH];
|
||||
WCHAR *tmpfile;
|
||||
BOOL ret;
|
||||
|
||||
if (!patch->path) continue;
|
||||
|
||||
GetTempPathW( MAX_PATH, tmpdir );
|
||||
GetTempFileNameW( tmpdir, NULL, 0, tmpfile );
|
||||
|
||||
if (!(tmpfile = msi_create_temp_file( package->db )))
|
||||
{
|
||||
rc = ERROR_INSTALL_FAILURE;
|
||||
goto done;
|
||||
}
|
||||
ret = ApplyPatchToFileW( patch->path, patch->File->TargetPath, tmpfile, 0 );
|
||||
if (ret)
|
||||
{
|
||||
|
@ -550,7 +547,7 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package )
|
|||
|
||||
DeleteFileW( patch->path );
|
||||
DeleteFileW( tmpfile );
|
||||
RemoveDirectoryW( tmpdir );
|
||||
msi_free( tmpfile );
|
||||
|
||||
if (!ret && !(patch->Attributes & msidbPatchAttributesNonVital))
|
||||
{
|
||||
|
|
|
@ -100,6 +100,7 @@ typedef struct tagMSIDATABASE
|
|||
UINT bytes_per_strref;
|
||||
LPWSTR path;
|
||||
LPWSTR deletefile;
|
||||
LPWSTR tempfolder;
|
||||
LPCWSTR mode;
|
||||
UINT media_transform_offset;
|
||||
UINT media_transform_disk_id;
|
||||
|
@ -580,12 +581,6 @@ typedef struct tagMSIFILE
|
|||
UINT disk_id;
|
||||
} MSIFILE;
|
||||
|
||||
typedef struct tagMSITEMPFILE
|
||||
{
|
||||
struct list entry;
|
||||
LPWSTR Path;
|
||||
} MSITEMPFILE;
|
||||
|
||||
typedef struct tagMSIFILEPATCH
|
||||
{
|
||||
struct list entry;
|
||||
|
@ -1025,7 +1020,7 @@ extern MSICOMPONENT *msi_get_loaded_component(MSIPACKAGE *package, const WCHAR *
|
|||
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 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 WCHAR *msi_create_temp_file(MSIDATABASE *db) DECLSPEC_HIDDEN;
|
||||
extern void msi_free_action_script(MSIPACKAGE *package, UINT script) DECLSPEC_HIDDEN;
|
||||
extern WCHAR *msi_build_icon_path(MSIPACKAGE *, const WCHAR *) DECLSPEC_HIDDEN;
|
||||
extern WCHAR *msi_build_directory_name(DWORD , ...) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -49,22 +49,6 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||
|
||||
static void remove_tracked_tempfiles( MSIPACKAGE *package )
|
||||
{
|
||||
struct list *item, *cursor;
|
||||
|
||||
LIST_FOR_EACH_SAFE( item, cursor, &package->tempfiles )
|
||||
{
|
||||
MSITEMPFILE *temp = LIST_ENTRY( item, MSITEMPFILE, entry );
|
||||
|
||||
list_remove( &temp->entry );
|
||||
TRACE("deleting temp file %s\n", debugstr_w( temp->Path ));
|
||||
DeleteFileW( temp->Path );
|
||||
msi_free( temp->Path );
|
||||
msi_free( temp );
|
||||
}
|
||||
}
|
||||
|
||||
static void free_feature( MSIFEATURE *feature )
|
||||
{
|
||||
struct list *item, *cursor;
|
||||
|
@ -170,6 +154,22 @@ static void free_package_structures( MSIPACKAGE *package )
|
|||
free_folder( folder );
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_SAFE( item, cursor, &package->files )
|
||||
{
|
||||
MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
|
||||
|
||||
list_remove( &file->entry );
|
||||
msi_free( file->File );
|
||||
msi_free( file->FileName );
|
||||
msi_free( file->ShortName );
|
||||
msi_free( file->LongName );
|
||||
msi_free( file->Version );
|
||||
msi_free( file->Language );
|
||||
if (msi_is_global_assembly( file->Component )) DeleteFileW( file->TargetPath );
|
||||
msi_free( file->TargetPath );
|
||||
msi_free( file );
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_SAFE( item, cursor, &package->components )
|
||||
{
|
||||
MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
|
||||
|
@ -185,21 +185,6 @@ static void free_package_structures( MSIPACKAGE *package )
|
|||
msi_free( comp );
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_SAFE( item, cursor, &package->files )
|
||||
{
|
||||
MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
|
||||
|
||||
list_remove( &file->entry );
|
||||
msi_free( file->File );
|
||||
msi_free( file->FileName );
|
||||
msi_free( file->ShortName );
|
||||
msi_free( file->LongName );
|
||||
msi_free( file->Version );
|
||||
msi_free( file->Language );
|
||||
msi_free( file->TargetPath );
|
||||
msi_free( file );
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches )
|
||||
{
|
||||
MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, entry );
|
||||
|
@ -347,8 +332,6 @@ static void free_package_structures( MSIPACKAGE *package )
|
|||
msi_free( package->LastAction );
|
||||
msi_free( package->langids );
|
||||
|
||||
remove_tracked_tempfiles(package);
|
||||
|
||||
/* cleanup control event subscriptions */
|
||||
msi_event_cleanup_all_subscriptions( package );
|
||||
}
|
||||
|
@ -1329,22 +1312,6 @@ static UINT validate_package( MSIPACKAGE *package )
|
|||
return ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int msi_track_tempfile( MSIPACKAGE *package, const WCHAR *path )
|
||||
{
|
||||
MSITEMPFILE *temp;
|
||||
|
||||
TRACE("%s\n", debugstr_w(path));
|
||||
|
||||
LIST_FOR_EACH_ENTRY( temp, &package->tempfiles, MSITEMPFILE, entry )
|
||||
{
|
||||
if (!strcmpW( path, temp->Path )) return 0;
|
||||
}
|
||||
if (!(temp = msi_alloc_zero( sizeof (MSITEMPFILE) ))) return -1;
|
||||
list_add_head( &package->tempfiles, &temp->entry );
|
||||
temp->Path = strdupW( path );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static WCHAR *get_product_code( MSIDATABASE *db )
|
||||
{
|
||||
static const WCHAR query[] = {
|
||||
|
|
Loading…
Reference in New Issue