cab_G_00-pre1 (RFC)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Alexandre, please do not apply.

This is a crack at implementing SetupIterateCabinet
using the stuff in fdi.c.  I'd appreciate some comments
on this code, esp. from any SETUPAPI experts out there.  

Would love to hear if I have not done things in a properly
"SETUPAPI" way, i.e., am I supposed to be performing certain
logging or memory allocation rituals, anything like that? 
This code works under laboratory conditions.

Also, I don't know of anything in the wild that calls this
API.  Real-world examples, preferably free ones, would be
appreciated, if anyone happens to know of any, against which
I could test.

LICENSE: Bugroff

--
diff -ur --minimal --exclude-from=/home/greg/bin/winetreediff_excl ../wine.test/dlls/setupapi/Makefile.in ./dlls/setupapi/Makefile.in
--- ../wine.test/dlls/setupapi/Makefile.in	2003-07-30 23:23:26.000000000 -0500
+++ ./dlls/setupapi/Makefile.in	2003-07-31 21:24:43.000000000 -0500
@@ -4,7 +4,7 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = setupapi.dll
-IMPORTS   = user32 version advapi32 kernel32 ntdll
+IMPORTS   = user32 version advapi32 kernel32 ntdll msvcrt
 ALTNAMES  = setupx.dll
 EXTRALIBS = $(LIBUNICODE)
 
@@ -20,6 +20,7 @@
 	install.c \
 	parser.c \
 	queue.c \
+	setupcab.c \
 	setupx_main.c \
 	stubs.c \
 	virtcopy.c
diff -ur --minimal --exclude-from=/home/greg/bin/winetreediff_excl ../wine.test/dlls/setupapi/setupapi_private.h ./dlls/setupapi/setupapi_private.h
--- ../wine.test/dlls/setupapi/setupapi_private.h	2003-07-30 23:23:26.000000000 -0500
+++ ./dlls/setupapi/setupapi_private.h	2003-08-01 23:05:49.000000000 -0500
@@ -64,4 +64,17 @@
 
 UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification, UINT_PTR, UINT_PTR );
 
+void UnloadCABINETDll();
+
+/* from include/msvcrt/io.h */
+extern int         _open(const char*,int,...);
+extern int         _close(int);
+extern int         _read(int,void*,unsigned int);
+extern int         _write(int,const void*,unsigned int);
+extern long        _lseek(int,long,int);
+
+/* from msvcrt/sys/stat.h */
+#define _S_IWRITE 0x0080
+#define _S_IREAD  0x0100
+
 #endif /* __SETUPAPI_PRIVATE_H */
diff -ur --minimal --exclude-from=/home/greg/bin/winetreediff_excl ../wine.test/dlls/setupapi/setupx_main.c ./dlls/setupapi/setupx_main.c
--- ../wine.test/dlls/setupapi/setupx_main.c	2003-07-30 23:23:26.000000000 -0500
+++ ./dlls/setupapi/setupx_main.c	2003-07-29 21:50:55.000000000 -0500
@@ -70,6 +70,32 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
 
+/***********************************************************************
+ * DllMain
+ *
+ * PARAMS
+ *     hinstDLL    [I] handle to the DLL's instance
+ *     fdwReason   [I]
+ *     lpvReserved [I] reserved, must be NULL
+ *
+ * RETURNS
+ *     Success: TRUE
+ *     Failure: FALSE
+ */
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+    switch (fdwReason) {
+    case DLL_PROCESS_ATTACH:
+        DisableThreadLibraryCalls(hinstDLL);
+        break;
+    case DLL_PROCESS_DETACH:
+        UnloadCABINETDll();
+        break;
+    }
+
+    return TRUE;
+}
 
 /***********************************************************************
  *		SURegOpenKey (SETUPX.47)
diff -ur --minimal --exclude-from=/home/greg/bin/winetreediff_excl ../wine.test/dlls/setupapi/stubs.c ./dlls/setupapi/stubs.c
--- ../wine.test/dlls/setupapi/stubs.c	2003-07-30 23:23:26.000000000 -0500
+++ ./dlls/setupapi/stubs.c	2003-07-29 20:16:43.000000000 -0500
@@ -24,28 +24,6 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
 
-
-/***********************************************************************
- *		SetupIterateCabinetA (SETUPAPI.@)
- */
-BOOL WINAPI SetupIterateCabinetA(PCSTR CabinetFile, DWORD Reserved,
-                                 PSP_FILE_CALLBACK_A MsgHandler, PVOID Context)
-{
-	FIXME("not implemented (setupapi.dll) \n");
-	return 0;
-}
-
-/***********************************************************************
- *		SetupIterateCabinetW (SETUPAPI.@)
- */
-BOOL WINAPI SetupIterateCabinetW(PWSTR CabinetFile, DWORD Reserved,
-                                 PSP_FILE_CALLBACK_W MsgHandler, PVOID Context)
-{
-	FIXME("not implemented (setupapi.dll) \n");
-	return 0;
-}
-
-
 /***********************************************************************
  *		TPWriteProfileString (SETUPX.62)
  */
