MSI: beginnings of costing and organizing into components and features

Mike McCormack mike at codeweavers.com
Thu Jul 1 12:18:03 CDT 2004


ChangeLog:
<aric at codeweavers.com>
* beginnings of costing and organizing into components and features
-------------- next part --------------
diff -u dlls/msi.old/Makefile.in dlls/msi/Makefile.in
--- dlls/msi.old/Makefile.in	2004-07-01 12:11:53.000000000 -0500
+++ dlls/msi/Makefile.in	2004-07-01 12:12:50.000000000 -0500
@@ -3,7 +3,7 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = msi.dll
-IMPORTS   = shell32 cabinet oleaut32 ole32 user32 advapi32 kernel32
+IMPORTS   = shell32 cabinet oleaut32 ole32 version user32 advapi32 kernel32
 EXTRALIBS = -luuid $(LIBUNICODE)
 
 C_SRCS = \
diff -u dlls/msi.old/action.c dlls/msi/action.c
--- dlls/msi.old/action.c	2004-07-01 12:11:53.000000000 -0500
+++ dlls/msi/action.c	2004-07-01 12:12:16.000000000 -0500
@@ -24,7 +24,6 @@
 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/installexecutesequence_table.asp
 
 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/standard_actions_reference.asp
-
  */
 
 #include <stdarg.h>
@@ -44,6 +43,7 @@
 #include "winuser.h"
 #include "shlobj.h"
 #include "wine/unicode.h"
+#include "ver.h"
 
 #define CUSTOM_ACTION_TYPE_MASK 0x3F
 
@@ -62,7 +62,8 @@
     
     INSTALLSTATE State;
     INT ComponentCount;
-    INT Components[1024]; /* yes hardcoded limit.... */
+    INT Components[1024]; /* yes hardcoded limit.... I am bad */
+    INT Cost;
 } MSIFEATURE;
 
 typedef struct tagMSICOMPONENT
@@ -76,6 +77,7 @@
 
     INSTALLSTATE State;
     BOOL Enabled;
+    INT  Cost;
 }MSICOMPONENT;
 
 typedef struct tagMSIFOLDER
@@ -93,8 +95,32 @@
         /* 1 = existing */
         /* 2 = created remove if empty */
         /* 3 = created persist if empty */
+    INT   Cost;
+    INT   Space;
 }MSIFOLDER;
 
+typedef struct tagMSIFILE
+{
+    WCHAR File[72];
+    INT ComponentIndex;
+    WCHAR FileName[MAX_PATH];
+    INT FileSize;
+    WCHAR Version[72];
+    WCHAR Language[20];
+    INT Attributes;
+    INT Sequence;   
+
+    INT State;
+       /* 0 = uninitialize */
+       /* 1 = not present */
+       /* 2 = present but replace */
+       /* 3 = present do not replace */
+       /* 4 = Installed */
+    WCHAR   SourcePath[MAX_PATH];
+    WCHAR   TargetPath[MAX_PATH];
+    BOOL    Temporary; 
+}MSIFILE;
+
 /*
  * Prototypes
  */
@@ -105,6 +131,7 @@
 static UINT ACTION_CostInitialize(MSIHANDLE hPackage);
 static UINT ACTION_CreateFolders(MSIHANDLE hPackage);
 static UINT ACTION_CostFinalize(MSIHANDLE hPackage);
+static UINT ACTION_FileCost(MSIHANDLE hPackage);
 static UINT ACTION_InstallFiles(MSIHANDLE hPackage);
 static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage);
 static UINT ACTION_WriteRegistryValues(MSIHANDLE hPackage);
@@ -119,7 +146,8 @@
 static UINT resolve_folder(MSIHANDLE hPackage, LPCWSTR name, LPWSTR path, 
                            BOOL source, BOOL set_prop, MSIFOLDER **folder);
 
-
+static UINT track_tempfile(MSIHANDLE hPackage, LPCWSTR name, LPCWSTR path);
+ 
 /*
  * consts and values used
  */
