cab_G_00-r2

Gregory M. Turner gmturner007 at ameritech.net
Tue Aug 26 12:49:35 CDT 2003


This simply reconciles cab_G_00 with CVS.

License: Bugroff

* dlls/setupapi: Makefile.in, setupapi_private.h,
    setupx_main.c, stubs.c, setupapi.h, setupcab.c (new)
  Greg Turner <gmturner007 at ameritech.net>
- implement (most of) SetupIterateCabinet.

--
diff -ur --minimal --exclude-from=/home/greg/bin/winetreediff_excl ../wine.vanilla/dlls/setupapi/Makefile.in ./dlls/setupapi/Makefile.in
--- ../wine.vanilla/dlls/setupapi/Makefile.in	2003-08-26 12:33:14.000000000 -0500
+++ ./dlls/setupapi/Makefile.in	2003-08-26 12:36:26.000000000 -0500
@@ -20,6 +20,7 @@
 	install.c \
 	parser.c \
 	queue.c \
+	setupcab.c \
 	stubs.c
 
 C_SRCS16 = \
diff -ur --minimal --exclude-from=/home/greg/bin/winetreediff_excl ../wine.vanilla/dlls/setupapi/setupapi_private.h ./dlls/setupapi/setupapi_private.h
--- ../wine.vanilla/dlls/setupapi/setupapi_private.h	2003-01-29 21:49:56.000000000 -0600
+++ ./dlls/setupapi/setupapi_private.h	2003-08-18 09:17:44.000000000 -0500
@@ -64,4 +64,10 @@
 
 UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification, UINT_PTR, UINT_PTR );
 
