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