Mike McCormack : msi: Load all folders in one query,
rather one per query.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed Nov 22 05:21:58 CST 2006
Module: wine
Branch: master
Commit: 7eb270265f143861553cbf64f23024f7b2b2221e
URL: http://source.winehq.org/git/wine.git/?a=commit;h=7eb270265f143861553cbf64f23024f7b2b2221e
Author: Mike McCormack <mike at codeweavers.com>
Date: Wed Nov 22 15:13:12 2006 +0900
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 c49d26d..668b49e 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -1439,6 +1439,89 @@ static UINT load_all_files(MSIPACKAGE *p
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(MSIPAC
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 *
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_CostFinalizeDirector
/* 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 3da5a05..e0ec6e6 100644
--- a/dlls/msi/helpers.c
+++ b/dlls/msi/helpers.c
@@ -293,7 +293,7 @@ LPWSTR resolve_folder(MSIPACKAGE *packag
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( MSI
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( MSI
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 23879a4..f6089da 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 */
More information about the wine-cvs
mailing list