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.
This commit is contained in:
parent
5a8ce4c793
commit
06505c9a34
|
@ -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 (file == INVALID_HANDLE_VALUE)
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
else
|
||||
if (!(binary = msi_alloc_zero( sizeof(MSIBINARY) )))
|
||||
{
|
||||
do
|
||||
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 );
|
||||
return NULL;
|
||||
}
|
||||
do
|
||||
{
|
||||
sz = sizeof(buffer);
|
||||
r = MSI_RecordReadStream( row, 2, buffer, &sz );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
DWORD write;
|
||||
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);
|
||||
} while (sz == sizeof buffer);
|
||||
CloseHandle(file);
|
||||
ERR("Failed to get stream\n");
|
||||
break;
|
||||
}
|
||||
WriteFile( file, buffer, sz, &write, NULL );
|
||||
} while (sz == sizeof buffer);
|
||||
|
||||
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;
|
||||
if (!(binary = get_temp_binary( package, source, TRUE )))
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
TRACE("Calling function %s from %s\n",debugstr_w(target),
|
||||
debugstr_w(tmp_file));
|
||||
TRACE("Calling function %s from %s\n", debugstr_w(target), debugstr_w(binary->tmpfile));
|
||||
|
||||
if (!strchrW(tmp_file,'.'))
|
||||
strcatW(tmp_file, szDot);
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue