MSI: fix MsiGetTargetPath, MsiGetSourcePath and MsiSetTargetPath
Mike McCormack
mike at codeweavers.com
Thu Jul 1 12:05:34 CDT 2004
ChangeLog:
<aric at codeweavers.com>
* fix MsiGetTargetPath, MsiGetSourcePath and MsiSetTargetPath
-------------- next part --------------
diff -u dlls/msi.old/action.c dlls/msi/action.c
--- dlls/msi.old/action.c 2004-07-01 10:51:49.000000000 -0500
+++ dlls/msi/action.c 2004-07-01 10:53:20.000000000 -0500
@@ -49,6 +49,53 @@
WINE_DEFAULT_DEBUG_CHANNEL(msi);
+typedef struct tagMSIFEATURE
+{
+ WCHAR Feature[96];
+ WCHAR Feature_Parent[96];
+ WCHAR Title[0x100];
+ WCHAR Description[0x100];
+ INT Display;
+ INT Level;
+ WCHAR Directory[96];
+ INT Attributes;
+
+ INSTALLSTATE State;
+ INT ComponentCount;
+ INT Components[1024]; /* yes hardcoded limit.... */
+} MSIFEATURE;
+
+typedef struct tagMSICOMPONENT
+{
+ WCHAR Component[96];
+ WCHAR ComponentId[96];
+ WCHAR Directory[96];
+ INT Attributes;
+ WCHAR Condition[0x100];
+ WCHAR KeyPath[96];
+
+ INSTALLSTATE State;
+ BOOL Enabled;
+}MSICOMPONENT;
+
+typedef struct tagMSIFOLDER
+{
+ WCHAR Directory[96];
+ WCHAR TargetDefault[96];
+ WCHAR SourceDefault[96];
+
+ WCHAR ResolvedTarget[MAX_PATH];
+ WCHAR ResolvedSource[MAX_PATH];
+
+ BOOL Property; /* initialy set property */
+ INT ParentIndex;
+ INT State;
+ /* 0 = uninitialized */
+ /* 1 = existing */
+ /* 2 = created remove if empty */
+ /* 3 = created persist if empty */
+}MSIFOLDER;
+
/*
* Prototypes
*/
@@ -70,6 +117,9 @@
const LPWSTR target, const INT type);
static DWORD deformat_string(MSIHANDLE hPackage, WCHAR* ptr,WCHAR** data);
+static UINT resolve_folder(MSIHANDLE hPackage, LPCWSTR name, LPWSTR path,
+ BOOL source, BOOL set_prop, MSIFOLDER **folder);
+
/*
* consts and values used
@@ -77,6 +127,8 @@
static const WCHAR cszSourceDir[] = {'S','o','u','r','c','e','D','i','r',0};
static const WCHAR cszRootDrive[] = {'R','O','O','T','D','R','I','V','E',0};
static const WCHAR cszTargetDir[] = {'T','A','R','G','E','T','D','I','R',0};
+static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
+static const WCHAR cszDatabase[]={'D','A','T','A','B','A','S','E',0};
static const WCHAR c_collen[] = {'C',':','\\',0};
static const WCHAR cszlsb[]={'[',0};
@@ -100,6 +152,22 @@
return ret;
}
+int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component )
+{
+ INT rc = -1;
+ INT i;
+
+ for (i = 0; i < package->loaded_components; i++)
+ {
+ if (strcmpW(Component,package->components[i].Component)==0)
+ {
+ rc = i;
+ break;
+ }
+ }
+ return rc;
+}
+
/****************************************************
* TOP level entry points
*****************************************************/
@@ -585,10 +653,10 @@
static UINT store_binary_to_temp(MSIHANDLE hPackage, const LPWSTR source,
LPWSTR tmp_file)
{
- static const WCHAR TF[]= {'T','e','m','p','F','o','l','d','e','r',0};
DWORD sz=MAX_PATH;
- if (MsiGetPropertyW(hPackage, TF,tmp_file, &sz) != ERROR_SUCCESS)
+ if (MsiGetPropertyW(hPackage, cszTempFolder, tmp_file, &sz)
+ != ERROR_SUCCESS)
GetTempPathW(MAX_PATH,tmp_file);
strcatW(tmp_file,source);
@@ -820,6 +888,7 @@
UINT rc;
MSIHANDLE view;
MSIHANDLE db;
+ MSIFOLDER *folder;
db = MsiGetActiveDatabase(hPackage);
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
@@ -861,7 +930,7 @@
}
sz = MAX_PATH;
- rc = MsiGetPropertyW(hPackage, dir,full_path,&sz);
+ rc = resolve_folder(hPackage,dir,full_path,FALSE,FALSE,&folder);
if (rc != ERROR_SUCCESS)
{
@@ -871,7 +940,10 @@
}
TRACE("Folder is %s\n",debugstr_w(full_path));
- create_full_pathW(full_path);
+ if (folder->State == 0)
+ create_full_pathW(full_path);
+
+ folder->State = 3;
MsiCloseHandle(row);
}
@@ -881,17 +953,263 @@
return rc;
}
+
+static int load_component(MSIPACKAGE* package, MSIHANDLE row)
+{
+ int index = package->loaded_components;
+ DWORD sz;
+
+ /* fill in the data */
+
+ package->loaded_components++;
+ if (package->loaded_components == 1)
+ package->components = HeapAlloc(GetProcessHeap(),0,
+ sizeof(MSICOMPONENT));
+ else
+ package->components = HeapReAlloc(GetProcessHeap(),0,
+ package->components, package->loaded_components *
+ sizeof(MSICOMPONENT));
+
+ memset(&package->components[index],0,sizeof(MSICOMPONENT));
+
+ sz = 96;
+ MsiRecordGetStringW(row,1,package->components[index].Component,&sz);
+
+ TRACE("Loading Component %s\n",
+ debugstr_w(package->components[index].Component));
+
+ sz = 0x100;
+ if (!MsiRecordIsNull(row,2))
+ MsiRecordGetStringW(row,2,package->components[index].ComponentId,&sz);
+
+ sz = 96;
+ MsiRecordGetStringW(row,3,package->components[index].Directory,&sz);
+
+ package->components[index].Attributes = MsiRecordGetInteger(row,4);
+
+ sz = 0x100;
+ MsiRecordGetStringW(row,5,package->components[index].Condition,&sz);
+
+ sz = 96;
+ MsiRecordGetStringW(row,6,package->components[index].KeyPath,&sz);
+
+ package->components[index].State = INSTALLSTATE_UNKNOWN;
+ package->components[index].Enabled = TRUE;
+
+ return index;
+}
+
+static void load_feature(MSIPACKAGE* package, MSIHANDLE row)
+{
+ int index = package->loaded_features;
+ DWORD sz;
+ static const WCHAR Query1[] = {'S','E','L','E','C','T',' ','C','o','m','p',
+'o','n','e','n','t','_',' ','F','R','O','M',' ','F','e','a','t','u','r','e',
+'C','o','m','p','o','n','e','n','t','s',' ','W','H','E','R','E',' ','F','e',
+'a','t','u','r','e','_','=','\'','%','s','\'',0};
+ static const WCHAR Query2[] = {'S','E','L','E','C','T',' ','*',' ','F','R',
+'O','M',' ','C','o','m','p','o','n','e','n','t',' ','W','H','E','R','E',' ','C',
+'o','m','p','o','n','e','n','t','=','\'','%','s','\'',0};
+ WCHAR Query[1024];
+ MSIHANDLE view;
+ MSIHANDLE view2;
+ MSIHANDLE row2;
+ MSIHANDLE row3;
+
+ /* fill in the data */
+
+ package->loaded_features ++;
+ if (package->loaded_features == 1)
+ package->features = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFEATURE));
+ else
+ package->features = HeapReAlloc(GetProcessHeap(),0,package->features,
+ package->loaded_features * sizeof(MSIFEATURE));
+
+ memset(&package->features[index],0,sizeof(MSIFEATURE));
+
+ sz = 96;
+ MsiRecordGetStringW(row,1,package->features[index].Feature,&sz);
+
+ TRACE("Loading feature %s\n",debugstr_w(package->features[index].Feature));
+
+ sz = 96;
+ if (!MsiRecordIsNull(row,2))
+ MsiRecordGetStringW(row,2,package->features[index].Feature_Parent,&sz);
+
+ sz = 0x100;
+ if (!MsiRecordIsNull(row,3))
+ MsiRecordGetStringW(row,3,package->features[index].Title,&sz);
+
+ sz = 0x100;
+ if (!MsiRecordIsNull(row,4))
+ MsiRecordGetStringW(row,4,package->features[index].Description,&sz);
+
+ if (!MsiRecordIsNull(row,5))
+ package->features[index].Display = MsiRecordGetInteger(row,5);
+
+ package->features[index].Level= MsiRecordGetInteger(row,6);
+
+ sz = 96;
+ if (!MsiRecordIsNull(row,7))
+ MsiRecordGetStringW(row,7,package->features[index].Directory,&sz);
+
+ package->features[index].Attributes= MsiRecordGetInteger(row,8);
+ package->features[index].State = INSTALLSTATE_UNKNOWN;
+
+ /* load feature components */
+
+ sprintfW(Query,Query1,package->features[index].Feature);
+ MsiDatabaseOpenViewW(package->db,Query,&view);
+ MsiViewExecute(view,0);
+ while (1)
+ {
+ DWORD sz = 0x100;
+ WCHAR buffer[0x100];
+ DWORD rc;
+ INT c_indx;
+ INT cnt = package->features[index].ComponentCount;
+
+ rc = MsiViewFetch(view,&row2);
+ if (rc != ERROR_SUCCESS)
+ break;
+
+ sz = 0x100;
+ MsiRecordGetStringW(row2,1,buffer,&sz);
+
+ /* check to see if the component is already loaded */
+ c_indx = get_loaded_component(package,buffer);
+ if (c_indx != -1)
+ {
+ TRACE("Component %s already loaded at %i\n", debugstr_w(buffer),
+ c_indx);
+ package->features[index].Components[cnt] = c_indx;
+ package->features[index].ComponentCount ++;
+ }
+
+ sprintfW(Query,Query2,buffer);
+
+ MsiDatabaseOpenViewW(package->db,Query,&view2);
+ MsiViewExecute(view2,0);
+ while (1)
+ {
+ DWORD rc;
+
+ rc = MsiViewFetch(view2,&row3);
+ if (rc != ERROR_SUCCESS)
+ break;
+ c_indx = load_component(package,row3);
+ MsiCloseHandle(row3);
+
+ package->features[index].Components[cnt] = c_indx;
+ package->features[index].ComponentCount ++;
+ }
+ MsiViewClose(view2);
+ MsiCloseHandle(view2);
+ MsiCloseHandle(row2);
+ }
+ MsiViewClose(view);
+ MsiCloseHandle(view);
+}
+
/*
- * Workhorse function for creating the directories
- * during Costing
+ * I am not doing any of the costing functionality yet.
+ * Mostly looking at doing the Component and Feature loading
+ *
+ * The native MSI does ALOT of modification to tables here. Mostly adding alot
+ * of temporary columns to the Feature and Component tables.
+ *
+ * note: native msi also tracks the short filename. but i am only going to
+ * track the long ones. Also looking at this directory table
+ * it appears that the directory table does not get the parents
+ * resolved base on property only based on their entrys in the
+ * directory table.
*/
-static UINT resolve_directory(MSIHANDLE hPackage, const WCHAR* dir,
- WCHAR* path, BOOL source)
+static UINT ACTION_CostInitialize(MSIHANDLE hPackage)
{
- static const WCHAR cszsrc[]={'_','S','o','u','r','c','e',0};
- static const WCHAR cszsrcroot[]=
- {'[','S','o','u','r','c','e','D','i','r',']',0};
+ MSIHANDLE view;
+ MSIHANDLE row;
+ CHAR local[0x100];
+ DWORD sz;
+ MSIPACKAGE *package;
+
+ static const CHAR Query_all[] = "SELECT * FROM Feature";
+ static const CHAR Query_one[] = "SELECT * FROM Feature WHERE Feature='%s'";
+ CHAR Query[1023];
+
+ MsiSetPropertyA(hPackage,"CostingComplete","0");
+ MsiSetPropertyW(hPackage, cszRootDrive , c_collen);
+
+ package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
+
+ sz = 0x100;
+ if (MsiGetPropertyA(hPackage,"ADDLOCAL",local,&sz)==ERROR_SUCCESS)
+ {
+ if (strcasecmp(local,"ALL")==0)
+ {
+ MsiDatabaseOpenViewA(package->db,Query_all,&view);
+ MsiViewExecute(view,0);
+ while (1)
+ {
+ DWORD rc;
+
+ rc = MsiViewFetch(view,&row);
+ if (rc != ERROR_SUCCESS)
+ break;
+
+ load_feature(package,row);
+ MsiCloseHandle(row);
+ }
+ MsiViewClose(view);
+ MsiCloseHandle(view);
+ }
+ else
+ {
+ LPSTR ptr,ptr2;
+ ptr = local;
+
+ while (ptr && *ptr)
+ {
+ CHAR feature[0x100];
+ DWORD rc;
+ ptr2 = strchr(ptr,',');
+
+ if (ptr2)
+ {
+ strncpy(feature,ptr,ptr2-ptr);
+ feature[ptr2-ptr]=0;
+ ptr2++;
+ ptr = ptr2;
+ }
+ else
+ {
+ strcpy(feature,ptr);
+ ptr = NULL;
+ }
+
+ sprintf(Query,Query_one,feature);
+
+ MsiDatabaseOpenViewA(package->db,Query,&view);
+ MsiViewExecute(view,0);
+ rc = MsiViewFetch(view,&row);
+ if (rc != ERROR_SUCCESS)
+ break;
+
+ load_feature(package,row);
+
+ MsiCloseHandle(row);
+ MsiViewClose(view);
+ MsiCloseHandle(view);
+ }
+ }
+ }
+
+ return ERROR_SUCCESS;
+}
+
+static INT load_folder(MSIHANDLE hPackage, const WCHAR* dir)
+
+{
WCHAR Query[1024] =
{'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',
@@ -902,59 +1220,56 @@
WCHAR targetbuffer[0x100];
WCHAR *srcdir = NULL;
WCHAR *targetdir = NULL;
- WCHAR buffer[0x100];
WCHAR parent[0x100];
- WCHAR parent_path[MAX_PATH];
DWORD sz=0x100;
MSIHANDLE row = 0;
- WCHAR full_path[MAX_PATH];
- WCHAR name_source[0x100];
- MSIHANDLE db;
+ MSIPACKAGE *package;
+ INT i,index = -1;;
- sz = MAX_PATH;
- if (MsiGetPropertyW(hPackage,dir,path,&sz)==ERROR_SUCCESS)
- return ERROR_SUCCESS;
+ package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
- TRACE("Working to resolve %s\n",debugstr_w(dir));
+ TRACE("Looking for dir %s\n",debugstr_w(dir));
- /* special case... root drive */
- if (strcmpW(dir,cszTargetDir)==0)
+ for (i = 0; i < package->loaded_folders; i++)
{
- if (!source)
+ if (strcmpW(package->folders[i].Directory,dir)==0)
{
- sz = 0x100;
- if(!MsiGetPropertyW(hPackage,cszRootDrive,buffer,&sz))
- {
- MsiSetPropertyW(hPackage,cszTargetDir,buffer);
- strcpyW(path,buffer);
- }
- else
- {
- strcpyW(path,c_collen);
- }
+ TRACE(" %s retuning on index %i\n",debugstr_w(dir),i);
+ return i;
}
- else
- strcpyW(path,cszsrcroot);
-
- return ERROR_SUCCESS;
}
+ TRACE("Working to load %s\n",debugstr_w(dir));
+
+ index = package->loaded_folders;
+
+ package->loaded_folders++;
+ if (package->loaded_folders== 1)
+ package->folders = HeapAlloc(GetProcessHeap(),0,
+ sizeof(MSIFOLDER));
+ else
+ package->folders= HeapReAlloc(GetProcessHeap(),0,
+ package->folders, package->loaded_folders*
+ sizeof(MSIFOLDER));
+
+ memset(&package->folders[index],0,sizeof(MSIFOLDER));
+
+ strcpyW(package->folders[index].Directory,dir);
+
strcatW(Query,dir);
strcatW(Query,end);
- db = MsiGetActiveDatabase(hPackage);
- rc = MsiDatabaseOpenViewW(db, Query, &view);
- MsiCloseHandle(db);
+ rc = MsiDatabaseOpenViewW(package->db, Query, &view);
if (rc != ERROR_SUCCESS)
- return rc;
+ return -1;
rc = MsiViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
MsiViewClose(view);
MsiCloseHandle(view);
- return rc;
+ return -1;
}
rc = MsiViewFetch(view,&row);
@@ -962,7 +1277,7 @@
{
MsiViewClose(view);
MsiCloseHandle(view);
- return rc;
+ return -1;
}
sz=0x100;
@@ -1000,6 +1315,14 @@
if (srcdir && srcdir[0] == '.' && srcdir[1] == 0)
srcdir = NULL;
+ if (targetdir)
+ strcpyW(package->folders[index].TargetDefault,targetdir);
+
+ if (srcdir)
+ strcpyW(package->folders[index].SourceDefault,srcdir);
+ else if (targetdir)
+ strcpyW(package->folders[index].SourceDefault,targetdir);
+
if (MsiRecordIsNull(row,2))
parent[0]=0;
else
@@ -1010,175 +1333,145 @@
if (parent[0])
{
- resolve_directory(hPackage,parent,parent_path,FALSE);
- strcpyW(full_path,parent_path);
- if (targetdir)
- {
- strcatW(full_path,targetdir);
- strcatW(full_path,cszbs);
- }
- MsiSetPropertyW(hPackage,dir,full_path);
- if (!source)
- strcpyW(path,full_path);
+ i = load_folder(hPackage,parent);
+ package->folders[index].ParentIndex = i;
+ TRACE("Parent is index %i... %s %s\n",
+ package->folders[index].ParentIndex,
+ debugstr_w(package->folders[package->folders[index].ParentIndex].Directory),
+ debugstr_w(parent));
+ }
+ else
+ package->folders[index].ParentIndex = -2;
- resolve_directory(hPackage,parent,parent_path,TRUE);
- strcpyW(full_path,parent_path);
- if (srcdir)
- {
- strcatW(full_path,srcdir);
- strcatW(full_path,cszbs);
- }
- else if (targetdir)
- {
- strcatW(full_path,targetdir);
- strcatW(full_path,cszbs);
- }
-
- strcpyW(name_source,dir);
- strcatW(name_source,cszsrc);
- MsiSetPropertyW(hPackage,name_source,full_path);
- if (source)
- strcpyW(path,full_path);
+ sz = MAX_PATH;
+ rc = MsiGetPropertyW(hPackage, dir, package->folders[index].ResolvedTarget,
+ &sz);
+ if (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA)
+ package->folders[index].Property = TRUE;
+ else
+ {
+ package->folders[index].Property = FALSE;
}
MsiCloseHandle(row);
MsiViewClose(view);
MsiCloseHandle(view);
- return rc;
+ TRACE(" %s retuning on index %i\n",debugstr_w(dir),index);
+ return index;
}
-/*
- * I am not doing any of the costing functionality yet.
- * Mostly looking at doing the Component and Feature loading
- *
- * The native MSI does ALOT of modification to tables here. Mostly adding alot
- * of temporary columns to the Feature and Component tables.
- * Unfortunately I cannot add temporary columns yet, nor can I really figure
- * out what all the columns are for. So I am going to attack this another way
- * and make some temporary tables to hold the data I think I need.
- *
- * WINE_Feature
- * Feature Identifier : key into the Feature table
- * Enabled Int : 1 if being installed, 0 if not
- */
-static UINT ACTION_CostInitialize(MSIHANDLE hPackage)
+static UINT resolve_folder(MSIHANDLE hPackage, LPCWSTR name, LPWSTR path,
+ BOOL source, BOOL set_prop, MSIFOLDER **folder)
{
- MSIHANDLE db;
- MSIHANDLE view;
- MSIHANDLE row;
- CHAR local[0x100];
- WCHAR buffer[0x100];
+ MSIPACKAGE *package;
+ INT i;
+ UINT rc = ERROR_SUCCESS;
DWORD sz;
- static const CHAR CreateSql[] = "CREATE TABLE `WINE_Feature` ( `Feature`"
- "CHAR(56) NOT NULL, `Enabled` INT NOT NULL PRIMARY KEY `Feature`)";
- static const CHAR Insert[] =
- "INSERT into `WINE_Feature` (`Feature`, `Enabled`) VALUES (?)";
- static const CHAR Query_all[] = "SELECT * FROM Feature";
- static const CHAR Query_one[] = "SELECT * FROM Feature WHERE Feature='%s'";
- CHAR Query[1023];
+ package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
- MsiSetPropertyA(hPackage,"CostingComplete","0");
- MsiSetPropertyW(hPackage, cszRootDrive , c_collen);
+ TRACE("Working to resolve %s\n",debugstr_w(name));
- db = MsiGetActiveDatabase(hPackage);
- MsiDatabaseOpenViewA(db,CreateSql,&view);
- MsiViewExecute(view,0);
- MsiViewClose(view);
- MsiCloseHandle(view);
-
- sz = 0x100;
- if (MsiGetPropertyA(hPackage,"ADDLOCAL",local,&sz)==ERROR_SUCCESS)
+ /* special resolving for Target and Source root dir */
+ if (strcmpW(name,cszTargetDir)==0 || strcmpW(name,cszSourceDir)==0)
{
- if (strcasecmp(local,"ALL")==0)
+ if (!source)
{
- MsiDatabaseOpenViewA(db,Query_all,&view);
- MsiViewExecute(view,0);
- while (1)
+ sz = MAX_PATH;
+ rc = MsiGetPropertyW(hPackage,cszTargetDir,path,&sz);
+ if (rc != ERROR_SUCCESS)
{
- MSIHANDLE view2;
- MSIHANDLE row2;
- DWORD rc;
-
- rc = MsiViewFetch(view,&row);
- if (rc != ERROR_SUCCESS)
- break;
-
- row2 = MsiCreateRecord(2);
-
- sz=0x100;
- MsiRecordGetStringW(row,1,buffer,&sz);
- MsiRecordSetStringW(row2,1,buffer);
- MsiRecordSetInteger(row2,2,1);
-
- MsiDatabaseOpenViewA(db,Insert,&view2);
- MsiViewExecute(view2,row2);
- MsiCloseHandle(row2);
- MsiCloseHandle(row);
- MsiViewClose(view2);
- MsiCloseHandle(view2);
- TRACE("Enabling feature %s\n",debugstr_w(buffer));
+ rc = MsiGetPropertyW(hPackage,cszRootDrive,path,&sz);
+ if (set_prop)
+ MsiSetPropertyW(hPackage,cszTargetDir,path);
}
- MsiViewClose(view);
- MsiCloseHandle(view);
+ return rc;
}
else
{
- LPSTR ptr,ptr2;
- ptr = local;
-
- while (ptr && *ptr)
+ sz = MAX_PATH;
+ rc = MsiGetPropertyW(hPackage,cszSourceDir,path,&sz);
+ if (rc != ERROR_SUCCESS)
{
- CHAR feature[0x100];
- MSIHANDLE view2;
- MSIHANDLE row2;
- DWORD rc;
-
- ptr2 = strchr(ptr,',');
-
- if (ptr2)
- {
- strncpy(feature,ptr,ptr2-ptr);
- feature[ptr2-ptr]=0;
- ptr2++;
- ptr = ptr2;
- }
- else
+ sz = MAX_PATH;
+ rc = MsiGetPropertyW(hPackage,cszDatabase,path,&sz);
+ if (rc == ERROR_SUCCESS)
{
- strcpy(feature,ptr);
- ptr = NULL;
+ LPWSTR ptr = strrchrW(path,'\\');
+ if (ptr)
+ {
+ ptr++;
+ *ptr = 0;
+ }
}
+ }
+ return rc;
+ }
+ }
+
+ for (i = 0; i < package->loaded_folders; i++)
+ {
+ if (strcmpW(package->folders[i].Directory,name)==0)
+ break;
+ }
- sprintf(Query,Query_one,feature);
+ if (i >= package->loaded_folders)
+ return ERROR_FUNCTION_FAILED;
- MsiDatabaseOpenViewA(db,Query,&view);
- MsiViewExecute(view,0);
- rc = MsiViewFetch(view,&row);
- if (rc != ERROR_SUCCESS)
- break;
-
- row2 = MsiCreateRecord(2);
- sz=0x100;
- MsiRecordGetStringW(row,1,buffer,&sz);
- MsiRecordSetStringW(row2,1,buffer);
- MsiRecordSetInteger(row2,2,1);
-
- MsiDatabaseOpenViewA(db,Insert,&view2);
- MsiViewExecute(view,row2);
- MsiCloseHandle(row2);
- MsiCloseHandle(row);
- MsiViewClose(view2);
- MsiCloseHandle(view2);
- MsiViewClose(view);
- MsiCloseHandle(view);
- TRACE("Enabling feature %s\n",feature);
- }
- }
+ if (folder)
+ *folder = &(package->folders[i]);
+
+ if (!source && package->folders[i].ResolvedTarget[0])
+ {
+ strcpyW(path,package->folders[i].ResolvedTarget);
+ TRACE(" already resolved to %s\n",debugstr_w(path));
+ return ERROR_SUCCESS;
+ }
+ else if (source && package->folders[i].ResolvedSource[0])
+ {
+ strcpyW(path,package->folders[i].ResolvedSource);
+ return ERROR_SUCCESS;
}
- MsiCloseHandle(db);
- return ERROR_SUCCESS;
+ if (!source && package->folders[i].Property)
+ {
+ sz = MAX_PATH;
+ rc = MsiGetPropertyW(hPackage, name, package->folders[i].ResolvedTarget,
+ &sz);
+ if (rc == ERROR_SUCCESS)
+ {
+ strcpyW(path,package->folders[i].ResolvedTarget);
+ TRACE(" found as property %s\n",debugstr_w(path));
+ return ERROR_SUCCESS;
+ }
+ }
+
+ if (package->folders[i].ParentIndex >= 0)
+ {
+ TRACE(" ! Parent is %s\n", debugstr_w(package->folders[
+ package->folders[i].ParentIndex].Directory));
+ resolve_folder(hPackage, package->folders[
+ package->folders[i].ParentIndex].Directory, path,source,
+ set_prop, NULL);
+
+ if (!source && package->folders[i].TargetDefault[0])
+ {
+ strcatW(path,package->folders[i].TargetDefault);
+ strcatW(path,cszbs);
+ strcpyW(package->folders[i].ResolvedTarget,path);
+ TRACE(" resolved into %s\n",debugstr_w(path));
+ if (set_prop)
+ MsiSetPropertyW(hPackage,name,path);
+ }
+ else if (package->folders[i].SourceDefault[0])
+ {
+ strcatW(path,package->folders[i].SourceDefault);
+ strcatW(path,cszbs);
+ strcpyW(package->folders[i].ResolvedSource,path);
+ }
+ }
+ return rc;
}
/*
@@ -1186,12 +1479,7 @@
* The costing needs to be implemented at some point but for now I am going
* to focus on the directory building
*
- * WINE_Directory
- * Directory Identifier: key into the Directory Table
- * Source Path : resolved source path without SourceDir
- * Target Path : resolved target path wihout TARGETDIR
- * Created Int : 0 uncreated, 1 created but if empty remove, 2 created
- *
+ *
*/
static UINT ACTION_CostFinalize(MSIHANDLE hPackage)
{
@@ -1237,7 +1525,8 @@
/* This helper function now does ALL the work */
TRACE("Dir %s ...\n",debugstr_w(name));
- resolve_directory(hPackage,name,path,FALSE);
+ load_folder(hPackage,name);
+ resolve_folder(hPackage,name,path,FALSE,TRUE,NULL);
TRACE("resolves to %s\n",debugstr_w(path));
MsiCloseHandle(row);
@@ -1270,13 +1559,9 @@
if (rc != ERROR_SUCCESS)
return rc;
- write = 0x100;
- if (MsiGetPropertyW(hPackage, cszSourceDir, source, &write))
- {
- ERR("No Source dir defined \n");
- rc = ERROR_FUNCTION_FAILED;
- goto end;
- }
+ write = MAX_PATH;
+ if (MsiGetPropertyW(hPackage, cszTempFolder, source, &write))
+ GetTempPathW(MAX_PATH,source);
strcatW(source,stream_name);
the_file = CreateFileW(source, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
@@ -1408,7 +1693,7 @@
MSIHANDLE row = 0;
WCHAR source[MAX_PATH];
static const CHAR *ExecSeqQuery =
- "select * from Media where LastSequence > %i order by LastSequence";
+ "select * from Media where LastSequence >= %i order by LastSequence";
CHAR Query[1024];
WCHAR cab[0x100];
DWORD sz=0x100;
@@ -1453,6 +1738,7 @@
{
sz=0x100;
MsiRecordGetStringW(row,4,cab,&sz);
+ TRACE("Source is CAB %s\n",debugstr_w(cab));
/* the stream does not contain the # character */
if (cab[0]=='#')
{
@@ -1472,6 +1758,11 @@
{
strcpyW(path,source);
strcatW(source,cab);
+ /* extract the cab file into a folder in the temp folder */
+ sz = MAX_PATH;
+ if (MsiGetPropertyW(hPackage, cszTempFolder,path, &sz)
+ != ERROR_SUCCESS)
+ GetTempPathW(MAX_PATH,path);
}
}
rc = !extract_cabinet_file(source,path);
@@ -1506,6 +1797,7 @@
WCHAR dir[0x100];
DWORD sz=0x100;
MSIHANDLE db;
+ MSIFOLDER *folder;
strcatW(ExecSeqQuery,component);
strcatW(ExecSeqQuery,end);
@@ -1537,11 +1829,19 @@
sz=0x100;
MsiRecordGetStringW(row,3,dir,&sz);
sz=MAX_PATH;
- rc = MsiGetPropertyW(hPackage, dir, install_path, &sz);
+ rc = resolve_folder(hPackage, dir, install_path, FALSE, FALSE, &folder);
MsiCloseHandle(row);
MsiViewClose(view);
MsiCloseHandle(view);
+
+ /* create the path */
+ if (folder->State == 0)
+ {
+ create_full_pathW(install_path);
+ folder->State = 2;
+ }
+
return rc;
}
@@ -1639,8 +1939,6 @@
}
reduce_to_longfilename(filename);
- /* create the path */
- create_full_pathW(install_path);
strcatW(install_path,filename);
@@ -2115,8 +2413,26 @@
UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR
szPathBuf, DWORD* pcchPathBuf)
{
+ WCHAR path[MAX_PATH];
+ UINT rc;
+
TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);
- return MsiGetPropertyW(hInstall,szFolder,szPathBuf,pcchPathBuf);
+
+ rc = resolve_folder(hInstall, szFolder, path, FALSE, FALSE, NULL);
+
+ if (rc == ERROR_SUCCESS && strlenW(path) > *pcchPathBuf)
+ {
+ *pcchPathBuf = strlenW(path)+1;
+ return ERROR_MORE_DATA;
+ }
+ else if (rc == ERROR_SUCCESS)
+ {
+ *pcchPathBuf = strlenW(path)+1;
+ strcpyW(szPathBuf,path);
+ TRACE("Returning Path %s\n",debugstr_w(path));
+ }
+
+ return rc;
}
@@ -2158,23 +2474,24 @@
UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR
szPathBuf, DWORD* pcchPathBuf)
{
- static const WCHAR cszsrc[]={'_','S','o','u','r','c','e',0};
- LPWSTR newfolder;
+ WCHAR path[MAX_PATH];
UINT rc;
TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);
+ rc = resolve_folder(hInstall, szFolder, path, TRUE, FALSE, NULL);
- if (strcmpW(szFolder, cszSourceDir) != 0)
+ if (rc == ERROR_SUCCESS && strlenW(path) > *pcchPathBuf)
{
- newfolder = HeapAlloc(GetProcessHeap(),0,
- (strlenW(szFolder)+8)*sizeof(WCHAR));
- strcpyW(newfolder,szFolder);
- strcatW(newfolder,cszsrc);
- rc = MsiGetPropertyW(hInstall,newfolder,szPathBuf,pcchPathBuf);
- HeapFree(GetProcessHeap(),0,newfolder);
+ *pcchPathBuf = strlenW(path)+1;
+ return ERROR_MORE_DATA;
}
- else
- rc = MsiGetPropertyW(hInstall,szFolder,szPathBuf,pcchPathBuf);
+ else if (rc == ERROR_SUCCESS)
+ {
+ *pcchPathBuf = strlenW(path)+1;
+ strcpyW(szPathBuf,path);
+ TRACE("Returning Path %s\n",debugstr_w(path));
+ }
+
return rc;
}
@@ -2221,9 +2538,37 @@
UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
LPCWSTR szFolderPath)
{
+ MSIPACKAGE *package;
+ INT i;
+ WCHAR path[MAX_PATH];
+
TRACE("(%s %s)\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
- return MsiSetPropertyW(hInstall,szFolder,szFolderPath);
+ if (szFolderPath[0]==0)
+ return ERROR_FUNCTION_FAILED;
+
+ package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
+
+ if (package==NULL)
+ return ERROR_INVALID_HANDLE;
+
+ MsiSetPropertyW(hInstall,szFolder,szFolderPath);
+
+ for (i = 0; i < package->loaded_folders; i++)
+ {
+ package->folders[i].ResolvedTarget[0]=0;
+
+ if (strcmpW(package->folders[i].Directory,szFolder)==0)
+ package->folders[i].Property = TRUE;
+ }
+
+ for (i = 0; i < package->loaded_folders; i++)
+ {
+ resolve_folder(hInstall, package->folders[i].Directory, path, FALSE,
+ TRUE, NULL);
+ }
+
+ return ERROR_SUCCESS;
}
BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, DWORD iRunMode)
diff -u dlls/msi.old/msipriv.h dlls/msi/msipriv.h
--- dlls/msi.old/msipriv.h 2004-07-01 10:51:49.000000000 -0500
+++ dlls/msi/msipriv.h 2004-07-01 10:53:20.000000000 -0500
@@ -140,6 +140,17 @@
struct tagMSIHANDLEINFO *prev;
} MSIHANDLEINFO;
+typedef struct tagMSIPACKAGE
+{
+ MSIHANDLE db;
+ struct tagMSIFEATURE *features;
+ UINT loaded_features;
+ struct tagMSIFOLDER *folders;
+ UINT loaded_folders;
+ struct tagMSICOMPONENT *components;
+ UINT loaded_components;
+} MSIPACKAGE;
+
#define MSIHANDLETYPE_ANY 0
#define MSIHANDLETYPE_DATABASE 1
#define MSIHANDLETYPE_SUMMARYINFO 2
diff -u dlls/msi.old/package.c dlls/msi/package.c
--- dlls/msi.old/package.c 2004-07-01 10:51:49.000000000 -0500
+++ dlls/msi/package.c 2004-07-01 10:53:20.000000000 -0500
@@ -50,16 +50,20 @@
void MSI_FreePackage( VOID *arg);
-typedef struct tagMSIPACKAGE
-{
- MSIHANDLE db;
-} MSIPACKAGE;
-
void MSI_FreePackage( VOID *arg)
{
MSIPACKAGE *package= arg;
MsiCloseHandle(package->db);
+
+ if (package->features && package->loaded_features > 0)
+ HeapFree(GetProcessHeap(),0,package->features);
+
+ if (package->folders && package->loaded_folders > 0)
+ HeapFree(GetProcessHeap(),0,package->folders);
+
+ if (package->components && package->loaded_components > 0)
+ HeapFree(GetProcessHeap(),0,package->components);
}
UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
@@ -292,6 +296,12 @@
}
package->db = db;
+ package->features = NULL;
+ package->folders = NULL;
+ package->components = NULL;
+ package->loaded_features = 0;
+ package->loaded_folders = 0;
+ package->loaded_components= 0;
/* ok here is where we do a slew of things to the database to
* prep for all that is to come as a package */
@@ -341,7 +351,9 @@
DWORD log_type = 0;
LPSTR message;
DWORD sz;
+ DWORD total_size = 0;
INT msg_field=1;
+ INT i;
FIXME("STUB: %x \n",eMessageType);
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
@@ -355,24 +367,40 @@
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
log_type |= INSTALLLOGMODE_COMMONDATA;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
- {
log_type |= INSTALLLOGMODE_ACTIONSTART;
- msg_field = 2;
- }
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
log_type |= INSTALLLOGMODE_ACTIONDATA;
- sz = 0;
- MsiRecordGetStringA(hRecord,msg_field,NULL,&sz);
- sz++;
- message = HeapAlloc(GetProcessHeap(),0,sz);
- MsiRecordGetStringA(hRecord,msg_field,message,&sz);
+ message = HeapAlloc(GetProcessHeap(),0,1);
+ message[0]=0;
+ msg_field = MsiRecordGetFieldCount(hRecord);
+ for (i = 1; i <= msg_field; i++)
+ {
+ LPSTR tmp;
+ CHAR number[3];
+ sz = 0;
+ MsiRecordGetStringA(hRecord,i,NULL,&sz);
+ sz+=4;
+ total_size+=sz;
+ tmp = HeapAlloc(GetProcessHeap(),0,sz);
+ message = HeapReAlloc(GetProcessHeap(),0,message,total_size);
+
+ MsiRecordGetStringA(hRecord,i,tmp,&sz);
+
+ if (msg_field > 1)
+ {
+ sprintf(number,"%i: ",i);
+ strcat(message,number);
+ }
+ strcat(message,tmp);
+ HeapFree(GetProcessHeap(),0,tmp);
+ }
+
+ TRACE("(%p %lx %lx %s)\n",gUIHandler, gUIFilter, log_type,
+ debugstr_a(message));
- TRACE("(%p %lx %lx)\n",gUIHandler, gUIFilter, log_type);
if (gUIHandler && (gUIFilter & log_type))
gUIHandler(gUIContext,eMessageType,message);
- else
- TRACE("%s\n",debugstr_a(message));
HeapFree(GetProcessHeap(),0,message);
return ERROR_SUCCESS;
More information about the wine-patches
mailing list