@@ -138,6 +166,16 @@
 /******************************************************** 
  * helper functions to get around current HACKS and such
  ********************************************************/
+inline static void reduce_to_longfilename(WCHAR* filename)
+{
+    if (strchrW(filename,'|'))
+    {
+        WCHAR newname[MAX_PATH];
+        strcpyW(newname,strchrW(filename,'|')+1);
+        strcpyW(filename,newname);
+    }
+}
+
 inline static char *strdupWtoA( const WCHAR *str )
 {
     char *ret = NULL;
@@ -151,7 +189,7 @@
     return ret;
 }
 
-int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component )
+inline static int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component )
 {
     INT rc = -1;
     INT i;
@@ -167,6 +205,55 @@
     return rc;
 }
 
+static UINT track_tempfile(MSIHANDLE hPackage, LPCWSTR name, LPCWSTR path)
+{
+    MSIPACKAGE *package;
+    int i;
+    int index;
+
+    package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
+
+    if (!package)
+        return -2;
+
+    for (i=0; i < package->loaded_files; i++)
+        if (strcmpW(package->files[i].File,name)==0)
+            return -1;
+
+    index = package->loaded_files;
+    package->loaded_files++;
+    if (package->loaded_files== 1)
+        package->files = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFILE));
+    else
+        package->files = HeapReAlloc(GetProcessHeap(),0,
+            package->files , package->loaded_files * sizeof(MSIFILE));
+
+    memset(&package->files[index],0,sizeof(MSIFILE));
+
+    strcpyW(package->files[index].File,name);
+    strcpyW(package->files[index].TargetPath,path);
+    package->files[index].Temporary = TRUE;
+
+    TRACE("Tracking tempfile (%s)\n",debugstr_w(package->files[index].File));  
+
+    return 0;
+}
+
+void ACTION_remove_tracked_tempfiles(MSIPACKAGE* package)
+{
+    int i;
+
+    if (!package)
+        return;
+
+    for (i = 0; i < package->loaded_files; i++)
+    {
+        if (package->files[i].Temporary)
+            DeleteFileW(package->files[i].TargetPath);
+
+    }
+}
+
 /****************************************************
  * TOP level entry points 
  *****************************************************/
@@ -487,15 +574,19 @@
 {'W','r','i','t','e','R','e','g','i','s','t','r','y','V','a','l','u','e','s',0};
     const static WCHAR szCostInitialize[] = 
         {'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0};
+    const static WCHAR szFileCost[] = 
+        {'F','i','l','e','C','o','s','t',0};
 
     TRACE("Performing action (%s)\n",debugstr_w(action));
 
     if (strcmpW(action,szCostInitialize)==0)
         return ACTION_CostInitialize(hPackage);
-    if (strcmpW(action,szCreateFolders)==0)
-        return ACTION_CreateFolders(hPackage);
+    if (strcmpW(action,szFileCost)==0)
+        return ACTION_FileCost(hPackage);
     if (strcmpW(action,szCostFinalize)==0)
         return ACTION_CostFinalize(hPackage);
+    if (strcmpW(action,szCreateFolders)==0)
+        return ACTION_CreateFolders(hPackage);
     if (strcmpW(action,szInstallFiles)==0)
         return ACTION_InstallFiles(hPackage);
     if (strcmpW(action,szDuplicateFiles)==0)
@@ -567,7 +658,7 @@
      .
      */
      if (ACTION_CustomAction(hPackage,action) != ERROR_SUCCESS)
-        ERR("UNHANDLED MSI ACTION %s\n",debugstr_w(action));
+        FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action));
 
     return ERROR_SUCCESS;
 }
@@ -642,7 +733,7 @@
             HeapFree(GetProcessHeap(),0,deformated);
             break;
         default:
-            ERR("UNHANDLED ACTION TYPE %i (%s %s)\n",
+            FIXME("UNHANDLED ACTION TYPE %i (%s %s)\n",
              type & CUSTOM_ACTION_TYPE_MASK, debugstr_w(source),
              debugstr_w(target));
     }
