cab_G_00-r3
Gregory M. Turner
gmturner007 at ameritech.net
Tue Aug 26 13:00:53 CDT 2003
Reconciles cab_G_00 with CVS -- and compiles :P.
The problem was an unneccesary include of winnls.h
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-26 12:55:14.000000000 -0500
@@ -0,0 +1,662 @@
+/*
+ * 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 "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