msi: resend, promp for disk change

Aric Stewart aric at codeweavers.com
Wed Jun 29 07:48:36 CDT 2005


Handle installs off multiple volumes and properly pull the prompt string 
from the error table.
-------------- next part --------------
Index: dlls/msi/helpers.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/helpers.c,v
retrieving revision 1.3
diff -u -r1.3 helpers.c
--- dlls/msi/helpers.c	28 Jun 2005 19:14:30 -0000	1.3
+++ dlls/msi/helpers.c	29 Jun 2005 12:46:25 -0000
@@ -912,3 +917,53 @@
             component->Action, component->ActionRequest);
     } 
 }
+
+WCHAR* generate_error_string(MSIPACKAGE *package, UINT error, DWORD count, ... )
+{
+    static const WCHAR query[] = {'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ','F','R','O','M',' ','`','E','r','r','o','r','`',' ','W','H','E','R','E',' ','`','E','r','r','o','r','`',' ','=',' ','%','i',0};
+
+    MSIRECORD *rec;
+    MSIRECORD *row;
+    DWORD size = 0;
+    DWORD i;
+    va_list va;
+    LPCWSTR str;
+    LPWSTR data;
+
+    row = MSI_QueryGetRecord(package->db, query, error);
+    if (!row)
+        return 0;
+
+    rec = MSI_CreateRecord(count+2);
+
+    str = MSI_RecordGetString(row,1);
+    MSI_RecordSetStringW(rec,0,str);
+    msiobj_release( &row->hdr );
+    MSI_RecordSetInteger(rec,1,error);
+
+    va_start(va,count);
+    for (i = 0; i < count; i++)
+    {
+        str = va_arg(va,LPCWSTR);
+        MSI_RecordSetStringW(rec,(i+2),str);
+    }
+    va_end(va);
+
+    MSI_FormatRecordW(package,rec,NULL,&size);
+    if (size >= 0)
+    {
+        size++;
+        data = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR));
+        if (size > 1)
+            MSI_FormatRecordW(package,rec,data,&size);
+        else
+            data[0] = 0;
+        msiobj_release( &rec->hdr );
+        return data;
+    }
+
+    msiobj_release( &rec->hdr );
+    data = NULL;
+    return data;
+}
+
Index: dlls/msi/action.h
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.h,v
retrieving revision 1.20
diff -u -r1.20 action.h
--- dlls/msi/action.h	17 Jun 2005 20:56:55 -0000	1.20
+++ dlls/msi/action.h	29 Jun 2005 12:46:26 -0000
@@ -234,6 +242,7 @@
 void reduce_to_shortfilename(WCHAR*);
 LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR);
 void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature);
+WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... );
 
 
 /* control event stuff */
Index: dlls/msi/files.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/files.c,v
retrieving revision 1.4
diff -u -r1.4 files.c
--- dlls/msi/files.c	24 Jun 2005 12:14:35 -0000	1.4
+++ dlls/msi/files.c	29 Jun 2005 12:46:26 -0000
@@ -359,7 +359,78 @@
         file->SourcePath = build_directory_name(2, path, file->File);
 }
 