@@ -683,6 +774,9 @@
         CHAR buffer[1024];
         MSIHANDLE db;
 
+        if (track_tempfile(hPackage, source, tmp_file)!=0)
+            FIXME("File Name in temp tracking collision\n");
+
         the_file = CreateFileW(tmp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
                            FILE_ATTRIBUTE_NORMAL, NULL);
     
@@ -758,7 +852,7 @@
 
     if (type & 0xc0)
     {
-        ERR("Asynchronous execution.. UNHANDLED\n");
+        FIXME("Asynchronous execution.. UNHANDLED\n");
         return ERROR_SUCCESS;
     }
 
@@ -943,6 +1037,7 @@
         }
 
         TRACE("Folder is %s\n",debugstr_w(full_path));
+
         if (folder->State == 0)
             create_full_pathW(full_path);
 
@@ -956,7 +1051,6 @@
     return rc;
 }
 
-
 static int load_component(MSIPACKAGE* package, MSIHANDLE row)
 {
     int index = package->loaded_components;
@@ -1131,13 +1225,10 @@
 {
     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);
@@ -1145,67 +1236,124 @@
     package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
 
     sz = 0x100;
-    if (MsiGetPropertyA(hPackage,"ADDLOCAL",local,&sz)==ERROR_SUCCESS)
+    MsiDatabaseOpenViewA(package->db,Query_all,&view);
+    MsiViewExecute(view,0);
+    while (1)
     {
-        if (strcasecmp(local,"ALL")==0)
-        {
-            MsiDatabaseOpenViewA(package->db,Query_all,&view);
-            MsiViewExecute(view,0);
-            while (1)
-            {
-                DWORD rc;
+        DWORD rc;
 
-                rc = MsiViewFetch(view,&row);
-                if (rc != ERROR_SUCCESS)
-                    break;
+        rc = MsiViewFetch(view,&row);
+        if (rc != ERROR_SUCCESS)
+            break;
        
-                load_feature(package,row); 
-                MsiCloseHandle(row);
-            }
-            MsiViewClose(view);
-            MsiCloseHandle(view);
-        }
-        else
+        load_feature(package,row); 
+        MsiCloseHandle(row);
+    }
+    MsiViewClose(view);
+    MsiCloseHandle(view);
+
+    return ERROR_SUCCESS;
+}
+
+static int load_file(MSIPACKAGE* package, MSIHANDLE row)
+{
+    int index = package->loaded_files;
+    int i;
+    WCHAR buffer[0x100];
+    DWORD sz;
+
+    /* fill in the data */
+
+    package->loaded_files++;
+    if (package->loaded_files== 1)
+        package->files = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFILE));
+    else
+        package->files = HeapReAlloc(GetProcessHeap(),0,
+            package->files , package->loaded_files * sizeof(MSIFILE));
+
+    memset(&package->files[index],0,sizeof(MSIFILE));
+
+    sz = 72;       
+    MsiRecordGetStringW(row,1,package->files[index].File,&sz);
+
+    sz = 0x100;       
+    MsiRecordGetStringW(row,2,buffer,&sz);
+
+    package->files[index].ComponentIndex = -1;
+    for (i = 0; i < package->loaded_components; i++)
+        if (strcmpW(package->components[i].Component,buffer)==0)
         {
-            LPSTR ptr,ptr2;
-            ptr = local;
+            package->files[index].ComponentIndex = i;
+            break;
+        }
+    if (package->files[index].ComponentIndex == -1)
+        ERR("Unfound Component %s\n",debugstr_w(buffer));
 
