setupapi: Implement SetupIterateCabinetW() on top of SetupIterateCabinetA().
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
31af1aeb78
commit
85afec5f2d
|
@ -84,16 +84,6 @@ typedef struct {
|
||||||
CHAR most_recent_target[MAX_PATH];
|
CHAR most_recent_target[MAX_PATH];
|
||||||
} SC_HSC_A, *PSC_HSC_A;
|
} 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);
|
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
|
||||||
|
|
||||||
static BOOL LoadCABINETDll(void)
|
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.@)
|
* SetupIterateCabinetA (SETUPAPI.@)
|
||||||
*/
|
*/
|
||||||
|
@ -602,71 +440,111 @@ BOOL WINAPI SetupIterateCabinetA(PCSTR CabinetFile, DWORD Reserved,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct iterate_wtoa_ctx
|
||||||
/***********************************************************************
|
|
||||||
* SetupIterateCabinetW (SETUPAPI.@)
|
|
||||||
*/
|
|
||||||
BOOL WINAPI SetupIterateCabinetW(PCWSTR CabinetFile, DWORD Reserved,
|
|
||||||
PSP_FILE_CALLBACK_W MsgHandler, PVOID Context)
|
|
||||||
{
|
{
|
||||||
CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH];
|
PSP_FILE_CALLBACK_A orig_cb;
|
||||||
UINT len;
|
void *orig_ctx;
|
||||||
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",
|
static UINT WINAPI iterate_wtoa_cb(void *pctx, UINT message, UINT_PTR param1, UINT_PTR param2)
|
||||||
debugstr_w(CabinetFile), Reserved, MsgHandler, Context);
|
{
|
||||||
|
struct iterate_wtoa_ctx *ctx = pctx;
|
||||||
|
|
||||||
if (!LoadCABINETDll())
|
switch (message)
|
||||||
return FALSE;
|
{
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
if (!CabinetFile)
|
MultiByteToWideChar(CP_ACP, 0, infoA->CabinetPath, -1, pathW, ARRAY_SIZE(pathW));
|
||||||
{
|
MultiByteToWideChar(CP_ACP, 0, infoA->CabinetFile, -1, fileW, ARRAY_SIZE(fileW));
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
MultiByteToWideChar(CP_ACP, 0, infoA->DiskName, -1, diskW, ARRAY_SIZE(diskW));
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
fpnsize = GetFullPathNameW(CabinetFile, MAX_PATH, pszCabPathW, &p);
|
if (message == SPFILENOTIFY_CABINETINFO)
|
||||||
if (fpnsize > MAX_PATH) {
|
return ctx->orig_cb(ctx->orig_ctx, message, (UINT_PTR)&infoW, 0);
|
||||||
SetLastError(ERROR_BAD_PATHNAME);
|
else
|
||||||
return FALSE;
|
{
|
||||||
}
|
char *newpathA = (char *)param2;
|
||||||
|
WCHAR newpathW[MAX_PATH] = {0};
|
||||||
|
BOOL ret = ctx->orig_cb(ctx->orig_ctx, message, (UINT_PTR)&infoW, (UINT_PTR)newpathW);
|
||||||
|
|
||||||
if (p) {
|
WideCharToMultiByte(CP_ACP, 0, newpathW, -1, newpathA, MAX_PATH, NULL, NULL);
|
||||||
lstrcpyW(my_hsc.most_recent_cabinet_name, p);
|
return ret;
|
||||||
*p = 0;
|
}
|
||||||
len = WideCharToMultiByte(CP_ACP, 0, pszCabPathW, -1, pszCabPath,
|
}
|
||||||
MAX_PATH, 0, 0);
|
case SPFILENOTIFY_FILEINCABINET:
|
||||||
if (!len) return FALSE;
|
{
|
||||||
} else {
|
FILE_IN_CABINET_INFO_A *infoA = (FILE_IN_CABINET_INFO_A *)param1;
|
||||||
lstrcpyW(my_hsc.most_recent_cabinet_name, CabinetFile);
|
const char *cabA = (const char *)param2;
|
||||||
pszCabPath[0] = '\0';
|
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;
|
||||||
|
|
||||||
len = WideCharToMultiByte(CP_ACP, 0, my_hsc.most_recent_cabinet_name, -1,
|
MultiByteToWideChar(CP_ACP, 0, infoA->NameInCabinet, -1, fileW, ARRAY_SIZE(fileW));
|
||||||
pszCabinet, MAX_PATH, 0, 0);
|
MultiByteToWideChar(CP_ACP, 0, cabA, -1, cabW, ARRAY_SIZE(cabW));
|
||||||
if (!len) return FALSE;
|
|
||||||
|
|
||||||
TRACE("path: %s, cabfile: %s\n",
|
ret = ctx->orig_cb(ctx->orig_ctx, message, (UINT_PTR)&infoW, (UINT_PTR)cabW);
|
||||||
debugstr_a(pszCabPath), debugstr_a(pszCabinet));
|
|
||||||
|
|
||||||
my_hsc.magic = SC_HSC_W_MAGIC;
|
WideCharToMultiByte(CP_ACP, 0, infoW.FullTargetName, -1, infoA->FullTargetName,
|
||||||
my_hsc.msghandler = MsgHandler;
|
ARRAY_SIZE(infoA->FullTargetName), NULL, NULL);
|
||||||
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;
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
ret = sc_FDICopy(my_hsc.hfdi, pszCabinet, pszCabPath, 0, sc_FNNOTIFY_W, NULL, &my_hsc);
|
MultiByteToWideChar(CP_ACP, 0, pathsA->Target, -1, targetW, ARRAY_SIZE(targetW));
|
||||||
|
MultiByteToWideChar(CP_ACP, 0, pathsA->Source, -1, sourceW, ARRAY_SIZE(sourceW));
|
||||||
|
|
||||||
sc_FDIDestroy(my_hsc.hfdi);
|
return ctx->orig_cb(ctx->orig_ctx, message, (UINT_PTR)&pathsW, 0);
|
||||||
return ret;
|
}
|
||||||
|
default:
|
||||||
|
FIXME("Unexpected callback %#x.\n", message);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupIterateCabinetW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupIterateCabinetW(const WCHAR *fileW, DWORD reserved,
|
||||||
|
PSP_FILE_CALLBACK_W handler, void *context)
|
||||||
|
{
|
||||||
|
struct iterate_wtoa_ctx ctx = {handler, context};
|
||||||
|
char fileA[MAX_PATH];
|
||||||
|
|
||||||
|
if (!WideCharToMultiByte(CP_ACP, 0, fileW, -1, fileA, ARRAY_SIZE(fileA), NULL, NULL))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return SetupIterateCabinetA(fileA, reserved, iterate_wtoa_cb, &ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* DllMain
|
* DllMain
|
||||||
|
|
Loading…
Reference in New Issue