[PATCH 1/5] setupapi: Implement SetupIterateCabinetW() on top of SetupIterateCabinetA().

Zebediah Figura z.figura12 at gmail.com
Thu Mar 4 20:08:13 CST 2021


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/setupapi/setupcab.c | 318 ++++++++++++---------------------------
 1 file changed, 98 insertions(+), 220 deletions(-)

diff --git a/dlls/setupapi/setupcab.c b/dlls/setupapi/setupcab.c
index b9783b81356..55d0fe6f64c 100644
--- a/dlls/setupapi/setupcab.c
+++ b/dlls/setupapi/setupcab.c
@@ -84,16 +84,6 @@ typedef struct {
   CHAR most_recent_target[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];
-  WCHAR most_recent_target[MAX_PATH];
-} SC_HSC_W, *PSC_HSC_W;
-
 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
 
 static BOOL LoadCABINETDll(void)
@@ -386,158 +376,6 @@ static INT_PTR CDECL sc_FNNOTIFY_A(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION p
   }
 }
 
-static INT_PTR CDECL sc_FNNOTIFY_W(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
-{
-  FILE_IN_CABINET_INFO_W fici;
-  PSC_HSC_W phsc;
-  CABINET_INFO_W 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, SIZEOF_MYSTERIO * sizeof(WCHAR));
-  memset(buf, 0, MAX_PATH * sizeof(WCHAR));
-  memset(buf2, 0, MAX_PATH * sizeof(WCHAR));
-  memset(charbuf, 0, MAX_PATH);
-
-  TRACE("(fdint == %d, pfdin == ^%p)\n", fdint, pfdin);
-
-  if (pfdin && pfdin->pv && (((PSC_HSC_W) pfdin->pv)->magic == SC_HSC_W_MAGIC))
-    phsc = 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;
-    len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, buf, MAX_PATH);
-    if ((len > MAX_PATH) || (len <= 1))
-      buf[0] = '\0';
-    ci.CabinetPath = buf;
-    len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, buf2, MAX_PATH);
-    if ((len > MAX_PATH) || (len <= 1))
-      buf2[0] = '\0';
-    ci.DiskName = buf2;
-    ci.SetId = pfdin->setID;
-    ci.CabinetNumber = pfdin->iCabinet;
-    phsc->msghandler(phsc->context, SPFILENOTIFY_CABINETINFO, (UINT_PTR)&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, MAX_PATH);
-    if ((len > MAX_PATH) || (len <= 1))
-      buf2[0] = '\0';
-    fici.NameInCabinet = buf2;
-    fici.FileSize = pfdin->cb;
-    fici.Win32Error = 0;
-    fici.DosDate = pfdin->date;
-    fici.DosTime = pfdin->time;
-    fici.DosAttribs = pfdin->attribs;
-    memset(fici.FullTargetName, 0, MAX_PATH * sizeof(WCHAR));
-    err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEINCABINET,
-                           (UINT_PTR)&fici, (UINT_PTR)pfdin->psz1);
-    if (err == FILEOP_DOIT) {
-      TRACE("  Callback specified filename: %s\n", debugstr_w(fici.FullTargetName));
-      if (fici.FullTargetName[0]) {
-        len = lstrlenW(fici.FullTargetName) + 1;
-        if ((len > MAX_PATH ) || (len <= 1))
-          return 0;
-        if (!WideCharToMultiByte(CP_ACP, 0, fici.FullTargetName, len, charbuf, MAX_PATH, 0, 0))
-          return 0;
-      } else {
-        WARN("Empty buffer string caused abort.\n");
-        SetLastError(ERROR_PATH_NOT_FOUND);
-        return -1;
-      }
-      lstrcpyW( phsc->most_recent_target, fici.FullTargetName );
-      return sc_cb_open(charbuf, _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;
-    fp.Target = phsc->most_recent_target;
-    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"); */
-    if (sc_cb_close(pfdin->hf))
-      WARN("_close failed.\n");
-    err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT_PTR)&fp, 0);
-    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, MAX_PATH);
-    if ((len > MAX_PATH) || (len <= 1))
-      phsc->most_recent_cabinet_name[0] = '\0';
-    ci.CabinetFile = phsc->most_recent_cabinet_name;
-    len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, buf, MAX_PATH);
-    if ((len > MAX_PATH) || (len <= 1))
-      buf[0] = '\0';
-    ci.CabinetPath = buf;
-    len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, buf2, MAX_PATH);
-    if ((len > MAX_PATH) || (len <= 1))
-      buf2[0] = '\0';
-    ci.DiskName = buf2;
-    ci.SetId = pfdin->setID;
-    ci.CabinetNumber = pfdin->iCabinet;
-    err = phsc->msghandler(phsc->context, SPFILENOTIFY_NEEDNEWCABINET, (UINT_PTR)&ci, (UINT_PTR)mysterio);
-    if (err) {
-      SetLastError(err);
-      return -1;
-    } else {
-      if (mysterio[0]) {
-        len = lstrlenW(mysterio) + 1;
-        if ((len > 255) || (len <= 1))
-          return 0;
-        if (!WideCharToMultiByte(CP_ACP, 0, mysterio, len, pfdin->psz3, 255, 0, 0))
-          return 0;
-      }
-      return 0;
-    }
-  default:
-    FIXME("Unknown notification type %d.\n", fdint);
-    return 0;
-  }
-}
-
 /***********************************************************************
  *		SetupIterateCabinetA (SETUPAPI.@)
  */
@@ -602,72 +440,112 @@ BOOL WINAPI SetupIterateCabinetA(PCSTR CabinetFile, DWORD Reserved,
   return ret;
 }
 
+struct iterate_wtoa_ctx
+{
+    PSP_FILE_CALLBACK_A orig_cb;
+    void *orig_ctx;
+};
+
+static UINT WINAPI iterate_wtoa_cb(void *pctx, UINT message, UINT_PTR param1, UINT_PTR param2)
+{
+    struct iterate_wtoa_ctx *ctx = pctx;
+
+    switch (message)
+    {
+    case SPFILENOTIFY_CABINETINFO:
+    case SPFILENOTIFY_NEEDNEWCABINET:
+    {
+        const CABINET_INFO_A *infoA = (const CABINET_INFO_A *)param1;
+        WCHAR pathW[MAX_PATH], fileW[MAX_PATH], diskW[MAX_PATH];
+        CABINET_INFO_W infoW =
+        {
+            .CabinetPath = pathW,
+            .CabinetFile = fileW,
+            .DiskName = diskW,
+            .SetId = infoA->SetId,
+            .CabinetNumber = infoA->CabinetNumber,
+        };
+
+        MultiByteToWideChar(CP_ACP, 0, infoA->CabinetPath, -1, pathW, ARRAY_SIZE(pathW));
+        MultiByteToWideChar(CP_ACP, 0, infoA->CabinetFile, -1, fileW, ARRAY_SIZE(fileW));
+        MultiByteToWideChar(CP_ACP, 0, infoA->DiskName, -1, diskW, ARRAY_SIZE(diskW));
+
+        if (message == SPFILENOTIFY_CABINETINFO)
+            return ctx->orig_cb(ctx->orig_ctx, message, (UINT_PTR)&infoW, 0);
+        else
+        {
+            char *newpathA = (char *)param2;
+            WCHAR newpathW[MAX_PATH] = {0};
+            BOOL ret = ctx->orig_cb(ctx->orig_ctx, message, (UINT_PTR)&infoW, (UINT_PTR)newpathW);
+
+            WideCharToMultiByte(CP_ACP, 0, newpathW, -1, newpathA, MAX_PATH, NULL, NULL);
+            return ret;
+        }
+    }
+    case SPFILENOTIFY_FILEINCABINET:
+    {
+        FILE_IN_CABINET_INFO_A *infoA = (FILE_IN_CABINET_INFO_A *)param1;
+        const char *cabA = (const char *)param2;
+        WCHAR cabW[MAX_PATH], fileW[MAX_PATH];
+        FILE_IN_CABINET_INFO_W infoW =
+        {
+            .NameInCabinet = fileW,
+            .FileSize = infoA->FileSize,
+            .Win32Error = infoA->Win32Error,
+            .DosDate = infoA->DosDate,
+            .DosTime = infoA->DosTime,
+            .DosAttribs = infoA->DosAttribs,
+        };
+        BOOL ret;
+
+        MultiByteToWideChar(CP_ACP, 0, infoA->NameInCabinet, -1, fileW, ARRAY_SIZE(fileW));
+        MultiByteToWideChar(CP_ACP, 0, cabA, -1, cabW, ARRAY_SIZE(cabW));
+
+        ret = ctx->orig_cb(ctx->orig_ctx, message, (UINT_PTR)&infoW, (UINT_PTR)cabW);
+
+        WideCharToMultiByte(CP_ACP, 0, infoW.FullTargetName, -1, infoA->FullTargetName,
+                ARRAY_SIZE(infoA->FullTargetName), NULL, NULL);
+
+        return ret;
+    }
+    case SPFILENOTIFY_FILEEXTRACTED:
+    {
+        const FILEPATHS_A *pathsA = (const FILEPATHS_A *)param1;
+        WCHAR targetW[MAX_PATH], sourceW[MAX_PATH];
+        FILEPATHS_W pathsW =
+        {
+            .Target = targetW,
+            .Source = sourceW,
+            .Win32Error = pathsA->Win32Error,
+            .Flags = pathsA->Flags,
+        };
+
+        MultiByteToWideChar(CP_ACP, 0, pathsA->Target, -1, targetW, ARRAY_SIZE(targetW));
+        MultiByteToWideChar(CP_ACP, 0, pathsA->Source, -1, sourceW, ARRAY_SIZE(sourceW));
+
+        return ctx->orig_cb(ctx->orig_ctx, message, (UINT_PTR)&pathsW, 0);
+    }
+    default:
+        FIXME("Unexpected callback %#x.\n", message);
+        return FALSE;
+    }
+}
 
 /***********************************************************************
- *		SetupIterateCabinetW (SETUPAPI.@)
+ *              SetupIterateCabinetW (SETUPAPI.@)
  */