diff -ur --minimal --exclude-from=/home/greg/bin/winetreediff_excl ../wine.test/include/setupapi.h ./include/setupapi.h
--- ../wine.test/include/setupapi.h	2003-07-30 23:23:26.000000000 -0500
+++ ./include/setupapi.h	2003-08-01 23:05:42.000000000 -0500
@@ -153,6 +153,48 @@
 DECL_WINELIB_TYPE_AW(SP_DEVICE_INTERFACE_DETAIL_DATA)
 DECL_WINELIB_TYPE_AW(PSP_DEVICE_INTERFACE_DETAIL_DATA)
 
+typedef struct _FILE_IN_CABINET_INFOA {
+  LPCSTR NameInCabinet;
+  DWORD FileSize;
+  DWORD Win32Error;
+  WORD DosDate;
+  WORD DosTime;
+  WORD DosAttribs;
+  CHAR FullTargetName[MAX_PATH];
+} FILE_IN_CABINET_INFOA, *PFILE_IN_CABINET_INFOA;
+
+typedef struct _FILE_IN_CABINET_INFOW {
+  LPCWSTR NameInCabinet;
+  DWORD FileSize;
+  DWORD Win32Error;
+  WORD DosDate;
+  WORD DosTime;
+  WORD DosAttribs;
+  WCHAR FullTargetName[MAX_PATH];
+} FILE_IN_CABINET_INFOW, *PFILE_IN_CABINET_INFOW;
+
+DECL_WINELIB_TYPE_AW(FILE_IN_CABINET_INFO)
+DECL_WINELIB_TYPE_AW(PFILE_IN_CABINET_INFO)
+
+typedef struct _CABINET_INFOA {
+  PCSTR CabinetPath;
+  PCSTR CabinetFile;
+  PCSTR DiskName;
+  USHORT SetId;
+  USHORT CabinetNumber;
+} CABINET_INFOA, *PCABINET_INFOA;
+
+typedef struct _CABINET_INFOW {
+  PCWSTR CabinetPath;
+  PCWSTR CabinetFile;
+  PCWSTR DiskName;
+  USHORT SetId;
+  USHORT CabinetNumber;
+} CABINET_INFOW, *PCABINET_INFOW;
+
+DECL_WINELIB_TYPE_AW(CABINET_INFO);
+DECL_WINELIB_TYPE_AW(PCABINET_INFO);
+
 #define INF_STYLE_NONE           0x00
 #define INF_STYLE_OLDNT          0x01
 #define INF_STYLE_WIN4           0x02
@@ -542,6 +584,8 @@
 BOOL     WINAPI SetupInstallFromInfSectionW(HWND,HINF,PCWSTR,UINT,HKEY,PCWSTR,UINT,
                                             PSP_FILE_CALLBACK_W,PVOID,HDEVINFO,PSP_DEVINFO_DATA);
 #define         SetupInstallFromInfSection WINELIB_NAME_AW(SetupInstallFromInfSection)
-
+BOOL     WINAPI SetupIterateCabinetA(PCSTR, DWORD, PSP_FILE_CALLBACK_A, PVOID);
+BOOL     WINAPI SetupIterateCabinetW(PCWSTR, DWORD, PSP_FILE_CALLBACK_W, PVOID);
+#define         SetupIterateCabinet WINELIB_NAME_AW(SetupIterateCabinet)
 
 #endif /* _INC_SETUPAPI */
