MSI: Use FDI functions instead of advpack!ExtractFiles and cabinet!Extract

Robert Shearman rob at codeweavers.com
Fri Sep 10 14:19:51 CDT 2004


Changelog:
- Use FDI functions like native instead of advpack.ExtractFiles and cabinet.Extract (which doesn't work with native cabinet)
- If MoveFile fails the message now displayes the correct last error and bails rather than silently breaking the install.


-------------- next part --------------
Index: wine/dlls/msi/action.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.c,v
retrieving revision 1.34
diff -u -p -r1.34 action.c
--- wine/dlls/msi/action.c	6 Aug 2004 17:30:20 -0000	1.34
+++ wine/dlls/msi/action.c	10 Sep 2004 19:16:44 -0000
@@ -34,8 +34,10 @@ http://msdn.microsoft.com/library/defaul
 #include "winerror.h"
 #include "winreg.h"
 #include "wine/debug.h"
+#include "fdi.h"
 #include "msi.h"
 #include "msiquery.h"
+#include "msvcrt/fcntl.h"
 #include "objbase.h"
 #include "objidl.h"
 #include "msipriv.h"
@@ -2237,97 +2239,161 @@ end:
 }
 
 
-/***********************************************************************
- *            extract_cabinet_file
- *
- * Extract  files from a cab file.
- */
-static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD );
+/* Support functions for FDI functions */
 
-static BOOL extract_cabinet_file_advpack( const WCHAR *cabinet, 
-                                          const WCHAR *root)
+static void * cabinet_alloc(ULONG cb)
 {
-    static HMODULE advpack;
+    return HeapAlloc(GetProcessHeap(), 0, cb);
+}
 
-    char *cab_path, *cab_file;
+static void cabinet_free(void *pv)
+{
+    HeapFree(GetProcessHeap(), 0, pv);
+}
 
-    if (!pExtractFiles)
+static INT_PTR cabinet_open(char *pszFile, int oflag, int pmode)
+{
+    DWORD dwAccess = 0;
+    DWORD dwShareMode = 0;
+    DWORD dwCreateDisposition = OPEN_EXISTING;
+    switch (oflag & _O_ACCMODE)
     {
-        if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" )))
-        {
-            ERR( "could not load advpack.dll\n" );
-            return FALSE;
-        }
-        if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles"
-)))
-        {
-            ERR( "could not find ExtractFiles in advpack.dll\n" );
-            return FALSE;
-        }
+    case _O_RDONLY:
+        dwAccess = GENERIC_READ;
+        dwShareMode = FILE_SHARE_READ | FILE_SHARE_DELETE;
+        break;
+    case _O_WRONLY:
+        dwAccess = GENERIC_WRITE;
+        dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+        break;
+    case _O_RDWR:
+        dwAccess = GENERIC_READ | GENERIC_WRITE;
+        dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+        break;
     }
+    if ((oflag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL))
+        dwCreateDisposition = CREATE_NEW;
+    else if (oflag & _O_CREAT)
+        dwCreateDisposition = CREATE_ALWAYS;
+    return (INT_PTR)CreateFileA(pszFile, dwAccess, dwShareMode, NULL, dwCreateDisposition, 0, NULL);
+}
 
-    if (!(cab_file = strdupWtoA( cabinet ))) return FALSE;
-    if (!(cab_path = strdupWtoA( root ))) return FALSE;
-
-    FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) );
-    pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 );
-    HeapFree( GetProcessHeap(), 0, cab_file );
-    HeapFree( GetProcessHeap(), 0, cab_path );
-    return TRUE;
+static UINT cabinet_read(INT_PTR hf, void *pv, UINT cb)
+{
+    DWORD dwRead;
+    if (ReadFile((HANDLE)hf, pv, cb, &dwRead, NULL))
+        return dwRead;
+    return 0;
 }
 
-static BOOL extract_cabinet_file_cabinet( const WCHAR *cabinet, 
-                                          const WCHAR *root)
-                                  
+static UINT cabinet_write(INT_PTR hf, void *pv, UINT cb)
 {
-    /* from cabinet.h */
+    DWORD dwWritten;
+    if (WriteFile((HANDLE)hf, pv, cb, &dwWritten, NULL))
+        return dwWritten;
+    return 0;
+}
 
-    struct ExtractFileList {
-        LPSTR  filename;
-        struct ExtractFileList *next;
-        BOOL   unknown;  /* always 1L */
-    } ;
+static int cabinet_close(INT_PTR hf)
+{
+    return CloseHandle((HANDLE)hf) ? 0 : -1;
+}
 
-    typedef struct {
-        long  result1;          /* 0x000 */
-        long  unknown1[3];      /* 0x004 */
-        struct ExtractFileList* filelist;         /* 0x010 */
-        long  filecount;        /* 0x014 */
-        long  unknown2;         /* 0x018 */
-        char  directory[0x104]; /* 0x01c */
-        char  lastfile[0x20c];  /* 0x120 */
-    } EXTRACTdest;
+static long cabinet_seek(INT_PTR hf, long dist, int seektype)
+{
+    /* flags are compatible and so are passed straight through */
+    return SetFilePointer((HANDLE)hf, dist, NULL, seektype);
+}
 