-BOOL WINAPI SetupIterateCabinetW(PCWSTR CabinetFile, DWORD Reserved,
-                                 PSP_FILE_CALLBACK_W MsgHandler, PVOID Context)
+BOOL WINAPI SetupIterateCabinetW(const WCHAR *fileW, DWORD reserved,
+        PSP_FILE_CALLBACK_W handler, void *context)
 {
-  CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH];
-  UINT len;
-  SC_HSC_W my_hsc;
-  ERF erf;
-  WCHAR pszCabPathW[MAX_PATH], *p = NULL;
-  DWORD fpnsize;
-  BOOL ret;
-
-  TRACE("(CabinetFile == %s, Reserved == %u, MsgHandler == ^%p, Context == ^%p)\n",
-        debugstr_w(CabinetFile), Reserved, MsgHandler, Context);
-
-  if (!LoadCABINETDll())
-    return FALSE;
-
-  if (!CabinetFile)
-  {
-    SetLastError(ERROR_INVALID_PARAMETER);
-    return FALSE;
-  }
+    struct iterate_wtoa_ctx ctx = {handler, context};
+    char fileA[MAX_PATH];
 
-  fpnsize = GetFullPathNameW(CabinetFile, MAX_PATH, pszCabPathW, &p);
-  if (fpnsize > MAX_PATH) {
-    SetLastError(ERROR_BAD_PATHNAME);
-    return FALSE;
-  }
+    if (!WideCharToMultiByte(CP_ACP, 0, fileW, -1, fileA, ARRAY_SIZE(fileA), NULL, NULL))
+        return FALSE;
 
-  if (p) {
-    lstrcpyW(my_hsc.most_recent_cabinet_name, p);
-    *p = 0;
-    len = WideCharToMultiByte(CP_ACP, 0, pszCabPathW, -1, pszCabPath,
-				MAX_PATH, 0, 0);
-    if (!len) return FALSE;
-  } else {
-    lstrcpyW(my_hsc.most_recent_cabinet_name, CabinetFile);
-    pszCabPath[0] = '\0';
-  }
-
-  len = WideCharToMultiByte(CP_ACP, 0, my_hsc.most_recent_cabinet_name, -1,
-				pszCabinet, MAX_PATH, 0, 0);
-  if (!len) return FALSE;
-
-  TRACE("path: %s, cabfile: %s\n",
-	debugstr_a(pszCabPath), debugstr_a(pszCabinet));
-
-  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);
-
-  sc_FDIDestroy(my_hsc.hfdi);
-  return ret;
+    return SetupIterateCabinetA(fileA, reserved, iterate_wtoa_cb, &ctx);
 }
 
-
 /***********************************************************************
  * DllMain
  *
-- 
2.20.1




More information about the wine-devel mailing list