[WINESYNC] setupapi: Handle NULL source filename in build_filepathsW.

Source filename is NULL for files to be deleted.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id fac1e40aaf0726a3e328a922cb496927548190cf by Hans Leidekker <hans@codeweavers.com>

[WINESYNC] setupapi: Implement SetupIterateCabinetW() on top of SetupIterateCabinetA().

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 85afec5f2d09286d835c69bcc519780f6c103f22 by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi: Link directly to cabinet.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id ad59a006ac9839c8bd29e4c4c6b80e6fc736136d by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi: Remove some superfluous traces.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 0b4d3dc2e8d4097997e69dd27ede7bbd8d92af05 by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi: Remove unnecessary error handling from cabinet callbacks.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 6b248f788c251223e2b7123cad90a25f55e13337 by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi: Make the FDI handle a local variable.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id b70b153c59e2aa9365beecc94ef63f6fefb19b9f by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi/tests: Expand tests for SetupIterateCabinet().

Partially based on a patch by Sebastian Lackner.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 978cc1d856c7f62191bf6b1b64ddecf737ea5eea by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi: Set the CabinetFile field to the name of the next cabinet.

Verified through manual testing.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 811da7bf1a37fc4e3851971a7e96e28b445efebc by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi: Set the Source field to the full cabinet path for SPFILENOTIFY_FILEEXTRACTED.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id b67deb0d2f03f7963f3247e4a4477b668a7ace35 by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi: Pass the full cabinet path as the second parameter to SPFILENOTIFY_FILEINCABINET.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 8cb6e9585eefd4b0c0257f549d738f6a10f0d097 by Zebediah Figura <z.figura12@gmail.com>
This commit is contained in:
winesync 2023-10-02 22:16:56 +02:00 committed by Hermès Bélusca-Maïto
parent e1e06fef84
commit e96236418f
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
5 changed files with 367 additions and 484 deletions

View file

@ -41,7 +41,7 @@ add_library(setupapi MODULE
set_module_type(setupapi win32dll UNICODE)
target_link_libraries(setupapi uuid wine ${PSEH_LIB} oldnames)
add_delay_importlibs(setupapi comdlg32 shell32 winspool.drv wintrust)
add_delay_importlibs(setupapi cabinet comdlg32 shell32 winspool.drv wintrust)
add_importlibs(setupapi gdi32 comctl32 advapi32 user32 rpcrt4 version msvcrt kernel32 ntdll)
add_pch(setupapi setupapi_private.h "${PCH_SKIP_SOURCE}")
add_cd_file(TARGET setupapi DESTINATION reactos/system32 FOR all)

View file

@ -151,7 +151,7 @@ static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths )
WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target;
#ifdef __WINESRC__
if (op->src_file[0] != '@')
if (!op->src_file || op->src_file[0] != '@')
#endif
{
if (op->media) src_len += lstrlenW(op->media->root) + 1;
@ -175,7 +175,7 @@ static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths )
}
if (!source || !target) return FALSE;
#ifdef __WINESRC__
if (op->src_file[0] != '@')
if (!op->src_file || op->src_file[0] != '@')
#endif
concat_W( source, op->media ? op->media->root : NULL, op->src_path, op->src_file );
#ifdef __WINESRC__

View file