-            while (ptr && *ptr)
-            {
-                CHAR feature[0x100];
-                DWORD rc;
+    sz = MAX_PATH;       
+    MsiRecordGetStringW(row,3,package->files[index].FileName,&sz);
 
-                ptr2 = strchr(ptr,',');
+    reduce_to_longfilename(package->files[index].FileName);
+    
+    package->files[index].FileSize = MsiRecordGetInteger(row,4);
 
-                if (ptr2)
-                {
-                    strncpy(feature,ptr,ptr2-ptr);
-                    feature[ptr2-ptr]=0;
-                    ptr2++;
-                    ptr = ptr2;
-                }
-                else
-                {
-                    strcpy(feature,ptr);
-                    ptr = NULL;
-                }
+    sz = 72;       
+    if (!MsiRecordIsNull(row,5))
+        MsiRecordGetStringW(row,5,package->files[index].Version,&sz);
 
-                sprintf(Query,Query_one,feature);
+    sz = 20;       
+    if (!MsiRecordIsNull(row,6))
+        MsiRecordGetStringW(row,6,package->files[index].Language,&sz);
 
-                MsiDatabaseOpenViewA(package->db,Query,&view);
-                MsiViewExecute(view,0);
-                rc = MsiViewFetch(view,&row);
-                if (rc != ERROR_SUCCESS)
-                    break;
-        
-                load_feature(package,row); 
+    if (!MsiRecordIsNull(row,7))
+        package->files[index].Attributes= MsiRecordGetInteger(row,7);
 
-                MsiCloseHandle(row);
-                MsiViewClose(view);
-                MsiCloseHandle(view);
-            }
+    package->files[index].Sequence= MsiRecordGetInteger(row,8);
+
+    package->files[index].Temporary = FALSE;
+    package->files[index].State = 0;
+
+    TRACE("File Loaded (%s)\n",debugstr_w(package->files[index].File));  
+ 
+    return ERROR_SUCCESS;
+}
+
+static UINT ACTION_FileCost(MSIHANDLE hPackage)
+{
+    MSIHANDLE view;
+    MSIHANDLE row;
+    MSIPACKAGE *package;
+    UINT rc;
+    static const CHAR Query[] = "SELECT * FROM File Order by Sequence";
+
+    package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
+    if (!package)
+        return ERROR_INVALID_HANDLE;
+
+    rc = MsiDatabaseOpenViewA(package->db, Query, &view);
+    if (rc != ERROR_SUCCESS)
+        return rc;
+   
+    rc = MsiViewExecute(view, 0);
+    if (rc != ERROR_SUCCESS)
+    {
+        MsiViewClose(view);
+        MsiCloseHandle(view);
+        return rc;
+    }
+
+    while (1)
+    {
+        rc = MsiViewFetch(view,&row);
+        if (rc != ERROR_SUCCESS)
+        {
+            rc = ERROR_SUCCESS;
+            break;
         }
+        load_file(package,row);
+        MsiCloseHandle(row);
     }
+    MsiViewClose(view);
+    MsiCloseHandle(view);
 
     return ERROR_SUCCESS;
 }
@@ -1370,6 +1518,22 @@
 
     TRACE("Working to resolve %s\n",debugstr_w(name));
 
+    for (i = 0; i < package->loaded_folders; i++)
+    {
+        if (strcmpW(package->folders[i].Directory,name)==0)
+            break;
+    }
+
+    if (i >= package->loaded_folders)
+        return ERROR_FUNCTION_FAILED;
+
+
+    if (folder)
+        *folder = &(package->folders[i]);
+
+    if (!path)
+        return rc;
+
     /* special resolving for Target and Source root dir */
     if (strcmpW(name,cszTargetDir)==0 || strcmpW(name,cszSourceDir)==0)
     {
@@ -1379,6 +1543,7 @@
             rc = MsiGetPropertyW(hPackage,cszTargetDir,path,&sz);
             if (rc != ERROR_SUCCESS)
             {
+                sz = MAX_PATH;
                 rc = MsiGetPropertyW(hPackage,cszRootDrive,path,&sz);
                 if (set_prop)
                     MsiSetPropertyW(hPackage,cszTargetDir,path);
@@ -1406,19 +1571,6 @@
             return rc;
         }
     }
