diff --git a/dll/win32/setupapi/queue.c b/dll/win32/setupapi/queue.c index 80b2c03c4e4..cba3bba0803 100644 --- a/dll/win32/setupapi/queue.c +++ b/dll/win32/setupapi/queue.c @@ -44,20 +44,24 @@ struct default_callback_context DWORD_PTR unk3[5]; }; +struct source_media +{ + WCHAR root[MAX_PATH]; + WCHAR *desc, *tag; +}; + struct file_op { struct file_op *next; UINT style; - WCHAR *src_root; WCHAR *src_path; WCHAR *src_file; - WCHAR *src_descr; - WCHAR *src_tag; WCHAR *dst_path; WCHAR *dst_file; #ifdef __REACTOS__ PSECURITY_DESCRIPTOR dst_sd; #endif + struct source_media *media; }; struct file_op_queue @@ -72,7 +76,9 @@ struct file_queue struct file_op_queue copy_queue; struct file_op_queue delete_queue; struct file_op_queue rename_queue; - DWORD flags; + DWORD flags; + struct source_media **sources; + unsigned int source_count; }; @@ -93,11 +99,8 @@ static void free_file_op_queue( struct file_op_queue *queue ) while( op ) { - HeapFree( GetProcessHeap(), 0, op->src_root ); HeapFree( GetProcessHeap(), 0, op->src_path ); HeapFree( GetProcessHeap(), 0, op->src_file ); - HeapFree( GetProcessHeap(), 0, op->src_descr ); - HeapFree( GetProcessHeap(), 0, op->src_tag ); HeapFree( GetProcessHeap(), 0, op->dst_path ); #ifdef __REACTOS__ if (op->dst_sd) LocalFree(op->dst_sd); @@ -144,7 +147,7 @@ static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths ) unsigned int src_len = 1, dst_len = 1; WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target; - if (op->src_root) src_len += strlenW(op->src_root) + 1; + if (op->media) src_len += strlenW(op->media->root) + 1; if (op->src_path) src_len += strlenW(op->src_path) + 1; if (op->src_file) src_len += strlenW(op->src_file) + 1; if (op->dst_path) dst_len += strlenW(op->dst_path) + 1; @@ -163,7 +166,7 @@ static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths ) paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len ); } if (!source || !target) return FALSE; - concat_W( source, op->src_root, op->src_path, op->src_file ); + concat_W( source, op->media ? op->media->root : NULL, op->src_path, op->src_file ); concat_W( target, NULL, op->dst_path, op->dst_file ); paths->Win32Error = 0; paths->Flags = 0; @@ -504,10 +507,18 @@ HSPFILEQ WINAPI SetupOpenFileQueue(void) BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle ) { struct file_queue *queue = handle; + unsigned int i; free_file_op_queue( &queue->copy_queue ); free_file_op_queue( &queue->rename_queue ); free_file_op_queue( &queue->delete_queue ); + for (i = 0; i < queue->source_count; ++i) + { + heap_free( queue->sources[i]->desc ); + heap_free( queue->sources[i]->tag ); + heap_free( queue->sources[i] ); + } + heap_free( queue->sources ); HeapFree( GetProcessHeap(), 0, queue ); return TRUE; } @@ -547,22 +558,48 @@ BOOL WINAPI SetupQueueCopyIndirectA( SP_FILE_COPY_PARAMS_A *paramsA ) return ret; } +static BOOL equal_str(const WCHAR *a, const WCHAR *b) +{ + return (!a && !b) || (a && b && !strcmpW(a, b)); +} + +static struct source_media *get_source_media(struct file_queue *queue, + const WCHAR *root, const WCHAR *desc, const WCHAR *tag) +{ + unsigned int i; + + for (i = 0; i < queue->source_count; ++i) + { + if (!strcmpW(root, queue->sources[i]->root) + && equal_str(desc, queue->sources[i]->desc) + && equal_str(tag, queue->sources[i]->tag)) + { + return queue->sources[i]; + } + } + + queue->sources = heap_realloc( queue->sources, ++queue->source_count * sizeof(*queue->sources) ); + queue->sources[i] = heap_alloc( sizeof(*queue->sources[i]) ); + strcpyW(queue->sources[i]->root, root); + queue->sources[i]->desc = strdupW(desc); + queue->sources[i]->tag = strdupW(tag); + + return queue->sources[i]; +} /*********************************************************************** * SetupQueueCopyIndirectW (SETUPAPI.@) */ BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params ) { + static const WCHAR emptyW[] = {0}; struct file_queue *queue = params->QueueHandle; struct file_op *op; if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; op->style = params->CopyStyle; - op->src_root = strdupW( params->SourceRootPath ); op->src_path = strdupW( params->SourcePath ); op->src_file = strdupW( params->SourceFilename ); - op->src_descr = strdupW( params->SourceDescription ); - op->src_tag = strdupW( params->SourceTagfile ); op->dst_path = strdupW( params->TargetDirectory ); op->dst_file = strdupW( params->TargetFilename ); #ifdef __REACTOS__ @@ -583,10 +620,13 @@ BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params ) FIXME("Unhandled LayoutInf %p.\n", params->LayoutInf); #endif + op->media = get_source_media( queue, params->SourceRootPath ? params->SourceRootPath : emptyW, + params->SourceDescription, params->SourceTagfile ); + 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->media->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) ); + debugstr_w(op->media->desc), debugstr_w(op->media->tag) ); queue_file_op( &queue->copy_queue, op ); return TRUE; @@ -718,18 +758,9 @@ BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 ) struct file_queue *queue = handle; struct file_op *op; - if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; - op->style = 0; - op->src_root = NULL; - op->src_path = NULL; - op->src_file = NULL; - op->src_descr = NULL; - op->src_tag = NULL; - op->dst_path = strdupAtoW( part1 ); - op->dst_file = strdupAtoW( part2 ); -#ifdef __REACTOS__ - op->dst_sd = NULL; -#endif + if (!(op = heap_alloc_zero( sizeof(*op) ))) return FALSE; + op->dst_path = strdupAtoW( part1 ); + op->dst_file = strdupAtoW( part2 ); queue_file_op( &queue->delete_queue, op ); return TRUE; } @@ -743,18 +774,9 @@ BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 ) struct file_queue *queue = handle; struct file_op *op; - if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; - op->style = 0; - op->src_root = NULL; - op->src_path = NULL; - op->src_file = NULL; - op->src_descr = NULL; - op->src_tag = NULL; - op->dst_path = strdupW( part1 ); - op->dst_file = strdupW( part2 ); -#ifdef __REACTOS__ - op->dst_sd = NULL; -#endif + if (!(op = heap_alloc_zero( sizeof(*op) ))) return FALSE; + op->dst_path = strdupW( part1 ); + op->dst_file = strdupW( part2 ); queue_file_op( &queue->delete_queue, op ); return TRUE; } @@ -769,18 +791,11 @@ BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFi struct file_queue *queue = handle; struct file_op *op; - if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; - op->style = 0; - op->src_root = NULL; - op->src_path = strdupAtoW( SourcePath ); - op->src_file = strdupAtoW( SourceFilename ); - op->src_descr = NULL; - op->src_tag = NULL; - op->dst_path = strdupAtoW( TargetPath ); - op->dst_file = strdupAtoW( TargetFilename ); -#ifdef __REACTOS__ - op->dst_sd = NULL; -#endif + if (!(op = heap_alloc_zero( sizeof(*op) ))) return FALSE; + op->src_path = strdupAtoW( SourcePath ); + op->src_file = strdupAtoW( SourceFilename ); + op->dst_path = strdupAtoW( TargetPath ); + op->dst_file = strdupAtoW( TargetFilename ); queue_file_op( &queue->rename_queue, op ); return TRUE; } @@ -795,18 +810,11 @@ BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR Source struct file_queue *queue = handle; struct file_op *op; - if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; - op->style = 0; - op->src_root = NULL; - op->src_path = strdupW( SourcePath ); - op->src_file = strdupW( SourceFilename ); - op->src_descr = NULL; - op->src_tag = NULL; - op->dst_path = strdupW( TargetPath ); - op->dst_file = strdupW( TargetFilename ); -#ifdef __REACTOS__ - op->dst_sd = NULL; -#endif + if (!(op = heap_alloc_zero( sizeof(*op) ))) return FALSE; + op->src_path = strdupW( SourcePath ); + op->src_file = strdupW( SourceFilename ); + op->dst_path = strdupW( TargetPath ); + op->dst_file = strdupW( TargetFilename ); queue_file_op( &queue->rename_queue, op ); return TRUE; } @@ -1473,6 +1481,24 @@ BOOL WINAPI SetupInstallFileW( HINF hinf, PINFCONTEXT inf_context, PCWSTR source return SetupInstallFileExW( hinf, inf_context, source, root, dest, style, handler, context, NULL ); } +static BOOL queue_copy_file( const WCHAR *source, const WCHAR *dest, + const struct file_op *op, PSP_FILE_CALLBACK_W handler, void *context ) +{ + TRACE("copying file %s -> %s\n", debugstr_w(source), debugstr_w(dest)); + + if (op->dst_path && !create_full_pathW(op->dst_path)) + return FALSE; + + if (do_file_copyW(source, dest, op->style, handler, context)) + return TRUE; + + /* try to extract it from the cabinet file */ + if (op->media->tag && extract_cabinet_file(op->media->tag, op->media->root, op->src_file, dest)) + return TRUE; + + return FALSE; +} + /*********************************************************************** * SetupCommitFileQueueW (SETUPAPI.@) */ @@ -1557,27 +1583,10 @@ BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBAC if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT; while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH) { - TRACE( "copying file %s -> %s\n", - debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ), - debugstr_w(paths.Target) ); - if (op->dst_path) - { - if (!create_full_pathW( op->dst_path )) - { - paths.Win32Error = GetLastError(); - op_result = handler( context, SPFILENOTIFY_COPYERROR, - (UINT_PTR)&paths, (UINT_PTR)newpath ); - if (op_result == FILEOP_ABORT) goto done; - } - } - if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source, - paths.Target, op->style, handler, context )) break; /* success */ - /* try to extract it from the cabinet file */ - if (op->src_tag) - { - if (extract_cabinet_file( op->src_tag, op->src_root, - op->src_file, paths.Target )) break; - } + if (queue_copy_file( op_result == FILEOP_NEWPATH ? newpath : paths.Source, + paths.Target, op, handler, context )) + break; + paths.Win32Error = GetLastError(); op_result = handler( context, SPFILENOTIFY_COPYERROR, (UINT_PTR)&paths, (UINT_PTR)newpath ); diff --git a/sdk/tools/winesync/setupapi.cfg b/sdk/tools/winesync/setupapi.cfg index af1f5831a0e..c48c1c2d795 100644 --- a/sdk/tools/winesync/setupapi.cfg +++ b/sdk/tools/winesync/setupapi.cfg @@ -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: ee36f923c59d9ba51b429247df90e0ed30592e62 + wine: 31bb0097ad85090b1e006ade020c68aa5582dc0c