mirror of
https://github.com/reactos/reactos.git
synced 2025-02-28 19:32:59 +00:00
[WINESYNC] setupapi/tests: Avoid assert().
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org> wine commit id 2d13b6b74cfa4a21f2b575081331619fb6cebfed by Zebediah Figura <z.figura12@gmail.com> [WINESYNC] setupapi/tests: Add some tests for SetupInstallFilesFromInfSection(). Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org> wine commit id 02df7eeb5bbed4f94840cec4cd8c3d0ad3da9eda by Zebediah Figura <z.figura12@gmail.com> [WINESYNC] setupapi: Fill out all source file parameters in SetupQueueCopySection(). Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org> wine commit id f9f25ee227a60c335ea8767e8b09d2f3bc3d53f7 by Zebediah Figura <z.figura12@gmail.com> [WINESYNC] setupapi: Fill out all source file parameters in SetupQueueDefaultCopy(). Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org> wine commit id 705d3eed86f3ff96ee1190dbc694148c21c4939c by Zebediah Figura <z.figura12@gmail.com> [WINESYNC] setupapi: Implement SetupQueueCopyIndirectA() on top of the W variant. Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org> wine commit id 466b80786fbf7ced695358af3ee87302ed00eb1b by Zebediah Figura <z.figura12@gmail.com>
This commit is contained in:
parent
090f1b629b
commit
59c0527690
4 changed files with 482 additions and 68 deletions
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "setupapi_private.h"
|
||||
#include "wine/heap.h"
|
||||
|
||||
#ifdef __REACTOS__
|
||||
#include <aclapi.h>
|
||||
|
@ -29,6 +30,8 @@
|
|||
static const WCHAR DotSecurity[] = {'.','S','e','c','u','r','i','t','y',0};
|
||||
#endif
|
||||
|
||||
static const WCHAR backslashW[] = {'\\',0};
|
||||
|
||||
/* context structure for the default queue callback */
|
||||
struct default_callback_context
|
||||
{
|
||||
|
@ -333,6 +336,52 @@ static void get_src_file_info( HINF hinf, struct file_op *op )
|
|||
if (!op->src_root) op->src_root = PARSER_get_src_root(hinf);
|
||||
}
|
||||
|
||||
static void get_source_info( HINF hinf, const WCHAR *src_file, SP_FILE_COPY_PARAMS_W *params,
|
||||
WCHAR *src_root, WCHAR *src_path)
|
||||
{
|
||||
static const WCHAR SourceDisksNames[] =
|
||||
{'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0};
|
||||
static const WCHAR SourceDisksFiles[] =
|
||||
{'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
|
||||
|
||||
INFCONTEXT file_ctx, disk_ctx;
|
||||
INT id, diskid;
|
||||
DWORD len;
|
||||
|
||||
/* find the SourceDisksFiles entry */
|
||||
if (!SetupFindFirstLineW( hinf, SourceDisksFiles, src_file, &file_ctx )) return;
|
||||
if (!SetupGetIntField( &file_ctx, 1, &diskid )) return;
|
||||
|
||||
/* now find the diskid in the SourceDisksNames section */
|
||||
if (!SetupFindFirstLineW( hinf, SourceDisksNames, NULL, &disk_ctx )) return;
|
||||
for (;;)
|
||||
{
|
||||
if (SetupGetIntField( &disk_ctx, 0, &id ) && (id == diskid)) break;
|
||||
if (!SetupFindNextLine( &disk_ctx, &disk_ctx )) return;
|
||||
}
|
||||
|
||||
if (SetupGetStringFieldW( &disk_ctx, 1, NULL, 0, &len ) && len > sizeof(WCHAR)
|
||||
&& (params->SourceDescription = heap_alloc( len * sizeof(WCHAR) )))
|
||||
SetupGetStringFieldW( &disk_ctx, 1, (WCHAR *)params->SourceDescription, len, NULL );
|
||||
|
||||
if (SetupGetStringFieldW( &disk_ctx, 2, NULL, 0, &len ) && len > sizeof(WCHAR)
|
||||
&& (params->SourceTagfile = heap_alloc( len * sizeof(WCHAR) )))
|
||||
SetupGetStringFieldW( &disk_ctx, 2, (WCHAR *)params->SourceTagfile, len, NULL );
|
||||
|
||||
if (SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len ) && len > sizeof(WCHAR)
|
||||
&& len < MAX_PATH - strlenW( src_root ) - 1)
|
||||
{
|
||||
strcatW( src_root, backslashW );
|
||||
SetupGetStringFieldW( &disk_ctx, 4, src_root + strlenW( src_root ),
|
||||
MAX_PATH - strlenW( src_root ), NULL );
|
||||
}
|
||||
|
||||
if (SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len ) && len > sizeof(WCHAR) && len < MAX_PATH)
|
||||
{
|
||||
SetupGetStringFieldW( &file_ctx, 2, src_path, MAX_PATH, NULL );
|
||||
params->SourcePath = src_path;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_destination_dir
|
||||
|
@ -347,7 +396,7 @@ static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
|
|||
WCHAR systemdir[MAX_PATH], *dir;
|
||||
BOOL ret;
|
||||
|
||||
if (!(ret = SetupFindFirstLineW( hinf, Dest, section, &context )))
|
||||
if (!section || !(ret = SetupFindFirstLineW( hinf, Dest, section, &context )))
|
||||
ret = SetupFindFirstLineW( hinf, Dest, Def, &context );
|
||||
|
||||
if (ret && (dir = PARSER_get_dest_dir( &context )))
|
||||
|
@ -466,39 +515,35 @@ BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle )
|
|||
/***********************************************************************
|
||||
* SetupQueueCopyIndirectA (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params )
|
||||
BOOL WINAPI SetupQueueCopyIndirectA( SP_FILE_COPY_PARAMS_A *paramsA )
|
||||
{
|
||||
struct file_queue *queue = params->QueueHandle;
|
||||
struct file_op *op;
|
||||
SP_FILE_COPY_PARAMS_W paramsW;
|
||||
BOOL ret;
|
||||
|
||||
if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
|
||||
op->style = params->CopyStyle;
|
||||
op->src_root = strdupAtoW( params->SourceRootPath );
|
||||
op->src_path = strdupAtoW( params->SourcePath );
|
||||
op->src_file = strdupAtoW( params->SourceFilename );
|
||||
op->src_descr = strdupAtoW( params->SourceDescription );
|
||||
op->src_tag = strdupAtoW( params->SourceTagfile );
|
||||
op->dst_path = strdupAtoW( params->TargetDirectory );
|
||||
op->dst_file = strdupAtoW( params->TargetFilename );
|
||||
#ifdef __REACTOS__
|
||||
op->dst_sd = NULL;
|
||||
#endif
|
||||
paramsW.cbSize = sizeof(paramsW);
|
||||
paramsW.QueueHandle = paramsA->QueueHandle;
|
||||
paramsW.SourceRootPath = strdupAtoW( paramsA->SourceRootPath );
|
||||
paramsW.SourcePath = strdupAtoW( paramsA->SourcePath );
|
||||
paramsW.SourceFilename = strdupAtoW( paramsA->SourceFilename );
|
||||
paramsW.SourceDescription = strdupAtoW( paramsA->SourceDescription );
|
||||
paramsW.SourceTagfile = strdupAtoW( paramsA->SourceTagfile );
|
||||
paramsW.TargetDirectory = strdupAtoW( paramsA->TargetDirectory );
|
||||
paramsW.TargetFilename = strdupAtoW( paramsA->TargetFilename );
|
||||
paramsW.CopyStyle = paramsA->CopyStyle;
|
||||
paramsW.LayoutInf = paramsA->LayoutInf;
|
||||
paramsW.SecurityDescriptor = strdupAtoW( paramsA->SecurityDescriptor );
|
||||
|
||||
/* some defaults */
|
||||
if (!op->src_file) op->src_file = op->dst_file;
|
||||
if (params->LayoutInf)
|
||||
{
|
||||
get_src_file_info( params->LayoutInf, op );
|
||||
if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
|
||||
}
|
||||
ret = SetupQueueCopyIndirectW( ¶msW );
|
||||
|
||||
TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
|
||||
debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
|
||||
debugstr_w(op->dst_path), debugstr_w(op->dst_file),
|
||||
debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
|
||||
|
||||
queue_file_op( &queue->copy_queue, op );
|
||||
return TRUE;
|
||||
heap_free( (WCHAR *)paramsW.SourceRootPath );
|
||||
heap_free( (WCHAR *)paramsW.SourcePath );
|
||||
heap_free( (WCHAR *)paramsW.SourceFilename );
|
||||
heap_free( (WCHAR *)paramsW.SourceDescription );
|
||||
heap_free( (WCHAR *)paramsW.SourceTagfile );
|
||||
heap_free( (WCHAR *)paramsW.TargetDirectory );
|
||||
heap_free( (WCHAR *)paramsW.TargetFilename );
|
||||
heap_free( (WCHAR *)paramsW.SecurityDescriptor );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -596,24 +641,21 @@ BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, P
|
|||
/***********************************************************************
|
||||
* SetupQueueDefaultCopyA (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file,
|
||||
PCSTR dst_file, DWORD style )
|
||||
BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, const char *src_rootA,
|
||||
const char *src_fileA, const char *dst_fileA, DWORD style )
|
||||
{
|
||||
SP_FILE_COPY_PARAMS_A params;
|
||||
WCHAR src_rootW[MAX_PATH], src_fileW[MAX_PATH], dst_fileW[MAX_PATH];
|
||||
|
||||
params.cbSize = sizeof(params);
|
||||
params.QueueHandle = queue;
|
||||
params.SourceRootPath = src_root;
|
||||
params.SourcePath = NULL;
|
||||
params.SourceFilename = src_file;
|
||||
params.SourceDescription = NULL;
|
||||
params.SourceTagfile = NULL;
|
||||
params.TargetDirectory = NULL;
|
||||
params.TargetFilename = dst_file;
|
||||
params.CopyStyle = style;
|
||||
params.LayoutInf = hinf;
|
||||
params.SecurityDescriptor = NULL;
|
||||
return SetupQueueCopyIndirectA( ¶ms );
|
||||
if (!src_rootA || !src_fileA || !dst_fileA)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MultiByteToWideChar( CP_ACP, 0, src_rootA, -1, src_rootW, ARRAY_SIZE(src_rootW) );
|
||||
MultiByteToWideChar( CP_ACP, 0, src_fileA, -1, src_fileW, ARRAY_SIZE(src_fileW) );
|
||||
MultiByteToWideChar( CP_ACP, 0, dst_fileA, -1, dst_fileW, ARRAY_SIZE(dst_fileW) );
|
||||
return SetupQueueDefaultCopyW( queue, hinf, src_rootW, src_fileW, dst_fileW, style );
|
||||
}
|
||||
|
||||
|
||||
|
@ -623,21 +665,43 @@ BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, P
|
|||
BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file,
|
||||
PCWSTR dst_file, DWORD style )
|
||||
{
|
||||
WCHAR src_root_buffer[MAX_PATH], src_path[MAX_PATH];
|
||||
SP_FILE_COPY_PARAMS_W params;
|
||||
BOOL ret;
|
||||
|
||||
if (!src_root || !src_file || !dst_file)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
params.cbSize = sizeof(params);
|
||||
params.QueueHandle = queue;
|
||||
params.SourceRootPath = src_root;
|
||||
params.SourceRootPath = src_root_buffer;
|
||||
params.SourcePath = NULL;
|
||||
params.SourceFilename = src_file;
|
||||
params.SourceDescription = NULL;
|
||||
params.SourceTagfile = NULL;
|
||||
params.TargetDirectory = NULL;
|
||||
params.TargetFilename = dst_file;
|
||||
params.CopyStyle = style;
|
||||
#ifdef __REACTOS__
|
||||
params.LayoutInf = hinf;
|
||||
#else
|
||||
params.LayoutInf = NULL;
|
||||
#endif
|
||||
params.SecurityDescriptor = NULL;
|
||||
return SetupQueueCopyIndirectW( ¶ms );
|
||||
|
||||
strcpyW( src_root_buffer, src_root );
|
||||
src_path[0] = 0;
|
||||
if (!(params.TargetDirectory = get_destination_dir( hinf, NULL ))) return FALSE;
|
||||
get_source_info( hinf, src_file, ¶ms, src_root_buffer, src_path );
|
||||
|
||||
ret = SetupQueueCopyIndirectW( ¶ms );
|
||||
|
||||
heap_free( (WCHAR *)params.TargetDirectory );
|
||||
heap_free( (WCHAR *)params.SourceDescription );
|
||||
heap_free( (WCHAR *)params.SourceTagfile );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -773,25 +837,30 @@ BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, H
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetupQueueCopySectionW (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist,
|
||||
PCWSTR section, DWORD style )
|
||||
{
|
||||
SP_FILE_COPY_PARAMS_W params;
|
||||
WCHAR src_root_buffer[MAX_PATH], src_path[MAX_PATH], src_file[MAX_PATH], dst_file[MAX_PATH], *dest_dir;
|
||||
#ifdef __REACTOS__
|
||||
LPWSTR security_key, security_descriptor = NULL;
|
||||
INFCONTEXT security_context;
|
||||
#endif
|
||||
INFCONTEXT context;
|
||||
WCHAR dest[MAX_PATH], src[MAX_PATH], *dest_dir;
|
||||
SP_FILE_COPY_PARAMS_W params;
|
||||
INT flags;
|
||||
BOOL ret;
|
||||
|
||||
TRACE( "hinf=%p/%p section=%s root=%s\n",
|
||||
hinf, hlist, debugstr_w(section), debugstr_w(src_root) );
|
||||
TRACE("queue %p, src_root %s, hinf %p, hlist %p, section %s, style %#x.\n",
|
||||
queue, debugstr_w(src_root), hinf, hlist, debugstr_w(section), style);
|
||||
|
||||
if (!src_root)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef __REACTOS__
|
||||
/* Check for .Security section */
|
||||
|
@ -827,30 +896,47 @@ BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf,
|
|||
|
||||
params.cbSize = sizeof(params);
|
||||
params.QueueHandle = queue;
|
||||
params.SourceRootPath = src_root;
|
||||
params.SourcePath = NULL;
|
||||
params.SourceDescription = NULL;
|
||||
params.SourceTagfile = NULL;
|
||||
params.TargetFilename = dest;
|
||||
params.SourceRootPath = src_root_buffer;
|
||||
params.SourceFilename = src_file;
|
||||
params.TargetFilename = dst_file;
|
||||
params.CopyStyle = style;
|
||||
#ifdef __REACTOS__
|
||||
params.LayoutInf = hinf;
|
||||
#else
|
||||
params.LayoutInf = NULL;
|
||||
#endif
|
||||
params.SecurityDescriptor = security_descriptor;
|
||||
|
||||
strcpyW( src_root_buffer, src_root );
|
||||
|
||||
if (!hlist) hlist = hinf;
|
||||
if (!hinf) hinf = hlist;
|
||||
if (!SetupFindFirstLineW( hlist, section, NULL, &context )) goto done;
|
||||
if (!(params.TargetDirectory = dest_dir = get_destination_dir( hinf, section ))) goto done;
|
||||
do
|
||||
{
|
||||
if (!SetupGetStringFieldW( &context, 1, dest, ARRAY_SIZE( dest ), NULL ))
|
||||
params.SourcePath = NULL;
|
||||
params.SourceDescription = NULL;
|
||||
params.SourceTagfile = NULL;
|
||||
strcpyW( src_root_buffer, src_root );
|
||||
src_path[0] = 0;
|
||||
|
||||
if (!SetupGetStringFieldW( &context, 1, dst_file, ARRAY_SIZE( dst_file ), NULL ))
|
||||
goto end;
|
||||
if (!SetupGetStringFieldW( &context, 2, src, ARRAY_SIZE( src ), NULL )) *src = 0;
|
||||
if (!SetupGetStringFieldW( &context, 2, src_file, ARRAY_SIZE( src_file ), NULL ))
|
||||
strcpyW( src_file, dst_file );
|
||||
|
||||
if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */
|
||||
|
||||
params.SourceFilename = *src ? src : NULL;
|
||||
get_source_info( hinf, src_file, ¶ms, src_root_buffer, src_path );
|
||||
|
||||
if (!SetupQueueCopyIndirectW( ¶ms )) goto end;
|
||||
|
||||
heap_free( (WCHAR *)params.SourceDescription );
|
||||
heap_free( (WCHAR *)params.SourceTagfile );
|
||||
} while (SetupFindNextLine( &context, &context ));
|
||||
ret = TRUE;
|
||||
|
||||
end:
|
||||
HeapFree(GetProcessHeap(), 0, dest_dir);
|
||||
done:
|
||||
|
|
|
@ -20,7 +20,7 @@ list(APPEND SOURCE
|
|||
add_executable(setupapi_winetest ${SOURCE} setupapi.rc)
|
||||
set_module_type(setupapi_winetest win32cui)
|
||||
target_link_libraries(setupapi_winetest uuid)
|
||||
add_importlibs(setupapi_winetest advapi32 setupapi user32 shell32 msvcrt kernel32 ntdll)
|
||||
add_importlibs(setupapi_winetest advapi32 cabinet setupapi user32 shell32 msvcrt kernel32 ntdll)
|
||||
add_rostests_file(TARGET setupapi_winetest)
|
||||
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
|
@ -31,6 +31,7 @@
|
|||
#include "winsvc.h"
|
||||
#include "setupapi.h"
|
||||
#include "shlobj.h"
|
||||
#include "fci.h"
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
|
@ -59,12 +60,231 @@ static void create_inf_file(LPCSTR filename, const char *data)
|
|||
BOOL ret;
|
||||
HANDLE handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
assert(handle != INVALID_HANDLE_VALUE);
|
||||
ok(handle != INVALID_HANDLE_VALUE, "Failed to create %s, error %u.\n", filename, GetLastError());
|
||||
ret = WriteFile(handle, data, strlen(data), &res, NULL);
|
||||
assert(ret != 0);
|
||||
ok(ret, "Failed to write file, error %u.\n", GetLastError());
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
static void create_file(const char *filename)
|
||||
{
|
||||
create_inf_file(filename, "dummy");
|
||||
}
|
||||
|
||||
static BOOL delete_file(const char *filename)
|
||||
{
|
||||
if (GetFileAttributesA(filename) & FILE_ATTRIBUTE_DIRECTORY)
|
||||
return RemoveDirectoryA(filename);
|
||||
else
|
||||
return DeleteFileA(filename);
|
||||
}
|
||||
|
||||
static BOOL file_exists(const char *path)
|
||||
{
|
||||
return GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
static void * CDECL mem_alloc(ULONG cb)
|
||||
{
|
||||
return HeapAlloc(GetProcessHeap(), 0, cb);
|
||||
}
|
||||
|
||||
static void CDECL mem_free(void *memory)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, memory);
|
||||
}
|
||||
|
||||
static BOOL CDECL get_next_cabinet(PCCAB pccab, ULONG cbPrevCab, void *pv)
|
||||
{
|
||||
sprintf(pccab->szCab, pv, pccab->iCab);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static LONG CDECL progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int CDECL file_placed(PCCAB pccab, char *pszFile, LONG cbFile,
|
||||
BOOL fContinuation, void *pv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT_PTR CDECL fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
|
||||
{
|
||||
HANDLE handle;
|
||||
DWORD dwAccess = 0;
|
||||
DWORD dwShareMode = 0;
|
||||
DWORD dwCreateDisposition = OPEN_EXISTING;
|
||||
|
||||
dwAccess = GENERIC_READ | GENERIC_WRITE;
|
||||
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
|
||||
|
||||
if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
|
||||
dwCreateDisposition = OPEN_EXISTING;
|
||||
else
|
||||
dwCreateDisposition = CREATE_NEW;
|
||||
|
||||
handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
|
||||
dwCreateDisposition, 0, NULL);
|
||||
|
||||
ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
|
||||
|
||||
return (INT_PTR)handle;
|
||||
}
|
||||
|
||||
static UINT CDECL fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
|
||||
{
|
||||
HANDLE handle = (HANDLE)hf;
|
||||
DWORD dwRead;
|
||||
BOOL res;
|
||||
|
||||
res = ReadFile(handle, memory, cb, &dwRead, NULL);
|
||||
ok(res, "Failed to ReadFile\n");
|
||||
|
||||
return dwRead;
|
||||
}
|
||||
|
||||
static UINT CDECL fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
|
||||
{
|
||||
HANDLE handle = (HANDLE)hf;
|
||||
DWORD dwWritten;
|
||||
BOOL res;
|
||||
|
||||
res = WriteFile(handle, memory, cb, &dwWritten, NULL);
|
||||
ok(res, "Failed to WriteFile\n");
|
||||
|
||||
return dwWritten;
|
||||
}
|
||||
|
||||
static int CDECL fci_close(INT_PTR hf, int *err, void *pv)
|
||||
{
|
||||
HANDLE handle = (HANDLE)hf;
|
||||
ok(CloseHandle(handle), "Failed to CloseHandle\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LONG CDECL fci_seek(INT_PTR hf, LONG dist, int seektype, int *err, void *pv)
|
||||
{
|
||||
HANDLE handle = (HANDLE)hf;
|
||||
DWORD ret;
|
||||
|
||||
ret = SetFilePointer(handle, dist, NULL, seektype);
|
||||
ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int CDECL fci_delete(char *pszFile, int *err, void *pv)
|
||||
{
|
||||
BOOL ret = DeleteFileA(pszFile);
|
||||
ok(ret, "Failed to DeleteFile %s\n", pszFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL CDECL get_temp_file(char *pszTempName, int cbTempName, void *pv)
|
||||
{
|
||||
LPSTR tempname;
|
||||
|
||||
tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
|
||||
GetTempFileNameA(".", "xx", 0, tempname);
|
||||
|
||||
if (tempname && (strlen(tempname) < (unsigned)cbTempName))
|
||||
{
|
||||
lstrcpyA(pszTempName, tempname);
|
||||
HeapFree(GetProcessHeap(), 0, tempname);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, tempname);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static INT_PTR CDECL get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
|
||||
USHORT *pattribs, int *err, void *pv)
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION finfo;
|
||||
FILETIME filetime;
|
||||
HANDLE handle;
|
||||
DWORD attrs;
|
||||
BOOL res;
|
||||
|
||||
handle = CreateFileA(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||
|
||||
ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
|
||||
|
||||
res = GetFileInformationByHandle(handle, &finfo);
|
||||
ok(res, "Expected GetFileInformationByHandle to succeed\n");
|
||||
|
||||
FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
|
||||
FileTimeToDosDateTime(&filetime, pdate, ptime);
|
||||
|
||||
attrs = GetFileAttributesA(pszName);
|
||||
ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
|
||||
|
||||
return (INT_PTR)handle;
|
||||
}
|
||||
|
||||
static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
|
||||
{
|
||||
char path[MAX_PATH];
|
||||
char filename[MAX_PATH];
|
||||
|
||||
lstrcpyA(path, CURR_DIR);
|
||||
lstrcatA(path, "\\");
|
||||
lstrcatA(path, file);
|
||||
|
||||
lstrcpyA(filename, file);
|
||||
|
||||
return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
|
||||
progress, get_open_info, compress);
|
||||
}
|
||||
|
||||
static void create_cab_file(const CHAR *name, const CHAR *files)
|
||||
{
|
||||
CCAB cabParams = {0};
|
||||
LPCSTR ptr;
|
||||
HFCI hfci;
|
||||
ERF erf;
|
||||
BOOL res;
|
||||
|
||||
cabParams.cb = INT_MAX;
|
||||
cabParams.cbFolderThresh = 900000;
|
||||
cabParams.setID = 0xbeef;
|
||||
cabParams.iCab = 1;
|
||||
lstrcpyA(cabParams.szCabPath, CURR_DIR);
|
||||
lstrcatA(cabParams.szCabPath, "\\");
|
||||
lstrcpyA(cabParams.szCab, name);
|
||||
|
||||
hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
|
||||
fci_read, fci_write, fci_close, fci_seek, fci_delete,
|
||||
get_temp_file, &cabParams, NULL);
|
||||
|
||||
ok(hfci != NULL, "Failed to create an FCI context\n");
|
||||
|
||||
ptr = files;
|
||||
while (*ptr)
|
||||
{
|
||||
create_file(ptr);
|
||||
res = add_file(hfci, ptr, tcompTYPE_MSZIP);
|
||||
ok(res, "Failed to add file: %s\n", ptr);
|
||||
res = DeleteFileA(ptr);
|
||||
ok(res, "Failed to delete file %s, error %u\n", ptr, GetLastError());
|
||||
ptr += lstrlenA(ptr) + 1;
|
||||
}
|
||||
|
||||
res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
|
||||
ok(res, "Failed to flush the cabinet\n");
|
||||
|
||||
res = FCIDestroy(hfci);
|
||||
ok(res, "Failed to destroy the cabinet\n");
|
||||
}
|
||||
|
||||
/* CBT hook to ensure a window (e.g., MessageBox) cannot be created */
|
||||
static HHOOK hhook;
|
||||
static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
|
@ -761,6 +981,113 @@ static void test_dirid(void)
|
|||
check_dirid(40, expected);
|
||||
}
|
||||
|
||||
static void test_install_files_queue(void)
|
||||
{
|
||||
static const char inf_data[] = "[Version]\n"
|
||||
"Signature=\"$Chicago$\"\n"
|
||||
"[DefaultInstall]\n"
|
||||
"CopyFiles=files_section\n"
|
||||
"[files_section]\n"
|
||||
"one.txt\n"
|
||||
"two.txt\n"
|
||||
"three.txt\n"
|
||||
"four.txt\n"
|
||||
"five.txt\n"
|
||||
"six.txt\n"
|
||||
"seven.txt\n"
|
||||
"eight.txt\n"
|
||||
"[SourceDisksNames]\n"
|
||||
"1=heis\n"
|
||||
"2=duo,,,alpha\n"
|
||||
"3=treis,treis.cab\n"
|
||||
"4=tessares,tessares.cab,,alpha\n"
|
||||
"[SourceDisksFiles]\n"
|
||||
"one.txt=1\n"
|
||||
"two.txt=1,beta\n"
|
||||
"three.txt=2\n"
|
||||
"four.txt=2,beta\n"
|
||||
"five.txt=3\n"
|
||||
"six.txt=3,beta\n"
|
||||
"seven.txt=4\n"
|
||||
"eight.txt=4,beta\n"
|
||||
"[DestinationDirs]\n"
|
||||
"files_section=40000,dst\n";
|
||||
|
||||
char path[MAX_PATH];
|
||||
HSPFILEQ queue;
|
||||
void *context;
|
||||
HINF hinf;
|
||||
BOOL ret;
|
||||
|
||||
create_inf_file(inffile, inf_data);
|
||||
|
||||
sprintf(path, "%s\\%s", CURR_DIR, inffile);
|
||||
hinf = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
|
||||
ok(hinf != INVALID_HANDLE_VALUE, "Failed to open INF file, error %#x.\n", GetLastError());
|
||||
|
||||
ret = CreateDirectoryA("src", NULL);
|
||||
ok(ret, "Failed to create test directory, error %u.\n", GetLastError());
|
||||
ret = CreateDirectoryA("src/alpha", NULL);
|
||||
ok(ret, "Failed to create test directory, error %u.\n", GetLastError());
|
||||
ret = CreateDirectoryA("src/alpha/beta", NULL);
|
||||
ok(ret, "Failed to create test directory, error %u.\n", GetLastError());
|
||||
ret = CreateDirectoryA("src/beta", NULL);
|
||||
ok(ret, "Failed to create test directory, error %u.\n", GetLastError());
|
||||
ret = SetupSetDirectoryIdA(hinf, 40000, CURR_DIR);
|
||||
ok(ret, "Failed to set directory ID, error %u.\n", GetLastError());
|
||||
|
||||
create_file("src/one.txt");
|
||||
create_file("src/beta/two.txt");
|
||||
create_file("src/alpha/three.txt");
|
||||
create_file("src/alpha/beta/four.txt");
|
||||
create_cab_file("src/treis.cab", "src\\beta\\five.txt\0six.txt\0");
|
||||
create_cab_file("src/alpha/tessares.cab", "seven.txt\0eight.txt\0");
|
||||
|
||||
queue = SetupOpenFileQueue();
|
||||
ok(queue != INVALID_HANDLE_VALUE, "Failed to open queue, error %#x.\n", GetLastError());
|
||||
|
||||
context = SetupInitDefaultQueueCallbackEx(NULL, INVALID_HANDLE_VALUE, 0, 0, 0);
|
||||
ok(!!context, "Failed to create callback context, error %#x.\n", GetLastError());
|
||||
|
||||
ret = SetupInstallFilesFromInfSectionA(hinf, NULL, queue, "DefaultInstall", "src", 0);
|
||||
ok(ret, "Failed to install files, error %#x.\n", GetLastError());
|
||||
|
||||
ok(file_exists("src/one.txt"), "Source file should exist.\n");
|
||||
ok(!file_exists("dst/one.txt"), "Destination file should not exist.\n");
|
||||
|
||||
ret = SetupCommitFileQueueA(NULL, queue, SetupDefaultQueueCallbackA, context);
|
||||
ok(ret, "Failed to commit queue, error %#x.\n", GetLastError());
|
||||
|
||||
ok(file_exists("src/one.txt"), "Source file should exist.\n");
|
||||
ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
|
||||
ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
|
||||
ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
|
||||
ok(delete_file("dst/four.txt"), "Destination file should exist.\n");
|
||||
ok(delete_file("dst/five.txt"), "Destination file should exist.\n");
|
||||
ok(delete_file("dst/six.txt"), "Destination file should exist.\n");
|
||||
ok(delete_file("dst/seven.txt"), "Destination file should exist.\n");
|
||||
ok(delete_file("dst/eight.txt"), "Destination file should exist.\n");
|
||||
|
||||
SetupTermDefaultQueueCallback(context);
|
||||
ret = SetupCloseFileQueue(queue);
|
||||
ok(ret, "Failed to close queue, error %#x.\n", GetLastError());
|
||||
|
||||
SetupCloseInfFile(hinf);
|
||||
delete_file("src/one.txt");
|
||||
delete_file("src/beta/two.txt");
|
||||
delete_file("src/alpha/three.txt");
|
||||
delete_file("src/alpha/beta/four.txt");
|
||||
delete_file("src/treis.cab");
|
||||
delete_file("src/alpha/tessares.cab");
|
||||
delete_file("src/alpha/beta/");
|
||||
delete_file("src/alpha/");
|
||||
delete_file("src/beta/");
|
||||
delete_file("src/");
|
||||
delete_file("dst/");
|
||||
ret = DeleteFileA(inffile);
|
||||
ok(ret, "Failed to delete INF file, error %u.\n", GetLastError());
|
||||
}
|
||||
|
||||
START_TEST(install)
|
||||
{
|
||||
char temp_path[MAX_PATH], prev_path[MAX_PATH];
|
||||
|
@ -777,7 +1104,7 @@ START_TEST(install)
|
|||
|
||||
/* Set CBT hook to disallow MessageBox creation in current thread */
|
||||
hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
|
||||
assert(hhook != 0);
|
||||
ok(!!hhook, "Failed to set hook, error %u.\n", GetLastError());
|
||||
|
||||
test_cmdline();
|
||||
test_registry();
|
||||
|
@ -785,6 +1112,7 @@ START_TEST(install)
|
|||
test_install_svc_from();
|
||||
test_driver_install();
|
||||
test_dirid();
|
||||
test_install_files_queue();
|
||||
|
||||
UnhookWindowsHookEx(hhook);
|
||||
|
||||
|
|
|
@ -8,4 +8,4 @@ files:
|
|||
dlls/setupapi/setupcab.c: dll/win32/setupapi/setupcab.c
|
||||
dlls/setupapi/stringtable.c: dll/win32/setupapi/stringtable_wine.c
|
||||
tags:
|
||||
wine: fccb7552ebe81ea2c0c17bc747a920f90e2537a5
|
||||
wine: 466b80786fbf7ced695358af3ee87302ed00eb1b
|
||||
|
|
Loading…
Reference in a new issue