+void UnloadCABINETDll();
+
+/* 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.vanilla/dlls/setupapi/setupx_main.c ./dlls/setupapi/setupx_main.c
--- ../wine.vanilla/dlls/setupapi/setupx_main.c	2003-01-29 21:49:56.000000000 -0600
+++ ./dlls/setupapi/setupx_main.c	2003-08-18 09:17:44.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.vanilla/dlls/setupapi/stubs.c ./dlls/setupapi/stubs.c
--- ../wine.vanilla/dlls/setupapi/stubs.c	2003-04-09 16:43:30.000000000 -0500
+++ ./dlls/setupapi/stubs.c	2003-08-18 09:17:44.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.vanilla/include/setupapi.h ./include/setupapi.h
--- ../wine.vanilla/include/setupapi.h	2003-01-29 21:50:12.000000000 -0600
+++ ./include/setupapi.h	2003-08-18 09:17:44.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-18 09:17:44.000000000 -0500
@@ -0,0 +1,663 @@
+/* 
+ * 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
+ *
+ *
+ * Many useful traces are commented in code, uncomment them if you have
+ * trouble and run with --debugmsg +setupapi
+ * 
+ */
+
+#include "string.h"
+#include "stdlib.h"
+#include "winnls.h"
+#include "setupapi.h"
+#include "setupapi_private.h"
+#include "fdi.h"
+#include "wine/unicode.h"
+
+#include "msvcrt/fcntl.h"
+#include "msvcrt/share.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_cb_alloc(ULONG cb)
+{
+  return malloc(cb);
+}
+
+__cdecl void sc_cb_free(void *pv)
+{
+  free(pv);
+}
+
+__cdecl INT_PTR sc_cb_open(char *pszFile, int oflag, int pmode)
+{
+  DWORD creation = 0, sharing = 0;
+  int ioflag = 0;
+  INT_PTR ret = 0;
+  SECURITY_ATTRIBUTES sa;
+
+  /* TRACE("(pszFile == %s, oflag == %d, pmode == %d)\n", debugstr_a(pszFile), oflag, pmode); */
+
+  switch(oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
+  case _O_RDONLY:
+    ioflag |= GENERIC_READ;
+    break;
+  case _O_WRONLY:
+    ioflag |= GENERIC_WRITE;
+    break;
+  case _O_RDWR:
+    ioflag |= GENERIC_READ & GENERIC_WRITE;
+    break;
+  case _O_WRONLY | _O_RDWR: /* hmmm.. */
+    ERR("_O_WRONLY & _O_RDWR in oflag?\n");
+    return -1;
+  }
+
+  if (oflag & _O_CREAT) {
+    if (oflag & _O_EXCL)
+      creation = CREATE_NEW;
+    else if (oflag & _O_TRUNC)
+      creation = CREATE_ALWAYS;
+    else
+      creation = OPEN_ALWAYS;
+  } else  /* no _O_CREAT */ {
+    if (oflag & _O_TRUNC)
+      creation = TRUNCATE_EXISTING;
+    else
+      creation = OPEN_EXISTING;
+  }
+
+  switch( pmode & 0x70 ) {
+    case _SH_DENYRW:
+      sharing = 0L;
+      break;
+    case _SH_DENYWR:
+      sharing = FILE_SHARE_READ;
+      break;
+    case _SH_DENYRD:
+      sharing = FILE_SHARE_WRITE;
+      break;
+    case _SH_COMPAT:
+    case _SH_DENYNO:
+      sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
+      break;
+    default:
+      ERR("<-- -1 (Unhandled pmode 0x%x)\n", pmode);
+      return -1;
+  }
+
+  if (oflag & ~(_O_BINARY | _O_TRUNC | _O_EXCL | _O_CREAT | _O_RDWR | _O_WRONLY | _O_NOINHERIT))
+    WARN("unsupported oflag 0x%04x\n",oflag);
+
+  sa.nLength              = sizeof( SECURITY_ATTRIBUTES );
+  sa.lpSecurityDescriptor = NULL;
+  sa.bInheritHandle       = (ioflag & _O_NOINHERIT) ? FALSE : TRUE;
+
+  ret = (INT_PTR) CreateFileA(pszFile, ioflag, sharing, &sa, creation, FILE_ATTRIBUTE_NORMAL, NULL);
+
+  /* TRACE("<-- %d\n", ret); */
+
+  return ret;
+}
+
+__cdecl UINT sc_cb_read(INT_PTR hf, void *pv, UINT cb)
+{
+  DWORD num_read;
+  BOOL rslt;
+
+  /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */
+
+  rslt = ReadFile((HANDLE) hf, pv, cb, &num_read, NULL);
+
+
+  /* eof and failure both give "-1" return */
+  if ((! rslt) || ((cb > 0) && (num_read == 0))) {
+    /* TRACE("<-- -1\n"); */
+    return -1;
+  }
+
+  /* TRACE("<-- %lu\n", num_read); */
+  return num_read;
+}
+
+__cdecl UINT sc_cb_write(INT_PTR hf, void *pv, UINT cb)
+{
+  DWORD num_written;
+  /* BOOL rv; */
+
+  /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */
+
+  if ( /* (rv = */ WriteFile((HANDLE) hf, pv, cb, &num_written, NULL) /* ) */
+       && (num_written == cb)) {
+    /* TRACE("<-- %lu\n", num_written); */
+    return num_written;
+  } else {
+    /* TRACE("rv == %d, num_written == %lu, cb == %u\n", rv, num_written,cb); */
+    /* TRACE("<-- -1\n"); */
+    return -1;
+  }
+}
+
+__cdecl int sc_cb_close(INT_PTR hf)
+{
+  /* TRACE("(hf == %d)\n", hf); */
+
+  if (CloseHandle((HANDLE) hf))
+    return 0;
+  else
+    return -1;
+}
+
+__cdecl long sc_cb_lseek(INT_PTR hf, long dist, int seektype)
+{
+  DWORD ret;
+
+  /* TRACE("(hf == %d, dist == %ld, seektype == %d)\n", hf, dist, seektype); */
+
+  if (seektype < 0 || seektype > 2)
+    return -1;
+
+  if (((ret = SetFilePointer((HANDLE) hf, dist, NULL, seektype)) != INVALID_SET_FILE_POINTER) || !GetLastError()) {
+    /* TRACE("<-- %lu\n", ret); */
+    return ret;
+  } else {
+    /* TRACE("<-- -1\n"); */
+    return -1;
+  }
+}
+
+#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 sc_cb_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;
+    /* the following should be a fixme -- but it occurs too many times */
+    WARN("Should set file date/time/attribs (and execute files?)\n");
+    err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT) &fp, 0);
+    if (sc_cb_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 sc_cb_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 (sc_cb_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_cb_alloc, sc_cb_free, sc_cb_open, sc_cb_read,
+                           sc_cb_write, sc_cb_close, sc_cb_lseek, 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_cb_alloc, sc_cb_free, sc_cb_open, sc_cb_read,
+                              sc_cb_write, sc_cb_close, sc_cb_lseek, 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

"We have to get basically voters to say 'I'd like to vote
for the politician who thinks of global equity'"
  -- Bill Gates, World Economic Forum 2002




More information about the wine-patches mailing list