-    
-    for (i = 0; i < package->loaded_folders; i++)
-    {
-        if (strcmpW(package->folders[i].Directory,name)==0)
-            break;
-    }
-
-    if (i >= package->loaded_folders)
-        return ERROR_FUNCTION_FAILED;
-
-
-    if (folder)
-        *folder = &(package->folders[i]);
 
     if (!source && package->folders[i].ResolvedTarget[0])
     {
@@ -1479,13 +1631,13 @@
     static const CHAR *ExecSeqQuery = "select * from Directory";
     UINT rc;
     MSIHANDLE view;
-    MSIHANDLE db;
+    MSIPACKAGE *package;
+    INT i;
 
     TRACE("Building Directory properties\n");
 
-    db = MsiGetActiveDatabase(hPackage);
-    rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
-    MsiCloseHandle(db);
+    package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
+    rc = MsiDatabaseOpenViewA(package->db, ExecSeqQuery, &view);
 
     if (rc != ERROR_SUCCESS)
         return rc;
@@ -1527,6 +1679,69 @@
     MsiViewClose(view);
     MsiCloseHandle(view);
 
+    TRACE("File calculations %i files\n",package->loaded_files);
+
+    for (i = 0; i < package->loaded_files; i++)
+    {
+        MSICOMPONENT* comp = NULL;
+        MSIFILE* file= NULL;
+
+        file = &package->files[i];
+        if (file->ComponentIndex >= 0)
+            comp = &package->components[file->ComponentIndex];
+
+        if (comp)
+        {
+            /* calculate target */
+            resolve_folder(hPackage, comp->Directory, file->TargetPath, FALSE,
+                       FALSE, NULL);
+            strcatW(file->TargetPath,file->FileName);
+
+            TRACE("file %s resolves to %s\n",
+                   debugstr_w(file->File),debugstr_w(file->TargetPath));       
+ 
+            if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
+            {
+                file->State = 1;
+                comp->Cost += file->FileSize;
+            }
+            else
+            {
+                if (file->Version[0])
+                {
+                    DWORD handle;
+                    DWORD versize;
+                    UINT sz;
+                    LPVOID version;
+                    WCHAR filever[0x100];
+                    static const WCHAR name[] =
+                        {'\\','V','a','r','F','i','l','e','I','n','f','o',
+                         '\\','F','i','l','e','V','e','r','s','i','o','n',0};
+
+                    FIXME("Version comparison.. Untried Untested and most "
+                          "likely very very wrong\n");
+                    versize = GetFileVersionInfoSizeW(file->TargetPath,&handle);
+                    version = HeapAlloc(GetProcessHeap(),0,versize);
+                    GetFileVersionInfoW(file->TargetPath, 0, versize, version);
+                    sz = 0x100;
+                    VerQueryValueW(version,name,(LPVOID)filever,&sz);
+                    HeapFree(GetProcessHeap(),0,version);
+                
+                    if (strcmpW(version,file->Version)<0)
+                    {
+                        file->State = 2;
+                        FIXME("cost should be diff in size\n");
+                        comp->Cost += file->FileSize;
+                    }
+                    else
+                        file->State = 3;
+                }
+                else
+                    file->State = 3;
+            }
+        } 
+    }
+
     MsiSetPropertyA(hPackage,"CostingComplete","1");
 
     return ERROR_SUCCESS;
@@ -1559,6 +1774,7 @@
 
     GetTempFileNameW(tmp,stream_name,0,source);
 
+    track_tempfile(hPackage,strrchrW(source,'\\'), source);
     the_file = CreateFileW(source, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
                            FILE_ATTRIBUTE_NORMAL, NULL);
 
@@ -1662,7 +1878,6 @@
     return TRUE;
 }
 
-
 static BOOL extract_cabinet_file(const WCHAR* source, const WCHAR* path)
 {
     TRACE("Extracting %s to %s\n",debugstr_w(source), debugstr_w(path));
@@ -1759,67 +1974,18 @@
     return rc;
 }
 
