Commit 17b05316 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

msi: Clean up handling of temporary files.

parent 20ef12a7
......@@ -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;
GetTempPathW( MAX_PATH, tmp );
for (;;)
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( tmp, szMsi, ++id, dir )) return NULL;
if (CreateDirectoryW( dir, NULL )) break;
for (;;)
{
if (!GetTempFileNameW( db->tempfolder, szMsi, ++id, ret ))
{
msi_free( ret );
return NULL;
}
if (CreateDirectoryW( ret, NULL )) break;
}
}
return strdupW( dir );
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,21 +154,6 @@ static void free_package_structures( MSIPACKAGE *package )
free_folder( folder );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->components )
{
MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
list_remove( &comp->entry );
msi_free( comp->Component );
msi_free( comp->ComponentId );
msi_free( comp->Directory );
msi_free( comp->Condition );
msi_free( comp->KeyPath );
msi_free( comp->FullKeypath );
if (comp->assembly) free_assembly( comp->assembly );
msi_free( comp );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->files )
{
MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
......@@ -196,10 +165,26 @@ static void free_package_structures( MSIPACKAGE *package )
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 );
list_remove( &comp->entry );
msi_free( comp->Component );
msi_free( comp->ComponentId );
msi_free( comp->Directory );
msi_free( comp->Condition );
msi_free( comp->KeyPath );
msi_free( comp->FullKeypath );
if (comp->assembly) free_assembly( comp->assembly );
msi_free( comp );
}
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[] = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment