MSI: correct parse_data and source dirs

Aric Stewart aric at codeweavers.com
Mon May 16 14:13:22 CDT 2005


correct a problem with parse_data if binary data was not in full bytes. Fixes alot of random crashes in installs where this happened.

also more properly handle uncompressed file sources, fix the creating and parsing of Source Directories.

-------------- next part --------------
Index: dlls/msi/action.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.c,v
retrieving revision 1.113
diff -u -r1.113 action.c
--- dlls/msi/action.c	13 May 2005 13:56:39 -0000	1.113
+++ dlls/msi/action.c	16 May 2005 19:08:16 -0000
@@ -1917,6 +1917,7 @@
     UINT rc;
     MSIQUERY * view;
     LPWSTR ptargetdir, targetdir, parent, srcdir;
+    LPWSTR shortname = NULL;
     MSIRECORD * row = 0;
     INT index = -1;
     DWORD i;
@@ -1982,15 +1983,16 @@
     /* for now only pick long filename versions */
     if (strchrW(targetdir,'|'))
     {
+        shortname = targetdir;
         targetdir = strchrW(targetdir,'|'); 
         *targetdir = 0;
         targetdir ++;
     }
+    /* for the sourcedir pick the short filename */
     if (srcdir && strchrW(srcdir,'|'))
     {
-        srcdir= strchrW(srcdir,'|'); 
-        *srcdir= 0;
-        srcdir ++;
+        LPWSTR p = strchrW(srcdir,'|'); 
+        *p = 0;
     }
 
     /* now check for root dirs */
@@ -2009,9 +2011,12 @@
 
     if (srcdir)
         package->folders[index].SourceDefault = strdupW(srcdir);
+    else if (shortname)
+        package->folders[index].SourceDefault = strdupW(shortname);
     else if (targetdir)
         package->folders[index].SourceDefault = strdupW(targetdir);
     HeapFree(GetProcessHeap(), 0, ptargetdir);
+        TRACE("   SourceDefault = %s\n",debugstr_w(package->folders[index].SourceDefault));
 
     parent = load_dynamic_stringW(row,2);
     if (parent) 
@@ -2115,6 +2120,7 @@
     else if (source && package->folders[i].ResolvedSource)
     {
         path = strdupW(package->folders[i].ResolvedSource);
+        TRACE("   (source)already resolved to %s\n",debugstr_w(path));
         return path;
     }
     else if (!source && package->folders[i].Property)
@@ -2146,6 +2152,7 @@
         else 
         {
             path = build_directory_name(3, p, package->folders[i].SourceDefault, NULL);
+            TRACE("   (source)resolved into %s\n",debugstr_w(path));
             package->folders[i].ResolvedSource = strdupW(path);
         }
         HeapFree(GetProcessHeap(),0,p);
@@ -2952,8 +2959,8 @@
     return ret;
 }
 
-static UINT ready_media_for_file(MSIPACKAGE *package, UINT sequence, 
-                                 WCHAR* path, WCHAR* file)
+static UINT ready_media_for_file(MSIPACKAGE *package, WCHAR* path, 
+                                 MSIFILE* file)
 {
     UINT rc;
     MSIQUERY * view;
@@ -2971,14 +2978,21 @@
     INT seq;
     static UINT last_sequence = 0; 
 
-    if (sequence <= last_sequence)
+    if (file->Attributes & msidbFileAttributesNoncompressed)
+    {
+        sz = MAX_PATH;
+        MSI_GetPropertyW(package, cszSourceDir, path, &sz);
+        return ERROR_SUCCESS;
+    }
+
+    if (file->Sequence <= last_sequence)
     {
-        TRACE("Media already ready (%u, %u)\n",sequence,last_sequence);
-        /*extract_a_cabinet_file(package, source,path,file); */
+        TRACE("Media already ready (%u, %u)\n",file->Sequence,last_sequence);
+        /*extract_a_cabinet_file(package, source,path,file->File); */
         return ERROR_SUCCESS;
     }
 
-    sprintfW(Query,ExecSeqQuery,sequence);
+    sprintfW(Query,ExecSeqQuery,file->Sequence);
 
     rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
     if (rc != ERROR_SUCCESS)
@@ -3106,12 +3120,10 @@
         if ((file->State == 1) || (file->State == 2))
         {
             LPWSTR p;
-            INT len;
             MSICOMPONENT* comp = NULL;
 
             TRACE("Installing %s\n",debugstr_w(file->File));
-            rc = ready_media_for_file(package,file->Sequence,path_to_source,
-                            file->File);
+            rc = ready_media_for_file(package, path_to_source, file);
             /* 
              * WARNING!
              * our file table could change here because a new temp file
@@ -3136,11 +3148,18 @@
             HeapFree(GetProcessHeap(),0,file->TargetPath);
 
             file->TargetPath = build_directory_name(2, p, file->FileName);
+            HeapFree(GetProcessHeap(),0,p);
+
+            if (file->Attributes & msidbFileAttributesNoncompressed)
+            {
+                p = resolve_folder(package, comp->Directory, TRUE, FALSE, NULL);
+                file->SourcePath = build_directory_name(2, p, file->File);
+                HeapFree(GetProcessHeap(),0,p);
+            }
+            else
+                file->SourcePath = build_directory_name(2, path_to_source, 
+                            file->File);
 
-            len = strlenW(path_to_source) + strlenW(file->File) + 2;
-            file->SourcePath = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
-            strcpyW(file->SourcePath, path_to_source);
-            strcatW(file->SourcePath, file->File);
 
             TRACE("file paths %s to %s\n",debugstr_w(file->SourcePath),
                   debugstr_w(file->TargetPath));
@@ -3156,16 +3175,23 @@
             msiobj_release( &uirow->hdr );
             ui_progress(package,2,file->FileSize,0,0);
 
-            if (!MoveFileW(file->SourcePath,file->TargetPath))
+            
+            if (file->Attributes & msidbFileAttributesNoncompressed)
+                rc = CopyFileW(file->SourcePath,file->TargetPath,FALSE);
+            else
+                rc = MoveFileW(file->SourcePath, file->TargetPath);
+
+            if (!rc)
             {
                 rc = GetLastError();
-                ERR("Unable to move file (%s -> %s) (error %d)\n",
+                ERR("Unable to move/copy file (%s -> %s) (error %d)\n",
                      debugstr_w(file->SourcePath), debugstr_w(file->TargetPath),
                       rc);
                 if (rc == ERROR_ALREADY_EXISTS && file->State == 2)
                 {
                     CopyFileW(file->SourcePath,file->TargetPath,FALSE);
-                    DeleteFileW(file->SourcePath);
+                    if (!(file->Attributes & msidbFileAttributesNoncompressed))
+                        DeleteFileW(file->SourcePath);
                     rc = 0;
                 }
                 else if (rc == ERROR_FILE_NOT_FOUND)
@@ -3173,14 +3199,17 @@
                     ERR("Source File Not Found!  Continuing\n");
                     rc = 0;
                 }
-                else
+                else if (file->Attributes & msidbFileAttributesVital)
                 {
-                    ERR("Ignoring Error and continuing...\n");
+                    ERR("Ignoring Error and continuing (nonvital file)...\n");
                     rc = 0;
                 }
             }
             else
+            {
                 file->State = 4;
+                rc = ERROR_SUCCESS;
+            }
         }
     }
 
@@ -3372,21 +3401,35 @@
         {
             LPWSTR ptr;
             CHAR byte[5];
-            LPWSTR deformated;
+            LPWSTR deformated = NULL;
             int count;
 
             deformat_string(package, &value[2], &deformated);
 
             /* binary value type */
-            ptr = deformated; 
-            *type=REG_BINARY;
-            *size = strlenW(ptr)/2;
+            ptr = deformated;
+            *type = REG_BINARY;
+            if (strlenW(ptr)%2)
+                *size = (strlenW(ptr)/2)+1;
+            else
+                *size = strlenW(ptr)/2;
+
             data = HeapAlloc(GetProcessHeap(),0,*size);
-          
+
             byte[0] = '0'; 
             byte[1] = 'x'; 
             byte[4] = 0; 
             count = 0;
+            /* if uneven pad with a zero in front */
+            if (strlenW(ptr)%2)
+            {
+                byte[2]= '0';
+                byte[3]= *ptr;
+                ptr++;
+                data[count] = (BYTE)strtol(byte,NULL,0);
+                count ++;
+                TRACE("Uneven byte count\n");
+            }
             while (*ptr)
             {
                 byte[2]= *ptr;
Index: include/msidefs.h
===================================================================
RCS file: /home/wine/wine/include/msidefs.h,v
retrieving revision 1.6
diff -u -r1.6 msidefs.h
--- include/msidefs.h	10 May 2005 08:27:00 -0000	1.6
+++ include/msidefs.h	16 May 2005 19:08:16 -0000
@@ -23,6 +23,17 @@
 extern "C" {
 #endif
 
+enum msidbFileAttributes {
+    msidbFileAttributesReadOnly = 0x00000001,
+    msidbFileAttributesHidden = 0x00000002,
+    msidbFileAttributesSystem = 0x00000004,
+    msidbFileAttributesVital = 0x00000200,
+    msidbFileAttributesChecksum = 0x00000400,
+    msidbFileAttributesPatchAdded = 0x00001000,
+    msidbFileAttributesNoncompressed = 0x00002000,
+    msidbFileAttributesCompressed = 0x00004000
+};
+        
 enum msidbDialogAttributes {
     msidbDialogAttributesVisible = 0x00000001,
     msidbDialogAttributesModal = 0x00000002,


More information about the wine-patches mailing list