Module: wine Branch: master Commit: 06505c9a344a70a6510f3eb758187d634590f383 URL: http://source.winehq.org/git/wine.git/?a=commit;h=06505c9a344a70a6510f3eb758...
Author: Hans Leidekker hans@codeweavers.com Date: Thu Dec 2 11:32:26 2010 +0100
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.
---
dlls/msi/custom.c | 118 +++++++++++++++++++++++++++++++--------------------- dlls/msi/msipriv.h | 9 ++++ dlls/msi/package.c | 15 +++++++ 3 files changed, 94 insertions(+), 48 deletions(-)
diff --git a/dlls/msi/custom.c b/dlls/msi/custom.c index 8c080c9..391bf9a 100644 --- a/dlls/msi/custom.c +++ b/dlls/msi/custom.c @@ -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 { - do + 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; - - 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); }
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index feb82a0..fb24d30 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -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; diff --git a/dlls/msi/package.c b/dlls/msi/package.c index 596db2b..a81d0bd 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -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;