Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/setupapi/queue.c | 95 +++++++++++++++++++++++++++++------ dlls/setupapi/tests/install.c | 4 +- 2 files changed, 83 insertions(+), 16 deletions(-)
diff --git a/dlls/setupapi/queue.c b/dlls/setupapi/queue.c index f033ef75da..d9204a48e4 100644 --- a/dlls/setupapi/queue.c +++ b/dlls/setupapi/queue.c @@ -33,9 +33,12 @@ #include "setupapi_private.h" #include "winver.h" #include "wine/debug.h" +#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
+static const WCHAR backslashW[] = {'\',0}; + /* context structure for the default queue callback */ struct default_callback_context { @@ -329,6 +332,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 @@ -742,48 +791,66 @@ 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; INFCONTEXT context; - WCHAR dest[MAX_PATH], src[MAX_PATH], *dest_dir; + SP_FILE_COPY_PARAMS_W params; INT flags; BOOL ret = FALSE;
- 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; + }
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; - params.LayoutInf = hinf; + params.LayoutInf = NULL; params.SecurityDescriptor = NULL;
+ strcpyW( src_root_buffer, src_root ); + if (!hlist) hlist = hinf; if (!hinf) hinf = hlist; if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE; if (!(params.TargetDirectory = dest_dir = get_destination_dir( hinf, section ))) return FALSE; 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); return ret; diff --git a/dlls/setupapi/tests/install.c b/dlls/setupapi/tests/install.c index 7c614c7f90..32002a97b9 100644 --- a/dlls/setupapi/tests/install.c +++ b/dlls/setupapi/tests/install.c @@ -1065,8 +1065,8 @@ static void test_install_files_queue(void) 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"); - todo_wine ok(delete_file("dst/seven.txt"), "Destination file should exist.\n"); - todo_wine ok(delete_file("dst/eight.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);