mirror of
https://github.com/reactos/reactos.git
synced 2025-02-28 19:32:59 +00:00
[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:
parent
e1e06fef84
commit
e96236418f
5 changed files with 367 additions and 484 deletions
|
@ -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)
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue