Commit 06505c9a authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

msi: Reuse temporary executables.

Fixes a custom action in the Office 2010 installer and makes installers that pack multiple custom actions in an executable faster.
parent 5a8ce4c7
......@@ -355,60 +355,90 @@ end:
return rc;
}
static UINT store_binary_to_temp(MSIPACKAGE *package, LPCWSTR source,
LPWSTR tmp_file)
static MSIBINARY *create_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL dll )
{
static const WCHAR query[] = {
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','B','i' ,'n','a','r','y','`',' ','W','H','E','R','E',' ',
'`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0};
MSIRECORD *row = 0;
MSIRECORD *row;
MSIBINARY *binary;
HANDLE file;
CHAR buffer[1024];
WCHAR fmt[MAX_PATH];
DWORD sz = MAX_PATH;
WCHAR fmt[MAX_PATH], tmpfile[MAX_PATH];
DWORD sz = MAX_PATH, write;
UINT r;
if (msi_get_property(package->db, cszTempFolder, fmt, &sz) != ERROR_SUCCESS)
GetTempPathW(MAX_PATH, fmt);
if (GetTempFileNameW(fmt, szMsi, 0, tmp_file) == 0)
if (!GetTempFileNameW( fmt, szMsi, 0, tmpfile ))
{
TRACE("Unable to create file\n");
return ERROR_FUNCTION_FAILED;
TRACE("unable to create temp file %s (%u)\n", debugstr_w(tmpfile), GetLastError());
return NULL;
}
track_tempfile(package, tmp_file);
row = MSI_QueryGetRecord(package->db, query, source);
if (!row)
return ERROR_FUNCTION_FAILED;
return NULL;
/* write out the file */
file = CreateFileW(tmp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
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)
r = ERROR_FUNCTION_FAILED;
else
{
msiobj_release( &row->hdr );
return NULL;
}
do
{
DWORD write;
sz = sizeof buffer;
r = MSI_RecordReadStream(row, 2, buffer, &sz);
sz = sizeof(buffer);
r = MSI_RecordReadStream( row, 2, buffer, &sz );
if (r != ERROR_SUCCESS)
{
ERR("Failed to get stream\n");
break;
}
WriteFile(file, buffer, sz, &write, NULL);
WriteFile( file, buffer, sz, &write, NULL );
} while (sz == sizeof buffer);
CloseHandle(file);
CloseHandle( file );
msiobj_release( &row->hdr );
if (r != ERROR_SUCCESS)
{
DeleteFileW( tmpfile );
msi_free( binary );
return NULL;
}
msiobj_release(&row->hdr);
/* keep a reference to prevent the dll from being unloaded */
if (dll && !(binary->module = LoadLibraryW( tmpfile )))
{
ERR("failed to load dll %s (%u)\n", debugstr_w( binary->tmpfile ), GetLastError() );
DeleteFileW( tmpfile );
msi_free( binary );
return NULL;
}
binary->source = strdupW( source );
binary->tmpfile = strdupW( tmpfile );
list_add_tail( &package->binaries, &binary->entry );
return binary;
}
return r;
static MSIBINARY *get_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL dll )
{
MSIBINARY *binary;
LIST_FOR_EACH_ENTRY( binary, &package->binaries, MSIBINARY, entry )
{
if (!strcmpW( binary->source, source ))
return binary;
}
return create_temp_binary( package, source, dll );
}
static void file_running_action(MSIPACKAGE* package, HANDLE Handle,
......@@ -875,20 +905,15 @@ static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source,
LPCWSTR target, const INT type, LPCWSTR action)
{
msi_custom_action_info *info;
WCHAR tmp_file[MAX_PATH];
MSIBINARY *binary;
UINT r;
r = store_binary_to_temp(package, source, tmp_file);
if (r != ERROR_SUCCESS)
return r;
TRACE("Calling function %s from %s\n",debugstr_w(target),
debugstr_w(tmp_file));
if (!(binary = get_temp_binary( package, source, TRUE )))
return ERROR_FUNCTION_FAILED;
if (!strchrW(tmp_file,'.'))
strcatW(tmp_file, szDot);
TRACE("Calling function %s from %s\n", debugstr_w(target), debugstr_w(binary->tmpfile));
info = do_msidbCustomActionTypeDll( package, type, tmp_file, target, action );
info = do_msidbCustomActionTypeDll( package, type, binary->tmpfile, target, action );
r = wait_thread_handle( info );
release_custom_action_data( info );
......@@ -898,7 +923,6 @@ static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source,
static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source,
LPCWSTR target, const INT type, LPCWSTR action)
{
WCHAR tmp_file[MAX_PATH];
STARTUPINFOW si;
PROCESS_INFORMATION info;
BOOL rc;
......@@ -906,29 +930,27 @@ static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source,
WCHAR *deformated = NULL;
WCHAR *cmd;
static const WCHAR spc[] = {' ',0};
MSIBINARY *binary;
UINT r;
memset(&si,0,sizeof(STARTUPINFOW));
r = store_binary_to_temp(package, source, tmp_file);
if (r != ERROR_SUCCESS)
return r;
if (!(binary = get_temp_binary( package, source, FALSE )))
return ERROR_FUNCTION_FAILED;
deformat_string(package,target,&deformated);
len = strlenW(tmp_file)+2;
len = strlenW( binary->tmpfile ) + 2;
if (deformated)
len += strlenW(deformated);
cmd = msi_alloc(sizeof(WCHAR)*len);
strcpyW(cmd,tmp_file);
strcpyW( cmd, binary->tmpfile );
if (deformated)
{
strcatW(cmd,spc);
strcatW(cmd,deformated);
msi_free(deformated);
}
......
......@@ -163,6 +163,14 @@ typedef struct tagMSIPATCHINFO
MSIPATCHSTATE state;
} MSIPATCHINFO;
typedef struct tagMSIBINARY
{
struct list entry;
WCHAR *source;
WCHAR *tmpfile;
HMODULE module;
} MSIBINARY;
typedef struct _column_info
{
LPCWSTR table;
......@@ -330,6 +338,7 @@ typedef struct tagMSIPACKAGE
struct list files;
struct list tempfiles;
struct list folders;
struct list binaries;
LPWSTR ActionFormat;
LPWSTR LastAction;
HANDLE log_file;
......
......@@ -284,6 +284,20 @@ static void free_package_structures( MSIPACKAGE *package )
msi_free( patch );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->binaries )
{
MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry );
list_remove( &binary->entry );
if (binary->module)
FreeLibrary( binary->module );
if (!DeleteFileW( binary->tmpfile ))
ERR("failed to delete %s (%u)\n", debugstr_w(binary->tmpfile), GetLastError());
msi_free( binary->source );
msi_free( binary->tmpfile );
msi_free( binary );
}
msi_free( package->BaseURL );
msi_free( package->PackagePath );
msi_free( package->ProductCode );
......@@ -1059,6 +1073,7 @@ static MSIPACKAGE *msi_alloc_package( void )
list_init( &package->sourcelist_info );
list_init( &package->sourcelist_media );
list_init( &package->patches );
list_init( &package->binaries );
}
return package;
......
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