2 * Setupapi file queue routines
4 * Copyright 2002 Alexandre Julliard for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wine/unicode.h"
33 #include "setupapi_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
39 /* context structure for the default queue callback */
40 struct default_callback_context
69 struct file_op_queue copy_queue;
70 struct file_op_queue delete_queue;
71 struct file_op_queue rename_queue;
76 inline static WCHAR *strdupW( const WCHAR *str )
81 int len = (strlenW(str) + 1) * sizeof(WCHAR);
82 if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( ret, str, len );
88 inline static WCHAR *strdupAtoW( const char *str )
93 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
94 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
95 MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
100 inline static char *strdupWtoA( const WCHAR *str )
105 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
106 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
107 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
112 /* append a file operation to a queue */
113 inline static void queue_file_op( struct file_op_queue *queue, struct file_op *op )
116 if (queue->tail) queue->tail->next = op;
117 else queue->head = op;
122 /* free all the file operations on a given queue */
123 static void free_file_op_queue( struct file_op_queue *queue )
125 struct file_op *t, *op = queue->head;
129 HeapFree( GetProcessHeap(), 0, op->src_root );
130 HeapFree( GetProcessHeap(), 0, op->src_path );
131 HeapFree( GetProcessHeap(), 0, op->src_file );
132 HeapFree( GetProcessHeap(), 0, op->src_descr );
133 HeapFree( GetProcessHeap(), 0, op->src_tag );
134 HeapFree( GetProcessHeap(), 0, op->dst_path );
135 if (op->dst_file != op->src_file) HeapFree( GetProcessHeap(), 0, op->dst_file );
138 HeapFree( GetProcessHeap(), 0, t );
142 /* concat 3 strings to make a path, handling separators correctly */
143 static void concat_W( WCHAR *buffer, const WCHAR *src1, const WCHAR *src2, const WCHAR *src3 )
148 strcpyW( buffer, src1 );
149 buffer += strlenW(buffer );
150 if (buffer[-1] != '\\') *buffer++ = '\\';
151 if (src2) while (*src2 == '\\') src2++;
156 strcpyW( buffer, src2 );
157 buffer += strlenW(buffer );
158 if (buffer[-1] != '\\') *buffer++ = '\\';
159 if (src3) while (*src3 == '\\') src3++;
163 strcpyW( buffer, src3 );
164 buffer += strlenW(buffer );
169 /***********************************************************************
172 * Build a FILEPATHS_W structure for a given file operation.
174 static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths )
176 unsigned int src_len = 1, dst_len = 1;
177 WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target;
179 if (op->src_root) src_len += strlenW(op->src_root) + 1;
180 if (op->src_path) src_len += strlenW(op->src_path) + 1;
181 if (op->src_file) src_len += strlenW(op->src_file) + 1;
182 if (op->dst_path) dst_len += strlenW(op->dst_path) + 1;
183 if (op->dst_file) dst_len += strlenW(op->dst_file) + 1;
184 src_len *= sizeof(WCHAR);
185 dst_len *= sizeof(WCHAR);
187 if (!source || HeapSize( GetProcessHeap(), 0, source ) < src_len )
189 HeapFree( GetProcessHeap(), 0, source );
190 paths->Source = source = HeapAlloc( GetProcessHeap(), 0, src_len );
192 if (!target || HeapSize( GetProcessHeap(), 0, target ) < dst_len )
194 HeapFree( GetProcessHeap(), 0, target );
195 paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len );
197 if (!source || !target) return FALSE;
198 concat_W( source, op->src_root, op->src_path, op->src_file );
199 concat_W( target, NULL, op->dst_path, op->dst_file );
200 paths->Win32Error = 0;
206 /***********************************************************************
207 * QUEUE_callback_WtoA
209 * Map a file callback parameters from W to A and call the A callback.
211 UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification,
212 UINT_PTR param1, UINT_PTR param2 )
214 struct callback_WtoA_context *callback_ctx = context;
215 char buffer[MAX_PATH];
217 UINT_PTR old_param2 = param2;
221 case SPFILENOTIFY_COPYERROR:
222 param2 = (UINT_PTR)&buffer;
224 case SPFILENOTIFY_STARTDELETE:
225 case SPFILENOTIFY_ENDDELETE:
226 case SPFILENOTIFY_DELETEERROR:
227 case SPFILENOTIFY_STARTRENAME:
228 case SPFILENOTIFY_ENDRENAME:
229 case SPFILENOTIFY_RENAMEERROR:
230 case SPFILENOTIFY_STARTCOPY:
231 case SPFILENOTIFY_ENDCOPY:
233 FILEPATHS_W *pathsW = (FILEPATHS_W *)param1;
236 pathsA.Source = strdupWtoA( pathsW->Source );
237 pathsA.Target = strdupWtoA( pathsW->Target );
238 pathsA.Win32Error = pathsW->Win32Error;
239 pathsA.Flags = pathsW->Flags;
240 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
241 (UINT_PTR)&pathsA, param2 );
242 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Source );
243 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Target );
245 if (notification == SPFILENOTIFY_COPYERROR)
246 MultiByteToWideChar( CP_ACP, 0, buffer, -1, (WCHAR *)old_param2, MAX_PATH );
249 case SPFILENOTIFY_STARTREGISTRATION:
250 case SPFILENOTIFY_ENDREGISTRATION:
252 SP_REGISTER_CONTROL_STATUSW *statusW = (SP_REGISTER_CONTROL_STATUSW *)param1;
253 SP_REGISTER_CONTROL_STATUSA statusA;
255 statusA.cbSize = sizeof(statusA);
256 statusA.FileName = strdupWtoA( statusW->FileName );
257 statusA.Win32Error = statusW->Win32Error;
258 statusA.FailureCode = statusW->FailureCode;
259 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
260 (UINT_PTR)&statusA, param2 );
261 HeapFree( GetProcessHeap(), 0, (LPSTR)statusA.FileName );
265 case SPFILENOTIFY_NEEDMEDIA:
266 case SPFILENOTIFY_QUEUESCAN:
267 FIXME("mapping for %d not implemented\n",notification);
268 case SPFILENOTIFY_STARTQUEUE:
269 case SPFILENOTIFY_ENDQUEUE:
270 case SPFILENOTIFY_STARTSUBQUEUE:
271 case SPFILENOTIFY_ENDSUBQUEUE:
273 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, param1, param2 );
280 /***********************************************************************
283 * Retrieve the source file information for a given file.
285 static void get_src_file_info( HINF hinf, struct file_op *op )
287 static const WCHAR SourceDisksNames[] =
288 {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0};
289 static const WCHAR SourceDisksFiles[] =
290 {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
292 INFCONTEXT file_ctx, disk_ctx;
296 /* find the SourceDisksFiles entry */
297 if (!SetupFindFirstLineW( hinf, SourceDisksFiles, op->src_file, &file_ctx ))
299 if ((op->style & (SP_COPY_SOURCE_ABSOLUTE|SP_COPY_SOURCEPATH_ABSOLUTE))) return;
300 /* no specific info, use .inf file source directory */
301 if (!op->src_root) op->src_root = PARSER_get_src_root( hinf );
304 if (!SetupGetIntField( &file_ctx, 1, &diskid )) return;
306 /* now find the diskid in the SourceDisksNames section */
307 if (!SetupFindFirstLineW( hinf, SourceDisksNames, NULL, &disk_ctx )) return;
310 if (SetupGetIntField( &disk_ctx, 0, &id ) && (id == diskid)) break;
311 if (!SetupFindNextLine( &disk_ctx, &disk_ctx )) return;
314 /* and fill in the missing info */
318 if (SetupGetStringFieldW( &disk_ctx, 1, NULL, 0, &len ) &&
319 (op->src_descr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
320 SetupGetStringFieldW( &disk_ctx, 1, op->src_descr, len, NULL );
324 if (SetupGetStringFieldW( &disk_ctx, 2, NULL, 0, &len ) &&
325 (op->src_tag = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
326 SetupGetStringFieldW( &disk_ctx, 2, op->src_tag, len, NULL );
328 if (!op->src_path && !(op->style & SP_COPY_SOURCE_ABSOLUTE))
330 if (!(op->style & SP_COPY_SOURCEPATH_ABSOLUTE))
332 /* retrieve relative path for this disk */
333 if (!SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len )) len = 0;
335 /* retrieve relative path for this file */
336 if (!SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len2 )) len2 = 0;
339 (op->src_path = HeapAlloc( GetProcessHeap(), 0, (len+len2)*sizeof(WCHAR) )))
341 WCHAR *ptr = op->src_path;
344 SetupGetStringFieldW( &disk_ctx, 4, op->src_path, len, NULL );
345 ptr = op->src_path + strlenW(op->src_path);
346 if (len2 && ptr > op->src_path && ptr[-1] != '\\') *ptr++ = '\\';
348 if (!SetupGetStringFieldW( &disk_ctx, 4, ptr, len2, NULL )) *ptr = 0;
351 if (!op->src_root) op->src_root = PARSER_get_src_root(hinf);
355 /***********************************************************************
356 * get_destination_dir
358 * Retrieve the destination dir for a given section.
360 static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
362 static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
363 static const WCHAR Def[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
366 if (!SetupFindFirstLineW( hinf, Dest, section, &context ) &&
367 !SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL;
368 return PARSER_get_dest_dir( &context );
372 static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD );
374 /***********************************************************************
375 * extract_cabinet_file
377 * Extract a file from a .cab file.
379 static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root,
380 const WCHAR *src, const WCHAR *dst )
382 static const WCHAR extW[] = {'.','c','a','b',0};
383 static HMODULE advpack;
385 char *cab_path, *cab_file;
386 int len = strlenW( cabinet );
388 /* make sure the cabinet file has a .cab extension */
389 if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE;
392 if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" )))
394 ERR( "could not load advpack.dll\n" );
397 if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" )))
399 ERR( "could not find ExtractFiles in advpack.dll\n" );
404 if (!(cab_path = strdupWtoA( root ))) return FALSE;
405 len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL );
406 if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 )))
408 HeapFree( GetProcessHeap(), 0, cab_path );
411 strcpy( cab_file, cab_path );
412 if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" );
413 WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL );
414 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) );
415 pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 );
416 HeapFree( GetProcessHeap(), 0, cab_file );
417 HeapFree( GetProcessHeap(), 0, cab_path );
418 return CopyFileW( src, dst, FALSE /*FIXME*/ );
422 /***********************************************************************
423 * SetupOpenFileQueue (SETUPAPI.@)
425 HSPFILEQ WINAPI SetupOpenFileQueue(void)
427 struct file_queue *queue;
429 if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue))))
430 return (HSPFILEQ)INVALID_HANDLE_VALUE;
435 /***********************************************************************
436 * SetupCloseFileQueue (SETUPAPI.@)
438 BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle )
440 struct file_queue *queue = handle;
442 free_file_op_queue( &queue->copy_queue );
443 free_file_op_queue( &queue->rename_queue );
444 free_file_op_queue( &queue->delete_queue );
445 HeapFree( GetProcessHeap(), 0, queue );
450 /***********************************************************************
451 * SetupQueueCopyIndirectA (SETUPAPI.@)
453 BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params )
455 struct file_queue *queue = params->QueueHandle;
458 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
459 op->style = params->CopyStyle;
460 op->src_root = strdupAtoW( params->SourceRootPath );
461 op->src_path = strdupAtoW( params->SourcePath );
462 op->src_file = strdupAtoW( params->SourceFilename );
463 op->src_descr = strdupAtoW( params->SourceDescription );
464 op->src_tag = strdupAtoW( params->SourceTagfile );
465 op->dst_path = strdupAtoW( params->TargetDirectory );
466 op->dst_file = strdupAtoW( params->TargetFilename );
469 if (!op->src_file) op->src_file = op->dst_file;
470 if (params->LayoutInf)
472 get_src_file_info( params->LayoutInf, op );
473 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
476 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
477 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
478 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
479 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
481 queue_file_op( &queue->copy_queue, op );
486 /***********************************************************************
487 * SetupQueueCopyIndirectW (SETUPAPI.@)
489 BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params )
491 struct file_queue *queue = params->QueueHandle;
494 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
495 op->style = params->CopyStyle;
496 op->src_root = strdupW( params->SourceRootPath );
497 op->src_path = strdupW( params->SourcePath );
498 op->src_file = strdupW( params->SourceFilename );
499 op->src_descr = strdupW( params->SourceDescription );
500 op->src_tag = strdupW( params->SourceTagfile );
501 op->dst_path = strdupW( params->TargetDirectory );
502 op->dst_file = strdupW( params->TargetFilename );
505 if (!op->src_file) op->src_file = op->dst_file;
506 if (params->LayoutInf)
508 get_src_file_info( params->LayoutInf, op );
509 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
512 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
513 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
514 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
515 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
517 queue_file_op( &queue->copy_queue, op );
522 /***********************************************************************
523 * SetupQueueCopyA (SETUPAPI.@)
525 BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file,
526 PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file,
529 SP_FILE_COPY_PARAMS_A params;
531 params.cbSize = sizeof(params);
532 params.QueueHandle = queue;
533 params.SourceRootPath = src_root;
534 params.SourcePath = src_path;
535 params.SourceFilename = src_file;
536 params.SourceDescription = src_descr;
537 params.SourceTagfile = src_tag;
538 params.TargetDirectory = dst_dir;
539 params.TargetFilename = dst_file;
540 params.CopyStyle = style;
541 params.LayoutInf = 0;
542 params.SecurityDescriptor = NULL;
543 return SetupQueueCopyIndirectA( ¶ms );
547 /***********************************************************************
548 * SetupQueueCopyW (SETUPAPI.@)
550 BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file,
551 PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file,
554 SP_FILE_COPY_PARAMS_W params;
556 params.cbSize = sizeof(params);
557 params.QueueHandle = queue;
558 params.SourceRootPath = src_root;
559 params.SourcePath = src_path;
560 params.SourceFilename = src_file;
561 params.SourceDescription = src_descr;
562 params.SourceTagfile = src_tag;
563 params.TargetDirectory = dst_dir;
564 params.TargetFilename = dst_file;
565 params.CopyStyle = style;
566 params.LayoutInf = 0;
567 params.SecurityDescriptor = NULL;
568 return SetupQueueCopyIndirectW( ¶ms );
572 /***********************************************************************
573 * SetupQueueDefaultCopyA (SETUPAPI.@)
575 BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file,
576 PCSTR dst_file, DWORD style )
578 SP_FILE_COPY_PARAMS_A params;
580 params.cbSize = sizeof(params);
581 params.QueueHandle = queue;
582 params.SourceRootPath = src_root;
583 params.SourcePath = NULL;
584 params.SourceFilename = src_file;
585 params.SourceDescription = NULL;
586 params.SourceTagfile = NULL;
587 params.TargetDirectory = NULL;
588 params.TargetFilename = dst_file;
589 params.CopyStyle = style;
590 params.LayoutInf = hinf;
591 params.SecurityDescriptor = NULL;
592 return SetupQueueCopyIndirectA( ¶ms );
596 /***********************************************************************
597 * SetupQueueDefaultCopyW (SETUPAPI.@)
599 BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file,
600 PCWSTR dst_file, DWORD style )
602 SP_FILE_COPY_PARAMS_W params;
604 params.cbSize = sizeof(params);
605 params.QueueHandle = queue;
606 params.SourceRootPath = src_root;
607 params.SourcePath = NULL;
608 params.SourceFilename = src_file;
609 params.SourceDescription = NULL;
610 params.SourceTagfile = NULL;
611 params.TargetDirectory = NULL;
612 params.TargetFilename = dst_file;
613 params.CopyStyle = style;
614 params.LayoutInf = hinf;
615 params.SecurityDescriptor = NULL;
616 return SetupQueueCopyIndirectW( ¶ms );
620 /***********************************************************************
621 * SetupQueueDeleteA (SETUPAPI.@)
623 BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 )
625 struct file_queue *queue = handle;
628 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
633 op->src_descr = NULL;
635 op->dst_path = strdupAtoW( part1 );
636 op->dst_file = strdupAtoW( part2 );
637 queue_file_op( &queue->delete_queue, op );
642 /***********************************************************************
643 * SetupQueueDeleteW (SETUPAPI.@)
645 BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 )
647 struct file_queue *queue = handle;
650 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
655 op->src_descr = NULL;
657 op->dst_path = strdupW( part1 );
658 op->dst_file = strdupW( part2 );
659 queue_file_op( &queue->delete_queue, op );
664 /***********************************************************************
665 * SetupQueueRenameA (SETUPAPI.@)
667 BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename,
668 PCSTR TargetPath, PCSTR TargetFilename )
670 struct file_queue *queue = handle;
673 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
676 op->src_path = strdupAtoW( SourcePath );
677 op->src_file = strdupAtoW( SourceFilename );
678 op->src_descr = NULL;
680 op->dst_path = strdupAtoW( TargetPath );
681 op->dst_file = strdupAtoW( TargetFilename );
682 queue_file_op( &queue->rename_queue, op );
687 /***********************************************************************
688 * SetupQueueRenameW (SETUPAPI.@)
690 BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename,
691 PCWSTR TargetPath, PCWSTR TargetFilename )
693 struct file_queue *queue = handle;
696 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
699 op->src_path = strdupW( SourcePath );
700 op->src_file = strdupW( SourceFilename );
701 op->src_descr = NULL;
703 op->dst_path = strdupW( TargetPath );
704 op->dst_file = strdupW( TargetFilename );
705 queue_file_op( &queue->rename_queue, op );
710 /***********************************************************************
711 * SetupQueueCopySectionA (SETUPAPI.@)
713 BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist,
714 PCSTR section, DWORD style )
716 UNICODE_STRING sectionW;
719 if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
721 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
725 ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style );
729 if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root ))
731 ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style );
732 RtlFreeUnicodeString( &srcW );
734 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
736 RtlFreeUnicodeString( §ionW );
741 /***********************************************************************
742 * SetupQueueCopySectionW (SETUPAPI.@)
744 BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist,
745 PCWSTR section, DWORD style )
747 SP_FILE_COPY_PARAMS_W params;
749 WCHAR dest[MAX_PATH], src[MAX_PATH];
752 TRACE( "hinf=%p/%p section=%s root=%s\n",
753 hinf, hlist, debugstr_w(section), debugstr_w(src_root) );
755 params.cbSize = sizeof(params);
756 params.QueueHandle = queue;
757 params.SourceRootPath = src_root;
758 params.SourcePath = NULL;
759 params.SourceDescription = NULL;
760 params.SourceTagfile = NULL;
761 params.TargetFilename = dest;
762 params.CopyStyle = style;
763 params.LayoutInf = hinf;
764 params.SecurityDescriptor = NULL;
766 if (!hlist) hlist = hinf;
767 if (!hinf) hinf = hlist;
768 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
769 if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) return FALSE;
772 if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL ))
774 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0;
775 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */
777 params.SourceFilename = *src ? src : NULL;
778 if (!SetupQueueCopyIndirectW( ¶ms )) return FALSE;
779 } while (SetupFindNextLine( &context, &context ));
784 /***********************************************************************
785 * SetupQueueDeleteSectionA (SETUPAPI.@)
787 BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
789 UNICODE_STRING sectionW;
792 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
794 ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer );
795 RtlFreeUnicodeString( §ionW );
797 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
802 /***********************************************************************
803 * SetupQueueDeleteSectionW (SETUPAPI.@)
805 BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
809 WCHAR buffer[MAX_PATH];
813 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
815 if (!hlist) hlist = hinf;
816 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
817 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
820 if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
822 if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
823 if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done;
824 } while (SetupFindNextLine( &context, &context ));
828 HeapFree( GetProcessHeap(), 0, dest_dir );
833 /***********************************************************************
834 * SetupQueueRenameSectionA (SETUPAPI.@)
836 BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
838 UNICODE_STRING sectionW;
841 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
843 ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer );
844 RtlFreeUnicodeString( §ionW );
846 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
851 /***********************************************************************
852 * SetupQueueRenameSectionW (SETUPAPI.@)
854 BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
858 WCHAR src[MAX_PATH], dst[MAX_PATH];
861 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
863 if (!hlist) hlist = hinf;
864 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
865 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
868 if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL ))
870 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL ))
872 if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done;
873 } while (SetupFindNextLine( &context, &context ));
877 HeapFree( GetProcessHeap(), 0, dest_dir );
882 /***********************************************************************
883 * SetupCommitFileQueueA (SETUPAPI.@)
885 BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler,
888 struct callback_WtoA_context ctx;
890 ctx.orig_context = context;
891 ctx.orig_handler = handler;
892 return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx );
896 /***********************************************************************
899 * Recursively create all directories in the path.
901 static BOOL create_full_pathW(const WCHAR *path)
907 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
908 strcpyW(new_path, path);
910 while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
911 new_path[len - 1] = 0;
913 while(!CreateDirectoryW(new_path, NULL))
916 DWORD last_error = GetLastError();
918 if(last_error == ERROR_ALREADY_EXISTS)
921 if(last_error != ERROR_PATH_NOT_FOUND)
927 if(!(slash = strrchrW(new_path, '\\')))
933 len = slash - new_path;
935 if(!create_full_pathW(new_path))
940 new_path[len] = '\\';
943 HeapFree(GetProcessHeap(), 0, new_path);
947 static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style,
948 PSP_FILE_CALLBACK_W handler, PVOID context )
953 TRACE("copy %s to %s style 0x%lx\n",debugstr_w(source),debugstr_w(target),style);
955 /* before copy processing */
956 if (style & SP_COPY_REPLACEONLY)
958 if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES)
961 if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER))
963 DWORD VersionSizeSource=0;
964 DWORD VersionSizeTarget=0;
968 * This is sort of an interesting workaround. You see, calling
969 * GetVersionInfoSize on a builtin dll loads that dll into memory
970 * and we do not properly unload builtin dlls.. so we effectively
971 * lock into memory all the targets we are replacing. This leads
972 * to problems when we try to register the replaced dlls.
974 * So I will test for the existence of the files first so that
975 * we just basically unconditionally replace the builtin versions.
977 if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) &&
978 (GetFileAttributesW(source) != INVALID_FILE_ATTRIBUTES))
980 VersionSizeSource = GetFileVersionInfoSizeW(source,&zero);
981 VersionSizeTarget = GetFileVersionInfoSizeW(target,&zero);
984 TRACE("SizeTarget %li ... SizeSource %li\n",VersionSizeTarget,
987 if (VersionSizeSource && VersionSizeTarget)
989 LPVOID VersionSource;
990 LPVOID VersionTarget;
991 VS_FIXEDFILEINFO *TargetInfo;
992 VS_FIXEDFILEINFO *SourceInfo;
994 WCHAR SubBlock[2]={'\\',0};
997 VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource);
998 VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget);
1000 ret = GetFileVersionInfoW(source,0,VersionSizeSource,VersionSource);
1002 ret = GetFileVersionInfoW(target, 0, VersionSizeTarget,
1007 ret = VerQueryValueW(VersionSource, SubBlock,
1008 (LPVOID*)&SourceInfo, &length);
1010 ret = VerQueryValueW(VersionTarget, SubBlock,
1011 (LPVOID*)&TargetInfo, &length);
1015 FILEPATHS_W filepaths;
1017 TRACE("Versions: Source %li.%li target %li.%li\n",
1018 SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS,
1019 TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS);
1021 /* used in case of notification */
1022 filepaths.Target = target;
1023 filepaths.Source = source;
1024 filepaths.Win32Error = 0;
1025 filepaths.Flags = 0;
1027 if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS)
1030 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1034 else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS)
1035 && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS))
1038 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1042 else if ((style & SP_COPY_NEWER_ONLY) &&
1043 (TargetInfo->dwFileVersionMS ==
1044 SourceInfo->dwFileVersionMS)
1045 &&(TargetInfo->dwFileVersionLS ==
1046 SourceInfo->dwFileVersionLS))
1049 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1055 HeapFree(GetProcessHeap(),0,VersionSource);
1056 HeapFree(GetProcessHeap(),0,VersionTarget);
1059 if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE))
1061 if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES)
1063 FIXME("Notify user target file exists\n");
1067 if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE |
1068 SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP))
1070 ERR("Unsupported style(s) 0x%lx\n",style);
1075 rc = CopyFileW(source,target,FALSE);
1076 TRACE("Did copy... rc was %i\n",rc);
1079 /* after copy processing */
1080 if (style & SP_COPY_DELETESOURCE)
1083 DeleteFileW(source);
1089 /***********************************************************************
1090 * SetupCommitFileQueueW (SETUPAPI.@)
1092 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler,
1095 struct file_queue *queue = handle;
1097 BOOL result = FALSE;
1101 paths.Source = paths.Target = NULL;
1103 if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count)
1104 return TRUE; /* nothing to do */
1106 if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE;
1108 /* perform deletes */
1110 if (queue->delete_queue.count)
1112 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE,
1113 queue->delete_queue.count ))) goto done;
1114 for (op = queue->delete_queue.head; op; op = op->next)
1116 build_filepathsW( op, &paths );
1117 op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE);
1118 if (op_result == FILEOP_ABORT) goto done;
1119 while (op_result == FILEOP_DOIT)
1121 TRACE( "deleting file %s\n", debugstr_w(paths.Target) );
1122 if (DeleteFileW( paths.Target )) break; /* success */
1123 paths.Win32Error = GetLastError();
1124 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 );
1125 if (op_result == FILEOP_ABORT) goto done;
1127 handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 );
1129 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 );
1132 /* perform renames */
1134 if (queue->rename_queue.count)
1136 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME,
1137 queue->rename_queue.count ))) goto done;
1138 for (op = queue->rename_queue.head; op; op = op->next)
1140 build_filepathsW( op, &paths );
1141 op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME);
1142 if (op_result == FILEOP_ABORT) goto done;
1143 while (op_result == FILEOP_DOIT)
1145 TRACE( "renaming file %s -> %s\n",
1146 debugstr_w(paths.Source), debugstr_w(paths.Target) );
1147 if (MoveFileW( paths.Source, paths.Target )) break; /* success */
1148 paths.Win32Error = GetLastError();
1149 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 );
1150 if (op_result == FILEOP_ABORT) goto done;
1152 handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 );
1154 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 );
1157 /* perform copies */
1159 if (queue->copy_queue.count)
1161 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY,
1162 queue->copy_queue.count ))) goto done;
1163 for (op = queue->copy_queue.head; op; op = op->next)
1165 WCHAR newpath[MAX_PATH];
1167 build_filepathsW( op, &paths );
1168 op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
1169 if (op_result == FILEOP_ABORT) goto done;
1170 if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT;
1171 while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
1173 TRACE( "copying file %s -> %s\n",
1174 debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ),
1175 debugstr_w(paths.Target) );
1178 if (!create_full_pathW( op->dst_path ))
1180 paths.Win32Error = GetLastError();
1181 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1182 (UINT_PTR)&paths, (UINT_PTR)newpath );
1183 if (op_result == FILEOP_ABORT) goto done;
1186 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
1187 paths.Target, op->style, handler, context )) break; /* success */
1188 /* try to extract it from the cabinet file */
1191 if (extract_cabinet_file( op->src_tag, op->src_root,
1192 paths.Source, paths.Target )) break;
1194 paths.Win32Error = GetLastError();
1195 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1196 (UINT_PTR)&paths, (UINT_PTR)newpath );
1197 if (op_result == FILEOP_ABORT) goto done;
1199 handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
1201 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 );
1208 handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 );
1209 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1210 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1215 /***********************************************************************
1216 * SetupScanFileQueueA (SETUPAPI.@)
1218 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ queue, DWORD flags, HWND window,
1219 PSP_FILE_CALLBACK_A callback, PVOID context, PDWORD result )
1226 /***********************************************************************
1227 * SetupScanFileQueueW (SETUPAPI.@)
1229 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ queue, DWORD flags, HWND window,
1230 PSP_FILE_CALLBACK_W callback, PVOID context, PDWORD result )
1237 /***********************************************************************
1238 * SetupGetFileQueueCount (SETUPAPI.@)
1240 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result )
1242 struct file_queue *queue = handle;
1247 *result = queue->copy_queue.count;
1250 *result = queue->rename_queue.count;
1253 *result = queue->delete_queue.count;
1260 /***********************************************************************
1261 * SetupGetFileQueueFlags (SETUPAPI.@)
1263 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags )
1265 struct file_queue *queue = handle;
1266 *flags = queue->flags;
1271 /***********************************************************************
1272 * SetupSetFileQueueFlags (SETUPAPI.@)
1274 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags )
1276 struct file_queue *queue = handle;
1277 queue->flags = (queue->flags & ~mask) | flags;
1282 /***********************************************************************
1283 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1285 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile)
1287 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile));
1292 /***********************************************************************
1293 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1295 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile)
1297 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile));
1302 /***********************************************************************
1303 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1305 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner )
1307 return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL );
1311 /***********************************************************************
1312 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1314 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg,
1315 DWORD reserved1, PVOID reserved2 )
1317 struct default_callback_context *context;
1319 if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) )))
1321 context->owner = owner;
1322 context->progress = progress;
1323 context->message = msg;
1329 /***********************************************************************
1330 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1332 void WINAPI SetupTermDefaultQueueCallback( PVOID context )
1334 HeapFree( GetProcessHeap(), 0, context );
1338 /***********************************************************************
1339 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1341 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification,
1342 UINT_PTR param1, UINT_PTR param2 )
1344 FILEPATHS_A *paths = (FILEPATHS_A *)param1;
1345 struct default_callback_context *ctx = (struct default_callback_context *)context;
1347 switch(notification)
1349 case SPFILENOTIFY_STARTQUEUE:
1350 TRACE( "start queue\n" );
1352 case SPFILENOTIFY_ENDQUEUE:
1353 TRACE( "end queue\n" );
1355 case SPFILENOTIFY_STARTSUBQUEUE:
1356 TRACE( "start subqueue %d count %d\n", param1, param2 );
1358 case SPFILENOTIFY_ENDSUBQUEUE:
1359 TRACE( "end subqueue %d\n", param1 );
1361 case SPFILENOTIFY_STARTDELETE:
1362 TRACE( "start delete %s\n", debugstr_a(paths->Target) );
1364 case SPFILENOTIFY_ENDDELETE:
1365 TRACE( "end delete %s\n", debugstr_a(paths->Target) );
1367 case SPFILENOTIFY_DELETEERROR:
1368 /*Windows Ignores attempts to delete files / folders which do not exist*/
1369 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1370 SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1372 case SPFILENOTIFY_STARTRENAME:
1373 TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1375 case SPFILENOTIFY_ENDRENAME:
1376 TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1378 case SPFILENOTIFY_RENAMEERROR:
1379 SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1381 case SPFILENOTIFY_STARTCOPY:
1382 TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1384 case SPFILENOTIFY_ENDCOPY:
1385 TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1387 case SPFILENOTIFY_COPYERROR:
1388 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1389 debugstr_a(paths->Source), debugstr_a(paths->Target) );
1391 case SPFILENOTIFY_NEEDMEDIA:
1392 TRACE( "need media\n" );
1395 FIXME( "notification %d params %x,%x\n", notification, param1, param2 );
1402 /***********************************************************************
1403 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1405 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification,
1406 UINT_PTR param1, UINT_PTR param2 )
1408 FILEPATHS_W *paths = (FILEPATHS_W *)param1;
1409 struct default_callback_context *ctx = (struct default_callback_context *)context;
1411 switch(notification)
1413 case SPFILENOTIFY_STARTQUEUE:
1414 TRACE( "start queue\n" );
1416 case SPFILENOTIFY_ENDQUEUE:
1417 TRACE( "end queue\n" );
1419 case SPFILENOTIFY_STARTSUBQUEUE:
1420 TRACE( "start subqueue %d count %d\n", param1, param2 );
1422 case SPFILENOTIFY_ENDSUBQUEUE:
1423 TRACE( "end subqueue %d\n", param1 );
1425 case SPFILENOTIFY_STARTDELETE:
1426 TRACE( "start delete %s\n", debugstr_w(paths->Target) );
1428 case SPFILENOTIFY_ENDDELETE:
1429 TRACE( "end delete %s\n", debugstr_w(paths->Target) );
1431 case SPFILENOTIFY_DELETEERROR:
1432 /*Windows Ignores attempts to delete files / folders which do not exist*/
1433 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1434 SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1436 case SPFILENOTIFY_STARTRENAME:
1437 SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1439 case SPFILENOTIFY_ENDRENAME:
1440 TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1442 case SPFILENOTIFY_RENAMEERROR:
1443 ERR( "rename error %d %s -> %s\n", paths->Win32Error,
1444 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1446 case SPFILENOTIFY_STARTCOPY:
1447 TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1449 case SPFILENOTIFY_ENDCOPY:
1450 TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1452 case SPFILENOTIFY_COPYERROR:
1453 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1454 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1456 case SPFILENOTIFY_NEEDMEDIA:
1457 TRACE( "need media\n" );
1460 FIXME( "notification %d params %x,%x\n", notification, param1, param2 );
1466 /***********************************************************************
1467 * SetupDeleteErrorA (SETUPAPI.@)
1470 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file,
1471 UINT w32error, DWORD style)
1473 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1474 w32error, debugstr_a(file) );
1475 return DPROMPT_SKIPFILE;
1478 /***********************************************************************
1479 * SetupDeleteErrorW (SETUPAPI.@)
1482 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file,
1483 UINT w32error, DWORD style)
1485 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1486 w32error, debugstr_w(file) );
1487 return DPROMPT_SKIPFILE;
1490 /***********************************************************************
1491 * SetupRenameErrorA (SETUPAPI.@)
1494 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source,
1495 PCSTR target, UINT w32error, DWORD style)
1497 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1498 w32error, debugstr_a(source), debugstr_a(target));
1499 return DPROMPT_SKIPFILE;
1502 /***********************************************************************
1503 * SetupRenameErrorW (SETUPAPI.@)
1506 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source,
1507 PCWSTR target, UINT w32error, DWORD style)
1509 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1510 w32error, debugstr_w(source), debugstr_w(target));
1511 return DPROMPT_SKIPFILE;
1515 /***********************************************************************
1516 * SetupCopyErrorA (SETUPAPI.@)
1519 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname,
1520 PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath,
1521 UINT w32error, DWORD style, PSTR pathbuffer,
1522 DWORD buffersize, PDWORD requiredsize)
1524 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1525 w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath));
1526 return DPROMPT_SKIPFILE;
1529 /***********************************************************************
1530 * SetupCopyErrorW (SETUPAPI.@)
1533 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname,
1534 PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath,
1535 UINT w32error, DWORD style, PWSTR pathbuffer,
1536 DWORD buffersize, PDWORD requiredsize)
1538 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1539 w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath));
1540 return DPROMPT_SKIPFILE;