From 23eabb44c894ebccb01cb0d4457b809127ed93a4 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Tue, 4 May 2010 09:06:42 +0200 Subject: [PATCH] msi: Make a local copy of patch packages. --- dlls/msi/action.c | 44 ++++++++++++++++++++++++++++++++++---------- dlls/msi/msipriv.h | 2 ++ dlls/msi/package.c | 13 ++++++++----- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 5ca786dbc2b..e744973ffd9 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -497,7 +497,7 @@ static UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch ) MSIPATCHINFO *pi; UINT r = ERROR_SUCCESS; - pi = msi_alloc( sizeof(MSIPATCHINFO) ); + pi = msi_alloc_zero( sizeof(MSIPATCHINFO) ); if (!pi) return ERROR_OUTOFMEMORY; @@ -522,11 +522,13 @@ static UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch ) static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file ) { + static const WCHAR dotmsp[] = {'.','m','s','p',0}; MSIDATABASE *patch_db = NULL; + WCHAR localfile[MAX_PATH]; LPWSTR *substorage; MSISUMMARYINFO *si; - MSIPATCHINFO *patch; - UINT i, r; + MSIPATCHINFO *patch = NULL; + UINT i, r = ERROR_SUCCESS; TRACE("%p %s\n", package, debugstr_w( file ) ); @@ -548,18 +550,28 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file ) if (r != ERROR_SUCCESS) { TRACE("patch not applicable\n"); - msiobj_release( &si->hdr ); - msiobj_release( &patch_db->hdr ); - return ERROR_SUCCESS; + r = ERROR_SUCCESS; + goto done; } r = msi_parse_patch_summary( si, &patch ); if ( r != ERROR_SUCCESS ) + goto done; + + r = msi_get_local_package_name( localfile, dotmsp ); + if ( r != ERROR_SUCCESS ) + goto done; + + TRACE("copying to local package %s\n", debugstr_w(localfile)); + + if (!CopyFileW( file, localfile, FALSE )) { - msiobj_release( &si->hdr ); - msiobj_release( &patch_db->hdr ); - return r; + ERR("Unable to copy package (%s -> %s) (error %u)\n", + debugstr_w(file), debugstr_w(localfile), GetLastError()); + r = GetLastError(); + goto done; } + patch->localfile = strdupW( localfile ); /* apply substorage transforms */ substorage = msi_split_string( patch->transforms, ';' ); @@ -567,6 +579,8 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file ) r = msi_apply_substorage_transform( package, patch_db, substorage[i] ); msi_free( substorage ); + if (r != ERROR_SUCCESS) + goto done; msi_set_media_source_prop( package ); /* @@ -577,10 +591,20 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file ) list_add_tail( &package->patches, &patch->entry ); +done: msiobj_release( &si->hdr ); msiobj_release( &patch_db->hdr ); + if (patch && r != ERROR_SUCCESS) + { + if (patch->localfile) + DeleteFileW( patch->localfile ); - return ERROR_SUCCESS; + msi_free( patch->patchcode ); + msi_free( patch->transforms ); + msi_free( patch->localfile ); + msi_free( patch ); + } + return r; } /* get the PATCH property, and apply all the patches it specifies */ diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index c339ea9bde6..a8594a84d33 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -151,6 +151,7 @@ typedef struct tagMSIPATCHINFO struct list entry; LPWSTR patchcode; LPWSTR transforms; + LPWSTR localfile; } MSIPATCHINFO; typedef struct _column_info @@ -996,6 +997,7 @@ extern WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... ); extern UINT msi_create_component_directories( MSIPACKAGE *package ); extern UINT msi_set_last_used_source(LPCWSTR product, LPCWSTR usersid, MSIINSTALLCONTEXT context, DWORD options, LPCWSTR value); +extern UINT msi_get_local_package_name(LPWSTR path, LPCWSTR suffix); /* media */ diff --git a/dlls/msi/package.c b/dlls/msi/package.c index 45b4dc9f311..2ffd66e37bd 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -271,6 +271,7 @@ static void free_package_structures( MSIPACKAGE *package ) list_remove( &patch->entry ); msi_free( patch->patchcode ); msi_free( patch->transforms ); + msi_free( patch->localfile ); msi_free( patch ); } @@ -1133,12 +1134,12 @@ UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename ) return ERROR_SUCCESS; } -static UINT msi_get_local_package_name( LPWSTR path ) +UINT msi_get_local_package_name( LPWSTR path, LPCWSTR suffix ) { static const WCHAR szInstaller[] = { '\\','I','n','s','t','a','l','l','e','r','\\',0}; - static const WCHAR fmt[] = { '%','x','.','m','s','i',0}; - DWORD time, len, i; + static const WCHAR fmt[] = {'%','x',0}; + DWORD time, len, i, offset; HANDLE handle; time = GetTickCount(); @@ -1149,7 +1150,8 @@ static UINT msi_get_local_package_name( LPWSTR path ) len = strlenW(path); for (i = 0; i < 0x10000; i++) { - snprintfW( &path[len], MAX_PATH - len, fmt, (time + i)&0xffff ); + offset = snprintfW( path + len, MAX_PATH - len, fmt, (time + i) & 0xffff ); + memcpy( path + len + offset, suffix, (strlenW( suffix ) + 1) * sizeof(WCHAR) ); handle = CreateFileW( path, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); if (handle != INVALID_HANDLE_VALUE) @@ -1170,6 +1172,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) static const WCHAR OriginalDatabase[] = {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0}; static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0}; + static const WCHAR dotmsi[] = {'.','m','s','i',0}; MSIDATABASE *db = NULL; MSIPACKAGE *package; MSIHANDLE handle; @@ -1228,7 +1231,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) file = temppath; } - r = msi_get_local_package_name( localfile ); + r = msi_get_local_package_name( localfile, dotmsi ); if (r != ERROR_SUCCESS) return r;