-static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex,
+static BOOL check_volume(LPCWSTR path, LPCWSTR want_volume, LPWSTR volume)
+{
+    WCHAR drive[4];
+    WCHAR name[MAX_PATH];
+    UINT type;
+
+    if (!(path[0] && path[1] == ':'))
+        return TRUE;
+
+    drive[0] = path[0];
+    drive[1] = path[1];
+    drive[2] = '\\';
+    drive[3] = 0;
+    TRACE("Checking volume %s .. (%s)\n",debugstr_w(drive), debugstr_w(want_volume));
+    type = GetDriveTypeW(drive);
+    TRACE("drive is of type %x\n",type);
+
+    if (type == DRIVE_UNKNOWN || type == DRIVE_NO_ROOT_DIR || 
+            type == DRIVE_FIXED || type == DRIVE_RAMDISK)
+        return TRUE;
+
+    GetVolumeInformationW(drive, name, MAX_PATH, NULL, NULL, NULL, NULL, 0);
+    TRACE("Drive contains %s\n", debugstr_w(name));
+    volume = strdupW(name);
+    return (strcmpiW(want_volume,name)==0);
+}
+
+static BOOL check_for_sourcefile(LPCWSTR source)
+{
+    DWORD attrib = GetFileAttributesW(source);
+    return (!(attrib == INVALID_FILE_ATTRIBUTES));
+}
+
+static UINT ready_volume(MSIPACKAGE* package, LPCWSTR path, LPWSTR last_volume, 
+                         MSIRECORD *row)
+{
+    LPWSTR volume = NULL; 
+    LPCWSTR want_volume = MSI_RecordGetString(row, 5);
+    BOOL ok = check_volume(path, want_volume, volume);
+
+    TRACE("Readying Volume for %s (%s, %s)\n",debugstr_w(path), debugstr_w(want_volume), debugstr_w(last_volume));
+
+    if (check_for_sourcefile(path) && !ok)
+    {
+        FIXME("Found the Sourcefile but not on the correct volume.(%s,%s,%s)\n",
+                debugstr_w(path),debugstr_w(want_volume), debugstr_w(volume));
+        return ERROR_SUCCESS;
+    }
+
+    while (!ok)
+    {
+        INT rc;
+        LPCWSTR prompt;
+        LPWSTR msg;
+      
+        prompt = MSI_RecordGetString(row,3);
+        msg = generate_error_string(package, 1302, 1, prompt);
+        rc = MessageBoxW(NULL,msg,NULL,MB_OKCANCEL);
+        HeapFree(GetProcessHeap(),0,volume);
+        HeapFree(GetProcessHeap(),0,msg);
+        if (rc == IDOK)
+            ok = check_for_sourcefile(path);
+        else
+            return ERROR_INSTALL_USEREXIT;
+    }
+
+    HeapFree(GetProcessHeap(),0,last_volume);
+    last_volume = strdupW(volume);
+    return ERROR_SUCCESS;
+}
+
+static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex, 
                                  MSICOMPONENT* comp)
 {
     UINT rc = ERROR_SUCCESS;
@@ -371,10 +442,11 @@
          '`','L','a','s','t','S','e','q','u','e','n','c','e','`',' ','>','=',
          ' ','%', 'i',' ','O','R','D','E','R',' ','B','Y',' ',
          '`','L','a','s','t','S','e','q','u','e','n','c','e','`',0};
-    LPCWSTR cab;
+    LPCWSTR cab, volume;
     DWORD sz;
     INT seq;
     static UINT last_sequence = 0; 
+    static LPWSTR last_volume = NULL;
     static LPWSTR last_path = NULL;
     MSIFILE* file = NULL;
 
@@ -382,6 +454,7 @@
     if (!package)
     {
         HeapFree(GetProcessHeap(),0,last_path);
+        HeapFree(GetProcessHeap(),0,last_volume);
         return ERROR_SUCCESS;
     }
 
@@ -404,6 +477,8 @@
     seq = MSI_RecordGetInteger(row,2);
     last_sequence = seq;
 
+    volume = MSI_RecordGetString(row, 5);
+
     HeapFree(GetProcessHeap(),0,last_path);
     last_path = NULL;
 
@@ -411,6 +486,7 @@
     {
         last_path = resolve_folder(package, comp->Directory, TRUE, FALSE, NULL);
         set_file_source(package,file,comp,last_path);
+        rc = ready_volume(package, file->SourcePath, last_volume, row);
         msiobj_release(&row->hdr);
         return rc;
     }
@@ -444,6 +520,7 @@
                 if (MSI_GetPropertyW(package, cszTempFolder,last_path, &sz) 
                                     != ERROR_SUCCESS)
                     GetTempPathW(MAX_PATH,last_path);
+                rc = ready_volume(package, source, last_volume, row);
             }
         }
         rc = !extract_cabinet_file(package, source, last_path);
@@ -456,6 +533,7 @@
         last_path = HeapAlloc(GetProcessHeap(),0,MAX_PATH*sizeof(WCHAR));
         MSI_GetPropertyW(package,cszSourceDir,source,&sz);
         strcpyW(last_path,source);
+        rc = ready_volume(package, last_path, last_volume, row);
     }
     set_file_source(package, file, comp, last_path);
     msiobj_release(&row->hdr);


More information about the wine-patches mailing list