From 7eb270265f143861553cbf64f23024f7b2b2221e Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Wed, 22 Nov 2006 15:13:12 +0900 Subject: [PATCH] msi: Load all folders in one query, rather one per query. --- dlls/msi/action.c | 177 +++++++++++++++++++++------------------------ dlls/msi/helpers.c | 5 +- dlls/msi/msipriv.h | 2 +- 3 files changed, 88 insertions(+), 96 deletions(-) diff --git a/dlls/msi/action.c b/dlls/msi/action.c index c49d26d6937..668b49e6a6b 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -1439,6 +1439,89 @@ static UINT load_all_files(MSIPACKAGE *package) return ERROR_SUCCESS; } +static UINT load_folder( MSIRECORD *row, LPVOID param ) +{ + MSIPACKAGE *package = param; + static const WCHAR szDot[] = { '.',0 }; + static WCHAR szEmpty[] = { 0 }; + LPWSTR p, tgt_short, tgt_long, src_short, src_long; + MSIFOLDER *folder; + + folder = msi_alloc_zero( sizeof (MSIFOLDER) ); + if (!folder) + return ERROR_NOT_ENOUGH_MEMORY; + + folder->Directory = msi_dup_record_field( row, 1 ); + + TRACE("%s\n", debugstr_w(folder->Directory)); + + p = msi_dup_record_field(row, 3); + + /* split src and target dir */ + tgt_short = p; + src_short = folder_split_path( p, ':' ); + + /* split the long and short paths */ + tgt_long = folder_split_path( tgt_short, '|' ); + src_long = folder_split_path( src_short, '|' ); + + /* check for no-op dirs */ + if (!lstrcmpW(szDot, tgt_short)) + tgt_short = szEmpty; + if (!lstrcmpW(szDot, src_short)) + src_short = szEmpty; + + if (!tgt_long) + tgt_long = tgt_short; + + if (!src_short) { + src_short = tgt_short; + src_long = tgt_long; + } + + if (!src_long) + src_long = src_short; + + /* FIXME: use the target short path too */ + folder->TargetDefault = strdupW(tgt_long); + folder->SourceShortPath = strdupW(src_short); + folder->SourceLongPath = strdupW(src_long); + msi_free(p); + + TRACE("TargetDefault = %s\n",debugstr_w( folder->TargetDefault )); + TRACE("SourceLong = %s\n", debugstr_w( folder->SourceLongPath )); + TRACE("SourceShort = %s\n", debugstr_w( folder->SourceShortPath )); + + folder->Parent = msi_dup_record_field( row, 2 ); + + folder->Property = msi_dup_property( package, folder->Directory ); + + list_add_tail( &package->folders, &folder->entry ); + + TRACE("returning %p\n", folder); + + return ERROR_SUCCESS; +} + +static UINT load_all_folders( MSIPACKAGE *package ) +{ + static const WCHAR query[] = { + 'S','E','L','E','C','T',' ','*',' ','F','R', 'O','M',' ', + '`','D','i','r','e','c','t','o','r','y','`',0 }; + MSIQUERY *view; + UINT r; + + if (!list_empty(&package->folders)) + return ERROR_SUCCESS; + + r = MSI_DatabaseOpenViewW( package->db, query, &view ); + if (r != ERROR_SUCCESS) + return r; + + r = MSI_IterateRecords(view, NULL, load_folder, package); + msiobj_release(&view->hdr); + return r; +} /* * I am not doing any of the costing functionality yet. @@ -1468,6 +1551,7 @@ static UINT ACTION_CostInitialize(MSIPACKAGE *package) load_all_components( package ); load_all_features( package ); load_all_files( package ); + load_all_folders( package ); return ERROR_SUCCESS; } @@ -1504,98 +1588,6 @@ static UINT ACTION_FileCost(MSIPACKAGE *package) return ERROR_SUCCESS; } -static MSIFOLDER *load_folder( MSIPACKAGE *package, LPCWSTR dir ) -{ - static const WCHAR Query[] = - {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', - '`','D','i','r','e','c', 't','o','r','y','`',' ', - 'W','H','E','R','E',' ', '`', 'D','i','r','e','c','t', 'o','r','y','`', - ' ','=',' ','\'','%','s','\'', - 0}; - static const WCHAR szDot[] = { '.',0 }; - static WCHAR szEmpty[] = { 0 }; - LPWSTR p, tgt_short, tgt_long, src_short, src_long; - LPCWSTR parent; - MSIRECORD *row; - MSIFOLDER *folder; - - TRACE("Looking for dir %s\n",debugstr_w(dir)); - - folder = get_loaded_folder( package, dir ); - if (folder) - return folder; - - TRACE("Working to load %s\n",debugstr_w(dir)); - - row = MSI_QueryGetRecord(package->db, Query, dir); - if (!row) - return NULL; - - folder = msi_alloc_zero( sizeof (MSIFOLDER) ); - if (!folder) - return NULL; - - folder->Directory = strdupW(dir); - - p = msi_dup_record_field(row, 3); - - /* split src and target dir */ - tgt_short = p; - src_short = folder_split_path( p, ':' ); - - /* split the long and short paths */ - tgt_long = folder_split_path( tgt_short, '|' ); - src_long = folder_split_path( src_short, '|' ); - - /* check for no-op dirs */ - if (!lstrcmpW(szDot, tgt_short)) - tgt_short = szEmpty; - if (!lstrcmpW(szDot, src_short)) - src_short = szEmpty; - - if (!tgt_long) - tgt_long = tgt_short; - - if (!src_short) { - src_short = tgt_short; - src_long = tgt_long; - } - - if (!src_long) - src_long = src_short; - - /* FIXME: use the target short path too */ - folder->TargetDefault = strdupW(tgt_long); - folder->SourceShortPath = strdupW(src_short); - folder->SourceLongPath = strdupW(src_long); - msi_free(p); - - TRACE("TargetDefault = %s\n",debugstr_w( folder->TargetDefault )); - TRACE("SourceLong = %s\n", debugstr_w( folder->SourceLongPath )); - TRACE("SourceShort = %s\n", debugstr_w( folder->SourceShortPath )); - - parent = MSI_RecordGetString(row, 2); - if (parent) - { - folder->Parent = load_folder( package, parent ); - if ( folder->Parent ) - TRACE("loaded parent %p %s\n", folder->Parent, - debugstr_w(folder->Parent->Directory)); - else - ERR("failed to load parent folder %s\n", debugstr_w(parent)); - } - - folder->Property = msi_dup_property( package, dir ); - - msiobj_release(&row->hdr); - - list_add_tail( &package->folders, &folder->entry ); - - TRACE("%s returning %p\n",debugstr_w(dir),folder); - - return folder; -} - static void ACTION_GetComponentInstallStates(MSIPACKAGE *package) { MSICOMPONENT *comp; @@ -1873,7 +1865,6 @@ static UINT ITERATE_CostFinalizeDirectories(MSIRECORD *row, LPVOID param) /* This helper function now does ALL the work */ TRACE("Dir %s ...\n",debugstr_w(name)); - load_folder(package,name); path = resolve_folder(package,name,FALSE,TRUE,NULL); TRACE("resolves to %s\n",debugstr_w(path)); msi_free(path); diff --git a/dlls/msi/helpers.c b/dlls/msi/helpers.c index 3da5a05dad4..e0ec6e69779 100644 --- a/dlls/msi/helpers.c +++ b/dlls/msi/helpers.c @@ -293,7 +293,7 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, if (!f->Parent) return path; - parent = f->Parent->Directory; + parent = f->Parent; TRACE(" ! Parent is %s\n", debugstr_w(parent)); @@ -496,6 +496,7 @@ void ACTION_free_package_structures( MSIPACKAGE* package) MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry ); list_remove( &folder->entry ); + msi_free( folder->Parent ); msi_free( folder->Directory ); msi_free( folder->TargetDefault ); msi_free( folder->SourceLongPath ); @@ -509,7 +510,7 @@ void ACTION_free_package_structures( MSIPACKAGE* package) LIST_FOR_EACH_SAFE( item, cursor, &package->components ) { MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry ); - + list_remove( &comp->entry ); msi_free( comp->Component ); msi_free( comp->ComponentId ); diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 23879a41fd7..f6089da0044 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -318,6 +318,7 @@ typedef struct tagMSIFOLDER { struct list entry; LPWSTR Directory; + LPWSTR Parent; LPWSTR TargetDefault; LPWSTR SourceLongPath; LPWSTR SourceShortPath; @@ -325,7 +326,6 @@ typedef struct tagMSIFOLDER LPWSTR ResolvedTarget; LPWSTR ResolvedSource; LPWSTR Property; /* initially set property */ - struct tagMSIFOLDER *Parent; INT State; /* 0 = uninitialized */ /* 1 = existing */