@ -16,11 +16,6 @@
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
*
* Many useful traces are commented in code, uncomment them if you have
* trouble and run with WINEDEBUG=+setupapi
*
*/
#include "setupapi_private.h"
@ -32,54 +27,14 @@
HINSTANCE SETUPAPI_hInstance = NULL;
OSVERSIONINFOEXW OsVersionInfo;
static HINSTANCE CABINET_hInstance = NULL;
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];
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;
static BOOL LoadCABINETDll(void)
typedef struct
{
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;
}
/* FDICreate callbacks */
PSP_FILE_CALLBACK_A msghandler;
void *context;
char cab_path[MAX_PATH];
char last_cab[MAX_PATH];
char most_recent_target[MAX_PATH];
} SC_HSC_A, *PSC_HSC_A;
static void * CDECL sc_cb_alloc(ULONG cb)
{
@ -95,11 +50,8 @@ static INT_PTR CDECL 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;
@ -110,9 +62,6 @@ static INT_PTR CDECL sc_cb_open(char *pszFile, int oflag, int pmode)
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) {
@ -122,7 +71,7 @@ static INT_PTR CDECL sc_cb_open(char *pszFile, int oflag, int pmode)
creation = CREATE_ALWAYS;
else
creation = OPEN_ALWAYS;
} else /* no _O_CREAT */ {
} else {
if (oflag & _O_TRUNC)
creation = TRUNCATE_EXISTING;
else
@ -143,99 +92,58 @@ static INT_PTR CDECL sc_cb_open(char *pszFile, int oflag, int pmode)
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);
ret = (INT_PTR) CreateFileA(pszFile, ioflag, sharing, &sa, creation, FILE_ATTRIBUTE_NORMAL, NULL);
/* TRACE("<-- %d\n", ret); */
return ret;
return (INT_PTR) CreateFileA(pszFile, ioflag, sharing, &sa, creation, FILE_ATTRIBUTE_NORMAL, NULL);
}
static UINT CDECL sc_cb_read(INT_PTR hf, void *pv, UINT cb)
{
DWORD num_read;
BOOL rslt;
DWORD num_read;
/* 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;
if (!ReadFile((HANDLE)hf, pv, cb, &num_read, NULL))
return -1;
return num_read;
}
static UINT CDECL sc_cb_write(INT_PTR hf, void *pv, UINT cb)
{
DWORD num_written;
/* BOOL rv; */
DWORD num_written;
/* 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); */
if (!WriteFile((HANDLE)hf, pv, cb, &num_written, NULL))
return -1;
return num_written;
} else {
/* TRACE("rv == %d, num_written == %lu, cb == %u\n", rv, num_written,cb); */
/* TRACE("<-- -1\n"); */
return -1;
}
}
static int CDECL sc_cb_close(INT_PTR hf)
{
/* TRACE("(hf == %d)\n", hf); */
if (CloseHandle((HANDLE) hf))
if (!CloseHandle((HANDLE)hf))
return -1;
return 0;
else
return -1;
}
static LONG CDECL sc_cb_lseek(INT_PTR hf, LONG dist, int seektype)
{
DWORD ret;
DWORD ret;
/* TRACE("(hf == %d, dist == %ld, seektype == %d)\n", hf, dist, seektype); */
if (seektype < 0 || seektype > 2)
return -1;
if (seektype < 0 || seektype > 2)
return -1;
if (((ret = SetFilePointer((HANDLE) hf, dist, NULL, seektype)) != INVALID_SET_FILE_POINTER) || !GetLastError()) {
/* TRACE("<-- %lu\n", ret); */
if (((ret = SetFilePointer((HANDLE)hf, dist, NULL, seektype)) == INVALID_SET_FILE_POINTER) && GetLastError())
return -1;
return ret;
} else {
/* TRACE("<-- -1\n"); */
return -1;
}
}
#define SIZEOF_MYSTERIO (MAX_PATH*3)
/* FDICopy callbacks */
static INT_PTR CDECL sc_FNNOTIFY_A(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
{
FILE_IN_CABINET_INFO_A fici;
PSC_HSC_A phsc;
PSC_HSC_A phsc = pfdin->pv;
CABINET_INFO_A ci;
FILEPATHS_A fp;
UINT err;
@ -244,25 +152,11 @@ static INT_PTR CDECL sc_FNNOTIFY_A(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION p
memset(mysterio, 0, SIZEOF_MYSTERIO);
TRACE("(fdint == %d, pfdin == ^%p)\n", fdint, pfdin);
if (pfdin && pfdin->pv && (((PSC_HSC_A) pfdin->pv)->magic == SC_HSC_A_MAGIC))
phsc = 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;
TRACE("New cabinet, path %s, set %u, number %u, next disk %s, next cabinet %s.\n",
debugstr_a(pfdin->psz3), pfdin->setID, pfdin->iCabinet, debugstr_a(pfdin->psz2), debugstr_a(pfdin->psz1));
ci.CabinetFile = pfdin->psz1;
ci.CabinetPath = pfdin->psz3;
ci.DiskName = pfdin->psz2;
ci.SetId = pfdin->setID;
@ -270,16 +164,10 @@ static INT_PTR CDECL sc_FNNOTIFY_A(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION p
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); */
TRACE("Copy file %s, length %d, date %#x, time %#x, attributes %#x.\n",
debugstr_a(pfdin->psz1), pfdin->cb, pfdin->date, pfdin->time, pfdin->attribs);
fici.NameInCabinet = pfdin->psz1;
fici.FileSize = pfdin->cb;
fici.Win32Error = 0;
@ -288,33 +176,28 @@ static INT_PTR CDECL sc_FNNOTIFY_A(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION p
fici.DosAttribs = pfdin->attribs;
memset(fici.FullTargetName, 0, MAX_PATH);
err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEINCABINET,
(UINT_PTR)&fici, (UINT_PTR)pfdin->psz1);
(UINT_PTR)&fici, (UINT_PTR)phsc->last_cab);
if (err == FILEOP_DOIT) {
TRACE(" Callback specified filename: %s\n", debugstr_a(fici.FullTargetName));
TRACE("Callback specified filename: %s\n", debugstr_a(fici.FullTargetName));
if (!fici.FullTargetName[0]) {
WARN(" Empty return string causing abort.\n");
WARN("Empty return string causing abort.\n");
SetLastError(ERROR_PATH_NOT_FOUND);
return -1;
}
strcpy( phsc->most_recent_target, fici.FullTargetName );
return sc_cb_open(fici.FullTargetName, _O_BINARY | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE);
} else {
TRACE(" Callback skipped file.\n");
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;
TRACE("File extracted.\n");
fp.Source = phsc->last_cab;
fp.Target = phsc->most_recent_target;
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");
if (sc_cb_close(pfdin->hf))
WARN("_close failed.\n");
/* FIXME: set file time and attributes */
sc_cb_close(pfdin->hf);
err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT_PTR)&fp, 0);
if (err) {
SetLastError(err);
@ -322,19 +205,15 @@ static INT_PTR CDECL sc_FNNOTIFY_A(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION p
} 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); */
TRACE("Need new cabinet, path %s, file %s, disk %s, set %u, number %u.\n",
debugstr_a(pfdin->psz3), debugstr_a(pfdin->psz1),
debugstr_a(pfdin->psz2), pfdin->setID, 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, pfdin->psz1);
sprintf(phsc->last_cab, "%s%s", phsc->cab_path, ci.CabinetFile);
err = phsc->msghandler(phsc->context, SPFILENOTIFY_NEEDNEWCABINET, (UINT_PTR)&ci, (UINT_PTR)mysterio);
if (err) {
SetLastError(err);
@ -352,288 +231,186 @@ 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.@)
*/
BOOL WINAPI SetupIterateCabinetA(PCSTR CabinetFile, DWORD Reserved,
PSP_FILE_CALLBACK_A MsgHandler, PVOID Context)
BOOL WINAPI SetupIterateCabinetA(const char *file, DWORD reserved,
PSP_FILE_CALLBACK_A callback, void *context)
{
SC_HSC_A my_hsc;
ERF erf;
CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH], *p = NULL;
DWORD fpnsize;
BOOL ret;
SC_HSC_A my_hsc;
ERF erf;
CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH], *filepart = NULL;
size_t path_size = 0;
const char *p;
DWORD fpnsize;
HFDI hfdi;
BOOL ret;
TRACE("(CabinetFile == %s, Reserved == %u, MsgHandler == ^%p, Context == ^%p)\n",
debugstr_a(CabinetFile), Reserved, MsgHandler, Context);
TRACE("file %s, reserved %#x, callback %p, context %p.\n",
debugstr_a(file), reserved, callback, context);
if (!LoadCABINETDll())
return FALSE;
if (!file)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!CabinetFile)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (strlen(file) >= MAX_PATH)
{
SetLastError(ERROR_BAD_PATHNAME);
return FALSE;
}
fpnsize = strlen(CabinetFile);
if (fpnsize >= MAX_PATH) {
SetLastError(ERROR_BAD_PATHNAME);
return FALSE;
}
fpnsize = GetFullPathNameA(file, MAX_PATH, pszCabPath, &filepart);
if (fpnsize > MAX_PATH)
{
SetLastError(ERROR_BAD_PATHNAME);
return FALSE;
}
fpnsize = GetFullPathNameA(CabinetFile, MAX_PATH, pszCabPath, &p);
if (fpnsize > MAX_PATH) {
SetLastError(ERROR_BAD_PATHNAME);
return FALSE;
}
if (filepart)
{
strcpy(pszCabinet, filepart);
*filepart = '\0';
}
else
{
strcpy(pszCabinet, file);
pszCabPath[0] = '\0';
}
if (p) {
strcpy(pszCabinet, p);
*p = '\0';
} else {
strcpy(pszCabinet, CabinetFile);
pszCabPath[0] = '\0';
}
for (p = file; *p; ++p)
{
if (*p == '/' || *p == '\\')
path_size = p - file;
}
memcpy(my_hsc.cab_path, file, path_size);
my_hsc.cab_path[path_size] = 0;
TRACE("path: %s, cabfile: %s\n", debugstr_a(pszCabPath), debugstr_a(pszCabinet));
TRACE("path: %s, cabfile: %s\n", debugstr_a(pszCabPath), debugstr_a(pszCabinet));
/* remember the cabinet name */
strcpy(my_hsc.most_recent_cabinet_name, pszCabinet);
strcpy(my_hsc.last_cab, file);
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 );
my_hsc.msghandler = callback;
my_hsc.context = context;
hfdi = 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;
if (!hfdi) return FALSE;
ret = sc_FDICopy(my_hsc.hfdi, pszCabinet, pszCabPath, 0, sc_FNNOTIFY_A, NULL, &my_hsc);
ret = FDICopy(hfdi, pszCabinet, pszCabPath, 0, sc_FNNOTIFY_A, NULL, &my_hsc);
sc_FDIDestroy(my_hsc.hfdi);
return ret;
FDIDestroy(hfdi);
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;
struct iterate_wtoa_ctx ctx = {handler, context};
char fileA[MAX_PATH];
TRACE("(CabinetFile == %s, Reserved == %u, MsgHandler == ^%p, Context == ^%p)\n",
debugstr_w(CabinetFile), Reserved, MsgHandler, Context);
if (!WideCharToMultiByte(CP_ACP, 0, fileW, -1, fileA, ARRAY_SIZE(fileA), NULL, NULL))
return FALSE;
if (!LoadCABINETDll())
return FALSE;
if (!CabinetFile)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
fpnsize = GetFullPathNameW(CabinetFile, MAX_PATH, pszCabPathW, &p);
if (fpnsize > MAX_PATH) {
SetLastError(ERROR_BAD_PATHNAME);
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
*
@ -660,7 +437,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
case DLL_PROCESS_DETACH:
if (lpvReserved) break;
SetupCloseLog();
if (CABINET_hInstance) FreeLibrary(CABINET_hInstance);
break;
}