--- /dev/null	1969-12-31 18:00:00.000000000 -0600
+++ ./dlls/setupapi/setupcab.c	2003-08-02 06:38:53.000000000 -0500
@@ -0,0 +1,554 @@
+/* 
+ * Setupapi cabinet routines
+ *
+ * Copyright 2003 Gregory M. Turner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "string.h"
+#include "stdlib.h"
+#include "winnls.h"
+#include "setupapi.h"
+#include "setupapi_private.h"
+#include "fdi.h"
+
+#include "msvcrt/fcntl.h"
+
+#include "wine/unicode.h"
+
+#include "wine/debug.h"
+
+static HINSTANCE CABINET_hInstance = 0;
+
+static HFDI (__cdecl *sc_FDICreate)(PFNALLOC, PFNFREE, PFNOPEN,
+                PFNREAD, PFNWRITE, PFNCLOSE, PFNSEEK, int, PERF);
+
+static BOOL (__cdecl *sc_FDICopy)(HFDI, char *, char *, int,
+                PFNFDINOTIFY, PFNFDIDECRYPT, void *);
+
+static BOOL (__cdecl *sc_FDIDestroy)(HFDI);
+
+#define SC_HSC_A_MAGIC 0xACABFEED
+typedef struct {
+  UINT magic;
+  HFDI hfdi;
+  PSP_FILE_CALLBACK_A msghandler;
+  PVOID context;
+  CHAR most_recent_cabinet_name[MAX_PATH];
+} SC_HSC_A, *PSC_HSC_A;
+
+#define SC_HSC_W_MAGIC 0x0CABFEED
+typedef struct {
+  UINT magic;
+  HFDI hfdi;
+  PSP_FILE_CALLBACK_W msghandler;
+  PVOID context;
+  WCHAR most_recent_cabinet_name[MAX_PATH];
+} SC_HSC_W, *PSC_HSC_W;
+
+WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
+
+BOOL LoadCABINETDll()
+{
+  if (!CABINET_hInstance) {
+    CABINET_hInstance = LoadLibraryA("cabinet.dll");
+    if (CABINET_hInstance)  {
+      sc_FDICreate = (void *)GetProcAddress(CABINET_hInstance, "FDICreate");
+      sc_FDICopy = (void *)GetProcAddress(CABINET_hInstance, "FDICopy");
+      sc_FDIDestroy = (void *)GetProcAddress(CABINET_hInstance, "FDIDestroy");
+      return TRUE;
+    } else {
+      ERR("load cabinet dll failed.\n");
+      return FALSE;
+    }
+  } else
+    return TRUE;
+}
+
+void UnloadCABINETDll()
+{
+  if (CABINET_hInstance) {
+    FreeLibrary(CABINET_hInstance);
+    CABINET_hInstance = 0;
+  }
+}
+
+/* FDICreate callbacks */
+
+__cdecl void *sc_FNALLOC(ULONG cb)
+{
+  return malloc(cb);
+}
+
+__cdecl void sc_FNFREE(void *pv)
+{
+  free(pv);
+}
+
+__cdecl INT_PTR sc_FNOPEN(char *pszFile, int oflag, int pmode)
+{
+  INT_PTR ret = 0;
+  /* TRACE("(pszFile == %s, oflag == %d, pmode == %d)\n", debugstr_a(pszFile), oflag, pmode); */
+  ret = _open(pszFile, oflag, pmode);
+  /* TRACE("<-- %d\n", ret); */
+  return ret;
+}
+
+__cdecl UINT sc_FNREAD(INT_PTR hf, void *pv, UINT cb)
+{
+  /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */
+  return _read(hf, pv, cb);
+}
+
+__cdecl UINT sc_FNWRITE(INT_PTR hf, void *pv, UINT cb)
+{
+  /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */
+  return _write(hf, pv, cb);
+}
+
+__cdecl int sc_FNCLOSE(INT_PTR hf)
+{
+  /* TRACE("(hf == %d)\n", hf); */
+  return _close(hf);
+}
+
+__cdecl long sc_FNSEEK(INT_PTR hf, long dist, int seektype)
+{
+  /* TRACE("(hf == %d, dist == %ld, seektype == %d)\n", hf, dist, seektype); */
+  return _lseek(hf, dist, seektype);
+}
+
+#define SIZEOF_MYSTERIO (MAX_PATH*3)
+
+/* FDICopy callbacks */
+
+__cdecl INT_PTR sc_FNNOTIFY_A(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
+{
+  FILE_IN_CABINET_INFOA fici;
+  PSC_HSC_A phsc;
+  CABINET_INFOA ci;
+  FILEPATHS_A fp;
+  UINT err;
+
+  CHAR mysterio[SIZEOF_MYSTERIO]; /* how big? undocumented! probably 256... */
+
+  memset(&(mysterio[0]), 0, SIZEOF_MYSTERIO);
+
+  TRACE("(fdint == %d, pfdin == ^%p)\n", fdint, pfdin);
+
+  if (pfdin && pfdin->pv && (*((void **) pfdin->pv) == (void *)SC_HSC_A_MAGIC))
+    phsc = (PSC_HSC_A) pfdin->pv;
+  else {
+    ERR("pv %p is not an SC_HSC_A.\n", (pfdin) ? pfdin->pv : NULL);
+    return -1;
+  }
+
+  switch (fdint) {
+  case fdintCABINET_INFO:
+    TRACE("Cabinet info notification\n");
+    /* TRACE("  Cabinet name: %s\n", debugstr_a(pfdin->psz1));
+    TRACE("  Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
+    TRACE("  Cabinet path: %s\n", debugstr_a(pfdin->psz3));
+    TRACE("  Cabinet Set#: %d\n", pfdin->setID);
+    TRACE("  Cabinet Cab#: %d\n", pfdin->iCabinet); */
+    WARN("SPFILENOTIFY_CABINETINFO undocumented: guess implementation.\n");
+    ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]);
+    ci.CabinetPath = pfdin->psz3;
+    ci.DiskName = pfdin->psz2;
+    ci.SetId = pfdin->setID;
+    ci.CabinetNumber = pfdin->iCabinet;
+    phsc->msghandler(phsc->context, SPFILENOTIFY_CABINETINFO, (UINT) &ci, 0);
+    return 0;
+  case fdintPARTIAL_FILE:
+    TRACE("Partial file notification\n");
+    /* TRACE("  Partial file name: %s\n", debugstr_a(pfdin->psz1)); */
+    return 0;
+  case fdintCOPY_FILE:
+    TRACE("Copy file notification\n");
+    TRACE("  File name: %s\n", debugstr_a(pfdin->psz1));
+    /* TRACE("  File size: %ld\n", pfdin->cb);
+    TRACE("  File date: %u\n", pfdin->date);
+    TRACE("  File time: %u\n", pfdin->time);
+    TRACE("  File attr: %u\n", pfdin->attribs); */
+    fici.NameInCabinet = pfdin->psz1;
+    fici.FileSize = pfdin->cb;
+    fici.Win32Error = 0;
+    fici.DosDate = pfdin->date;
+    fici.DosTime = pfdin->time;
+    fici.DosAttribs = pfdin->attribs;
+    memset(&(fici.FullTargetName[0]), 0, MAX_PATH);
+    err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEINCABINET,
+                           (UINT) &fici, (UINT) pfdin->psz1);
+    if (err == FILEOP_DOIT) {
+      TRACE("  Callback specified filename: %s\n", debugstr_a(&(fici.FullTargetName[0])));
+      if (!fici.FullTargetName[0]) {
+        WARN("  Empty return string causing abort.");
+        SetLastError(ERROR_PATH_NOT_FOUND);
+        return -1;
+      }
+      return _open(&(fici.FullTargetName[0]), _O_BINARY | _O_CREAT | _O_WRONLY,  _S_IREAD | _S_IWRITE);
+    } else {
+      TRACE("  Callback skipped file.\n");
+      return 0;
+    }
+  case fdintCLOSE_FILE_INFO:
+    TRACE("Close file notification\n");
+    /* TRACE("  File name: %s\n", debugstr_a(pfdin->psz1));
+    TRACE("  Exec file? %s\n", (pfdin->cb) ? "Yes" : "No");
+    TRACE("  File hndl: %d\n", pfdin->hf); */
+    fp.Source = &(phsc->most_recent_cabinet_name[0]);
+    fp.Target = pfdin->psz1;
+    fp.Win32Error = 0;
+    fp.Flags = 0;
+    /* a valid fixme -- but occurs too many times */
+    /* FIXME("Should set file date/time/attribs (and execute files?)\n"); */
+    err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT) &fp, 0);
+    if (_close(pfdin->hf))
+      WARN("_close failed.\n");
+    if (err) {
+      SetLastError(err);
+      return FALSE;
+    } else
+      return TRUE;
+  case fdintNEXT_CABINET:
+    TRACE("Next cabinet notification\n");
+    /* TRACE("  Cabinet name: %s\n", debugstr_a(pfdin->psz1));
+    TRACE("  Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
+    TRACE("  Cabinet path: %s\n", debugstr_a(pfdin->psz3));
+    TRACE("  Cabinet Set#: %d\n", pfdin->setID);
+    TRACE("  Cabinet Cab#: %d\n", pfdin->iCabinet); */
+    ci.CabinetFile = pfdin->psz1;
+    ci.CabinetPath = pfdin->psz3;
+    ci.DiskName = pfdin->psz2;
+    ci.SetId = pfdin->setID;
+    ci.CabinetNumber = pfdin->iCabinet;
+    /* remember the new cabinet name */
+    strcpy(&(phsc->most_recent_cabinet_name[0]), pfdin->psz1);
+    err = phsc->msghandler(phsc->context, SPFILENOTIFY_NEEDNEWCABINET, (UINT) &ci, (UINT) &(mysterio[0]));
+    if (err) {
+      SetLastError(err);
+      return -1;
+    } else {
+      if (mysterio[0]) {
+        /* some easy paranoia.  no such carefulness exists on the wide API IIRC */
+        mysterio[SIZEOF_MYSTERIO - 1] = '\0';
+        strncpy(pfdin->psz3, &(mysterio[0]), 255);
+        mysterio[255] = '\0';
+      }
+      return 0;
+    }
+  default:
+    FIXME("Unknown notification type %d.\n", fdint);
+    return 0;
+  }
+}
+
+__cdecl INT_PTR sc_FNNOTIFY_W(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
+{
+  FILE_IN_CABINET_INFOW fici;
+  PSC_HSC_W phsc;
+  CABINET_INFOW ci;
+  FILEPATHS_W fp;
+  UINT err;
+  int len;
+
+  WCHAR mysterio[SIZEOF_MYSTERIO]; /* how big? undocumented! */
+  WCHAR buf[MAX_PATH], buf2[MAX_PATH];
+  CHAR charbuf[MAX_PATH];
+
+  memset(&(mysterio[0]), 0, SIZEOF_MYSTERIO * sizeof(WCHAR));
+  memset(&(buf[0]), 0, MAX_PATH * sizeof(WCHAR));
+  memset(&(buf2[0]), 0, MAX_PATH * sizeof(WCHAR));
+  memset(&(charbuf[0]), 0, MAX_PATH);
+
+  TRACE("(fdint == %d, pfdin == ^%p)\n", fdint, pfdin);
+
+  if (pfdin && pfdin->pv && (*((void **) pfdin->pv) == (void *)SC_HSC_W_MAGIC))
+    phsc = (PSC_HSC_W) pfdin->pv;
+  else {
+    ERR("pv %p is not an SC_HSC_W.\n", (pfdin) ? pfdin->pv : NULL);
+    return -1;
+  }
+
+  switch (fdint) {
+  case fdintCABINET_INFO:
+    TRACE("Cabinet info notification\n");
+    /* TRACE("  Cabinet name: %s\n", debugstr_a(pfdin->psz1));
+    TRACE("  Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
+    TRACE("  Cabinet path: %s\n", debugstr_a(pfdin->psz3));
+    TRACE("  Cabinet Set#: %d\n", pfdin->setID);
+    TRACE("  Cabinet Cab#: %d\n", pfdin->iCabinet); */
+    WARN("SPFILENOTIFY_CABINETINFO undocumented: guess implementation.\n");
+    ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]);
+    len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, &(buf[0]), MAX_PATH);
+    if ((len > MAX_PATH) || (len <= 1))
+      buf[0] = '\0';
+    ci.CabinetPath = &(buf[0]);
+    len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, &(buf2[0]), MAX_PATH);
+    if ((len > MAX_PATH) || (len <= 1))
+      buf2[0] = '\0';
+    ci.DiskName = &(buf2[0]);
+    ci.SetId = pfdin->setID;
+    ci.CabinetNumber = pfdin->iCabinet;
+    phsc->msghandler(phsc->context, SPFILENOTIFY_CABINETINFO, (UINT) &ci, 0);
+    return 0;
+  case fdintPARTIAL_FILE:
+    TRACE("Partial file notification\n");
+    /* TRACE("  Partial file name: %s\n", debugstr_a(pfdin->psz1)); */
+    return 0;
+  case fdintCOPY_FILE:
+    TRACE("Copy file notification\n");
+    TRACE("  File name: %s\n", debugstr_a(pfdin->psz1));
+    /* TRACE("  File size: %ld\n", pfdin->cb);
+    TRACE("  File date: %u\n", pfdin->date);
+    TRACE("  File time: %u\n", pfdin->time);
+    TRACE("  File attr: %u\n", pfdin->attribs); */
+    len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(buf2[0]), MAX_PATH);
+    if ((len > MAX_PATH) || (len <= 1))
+      buf2[0] = '\0';
+    fici.NameInCabinet = &(buf2[0]);
+    fici.FileSize = pfdin->cb;
+    fici.Win32Error = 0;
+    fici.DosDate = pfdin->date;
+    fici.DosTime = pfdin->time;
+    fici.DosAttribs = pfdin->attribs;
+    memset(&(fici.FullTargetName[0]), 0, MAX_PATH * sizeof(WCHAR));
+    err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEINCABINET,
+                           (UINT) &fici, (UINT) pfdin->psz1);
+    if (err == FILEOP_DOIT) {
+      TRACE("  Callback specified filename: %s\n", debugstr_w(&(fici.FullTargetName[0])));
+      if (fici.FullTargetName[0]) {
+        len = strlenW(&(fici.FullTargetName[0])) + 1;
+        if ((len > MAX_PATH ) || (len <= 1))
+          return 0;
+        if (!WideCharToMultiByte(CP_ACP, 0, &(fici.FullTargetName[0]), len, &(charbuf[0]), MAX_PATH, 0, 0))
+          return 0;
+      } else {
+        WARN("Empty buffer string caused abort.\n");
+        SetLastError(ERROR_PATH_NOT_FOUND);
+        return -1;
+      }
+      return _open(&(charbuf[0]), _O_BINARY | _O_CREAT | _O_WRONLY,  _S_IREAD | _S_IWRITE);
+    } else {
+      TRACE("  Callback skipped file.\n");
+      return 0;
+    }
+  case fdintCLOSE_FILE_INFO:
+    TRACE("Close file notification\n");
+    /* TRACE("  File name: %s\n", debugstr_a(pfdin->psz1));
+    TRACE("  Exec file? %s\n", (pfdin->cb) ? "Yes" : "No");
+    TRACE("  File hndl: %d\n", pfdin->hf); */
+    fp.Source = &(phsc->most_recent_cabinet_name[0]);
+    len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(buf[0]), MAX_PATH);
+    if ((len > MAX_PATH) || (len <= 1))
+      buf[0] = '\0';
+    fp.Target = &(buf[0]);
+    fp.Win32Error = 0;
+    fp.Flags = 0;
+    /* a valid fixme -- but occurs too many times */
+    /* FIXME("Should set file date/time/attribs (and execute files?)\n"); */
+    err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT) &fp, 0);
+    if (_close(pfdin->hf))
+      WARN("_close failed.\n");
+    if (err) {
+      SetLastError(err);
+      return FALSE;
+    } else
+      return TRUE;
+  case fdintNEXT_CABINET:
+    TRACE("Next cabinet notification\n");
+    /* TRACE("  Cabinet name: %s\n", debugstr_a(pfdin->psz1));
+    TRACE("  Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
+    TRACE("  Cabinet path: %s\n", debugstr_a(pfdin->psz3));
+    TRACE("  Cabinet Set#: %d\n", pfdin->setID);
+    TRACE("  Cabinet Cab#: %d\n", pfdin->iCabinet); */
+    /* remember the new cabinet name */
+    len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(phsc->most_recent_cabinet_name[0]), MAX_PATH);
+    if ((len > MAX_PATH) || (len <= 1))
+      phsc->most_recent_cabinet_name[0] = '\0';
+    ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]);
+    len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, &(buf[0]), MAX_PATH);
+    if ((len > MAX_PATH) || (len <= 1))
+      buf[0] = '\0';
+    ci.CabinetPath = &(buf[0]);
+    len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, &(buf2[0]), MAX_PATH);
+    if ((len > MAX_PATH) || (len <= 1))
+      buf2[0] = '\0';
+    ci.DiskName = &(buf2[0]);
+    ci.SetId = pfdin->setID;
+    ci.CabinetNumber = pfdin->iCabinet;
+    err = phsc->msghandler(phsc->context, SPFILENOTIFY_NEEDNEWCABINET, (UINT) &ci, (UINT) &(mysterio[0]));
+    if (err) {
+      SetLastError(err);
+      return -1;
+    } else {
+      if (mysterio[0]) {
+        len = strlenW(&(mysterio[0])) + 1;
+        if ((len > 255) || (len <= 1))
+          return 0;
+        if (!WideCharToMultiByte(CP_ACP, 0, &(mysterio[0]), len, pfdin->psz3, 255, 0, 0))
+          return 0;
+      }
+      return 0;
+    }
+  default:
+    FIXME("Unknown notification type %d.\n", fdint);
+    return 0;
+  }
+}
+
+/***********************************************************************
+ *		SetupIterateCabinetA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupIterateCabinetA(PCSTR CabinetFile, DWORD Reserved,
+                                 PSP_FILE_CALLBACK_A MsgHandler, PVOID Context)
+{
+
+  SC_HSC_A my_hsc;
+  ERF erf;
+  CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH], *p;
+  DWORD fpnsize;
+  BOOL ret;
+
+
+  TRACE("(CabinetFile == %s, Reserved == %lu, MsgHandler == ^%p, Context == ^%p)\n",
+        debugstr_a(CabinetFile), Reserved, MsgHandler, Context);
+
+  if (! LoadCABINETDll()) 
+    return FALSE;
+
+  memset(&my_hsc, 0, sizeof(SC_HSC_A));
+  pszCabinet[0] = '\0';
+  pszCabPath[0] = '\0';
+
+  fpnsize = strlen(CabinetFile);
+  if (fpnsize >= MAX_PATH) {
+    SetLastError(ERROR_BAD_PATHNAME);
+    return FALSE;
+  }
+
+  fpnsize = GetFullPathNameA(CabinetFile, MAX_PATH, &(pszCabPath[0]), &p);
+  if (fpnsize > MAX_PATH) {
+    SetLastError(ERROR_BAD_PATHNAME);
+    return FALSE;
+  }
+
+  if (p) {
+    strcpy(pszCabinet, p);
+    *p = '\0';
+  } else {
+    strcpy(pszCabinet, CabinetFile);
+    pszCabPath[0] = '\0';
+  }
+
+  TRACE("path: %s, cabfile: %s\n", debugstr_a(pszCabPath), debugstr_a(pszCabinet));
+
+  /* remember the cabinet name */
+  strcpy(&(my_hsc.most_recent_cabinet_name[0]), pszCabinet);
+
+  my_hsc.magic = SC_HSC_A_MAGIC;
+  my_hsc.msghandler = MsgHandler;
+  my_hsc.context = Context;
+  my_hsc.hfdi = sc_FDICreate( sc_FNALLOC, sc_FNFREE, sc_FNOPEN, sc_FNREAD,
+                           sc_FNWRITE, sc_FNCLOSE, sc_FNSEEK, cpuUNKNOWN, &erf );
+
+  if (!my_hsc.hfdi) return FALSE;
+
+  ret = ( sc_FDICopy(my_hsc.hfdi, pszCabinet, pszCabPath,
+                     0, sc_FNNOTIFY_A, NULL, &my_hsc)     ) ? TRUE : FALSE;
+
+  sc_FDIDestroy(my_hsc.hfdi);
+  return ret;
+}
+
+/***********************************************************************
+ *		SetupIterateCabinetW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupIterateCabinetW(PCWSTR CabinetFile, DWORD Reserved,
+                                 PSP_FILE_CALLBACK_W MsgHandler, PVOID Context)
+{
+  CHAR _CabinetFile_A[MAX_PATH];
+  CHAR *CabinetFile_A = &(_CabinetFile_A[0]);
+  UINT32 len;
+  SC_HSC_W my_hsc;
+  ERF erf;
+  CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH], *p;
+  DWORD fpnsize;
+  BOOL ret;
+
+  TRACE("(CabinetFile == %s, Reserved == %lu, MsgHandler == ^%p, Context == ^%p)\n",
+        debugstr_w(CabinetFile), Reserved, MsgHandler, Context);
+
+  if (!LoadCABINETDll())
+    return FALSE;
+
+  if (CabinetFile) {
+    len = strlenW(CabinetFile) + 1;
+    if ((len > MAX_PATH ) || (len <= 1))
+      return FALSE;
+    if (!WideCharToMultiByte(CP_ACP, 0, CabinetFile, len, CabinetFile_A, MAX_PATH, 0, 0))
+      return FALSE;
+  } else
+    return FALSE;
+
+  memset(&my_hsc, 0, sizeof(SC_HSC_W));
+  pszCabinet[0] = '\0';
+  pszCabPath[0] = '\0';
+
+  fpnsize = strlen(CabinetFile_A);
+  if (fpnsize >= MAX_PATH) {
+    SetLastError(ERROR_BAD_PATHNAME);
+    return FALSE;
+  }
+
+  fpnsize = GetFullPathNameA(CabinetFile_A, MAX_PATH, &(pszCabPath[0]), &p);
+  if (fpnsize > MAX_PATH) {
+    SetLastError(ERROR_BAD_PATHNAME);
+    return FALSE;
+  }
+
+  if (p) {
+    strcpy(pszCabinet, p);
+    *p = '\0';
+  } else {
+    strcpy(pszCabinet, CabinetFile_A);
+    pszCabPath[0] = '\0';
+  }
+
+  TRACE("path: %s, cabfile: %s\n", debugstr_a(pszCabPath), debugstr_a(pszCabinet));
+
+  /* remember the cabinet name */
+  len = 1 + MultiByteToWideChar(CP_ACP, 0, pszCabinet, -1,
+             &(my_hsc.most_recent_cabinet_name[0]), MAX_PATH);
+  if (len > MAX_PATH)
+    return FALSE;
+  else if (len <= 1)
+    my_hsc.most_recent_cabinet_name[0] = '\0';
+  my_hsc.magic = SC_HSC_W_MAGIC;
+  my_hsc.msghandler = MsgHandler;
+  my_hsc.context = Context;
+  my_hsc.hfdi = sc_FDICreate( sc_FNALLOC, sc_FNFREE, sc_FNOPEN, sc_FNREAD,
+                           sc_FNWRITE, sc_FNCLOSE, sc_FNSEEK, cpuUNKNOWN, &erf );
+
+  if (!my_hsc.hfdi) return FALSE;
+
+  ret = ( sc_FDICopy(my_hsc.hfdi, pszCabinet, pszCabPath,
+                     0, sc_FNNOTIFY_W, NULL, &my_hsc)     ) ? TRUE : FALSE;
+
+  sc_FDIDestroy(my_hsc.hfdi);
+  return ret;
+}
+
-- 
gmt

"Microsoft is committed to making cabinet files an open technology"
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncabsdk/html/cabdl.asp



[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux