diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2012-10-22 14:31:10 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2012-12-06 20:25:48 +0100 |
commit | e77adbcbb6acc4775832065d80a721e248d675d3 (patch) | |
tree | 6fdb7bf869f100135fa8653cad6582dc153dcb55 /libmsi | |
parent | 0d6fdca97e8d8c0ee138f644f9ac42672db77965 (diff) | |
download | msitools-e77adbcbb6acc4775832065d80a721e248d675d3.tar.gz msitools-e77adbcbb6acc4775832065d80a721e248d675d3.tar.xz msitools-e77adbcbb6acc4775832065d80a721e248d675d3.zip |
kill patch.c
Diffstat (limited to 'libmsi')
-rw-r--r-- | libmsi/Makefile.am | 2 | ||||
-rw-r--r-- | libmsi/msipriv.h | 1 | ||||
-rw-r--r-- | libmsi/package.c | 13 | ||||
-rw-r--r-- | libmsi/patch.c | 766 |
4 files changed, 1 insertions, 781 deletions
diff --git a/libmsi/Makefile.am b/libmsi/Makefile.am index 3f8d2ad..ade1406 100644 --- a/libmsi/Makefile.am +++ b/libmsi/Makefile.am @@ -13,7 +13,7 @@ noinst_HEADERS = \ libmsi_la_SOURCES = alter.c create.c database.c delete.c distinct.c \ drop.c handle.c insert.c media.c msi.c msi_main.c msiquery.c \ - package.c patch.c record.c select.c source.c \ + package.c record.c select.c source.c \ storages.c streams.c string.c suminfo.c table.c tokenize.c update.c \ where.c \ sql-parser.y \ diff --git a/libmsi/msipriv.h b/libmsi/msipriv.h index 77939be..f064a07 100644 --- a/libmsi/msipriv.h +++ b/libmsi/msipriv.h @@ -362,7 +362,6 @@ typedef struct tagMSIPACKAGE enum platform platform; UINT num_langids; LANGID *langids; - struct list patches; struct list components; struct list features; struct list files; diff --git a/libmsi/package.c b/libmsi/package.c index 840040f..43a02f4 100644 --- a/libmsi/package.c +++ b/libmsi/package.c @@ -375,18 +375,6 @@ static void free_package_structures( MSIPACKAGE *package ) msi_free( cab ); } - LIST_FOR_EACH_SAFE( item, cursor, &package->patches ) - { - MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry ); - - list_remove( &patch->entry ); - if (patch->delete_on_close && !DeleteFileW( patch->localfile )) - { - ERR("failed to delete %s (%u)\n", debugstr_w(patch->localfile), GetLastError()); - } - msi_free_patchinfo( patch ); - } - msi_free( package->BaseURL ); msi_free( package->PackagePath ); msi_free( package->ProductCode ); @@ -553,7 +541,6 @@ static MSIPACKAGE *msi_alloc_package( void ) list_init( &package->RunningActions ); list_init( &package->sourcelist_info ); list_init( &package->sourcelist_media ); - list_init( &package->patches ); list_init( &package->binaries ); list_init( &package->cabinet_streams ); } diff --git a/libmsi/patch.c b/libmsi/patch.c deleted file mode 100644 index ca2458d..0000000 --- a/libmsi/patch.c +++ /dev/null @@ -1,766 +0,0 @@ -/* - * Implementation of the Microsoft Installer (msi.dll) - * - * Copyright 2004,2005 Aric Stewart for CodeWeavers - * Copyright 2011 Hans Leidekker for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include <stdarg.h> -#define COBJMACROS -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "objbase.h" -#include "shlwapi.h" -#include "wine/debug.h" -#include "wine/unicode.h" -#include "msipriv.h" - -WINE_DEFAULT_DEBUG_CHANNEL(msi); - -WCHAR **msi_split_string( const WCHAR *str, WCHAR sep ) -{ - LPCWSTR pc; - LPWSTR p, *ret = NULL; - UINT count = 0; - - if (!str) - return ret; - - /* count the number of substrings */ - for ( pc = str, count = 0; pc; count++ ) - { - pc = strchrW( pc, sep ); - if (pc) - pc++; - } - - /* allocate space for an array of substring pointers and the substrings */ - ret = msi_alloc( (count+1) * sizeof (LPWSTR) + - (lstrlenW(str)+1) * sizeof(WCHAR) ); - if (!ret) - return ret; - - /* copy the string and set the pointers */ - p = (LPWSTR) &ret[count+1]; - lstrcpyW( p, str ); - for( count = 0; (ret[count] = p); count++ ) - { - p = strchrW( p, sep ); - if (p) - *p++ = 0; - } - - return ret; -} - - -static BOOL match_language( MSIPACKAGE *package, LANGID langid ) -{ - UINT i; - - if (!package->num_langids || !langid) return TRUE; - for (i = 0; i < package->num_langids; i++) - { - if (package->langids[i] == langid) return TRUE; - } - return FALSE; -} - -static UINT check_transform_applicable( MSIPACKAGE *package, IStorage *patch ) -{ - LPWSTR prod_code, patch_product, template = NULL; - UINT ret = ERROR_FUNCTION_FAILED; - - prod_code = msi_dup_property( package->db, szProductCode ); - patch_product = msi_get_suminfo_product( patch ); - - TRACE("db = %s patch = %s\n", debugstr_w(prod_code), debugstr_w(patch_product)); - - if (strstrW( patch_product, prod_code )) - { - MSISUMMARYINFO *si; - const WCHAR *p; - - si = MSI_GetSummaryInformationW( patch, 0 ); - if (!si) - { - ERR("no summary information!\n"); - goto end; - } - template = msi_suminfo_dup_string( si, PID_TEMPLATE ); - if (!template) - { - ERR("no template property!\n"); - msiobj_release( &si->hdr ); - goto end; - } - if (!template[0]) - { - ret = ERROR_SUCCESS; - msiobj_release( &si->hdr ); - goto end; - } - TRACE("template: %s\n", debugstr_w(template)); - p = strchrW( template, ';' ); - if (p && match_language( package, atoiW( p + 1 ) )) - { - TRACE("applicable transform\n"); - ret = ERROR_SUCCESS; - } - /* FIXME: check platform */ - msiobj_release( &si->hdr ); - } - -end: - msi_free( patch_product ); - msi_free( prod_code ); - msi_free( template ); - return ret; -} - -static UINT apply_substorage_transform( MSIPACKAGE *package, MSIDATABASE *patch_db, LPCWSTR name ) -{ - UINT ret = ERROR_FUNCTION_FAILED; - IStorage *stg = NULL; - HRESULT r; - - TRACE("%p %s\n", package, debugstr_w(name)); - - if (*name++ != ':') - { - ERR("expected a colon in %s\n", debugstr_w(name)); - return ERROR_FUNCTION_FAILED; - } - r = IStorage_OpenStorage( patch_db->storage, name, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &stg ); - if (SUCCEEDED(r)) - { - ret = check_transform_applicable( package, stg ); - if (ret == ERROR_SUCCESS) - msi_table_apply_transform( package->db, stg ); - else - TRACE("substorage transform %s wasn't applicable\n", debugstr_w(name)); - IStorage_Release( stg ); - } - else - { - ERR("failed to open substorage %s\n", debugstr_w(name)); - } - return ERROR_SUCCESS; -} - -UINT msi_check_patch_applicable( MSIPACKAGE *package, MSISUMMARYINFO *si ) -{ - LPWSTR guid_list, *guids, product_code; - UINT i, ret = ERROR_FUNCTION_FAILED; - - product_code = msi_dup_property( package->db, szProductCode ); - if (!product_code) - { - /* FIXME: the property ProductCode should be written into the DB somewhere */ - ERR("no product code to check\n"); - return ERROR_SUCCESS; - } - guid_list = msi_suminfo_dup_string( si, PID_TEMPLATE ); - guids = msi_split_string( guid_list, ';' ); - for (i = 0; guids[i] && ret != ERROR_SUCCESS; i++) - { - if (!strcmpW( guids[i], product_code )) ret = ERROR_SUCCESS; - } - msi_free( guids ); - msi_free( guid_list ); - msi_free( product_code ); - return ret; -} - -static UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch ) -{ - MSIPATCHINFO *pi; - UINT r = ERROR_SUCCESS; - WCHAR *p; - - if (!(pi = msi_alloc_zero( sizeof(MSIPATCHINFO) ))) - { - return ERROR_OUTOFMEMORY; - } - if (!(pi->patchcode = msi_suminfo_dup_string( si, PID_REVNUMBER ))) - { - msi_free( pi ); - return ERROR_OUTOFMEMORY; - } - p = pi->patchcode; - if (*p != '{') - { - msi_free( pi->patchcode ); - msi_free( pi ); - return ERROR_PATCH_PACKAGE_INVALID; - } - if (!(p = strchrW( p + 1, '}' ))) - { - msi_free( pi->patchcode ); - msi_free( pi ); - return ERROR_PATCH_PACKAGE_INVALID; - } - if (p[1]) - { - FIXME("patch obsoletes %s\n", debugstr_w(p + 1)); - p[1] = 0; - } - TRACE("patch code %s\n", debugstr_w(pi->patchcode)); - if (!(pi->products = msi_suminfo_dup_string( si, PID_TEMPLATE ))) - { - msi_free( pi->patchcode ); - msi_free( pi ); - return ERROR_OUTOFMEMORY; - } - if (!(pi->transforms = msi_suminfo_dup_string( si, PID_LASTAUTHOR ))) - { - msi_free( pi->patchcode ); - msi_free( pi->products ); - msi_free( pi ); - return ERROR_OUTOFMEMORY; - } - *patch = pi; - return r; -} - -static UINT patch_set_media_source_prop( MSIPACKAGE *package ) -{ - static const WCHAR query[] = { - 'S','E','L','E','C','T',' ','`','S','o','u','r','c','e','`',' ','F','R','O','M',' ', - '`','M','e','d','i','a','`',' ','W','H','E','R','E',' ','`','S','o','u','r','c','e','`',' ', - 'I','S',' ','N','O','T',' ','N','U','L','L',0}; - MSIQUERY *view; - MSIRECORD *rec; - const WCHAR *property; - WCHAR *patch; - UINT r; - - r = MSI_DatabaseOpenViewW( package->db, query, &view ); - if (r != ERROR_SUCCESS) - return r; - - r = MSI_ViewExecute( view, 0 ); - if (r != ERROR_SUCCESS) - goto done; - - if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) - { - property = MSI_RecordGetString( rec, 1 ); - patch = msi_dup_property( package->db, szPatch ); - msi_set_property( package->db, property, patch ); - msi_free( patch ); - msiobj_release( &rec->hdr ); - } - -done: - msiobj_release( &view->hdr ); - return r; -} - -struct patch_offset -{ - struct list entry; - WCHAR *name; - UINT sequence; -}; - -struct patch_offset_list -{ - struct list files; - UINT count, min, max; - UINT offset_to_apply; -}; - -static struct patch_offset_list *patch_offset_list_create( void ) -{ - struct patch_offset_list *pos = msi_alloc( sizeof(struct patch_offset_list) ); - list_init( &pos->files ); - pos->count = pos->max = 0; - pos->min = 999999; - return pos; -} - -static void patch_offset_list_free( struct patch_offset_list *pos ) -{ - struct patch_offset *po, *po2; - - LIST_FOR_EACH_ENTRY_SAFE( po, po2, &pos->files, struct patch_offset, entry ) - { - msi_free( po->name ); - msi_free( po ); - } - msi_free( pos ); -} - -static void patch_offset_get_patches( MSIDATABASE *db, UINT last_sequence, struct patch_offset_list *pos ) -{ - static const WCHAR query[] = { - 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','P','a','t','c','h',' ', - 'W','H','E','R','E',' ','S','e','q','u','e','n','c','e',' ','<','=',' ','?',' ', - 'O','R','D','E','R',' ','B','Y',' ','S','e','q','u','e','n','c','e',0}; - MSIQUERY *view; - MSIRECORD *rec; - UINT r; - - r = MSI_DatabaseOpenViewW( db, query, &view ); - if (r != ERROR_SUCCESS) - return; - - rec = MSI_CreateRecord( 1 ); - MSI_RecordSetInteger( rec, 1, last_sequence ); - - r = MSI_ViewExecute( view, rec ); - msiobj_release( &rec->hdr ); - if (r != ERROR_SUCCESS) - return; - - while (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) - { - UINT sequence = MSI_RecordGetInteger( rec, 2 ); - - /* FIXME: we only use the max/min sequence numbers for now */ - pos->min = min( pos->min, sequence ); - pos->max = max( pos->max, sequence ); - pos->count++; - msiobj_release( &rec->hdr ); - } - msiobj_release( &view->hdr ); -} - -static void patch_offset_get_files( MSIDATABASE *db, UINT last_sequence, struct patch_offset_list *pos ) -{ - static const WCHAR query[] = { - 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','F','i','l','e',' ', - 'W','H','E','R','E',' ','S','e','q','u','e','n','c','e',' ','<','=',' ','?',' ', - 'O','R','D','E','R',' ','B','Y',' ','S','e','q','u','e','n','c','e',0}; - MSIQUERY *view; - MSIRECORD *rec; - UINT r; - - r = MSI_DatabaseOpenViewW( db, query, &view ); - if (r != ERROR_SUCCESS) - return; - - rec = MSI_CreateRecord( 1 ); - MSI_RecordSetInteger( rec, 1, last_sequence ); - - r = MSI_ViewExecute( view, rec ); - msiobj_release( &rec->hdr ); - if (r != ERROR_SUCCESS) - return; - - while (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) - { - UINT attributes = MSI_RecordGetInteger( rec, 7 ); - if (attributes & msidbFileAttributesPatchAdded) - { - struct patch_offset *po = msi_alloc( sizeof(struct patch_offset) ); - - po->name = msi_dup_record_field( rec, 1 ); - po->sequence = MSI_RecordGetInteger( rec, 8 ); - pos->min = min( pos->min, po->sequence ); - pos->max = max( pos->max, po->sequence ); - list_add_tail( &pos->files, &po->entry ); - pos->count++; - } - msiobj_release( &rec->hdr ); - } - msiobj_release( &view->hdr ); -} - -static UINT patch_offset_modify_db( MSIDATABASE *db, struct patch_offset_list *pos ) -{ - static const WCHAR query[] = { - 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','F','i','l','e',' ', - 'W','H','E','R','E',' ','S','e','q','u','e','n','c','e',' ','>','=',' ','?',' ', - 'A','N','D',' ','S','e','q','u','e','n','c','e',' ','<','=',' ','?',' ', - 'O','R','D','E','R',' ','B','Y',' ','S','e','q','u','e','n','c','e',0}; - struct patch_offset *po; - MSIRECORD *rec; - MSIQUERY *view; - UINT r; - - r = MSI_DatabaseOpenViewW( db, query, &view ); - if (r != ERROR_SUCCESS) - return ERROR_SUCCESS; - - rec = MSI_CreateRecord( 2 ); - MSI_RecordSetInteger( rec, 1, pos->min ); - MSI_RecordSetInteger( rec, 2, pos->max ); - - r = MSI_ViewExecute( view, rec ); - msiobj_release( &rec->hdr ); - if (r != ERROR_SUCCESS) - goto done; - - LIST_FOR_EACH_ENTRY( po, &pos->files, struct patch_offset, entry ) - { - UINT r_fetch; - while ((r_fetch = MSI_ViewFetch( view, &rec )) == ERROR_SUCCESS) - { - const WCHAR *file = MSI_RecordGetString( rec, 1 ); - UINT seq; - - if (!strcmpiW( file, po->name )) - { - /* update record */ - seq = MSI_RecordGetInteger( rec, 8 ); - MSI_RecordSetInteger( rec, 8, seq + pos->offset_to_apply ); - r = MSI_ViewModify( view, MSIMODIFY_UPDATE, rec ); - if (r != ERROR_SUCCESS) - ERR("Failed to update offset for file %s\n", debugstr_w(file)); - msiobj_release( &rec->hdr ); - break; - } - msiobj_release( &rec->hdr ); - } - if (r_fetch != ERROR_SUCCESS) break; - } - -done: - msiobj_release( &view->hdr ); - return ERROR_SUCCESS; -} - -static const WCHAR patch_media_query[] = { - 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','M','e','d','i','a','`',' ', - 'W','H','E','R','E',' ','`','S','o','u','r','c','e','`',' ','I','S',' ','N','O','T',' ','N','U','L','L',' ', - 'A','N','D',' ','`','C','a','b','i','n','e','t','`',' ','I','S',' ','N','O','T',' ','N','U','L','L',' ', - 'O','R','D','E','R',' ','B','Y',' ','`','D','i','s','k','I','d','`',0}; - -struct patch_media -{ - struct list entry; - UINT disk_id; - UINT last_sequence; - WCHAR *prompt; - WCHAR *cabinet; - WCHAR *volume; - WCHAR *source; -}; - -static UINT add_patch_media( MSIPACKAGE *package, IStorage *patch ) -{ - static const WCHAR delete_query[] = { - 'D','E','L','E','T','E',' ','F','R','O','M',' ','`','M','e','d','i','a','`',' ', - 'W','H','E','R','E',' ','`','D','i','s','k','I','d','`','=','?',0}; - static const WCHAR insert_query[] = { - 'I','N','S','E','R','T',' ','I','N','T','O',' ','`','M','e','d','i','a','`',' ', - '(','`','D','i','s','k','I','d','`',',','`','L','a','s','t','S','e','q','u','e','n','c','e','`',',', - '`','D','i','s','k','P','r','o','m','p','t','`',',','`','C','a','b','i','n','e','t','`',',', - '`','V','o','l','u','m','e','L','a','b','e','l','`',',','`','S','o','u','r','c','e','`',')',' ', - 'V','A','L','U','E','S',' ','(','?',',','?',',','?',',','?',',','?',',','?',')',0}; - MSIQUERY *view; - MSIRECORD *rec; - UINT r, disk_id; - struct list media_list; - struct patch_media *media, *next; - - r = MSI_DatabaseOpenViewW( package->db, patch_media_query, &view ); - if (r != ERROR_SUCCESS) return r; - - r = MSI_ViewExecute( view, 0 ); - if (r != ERROR_SUCCESS) - { - msiobj_release( &view->hdr ); - TRACE("query failed %u\n", r); - return r; - } - list_init( &media_list ); - while (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) - { - disk_id = MSI_RecordGetInteger( rec, 1 ); - TRACE("disk_id %u\n", disk_id); - if (disk_id >= MSI_INITIAL_MEDIA_TRANSFORM_DISKID) - { - msiobj_release( &rec->hdr ); - continue; - } - if (!(media = msi_alloc( sizeof( *media )))) goto done; - media->disk_id = disk_id; - media->last_sequence = MSI_RecordGetInteger( rec, 2 ); - media->prompt = msi_dup_record_field( rec, 3 ); - media->cabinet = msi_dup_record_field( rec, 4 ); - media->volume = msi_dup_record_field( rec, 5 ); - media->source = msi_dup_record_field( rec, 6 ); - - list_add_tail( &media_list, &media->entry ); - msiobj_release( &rec->hdr ); - } - LIST_FOR_EACH_ENTRY( media, &media_list, struct patch_media, entry ) - { - MSIQUERY *delete_view, *insert_view; - - r = MSI_DatabaseOpenViewW( package->db, delete_query, &delete_view ); - if (r != ERROR_SUCCESS) goto done; - - rec = MSI_CreateRecord( 1 ); - MSI_RecordSetInteger( rec, 1, media->disk_id ); - - r = MSI_ViewExecute( delete_view, rec ); - msiobj_release( &delete_view->hdr ); - msiobj_release( &rec->hdr ); - if (r != ERROR_SUCCESS) goto done; - - r = MSI_DatabaseOpenViewW( package->db, insert_query, &insert_view ); - if (r != ERROR_SUCCESS) goto done; - - disk_id = package->db->media_transform_disk_id; - TRACE("disk id %u\n", disk_id); - TRACE("last sequence %u\n", media->last_sequence); - TRACE("prompt %s\n", debugstr_w(media->prompt)); - TRACE("cabinet %s\n", debugstr_w(media->cabinet)); - TRACE("volume %s\n", debugstr_w(media->volume)); - TRACE("source %s\n", debugstr_w(media->source)); - - rec = MSI_CreateRecord( 6 ); - MSI_RecordSetInteger( rec, 1, disk_id ); - MSI_RecordSetInteger( rec, 2, media->last_sequence ); - MSI_RecordSetStringW( rec, 3, media->prompt ); - MSI_RecordSetStringW( rec, 4, media->cabinet ); - MSI_RecordSetStringW( rec, 5, media->volume ); - MSI_RecordSetStringW( rec, 6, media->source ); - - r = MSI_ViewExecute( insert_view, rec ); - msiobj_release( &insert_view->hdr ); - msiobj_release( &rec->hdr ); - if (r != ERROR_SUCCESS) goto done; - - r = msi_add_cabinet_stream( package, disk_id, patch, media->cabinet ); - if (r != ERROR_SUCCESS) WARN("failed to add cabinet stream %u\n", r); - package->db->media_transform_disk_id++; - } - -done: - msiobj_release( &view->hdr ); - LIST_FOR_EACH_ENTRY_SAFE( media, next, &media_list, struct patch_media, entry ) - { - list_remove( &media->entry ); - msi_free( media->prompt ); - msi_free( media->cabinet ); - msi_free( media->volume ); - msi_free( media->source ); - msi_free( media ); - } - return r; -} - -static UINT set_patch_offsets( MSIDATABASE *db ) -{ - MSIQUERY *view; - MSIRECORD *rec; - UINT r; - - r = MSI_DatabaseOpenViewW( db, patch_media_query, &view ); - if (r != ERROR_SUCCESS) - return r; - - r = MSI_ViewExecute( view, 0 ); - if (r != ERROR_SUCCESS) - goto done; - - while (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) - { - UINT last_sequence = MSI_RecordGetInteger( rec, 2 ); - struct patch_offset_list *pos; - - /* FIXME: set/check Source field instead? */ - if (last_sequence >= MSI_INITIAL_MEDIA_TRANSFORM_OFFSET) - { - msiobj_release( &rec->hdr ); - continue; - } - pos = patch_offset_list_create(); - patch_offset_get_files( db, last_sequence, pos ); - patch_offset_get_patches( db, last_sequence, pos ); - if (pos->count) - { - UINT offset = db->media_transform_offset - pos->min; - last_sequence = offset + pos->max; - - /* FIXME: this is for the patch table, which is not yet properly transformed */ - last_sequence += pos->min; - pos->offset_to_apply = offset; - patch_offset_modify_db( db, pos ); - - MSI_RecordSetInteger( rec, 2, last_sequence ); - r = MSI_ViewModify( view, MSIMODIFY_UPDATE, rec ); - if (r != ERROR_SUCCESS) - ERR("Failed to update Media table entry, expect breakage (%u)\n", r); - db->media_transform_offset = last_sequence + 1; - } - patch_offset_list_free( pos ); - msiobj_release( &rec->hdr ); - } - -done: - msiobj_release( &view->hdr ); - return r; -} - -static UINT msi_apply_patch_db( MSIPACKAGE *package, MSIDATABASE *patch_db, MSIPATCHINFO *patch ) -{ - UINT i, r = ERROR_SUCCESS; - WCHAR **substorage; - - /* apply substorage transforms */ - substorage = msi_split_string( patch->transforms, ';' ); - for (i = 0; substorage && substorage[i] && r == ERROR_SUCCESS; i++) - { - r = apply_substorage_transform( package, patch_db, substorage[i] ); - if (r == ERROR_SUCCESS) - { - add_patch_media( package, patch_db->storage ); - set_patch_offsets( package->db ); - } - } - msi_free( substorage ); - if (r != ERROR_SUCCESS) - return r; - - patch_set_media_source_prop( package ); - - patch->state = MSIPATCHSTATE_APPLIED; - list_add_tail( &package->patches, &patch->entry ); - return ERROR_SUCCESS; -} - -void msi_free_patchinfo( MSIPATCHINFO *patch ) -{ - msi_free( patch->patchcode ); - msi_free( patch->products ); - msi_free( patch->transforms ); - msi_free( patch->filename ); - msi_free( patch->localfile ); - msi_free( patch ); -} - -static UINT msi_apply_patch_package( MSIPACKAGE *package, const WCHAR *file ) -{ - static const WCHAR dotmsp[] = {'.','m','s','p',0}; - MSIDATABASE *patch_db = NULL; - WCHAR localfile[MAX_PATH]; - MSISUMMARYINFO *si; - MSIPATCHINFO *patch = NULL; - UINT r = ERROR_SUCCESS; - - TRACE("%p %s\n", package, debugstr_w(file)); - - r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY + MSIDBOPEN_PATCHFILE, &patch_db ); - if (r != ERROR_SUCCESS) - { - ERR("failed to open patch collection %s\n", debugstr_w( file ) ); - return r; - } - if (!(si = MSI_GetSummaryInformationW( patch_db->storage, 0 ))) - { - msiobj_release( &patch_db->hdr ); - return ERROR_FUNCTION_FAILED; - } - r = msi_check_patch_applicable( package, si ); - if (r != ERROR_SUCCESS) - { - TRACE("patch not applicable\n"); - r = ERROR_SUCCESS; - goto done; - } - r = msi_parse_patch_summary( si, &patch ); - if ( r != ERROR_SUCCESS ) - goto done; - - r = msi_create_empty_local_file( localfile, dotmsp ); - if ( r != ERROR_SUCCESS ) - goto done; - - r = ERROR_OUTOFMEMORY; - if (!(patch->filename = strdupW( file ))) goto done; - if (!(patch->localfile = strdupW( localfile ))) goto done; - - r = msi_apply_patch_db( package, patch_db, patch ); - if (r != ERROR_SUCCESS) WARN("patch failed to apply %u\n", r); - -done: - msiobj_release( &si->hdr ); - msiobj_release( &patch_db->hdr ); - if (patch && r != ERROR_SUCCESS) - { - DeleteFileW( patch->localfile ); - msi_free_patchinfo( patch ); - } - return r; -} - -/* get the PATCH property, and apply all the patches it specifies */ -UINT msi_apply_patches( MSIPACKAGE *package ) -{ - LPWSTR patch_list, *patches; - UINT i, r = ERROR_SUCCESS; - - patch_list = msi_dup_property( package->db, szPatch ); - - TRACE("patches to be applied: %s\n", debugstr_w(patch_list)); - - patches = msi_split_string( patch_list, ';' ); - for (i = 0; patches && patches[i] && r == ERROR_SUCCESS; i++) - r = msi_apply_patch_package( package, patches[i] ); - - msi_free( patches ); - msi_free( patch_list ); - return r; -} - -UINT msi_apply_transforms( MSIPACKAGE *package ) -{ - static const WCHAR szTransforms[] = {'T','R','A','N','S','F','O','R','M','S',0}; - LPWSTR xform_list, *xforms; - UINT i, r = ERROR_SUCCESS; - - xform_list = msi_dup_property( package->db, szTransforms ); - xforms = msi_split_string( xform_list, ';' ); - - for (i = 0; xforms && xforms[i] && r == ERROR_SUCCESS; i++) - { - if (xforms[i][0] == ':') - r = apply_substorage_transform( package, package->db, xforms[i] ); - else - { - WCHAR *transform; - - if (!PathIsRelativeW( xforms[i] )) transform = xforms[i]; - else - { - WCHAR *p = strrchrW( package->PackagePath, '\\' ); - DWORD len = p - package->PackagePath + 1; - - if (!(transform = msi_alloc( (len + strlenW( xforms[i] ) + 1) * sizeof(WCHAR)) )) - { - msi_free( xforms ); - msi_free( xform_list ); - return ERROR_OUTOFMEMORY; - } - memcpy( transform, package->PackagePath, len * sizeof(WCHAR) ); - memcpy( transform + len, xforms[i], (strlenW( xforms[i] ) + 1) * sizeof(WCHAR) ); - } - r = MSI_DatabaseApplyTransformW( package->db, transform, 0 ); - if (transform != xforms[i]) msi_free( transform ); - } - } - msi_free( xforms ); - msi_free( xform_list ); - return r; -} |