-static void reduce_to_longfilename(WCHAR* filename)
-{
-    if (strchrW(filename,'|'))
-    {
-        WCHAR newname[MAX_PATH];
-        strcpyW(newname,strchrW(filename,'|')+1);
-        strcpyW(filename,newname);
-    }
-}
-
-static UINT get_directory_for_component(MSIHANDLE hPackage, 
-    const WCHAR* component, WCHAR* install_path)
+inline static UINT create_component_directory (MSIHANDLE hPackage, MSIPACKAGE*
+                                               package, INT component)
 {
     UINT rc;
-    MSIHANDLE view;
-    MSIHANDLE row = 0;
-    WCHAR ExecSeqQuery[1023] = 
-{'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',' ','=',' ','`',0};
-    static const WCHAR end[]={'`',0};
-    WCHAR dir[0x100];
-    DWORD sz=0x100;
-    MSIHANDLE db;
     MSIFOLDER *folder;
+    WCHAR install_path[MAX_PATH];
 
-    strcatW(ExecSeqQuery,component);
-    strcatW(ExecSeqQuery,end);
-
-    db = MsiGetActiveDatabase(hPackage);
-    rc = MsiDatabaseOpenViewW(db, ExecSeqQuery, &view);
-    MsiCloseHandle(db);
-
-    if (rc != ERROR_SUCCESS)
-        return rc;
+    rc = resolve_folder(hPackage, package->components[component].Directory,
+                        install_path, FALSE, FALSE, &folder);
 
-    rc = MsiViewExecute(view, 0);
     if (rc != ERROR_SUCCESS)
-    {
-        MsiViewClose(view);
-        MsiCloseHandle(view);
-        return rc;
-    }
-
-    rc = MsiViewFetch(view,&row);
-    if (rc != ERROR_SUCCESS)
-    {
-        MsiViewClose(view);
-        MsiCloseHandle(view);
-        MsiCloseHandle(row);
-        return rc;
-    }
-
-    sz=0x100;
-    MsiRecordGetStringW(row,3,dir,&sz);
-    sz=MAX_PATH;
-    rc = resolve_folder(hPackage, dir, install_path, FALSE, FALSE, &folder);
-
-    MsiCloseHandle(row);
-    MsiViewClose(view);
-    MsiCloseHandle(view);
+        return rc; 
 
     /* create the path */
     if (folder->State == 0)
@@ -1833,12 +1999,9 @@
 
 static UINT ACTION_InstallFiles(MSIHANDLE hPackage)
 {
-    UINT rc;
-    MSIHANDLE view;
-    MSIHANDLE row = 0;
-    static const CHAR *ExecSeqQuery = 
-        "select * from File order by Sequence";
-    MSIHANDLE db;
+    UINT rc = ERROR_SUCCESS;
+    INT index;
+    MSIPACKAGE *package;
 
     /* REALLY what we want to do is go through all the enabled
      * features and check all the components of that feature and
@@ -1847,105 +2010,76 @@
      * but for sheer gratification I am going to just brute force
      * install all the files
      */
-    db = MsiGetActiveDatabase(hPackage);
-    rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
-    MsiCloseHandle(db);
 
-    if (rc != ERROR_SUCCESS)
-        return rc;
+    package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
 
-    rc = MsiViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MsiViewClose(view);
-        MsiCloseHandle(view);
-        return rc;
-    }
+    if (!package)
+        return ERROR_INVALID_HANDLE;
 
-    while (1)
+    for (index = 0; index < package->loaded_files; index++)
     {
-        INT seq = 0;
-        WCHAR component[0x100];
-        WCHAR install_path[MAX_PATH]; 
         WCHAR path_to_source[MAX_PATH];
-        WCHAR src_path[MAX_PATH];
-        WCHAR filename[0x100]; 
-        WCHAR sourcename[0x100]; 
-        DWORD sz=0x100;
+        MSIFILE *file;
+        
+        file = &package->files[index];
 
-        rc = MsiViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
+        if ((file->State == 1) || (file->State == 2))
         {
-            rc = ERROR_SUCCESS;
-            break;
-        }
+            TRACE("Installing %s\n",debugstr_w(file->File));
+            rc = ready_media_for_file(hPackage,file->Sequence,path_to_source);
+            /* 
+             * WARNING!
+             * our file table could change here because a new temp file
+             * may have been created
+             */
+            file = &package->files[index];
+            if (rc != ERROR_SUCCESS)
+            {
+                ERR("Unable to ready media\n");
+                rc = ERROR_FUNCTION_FAILED;
+                break;
+            }
 
-        seq = MsiRecordGetInteger(row,8);
-        rc = ready_media_for_file(hPackage,seq,path_to_source);
-        if (rc != ERROR_SUCCESS)
-        {
-            ERR("Unable to ready media\n");
-            MsiCloseHandle(row);
-            break;
-        }
-        sz=0x100;
-        rc = MsiRecordGetStringW(row,2,component,&sz);
-        if (rc != ERROR_SUCCESS)
-        {
-            ERR("Unable to read component\n");
-            MsiCloseHandle(row);
-            break;
-        }
-        rc = get_directory_for_component(hPackage,component,install_path);
-        if (rc != ERROR_SUCCESS)
-        {
-            ERR("Unable to get directory\n");
-            MsiCloseHandle(row);
-            break;
-        }
+            create_component_directory(hPackage, package, file->ComponentIndex);
 
-        sz=0x100;
-        rc = MsiRecordGetStringW(row,1,sourcename,&sz);
-        if (rc != ERROR_SUCCESS)
-        {
-            ERR("Unable to get sourcename\n");
-            MsiCloseHandle(row);
-            break;
-        }
-        strcpyW(src_path,path_to_source);
-        strcatW(src_path,sourcename);
+            strcpyW(file->SourcePath, path_to_source);
+            strcatW(file->SourcePath, file->File);
 
-        sz=0x100;
-        rc = MsiRecordGetStringW(row,3,filename,&sz);
-        if (rc != ERROR_SUCCESS)
-        {
-            ERR("Unable to get filename\n");
-            MsiCloseHandle(row);
-            break;
+            TRACE("file paths %s to %s\n",debugstr_w(file->SourcePath),
+                  debugstr_w(file->TargetPath));
+
+            rc = !MoveFileW(file->SourcePath,file->TargetPath);
+            if (rc)
+                ERR("Unable to move file\n");
+            else
+                file->State = 4;
         }
-        reduce_to_longfilename(filename);
+    }
 
+    return rc;
+}
 
-        strcatW(install_path,filename);
+inline static UINT get_file_target(MSIHANDLE hPackage, LPCWSTR file_key, 
+                                   LPWSTR file_source)
+{
+    MSIPACKAGE *package;
+    INT index;
 
-        TRACE("Installing file %s to %s\n",debugstr_w(src_path),
-              debugstr_w(install_path));
+    package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
+
+    if (!package)
+        return ERROR_INVALID_HANDLE;
 
-        rc = !MoveFileW(src_path,install_path);
-        if (rc)
+    for (index = 0; index < package->loaded_files; index ++)
+    {
+        if (strcmpW(file_key,package->files[index].File)==0)
         {
-            ERR("Unable to move file\n");
+            strcmpW(file_source,package->files[index].TargetPath);
+            return ERROR_SUCCESS;
         }
-
-        /* for future use lets keep track of this file and where it went */
-        MsiSetPropertyW(hPackage,sourcename,install_path);
-
-        MsiCloseHandle(row);
     }
-    MsiViewClose(view);
-    MsiCloseHandle(view);
 
-    return rc;
+    return ERROR_FUNCTION_FAILED;
 }
 
 static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage)
@@ -2001,8 +2135,8 @@
             break;
         }
 
-        sz = 0x100;
-        rc = MsiGetPropertyW(hPackage,file_key,file_source,&sz);
+        rc = get_file_target(hPackage,file_key,file_source);
+
         if (rc != ERROR_SUCCESS)
         {
             ERR("Original file unknown %s\n",debugstr_w(file_key));
@@ -2011,7 +2145,10 @@
         }
 
         if (MsiRecordIsNull(row,4))
+        {
+ERR("HERE target path %s\n",debugstr_w(file_source));
             strcpyW(dest_name,strrchrW(file_source,'\\')+1);
+        }
         else
         {
             sz=0x100;
@@ -2030,7 +2167,7 @@
             sz=0x100;
             MsiRecordGetStringW(row,5,destkey,&sz);
             sz = 0x100;
-            rc = MsiGetPropertyW(hPackage, destkey, dest_path, &sz);
+            rc = resolve_folder(hPackage, destkey, dest_path,FALSE,FALSE,NULL);
             if (rc != ERROR_SUCCESS)
             {
                 ERR("Unable to get destination folder\n");
@@ -2051,7 +2188,9 @@
         
         if (rc != ERROR_SUCCESS)
             ERR("Failed to copy file\n");
-    
+
+        FIXME("We should track these duplicate files as well\n");   
+ 
         MsiCloseHandle(row);
     }
     MsiViewClose(view);
diff -u dlls/msi.old/cond.y dlls/msi/cond.y
--- dlls/msi.old/cond.y	2004-07-01 12:11:53.000000000 -0500
+++ dlls/msi/cond.y	2004-07-01 12:12:16.000000000 -0500
@@ -573,7 +573,8 @@
 static int COND_IsAlpha( WCHAR x )
 {
     return( ( ( x >= 'A' ) && ( x <= 'Z' ) ) ||
-            ( ( x >= 'a' ) && ( x <= 'z' ) ) );
+            ( ( x >= 'a' ) && ( x <= 'z' ) ) ||
+            ( ( x == '_' ) ) );
 }
 
 static int COND_IsNumber( WCHAR x )
diff -u dlls/msi.old/msipriv.h dlls/msi/msipriv.h
--- dlls/msi.old/msipriv.h	2004-07-01 12:11:53.000000000 -0500
+++ dlls/msi/msipriv.h	2004-07-01 12:12:16.000000000 -0500
@@ -149,6 +149,8 @@
     UINT loaded_folders;
     struct tagMSICOMPONENT *components;
     UINT loaded_components;
+    struct tagMSIFILE *files;
+    UINT loaded_files;
 } MSIPACKAGE;
 
 #define MSIHANDLETYPE_ANY 0
@@ -220,6 +222,7 @@
                               USHORT **pdata, UINT *psz );
 UINT ACTION_DoTopLevelINSTALL(MSIHANDLE hPackage, LPCWSTR szPackagePath,
                               LPCWSTR szCommandLine);
+void ACTION_remove_tracked_tempfiles(MSIPACKAGE* hPackage);
 
 /* record internals */
 extern UINT WINAPI MSI_RecordSetIStream( MSIHANDLE handle, 
diff -u dlls/msi.old/package.c dlls/msi/package.c
--- dlls/msi.old/package.c	2004-07-01 12:11:53.000000000 -0500
+++ dlls/msi/package.c	2004-07-01 12:12:16.000000000 -0500
@@ -56,6 +56,8 @@
 
     MsiCloseHandle(package->db);
 
+    ACTION_remove_tracked_tempfiles(package);
+
     if (package->features && package->loaded_features > 0)
         HeapFree(GetProcessHeap(),0,package->features);
 
@@ -64,6 +66,9 @@
     
     if (package->components && package->loaded_components > 0)
         HeapFree(GetProcessHeap(),0,package->components);
+
+    if (package->files && package->loaded_files > 0)
+        HeapFree(GetProcessHeap(),0,package->files);
 }
 
 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
@@ -299,9 +304,11 @@
     package->features = NULL;
     package->folders = NULL;
     package->components = NULL;
+    package->files = NULL;
     package->loaded_features = 0;
     package->loaded_folders = 0;
     package->loaded_components= 0;
+    package->loaded_files = 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 */


More information about the wine-patches mailing list