View file

@ -297,108 +297,206 @@ static void test_invalid_callbackW(void)
DeleteFileW(source);
}
static const char *expected_files[] = {"tristram", "wine", "shandy"};
static const struct
{
const char *nameA;
const WCHAR *nameW;
DWORD size;
}
expected_files[] =
{
{"tristram", L"tristram", 10},
{"wine", L"wine", 14},
{"shandy", L"shandy", 8},
};
static UINT CALLBACK simple_callbackA(PVOID Context, UINT Notification,
UINT_PTR Param1, UINT_PTR Param2)
static UINT CALLBACK simple_callbackA(void *context, UINT message, UINT_PTR param1, UINT_PTR param2)
{
static int index;
int *file_count = Context;
int *file_count = context;
switch (Notification)
switch (message)
{
case SPFILENOTIFY_CABINETINFO:
index = 0;
return NO_ERROR;
{
const CABINET_INFO_A *info = (const CABINET_INFO_A *)param1;
char temp[MAX_PATH];
GetTempPathA(ARRAY_SIZE(temp), temp);
ok(!strcmp(info->CabinetPath, temp), "Got path %s.\n", debugstr_a(info->CabinetPath));
ok(!info->CabinetFile[0], "Got file %s.\n", debugstr_a(info->CabinetFile));
ok(!info->DiskName[0], "Got disk name %s.\n", debugstr_a(info->DiskName));
ok(!info->SetId, "Got set ID %#x.\n", info->SetId);
ok(!info->CabinetNumber, "Got cabinet number %u.\n", info->CabinetNumber);
ok(!param2, "Got param2 %#Ix.\n", param2);
return ERROR_SUCCESS;
}
case SPFILENOTIFY_FILEINCABINET:
{
FILE_IN_CABINET_INFO_A *info = (FILE_IN_CABINET_INFO_A *)Param1;
FILE_IN_CABINET_INFO_A *info = (FILE_IN_CABINET_INFO_A *)param1;
char temp[MAX_PATH], path[MAX_PATH];
(*file_count)++;
if (index < ARRAY_SIZE(expected_files))
{
ok(!strcmp(expected_files[index], info->NameInCabinet),
"[%d] Expected file \"%s\", got \"%s\"\n",
index, expected_files[index], info->NameInCabinet);
index++;
return FILEOP_SKIP;
}
else
{
ok(0, "Unexpectedly enumerated more than number of files in cabinet, index = %d\n", index);
return FILEOP_ABORT;
}
ok(index < ARRAY_SIZE(expected_files), "%u: Got unexpected file.\n", index);
ok(!strcmp(info->NameInCabinet, expected_files[index].nameA),
"%u: Got file name %s.\n", index, debugstr_a(info->NameInCabinet));
ok(info->FileSize == expected_files[index].size, "%u: Got file size %u.\n", index, info->FileSize);
ok(!info->Win32Error, "%u: Got error %u.\n", index, info->Win32Error);
ok(info->DosDate == 14545, "%u: Got date %u.\n", index, info->DosDate);
ok(info->DosTime == 18672, "%u: Got time %u.\n", index, info->DosTime);
ok(info->DosAttribs == FILE_ATTRIBUTE_ARCHIVE, "%u: Got attributes %#x.\n", index, info->DosAttribs);
GetTempPathA(ARRAY_SIZE(temp), temp);
snprintf(path, ARRAY_SIZE(path), "%s/./testcab.cab", temp);
ok(!strcmp((const char *)param2, path), "%u: Got file name %s.\n",
index, debugstr_a((const char *)param2));
snprintf(info->FullTargetName, ARRAY_SIZE(info->FullTargetName),
"%s\\%s", temp, expected_files[index].nameA);
return FILEOP_DOIT;
}
case SPFILENOTIFY_FILEEXTRACTED:
{
const FILEPATHS_A *info = (const FILEPATHS_A *)param1;
char temp[MAX_PATH], path[MAX_PATH];
GetTempPathA(ARRAY_SIZE(temp), temp);
ok(index < ARRAY_SIZE(expected_files), "%u: Got unexpected file.\n", index);
snprintf(path, ARRAY_SIZE(path), "%s/./testcab.cab", temp);
ok(!strcmp(info->Source, path), "%u: Got source %s.\n", index, debugstr_a(info->Source));
snprintf(path, ARRAY_SIZE(path), "%s\\%s", temp, expected_files[index].nameA);
ok(!strcmp(info->Target, path), "%u: Got target %s.\n", index, debugstr_a(info->Target));
ok(!info->Win32Error, "%u: Got error %u.\n", index, info->Win32Error);
/* info->Flags seems to contain garbage. */
ok(!param2, "Got param2 %#Ix.\n", param2);
++index;
return ERROR_SUCCESS;
}
default:
return NO_ERROR;
ok(0, "Unexpected message %#x.\n", message);
return ERROR_CALL_NOT_IMPLEMENTED;
}
}
static void test_simple_enumerationA(void)
{
BOOL ret;
char source[MAX_PATH], temp[MAX_PATH];
int enum_count = 0;
char temp[MAX_PATH], path[MAX_PATH];
unsigned int enum_count = 0, i;
GetTempPathA(sizeof(temp), temp);
GetTempFileNameA(temp, "doc", 0, source);
ret = SetupIterateCabinetA(NULL, 0, NULL, NULL);
if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
win_skip("SetupIterateCabinetW is not available\n");
return;
}
create_source_fileA(source, comp_cab_zip_multi, sizeof(comp_cab_zip_multi));
GetTempPathA(ARRAY_SIZE(temp), temp);
snprintf(path, ARRAY_SIZE(path), "%s/./testcab.cab", temp);
ret = SetupIterateCabinetA(source, 0, simple_callbackA, &enum_count);
ok(ret == 1, "Expected SetupIterateCabinetA to return 1, got %d\n", ret);
create_source_fileA(path, comp_cab_zip_multi, sizeof(comp_cab_zip_multi));
ret = SetupIterateCabinetA(path, 0, simple_callbackA, &enum_count);
ok(ret == 1, "Expected SetupIterateCabinetW to return 1, got %d\n", ret);
ok(enum_count == ARRAY_SIZE(expected_files), "Unexpectedly enumerated %d files\n", enum_count);
DeleteFileA(source);
for (i = 0; i < ARRAY_SIZE(expected_files); ++i)
{
snprintf(path, ARRAY_SIZE(path), "%s\\%s", temp, expected_files[i].nameA);
ret = DeleteFileA(path);
ok(ret, "Failed to delete %s, error %u.\n", debugstr_a(path), GetLastError());
}
snprintf(path, ARRAY_SIZE(path), "%s\\testcab.cab", temp);
ret = DeleteFileA(path);
ok(ret, "Failed to delete %s, error %u.\n", debugstr_a(path), GetLastError());
}
static const WCHAR tristramW[] = {'t','r','i','s','t','r','a','m',0};
static const WCHAR wineW[] = {'w','i','n','e',0};
static const WCHAR shandyW[] = {'s','h','a','n','d','y',0};
static const WCHAR *expected_filesW[] = {tristramW, wineW, shandyW};
static UINT CALLBACK simple_callbackW(PVOID Context, UINT Notification,
UINT_PTR Param1, UINT_PTR Param2)
static UINT CALLBACK simple_callbackW(void *context, UINT message, UINT_PTR param1, UINT_PTR param2)
{
static int index;
int *file_count = Context;
int *file_count = context;
switch (Notification)
switch (message)
{
case SPFILENOTIFY_CABINETINFO:
index = 0;
return NO_ERROR;
{
const CABINET_INFO_W *info = (const CABINET_INFO_W *)param1;
WCHAR temp[MAX_PATH];
GetTempPathW(ARRAY_SIZE(temp), temp);
ok(!wcscmp(info->CabinetPath, temp), "Got path %s.\n", debugstr_w(info->CabinetPath));
ok(!info->CabinetFile[0], "Got file %s.\n", debugstr_w(info->CabinetFile));
ok(!info->DiskName[0], "Got disk name %s.\n", debugstr_w(info->DiskName));
ok(!info->SetId, "Got set ID %#x.\n", info->SetId);
ok(!info->CabinetNumber, "Got cabinet number %u.\n", info->CabinetNumber);
ok(!param2, "Got param2 %#Ix.\n", param2);
return ERROR_SUCCESS;
}
case SPFILENOTIFY_FILEINCABINET:
{
FILE_IN_CABINET_INFO_W *info = (FILE_IN_CABINET_INFO_W *)Param1;
FILE_IN_CABINET_INFO_W *info = (FILE_IN_CABINET_INFO_W *)param1;
WCHAR temp[MAX_PATH], path[MAX_PATH];
(*file_count)++;
if (index < ARRAY_SIZE(expected_filesW))
{
ok(!lstrcmpW(expected_filesW[index], info->NameInCabinet),
"[%d] Expected file %s, got %s\n",
index, wine_dbgstr_w(expected_filesW[index]), wine_dbgstr_w(info->NameInCabinet));
index++;
return FILEOP_SKIP;
}
else
{
ok(0, "Unexpectedly enumerated more than number of files in cabinet, index = %d\n", index);
return FILEOP_ABORT;
}
ok(index < ARRAY_SIZE(expected_files), "%u: Got unexpected file.\n", index);
ok(!wcscmp(info->NameInCabinet, expected_files[index].nameW),
"%u: Got file name %s.\n", index, debugstr_w(info->NameInCabinet));
ok(info->FileSize == expected_files[index].size, "%u: Got file size %u.\n", index, info->FileSize);
ok(!info->Win32Error, "%u: Got error %u.\n", index, info->Win32Error);
ok(info->DosDate == 14545, "%u: Got date %u.\n", index, info->DosDate);
ok(info->DosTime == 18672, "%u: Got time %u.\n", index, info->DosTime);
ok(info->DosAttribs == FILE_ATTRIBUTE_ARCHIVE, "%u: Got attributes %#x.\n", index, info->DosAttribs);
GetTempPathW(ARRAY_SIZE(temp), temp);
swprintf(path, ARRAY_SIZE(path), L"%s/./testcab.cab", temp);
ok(!wcscmp((const WCHAR *)param2, path), "%u: Got file name %s.\n",
index, debugstr_w((const WCHAR *)param2));
swprintf(info->FullTargetName, ARRAY_SIZE(info->FullTargetName),
L"%s\\%s", temp, expected_files[index].nameW);
return FILEOP_DOIT;
}
case SPFILENOTIFY_FILEEXTRACTED:
{
const FILEPATHS_W *info = (const FILEPATHS_W *)param1;
WCHAR temp[MAX_PATH], path[MAX_PATH];
GetTempPathW(ARRAY_SIZE(temp), temp);
ok(index < ARRAY_SIZE(expected_files), "%u: Got unexpected file.\n", index);
swprintf(path, ARRAY_SIZE(path), L"%s/./testcab.cab", temp);
ok(!wcscmp(info->Source, path), "%u: Got source %s.\n", index, debugstr_w(info->Source));
swprintf(path, ARRAY_SIZE(path), L"%s\\%s", temp, expected_files[index].nameW);
ok(!wcscmp(info->Target, path), "%u: Got target %s.\n", index, debugstr_w(info->Target));
ok(!info->Win32Error, "%u: Got error %u.\n", index, info->Win32Error);
/* info->Flags seems to contain garbage. */
ok(!param2, "Got param2 %#Ix.\n", param2);
++index;
return ERROR_SUCCESS;
}
default:
return NO_ERROR;
ok(0, "Unexpected message %#x.\n", message);
return ERROR_CALL_NOT_IMPLEMENTED;
}
}
static void test_simple_enumerationW(void)
{
BOOL ret;
WCHAR source[MAX_PATH], temp[MAX_PATH];
int enum_count = 0;
WCHAR temp[MAX_PATH], path[MAX_PATH];
unsigned int enum_count = 0, i;
ret = SetupIterateCabinetW(NULL, 0, NULL, NULL);
if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
@ -408,15 +506,24 @@ static void test_simple_enumerationW(void)
}
GetTempPathW(ARRAY_SIZE(temp), temp);
GetTempFileNameW(temp, docW, 0, source);
swprintf(path, ARRAY_SIZE(path), L"%s/./testcab.cab", temp);
create_source_fileW(source, comp_cab_zip_multi, sizeof(comp_cab_zip_multi));
create_source_fileW(path, comp_cab_zip_multi, sizeof(comp_cab_zip_multi));
ret = SetupIterateCabinetW(source, 0, simple_callbackW, &enum_count);
ret = SetupIterateCabinetW(path, 0, simple_callbackW, &enum_count);
ok(ret == 1, "Expected SetupIterateCabinetW to return 1, got %d\n", ret);
ok(enum_count == ARRAY_SIZE(expected_files), "Unexpectedly enumerated %d files\n", enum_count);
DeleteFileW(source);
for (i = 0; i < ARRAY_SIZE(expected_files); ++i)
{
swprintf(path, ARRAY_SIZE(path), L"%s\\%s", temp, expected_files[i].nameW);
ret = DeleteFileW(path);
ok(ret, "Failed to delete %s, error %u.\n", debugstr_w(path), GetLastError());
}
swprintf(path, ARRAY_SIZE(path), L"%s\\testcab.cab", temp);
ret = DeleteFileW(path);
ok(ret, "Failed to delete %s, error %u.\n", debugstr_w(path), GetLastError());
}
START_TEST(setupcab)

View file

@ -10,4 +10,4 @@ files:
dlls/setupapi/setupcab.c: dll/win32/setupapi/setupcab.c
dlls/setupapi/stringtable.c: dll/win32/setupapi/stringtable_wine.c
tags:
wine: 5696c3c23d5be9f5ce57ef7e361d88722120da09
wine: 8cb6e9585eefd4b0c0257f549d738f6a10f0d097