-    HRESULT WINAPI Extract(EXTRACTdest *dest, LPCSTR what);
+static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
+{
+    /* FIXME: try to do more processing in this function */
+    switch (fdint)
+    {
+    case fdintCOPY_FILE:
+    {
+        ULONG len = strlen((char*)pfdin->pv) + strlen(pfdin->psz1);
+        char *file = cabinet_alloc((len+1)*sizeof(char));
 
-    char *cab_path, *src_path;
-    EXTRACTdest exd;
-    struct ExtractFileList fl;
+        strcpy(file, (char*)pfdin->pv);
+        strcat(file, pfdin->psz1);
 
-    if (!(cab_path = strdupWtoA( cabinet ))) return FALSE;
-    if (!(src_path = strdupWtoA( root ))) return FALSE;
+        TRACE("file: %s\n", debugstr_a(file));
 
-    memset(&exd,0,sizeof(exd));
-    strcpy(exd.directory,src_path);
-    exd.unknown2 = 0x1;
-    fl.filename = cab_path;
-    fl.next = NULL;
-    fl.unknown = 1;
-    exd.filelist = &fl;
-    FIXME( "more aweful hack: extracting cabinet %s\n", debugstr_a(cab_path) );
-    Extract(&exd,cab_path);
+        return cabinet_open(file, _O_WRONLY | _O_CREAT, 0);
+    }
+    case fdintCLOSE_FILE_INFO:
+    {
+        FILETIME ft;
+	    FILETIME ftLocal;
+        if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft))
+            return -1;
+        if (!LocalFileTimeToFileTime(&ft, &ftLocal))
+            return -1;
+        if (!SetFileTime((HANDLE)pfdin->hf, &ftLocal, 0, &ftLocal))
+            return -1;
 
-    HeapFree( GetProcessHeap(), 0, cab_path );
-    HeapFree( GetProcessHeap(), 0, src_path );
-    return TRUE;
+        cabinet_close(pfdin->hf);
+        return 1;
+    }
+    default:
+        return 0;
+    }
 }
 
+/***********************************************************************
+ *            extract_cabinet_file
+ *
+ * Extract files from a cab file.
+ */
 static BOOL extract_cabinet_file(const WCHAR* source, const WCHAR* path)
 {
+    HFDI hfdi;
+    ERF erf;
+    BOOL ret;
+    char *cabinet;
+    char *cab_path;
+
     TRACE("Extracting %s to %s\n",debugstr_w(source), debugstr_w(path));
-    if (!extract_cabinet_file_advpack(source,path))
-        return extract_cabinet_file_cabinet(source,path);
-    return TRUE;
+
+    hfdi = FDICreate(cabinet_alloc,
+                     cabinet_free,
+                     cabinet_open,
+                     cabinet_read,
+                     cabinet_write,
+                     cabinet_close,
+                     cabinet_seek,
+                     0,
+                     &erf);
+    if (!hfdi)
+    {
+        ERR("FDICreate failed\n");
+        return FALSE;
+    }
+
+    if (!(cabinet = strdupWtoA( source )))
+    {
+        FDIDestroy(hfdi);
+        return FALSE;
+    }
+    if (!(cab_path = strdupWtoA( path )))
+    {
+        FDIDestroy(hfdi);
+        HeapFree(GetProcessHeap(), 0, cabinet);
+        return FALSE;
+    }
+
+    ret = FDICopy(hfdi, cabinet, "", 0, cabinet_notify, NULL, cab_path);
+
+    if (!ret)
+        ERR("FDICopy failed\n");
+
+    FDIDestroy(hfdi);
+
+    HeapFree(GetProcessHeap(), 0, cabinet);
+    HeapFree(GetProcessHeap(), 0, cab_path);
+
+    return ret;
 }
 
 static UINT ready_media_for_file(MSIPACKAGE *package, UINT sequence, 
@@ -2505,16 +2571,16 @@ static UINT ACTION_InstallFiles(MSIPACKA
             ui_actiondata(package,szInstallFiles,uirow);
             msiobj_release( &uirow->hdr );
 
-            rc = !MoveFileW(file->SourcePath,file->TargetPath);
-            ui_progress(package,2,0,0,0);
-
-            if (rc)
+            if (!MoveFileW(file->SourcePath,file->TargetPath))
             {
-                ERR("Unable to move file (error %li)\n",GetLastError());
-                rc = ERROR_SUCCESS;
+                rc = GetLastError();
+                ERR("Unable to move file (error %d)\n", rc);
+                break;
             }
             else
                 file->State = 4;
+
+            ui_progress(package,2,0,0,0);
         }
     }
 


More information about the wine-patches mailing list