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 static inline WCHAR *strdupW( const WCHAR *str )
81 int len = (strlenW(str) + 1) * sizeof(WCHAR);
82 if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( ret, str, len );
87 static inline char *strdupWtoA( const WCHAR *str )
92 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
93 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
94 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
99 /* append a file operation to a queue */
100 static inline void queue_file_op( struct file_op_queue *queue, struct file_op *op )
103 if (queue->tail) queue->tail->next = op;
104 else queue->head = op;
109 /* free all the file operations on a given queue */
110 static void free_file_op_queue( struct file_op_queue *queue )
112 struct file_op *t, *op = queue->head;
116 HeapFree( GetProcessHeap(), 0, op->src_root );
117 HeapFree( GetProcessHeap(), 0, op->src_path );
118 HeapFree( GetProcessHeap(), 0, op->src_file );
119 HeapFree( GetProcessHeap(), 0, op->src_descr );
120 HeapFree( GetProcessHeap(), 0, op->src_tag );
121 HeapFree( GetProcessHeap(), 0, op->dst_path );
122 if (op->dst_file != op->src_file) HeapFree( GetProcessHeap(), 0, op->dst_file );
125 HeapFree( GetProcessHeap(), 0, t );
129 /* concat 3 strings to make a path, handling separators correctly */
130 static void concat_W( WCHAR *buffer, const WCHAR *src1, const WCHAR *src2, const WCHAR *src3 )
135 strcpyW( buffer, src1 );
136 buffer += strlenW(buffer );
137 if (buffer[-1] != '\\') *buffer++ = '\\';
138 if (src2) while (*src2 == '\\') src2++;
143 strcpyW( buffer, src2 );
144 buffer += strlenW(buffer );
145 if (buffer[-1] != '\\') *buffer++ = '\\';
146 if (src3) while (*src3 == '\\') src3++;
150 strcpyW( buffer, src3 );
151 buffer += strlenW(buffer );
156 /***********************************************************************
159 * Build a FILEPATHS_W structure for a given file operation.
161 static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths )
163 unsigned int src_len = 1, dst_len = 1;
164 WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target;
166 if (op->src_root) src_len += strlenW(op->src_root) + 1;
167 if (op->src_path) src_len += strlenW(op->src_path) + 1;
168 if (op->src_file) src_len += strlenW(op->src_file) + 1;
169 if (op->dst_path) dst_len += strlenW(op->dst_path) + 1;
170 if (op->dst_file) dst_len += strlenW(op->dst_file) + 1;
171 src_len *= sizeof(WCHAR);
172 dst_len *= sizeof(WCHAR);
174 if (!source || HeapSize( GetProcessHeap(), 0, source ) < src_len )
176 HeapFree( GetProcessHeap(), 0, source );
177 paths->Source = source = HeapAlloc( GetProcessHeap(), 0, src_len );
179 if (!target || HeapSize( GetProcessHeap(), 0, target ) < dst_len )
181 HeapFree( GetProcessHeap(), 0, target );
182 paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len );
184 if (!source || !target) return FALSE;
185 concat_W( source, op->src_root, op->src_path, op->src_file );
186 concat_W( target, NULL, op->dst_path, op->dst_file );
187 paths->Win32Error = 0;
193 /***********************************************************************
194 * QUEUE_callback_WtoA
196 * Map a file callback parameters from W to A and call the A callback.
198 UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification,
199 UINT_PTR param1, UINT_PTR param2 )
201 struct callback_WtoA_context *callback_ctx = context;
202 char buffer[MAX_PATH];
204 UINT_PTR old_param2 = param2;
208 case SPFILENOTIFY_COPYERROR:
209 param2 = (UINT_PTR)&buffer;
211 case SPFILENOTIFY_STARTDELETE:
212 case SPFILENOTIFY_ENDDELETE:
213 case SPFILENOTIFY_DELETEERROR:
214 case SPFILENOTIFY_STARTRENAME:
215 case SPFILENOTIFY_ENDRENAME:
216 case SPFILENOTIFY_RENAMEERROR:
217 case SPFILENOTIFY_STARTCOPY:
218 case SPFILENOTIFY_ENDCOPY:
220 FILEPATHS_W *pathsW = (FILEPATHS_W *)param1;
223 pathsA.Source = strdupWtoA( pathsW->Source );
224 pathsA.Target = strdupWtoA( pathsW->Target );
225 pathsA.Win32Error = pathsW->Win32Error;
226 pathsA.Flags = pathsW->Flags;
227 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
228 (UINT_PTR)&pathsA, param2 );
229 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Source );
230 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Target );
232 if (notification == SPFILENOTIFY_COPYERROR)
233 MultiByteToWideChar( CP_ACP, 0, buffer, -1, (WCHAR *)old_param2, MAX_PATH );
236 case SPFILENOTIFY_STARTREGISTRATION:
237 case SPFILENOTIFY_ENDREGISTRATION:
239 SP_REGISTER_CONTROL_STATUSW *statusW = (SP_REGISTER_CONTROL_STATUSW *)param1;
240 SP_REGISTER_CONTROL_STATUSA statusA;
242 statusA.cbSize = sizeof(statusA);
243 statusA.FileName = strdupWtoA( statusW->FileName );
244 statusA.Win32Error = statusW->Win32Error;
245 statusA.FailureCode = statusW->FailureCode;
246 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
247 (UINT_PTR)&statusA, param2 );
248 HeapFree( GetProcessHeap(), 0, (LPSTR)statusA.FileName );
252 case SPFILENOTIFY_NEEDMEDIA:
253 case SPFILENOTIFY_QUEUESCAN:
254 FIXME("mapping for %d not implemented\n",notification);
255 case SPFILENOTIFY_STARTQUEUE:
256 case SPFILENOTIFY_ENDQUEUE:
257 case SPFILENOTIFY_STARTSUBQUEUE:
258 case SPFILENOTIFY_ENDSUBQUEUE:
260 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, param1, param2 );
267 /***********************************************************************
270 * Retrieve the source file information for a given file.
272 static void get_src_file_info( HINF hinf, struct file_op *op )
274 static const WCHAR SourceDisksNames[] =
275 {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0};
276 static const WCHAR SourceDisksFiles[] =
277 {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
279 INFCONTEXT file_ctx, disk_ctx;
283 /* find the SourceDisksFiles entry */
284 if (!SetupFindFirstLineW( hinf, SourceDisksFiles, op->src_file, &file_ctx ))
286 if ((op->style & (SP_COPY_SOURCE_ABSOLUTE|SP_COPY_SOURCEPATH_ABSOLUTE))) return;
287 /* no specific info, use .inf file source directory */
288 if (!op->src_root) op->src_root = PARSER_get_src_root( hinf );
291 if (!SetupGetIntField( &file_ctx, 1, &diskid )) return;
293 /* now find the diskid in the SourceDisksNames section */
294 if (!SetupFindFirstLineW( hinf, SourceDisksNames, NULL, &disk_ctx )) return;
297 if (SetupGetIntField( &disk_ctx, 0, &id ) && (id == diskid)) break;
298 if (!SetupFindNextLine( &disk_ctx, &disk_ctx )) return;
301 /* and fill in the missing info */
305 if (SetupGetStringFieldW( &disk_ctx, 1, NULL, 0, &len ) &&
306 (op->src_descr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
307 SetupGetStringFieldW( &disk_ctx, 1, op->src_descr, len, NULL );
311 if (SetupGetStringFieldW( &disk_ctx, 2, NULL, 0, &len ) &&
312 (op->src_tag = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
313 SetupGetStringFieldW( &disk_ctx, 2, op->src_tag, len, NULL );
315 if (!op->src_path && !(op->style & SP_COPY_SOURCE_ABSOLUTE))
318 if (!(op->style & SP_COPY_SOURCEPATH_ABSOLUTE))
320 /* retrieve relative path for this disk */
321 if (!SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len )) len = 0;
323 /* retrieve relative path for this file */
324 if (!SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len2 )) len2 = 0;
327 (op->src_path = HeapAlloc( GetProcessHeap(), 0, (len+len2)*sizeof(WCHAR) )))
329 WCHAR *ptr = op->src_path;
332 SetupGetStringFieldW( &disk_ctx, 4, op->src_path, len, NULL );
333 ptr = op->src_path + strlenW(op->src_path);
334 if (len2 && ptr > op->src_path && ptr[-1] != '\\') *ptr++ = '\\';
336 if (!SetupGetStringFieldW( &file_ctx, 2, ptr, len2, NULL )) *ptr = 0;
339 if (!op->src_root) op->src_root = PARSER_get_src_root(hinf);
343 /***********************************************************************
344 * get_destination_dir
346 * Retrieve the destination dir for a given section.
348 static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
350 static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
351 static const WCHAR Def[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
354 if (!SetupFindFirstLineW( hinf, Dest, section, &context ) &&
355 !SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL;
356 return PARSER_get_dest_dir( &context );
360 static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD );
362 /***********************************************************************
363 * extract_cabinet_file
365 * Extract a file from a .cab file.
367 static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root,
368 const WCHAR *src, const WCHAR *dst )
370 static const WCHAR extW[] = {'.','c','a','b',0};
371 static HMODULE advpack;
373 char *cab_path, *cab_file;
374 int len = strlenW( cabinet );
376 /* make sure the cabinet file has a .cab extension */
377 if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE;
380 if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" )))
382 ERR( "could not load advpack.dll\n" );
385 if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" )))
387 ERR( "could not find ExtractFiles in advpack.dll\n" );
392 if (!(cab_path = strdupWtoA( root ))) return FALSE;
393 len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL );
394 if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 )))
396 HeapFree( GetProcessHeap(), 0, cab_path );
399 strcpy( cab_file, cab_path );
400 if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" );
401 WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL );
402 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) );
403 pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 );
404 HeapFree( GetProcessHeap(), 0, cab_file );
405 HeapFree( GetProcessHeap(), 0, cab_path );
406 return CopyFileW( src, dst, FALSE /*FIXME*/ );
410 /***********************************************************************
411 * SetupOpenFileQueue (SETUPAPI.@)
413 HSPFILEQ WINAPI SetupOpenFileQueue(void)
415 struct file_queue *queue;
417 if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue))))
418 return (HSPFILEQ)INVALID_HANDLE_VALUE;
423 /***********************************************************************
424 * SetupCloseFileQueue (SETUPAPI.@)
426 BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle )
428 struct file_queue *queue = handle;
430 free_file_op_queue( &queue->copy_queue );
431 free_file_op_queue( &queue->rename_queue );
432 free_file_op_queue( &queue->delete_queue );
433 HeapFree( GetProcessHeap(), 0, queue );
438 /***********************************************************************
439 * SetupQueueCopyIndirectA (SETUPAPI.@)
441 BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params )
443 struct file_queue *queue = params->QueueHandle;
446 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
447 op->style = params->CopyStyle;
448 op->src_root = strdupAtoW( params->SourceRootPath );
449 op->src_path = strdupAtoW( params->SourcePath );
450 op->src_file = strdupAtoW( params->SourceFilename );
451 op->src_descr = strdupAtoW( params->SourceDescription );
452 op->src_tag = strdupAtoW( params->SourceTagfile );
453 op->dst_path = strdupAtoW( params->TargetDirectory );
454 op->dst_file = strdupAtoW( params->TargetFilename );
457 if (!op->src_file) op->src_file = op->dst_file;
458 if (params->LayoutInf)
460 get_src_file_info( params->LayoutInf, op );
461 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
464 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
465 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
466 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
467 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
469 queue_file_op( &queue->copy_queue, op );
474 /***********************************************************************
475 * SetupQueueCopyIndirectW (SETUPAPI.@)
477 BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params )
479 struct file_queue *queue = params->QueueHandle;
482 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
483 op->style = params->CopyStyle;
484 op->src_root = strdupW( params->SourceRootPath );
485 op->src_path = strdupW( params->SourcePath );
486 op->src_file = strdupW( params->SourceFilename );
487 op->src_descr = strdupW( params->SourceDescription );
488 op->src_tag = strdupW( params->SourceTagfile );
489 op->dst_path = strdupW( params->TargetDirectory );
490 op->dst_file = strdupW( params->TargetFilename );
493 if (!op->src_file) op->src_file = op->dst_file;
494 if (params->LayoutInf)
496 get_src_file_info( params->LayoutInf, op );
497 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
500 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
501 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
502 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
503 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
505 queue_file_op( &queue->copy_queue, op );
510 /***********************************************************************
511 * SetupQueueCopyA (SETUPAPI.@)
513 BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file,
514 PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file,
517 SP_FILE_COPY_PARAMS_A params;
519 params.cbSize = sizeof(params);
520 params.QueueHandle = queue;
521 params.SourceRootPath = src_root;
522 params.SourcePath = src_path;
523 params.SourceFilename = src_file;
524 params.SourceDescription = src_descr;
525 params.SourceTagfile = src_tag;
526 params.TargetDirectory = dst_dir;
527 params.TargetFilename = dst_file;
528 params.CopyStyle = style;
529 params.LayoutInf = 0;
530 params.SecurityDescriptor = NULL;
531 return SetupQueueCopyIndirectA( ¶ms );
535 /***********************************************************************
536 * SetupQueueCopyW (SETUPAPI.@)
538 BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file,
539 PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file,
542 SP_FILE_COPY_PARAMS_W params;
544 params.cbSize = sizeof(params);
545 params.QueueHandle = queue;
546 params.SourceRootPath = src_root;
547 params.SourcePath = src_path;
548 params.SourceFilename = src_file;
549 params.SourceDescription = src_descr;
550 params.SourceTagfile = src_tag;
551 params.TargetDirectory = dst_dir;
552 params.TargetFilename = dst_file;
553 params.CopyStyle = style;
554 params.LayoutInf = 0;
555 params.SecurityDescriptor = NULL;
556 return SetupQueueCopyIndirectW( ¶ms );
560 /***********************************************************************
561 * SetupQueueDefaultCopyA (SETUPAPI.@)
563 BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file,
564 PCSTR dst_file, DWORD style )
566 SP_FILE_COPY_PARAMS_A params;
568 params.cbSize = sizeof(params);
569 params.QueueHandle = queue;
570 params.SourceRootPath = src_root;
571 params.SourcePath = NULL;
572 params.SourceFilename = src_file;
573 params.SourceDescription = NULL;
574 params.SourceTagfile = NULL;
575 params.TargetDirectory = NULL;
576 params.TargetFilename = dst_file;
577 params.CopyStyle = style;
578 params.LayoutInf = hinf;
579 params.SecurityDescriptor = NULL;
580 return SetupQueueCopyIndirectA( ¶ms );
584 /***********************************************************************
585 * SetupQueueDefaultCopyW (SETUPAPI.@)
587 BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file,
588 PCWSTR dst_file, DWORD style )
590 SP_FILE_COPY_PARAMS_W params;
592 params.cbSize = sizeof(params);
593 params.QueueHandle = queue;
594 params.SourceRootPath = src_root;
595 params.SourcePath = NULL;
596 params.SourceFilename = src_file;
597 params.SourceDescription = NULL;
598 params.SourceTagfile = NULL;
599 params.TargetDirectory = NULL;
600 params.TargetFilename = dst_file;
601 params.CopyStyle = style;
602 params.LayoutInf = hinf;
603 params.SecurityDescriptor = NULL;
604 return SetupQueueCopyIndirectW( ¶ms );
608 /***********************************************************************
609 * SetupQueueDeleteA (SETUPAPI.@)
611 BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 )
613 struct file_queue *queue = handle;
616 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
621 op->src_descr = NULL;
623 op->dst_path = strdupAtoW( part1 );
624 op->dst_file = strdupAtoW( part2 );
625 queue_file_op( &queue->delete_queue, op );
630 /***********************************************************************
631 * SetupQueueDeleteW (SETUPAPI.@)
633 BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 )
635 struct file_queue *queue = handle;
638 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
643 op->src_descr = NULL;
645 op->dst_path = strdupW( part1 );
646 op->dst_file = strdupW( part2 );
647 queue_file_op( &queue->delete_queue, op );
652 /***********************************************************************
653 * SetupQueueRenameA (SETUPAPI.@)
655 BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename,
656 PCSTR TargetPath, PCSTR TargetFilename )
658 struct file_queue *queue = handle;
661 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
664 op->src_path = strdupAtoW( SourcePath );
665 op->src_file = strdupAtoW( SourceFilename );
666 op->src_descr = NULL;
668 op->dst_path = strdupAtoW( TargetPath );
669 op->dst_file = strdupAtoW( TargetFilename );
670 queue_file_op( &queue->rename_queue, op );
675 /***********************************************************************
676 * SetupQueueRenameW (SETUPAPI.@)
678 BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename,
679 PCWSTR TargetPath, PCWSTR TargetFilename )
681 struct file_queue *queue = handle;
684 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
687 op->src_path = strdupW( SourcePath );
688 op->src_file = strdupW( SourceFilename );
689 op->src_descr = NULL;
691 op->dst_path = strdupW( TargetPath );
692 op->dst_file = strdupW( TargetFilename );
693 queue_file_op( &queue->rename_queue, op );
698 /***********************************************************************
699 * SetupQueueCopySectionA (SETUPAPI.@)
701 BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist,
702 PCSTR section, DWORD style )
704 UNICODE_STRING sectionW;
707 if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
709 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
713 ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style );
717 if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root ))
719 ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style );
720 RtlFreeUnicodeString( &srcW );
722 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
724 RtlFreeUnicodeString( §ionW );
729 /***********************************************************************
730 * SetupQueueCopySectionW (SETUPAPI.@)
732 BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist,
733 PCWSTR section, DWORD style )
735 SP_FILE_COPY_PARAMS_W params;
737 WCHAR dest[MAX_PATH], src[MAX_PATH];
740 TRACE( "hinf=%p/%p section=%s root=%s\n",
741 hinf, hlist, debugstr_w(section), debugstr_w(src_root) );
743 params.cbSize = sizeof(params);
744 params.QueueHandle = queue;
745 params.SourceRootPath = src_root;
746 params.SourcePath = NULL;
747 params.SourceDescription = NULL;
748 params.SourceTagfile = NULL;
749 params.TargetFilename = dest;
750 params.CopyStyle = style;
751 params.LayoutInf = hinf;
752 params.SecurityDescriptor = NULL;
754 if (!hlist) hlist = hinf;
755 if (!hinf) hinf = hlist;
756 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
757 if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) return FALSE;
760 if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL ))
762 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0;
763 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */
765 params.SourceFilename = *src ? src : NULL;
766 if (!SetupQueueCopyIndirectW( ¶ms )) return FALSE;
767 } while (SetupFindNextLine( &context, &context ));
772 /***********************************************************************
773 * SetupQueueDeleteSectionA (SETUPAPI.@)
775 BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
777 UNICODE_STRING sectionW;
780 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
782 ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer );
783 RtlFreeUnicodeString( §ionW );
785 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
790 /***********************************************************************
791 * SetupQueueDeleteSectionW (SETUPAPI.@)
793 BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
797 WCHAR buffer[MAX_PATH];
801 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
803 if (!hlist) hlist = hinf;
804 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
805 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
808 if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
810 if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
811 if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done;
812 } while (SetupFindNextLine( &context, &context ));
816 HeapFree( GetProcessHeap(), 0, dest_dir );
821 /***********************************************************************
822 * SetupQueueRenameSectionA (SETUPAPI.@)
824 BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
826 UNICODE_STRING sectionW;
829 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
831 ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer );
832 RtlFreeUnicodeString( §ionW );
834 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
839 /***********************************************************************
840 * SetupQueueRenameSectionW (SETUPAPI.@)
842 BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
846 WCHAR src[MAX_PATH], dst[MAX_PATH];
849 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
851 if (!hlist) hlist = hinf;
852 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
853 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
856 if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL ))
858 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL ))
860 if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done;
861 } while (SetupFindNextLine( &context, &context ));
865 HeapFree( GetProcessHeap(), 0, dest_dir );
870 /***********************************************************************
871 * SetupCommitFileQueueA (SETUPAPI.@)
873 BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler,
876 struct callback_WtoA_context ctx;
878 ctx.orig_context = context;
879 ctx.orig_handler = handler;
880 return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx );
884 /***********************************************************************
887 * Recursively create all directories in the path.
889 static BOOL create_full_pathW(const WCHAR *path)
895 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
896 strcpyW(new_path, path);
898 while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
899 new_path[len - 1] = 0;
901 while(!CreateDirectoryW(new_path, NULL))
904 DWORD last_error = GetLastError();
906 if(last_error == ERROR_ALREADY_EXISTS)
909 if(last_error != ERROR_PATH_NOT_FOUND)
915 if(!(slash = strrchrW(new_path, '\\')))
921 len = slash - new_path;
923 if(!create_full_pathW(new_path))
928 new_path[len] = '\\';
931 HeapFree(GetProcessHeap(), 0, new_path);
935 static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style,
936 PSP_FILE_CALLBACK_W handler, PVOID context )
941 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source),debugstr_w(target),style);
943 /* before copy processing */
944 if (style & SP_COPY_REPLACEONLY)
946 if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES)
949 if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER))
951 DWORD VersionSizeSource=0;
952 DWORD VersionSizeTarget=0;
956 * This is sort of an interesting workaround. You see, calling
957 * GetVersionInfoSize on a builtin dll loads that dll into memory
958 * and we do not properly unload builtin dlls.. so we effectively
959 * lock into memory all the targets we are replacing. This leads
960 * to problems when we try to register the replaced dlls.
962 * So I will test for the existence of the files first so that
963 * we just basically unconditionally replace the builtin versions.
965 if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) &&
966 (GetFileAttributesW(source) != INVALID_FILE_ATTRIBUTES))
968 VersionSizeSource = GetFileVersionInfoSizeW(source,&zero);
969 VersionSizeTarget = GetFileVersionInfoSizeW(target,&zero);
972 TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget,
975 if (VersionSizeSource && VersionSizeTarget)
977 LPVOID VersionSource;
978 LPVOID VersionTarget;
979 VS_FIXEDFILEINFO *TargetInfo;
980 VS_FIXEDFILEINFO *SourceInfo;
982 WCHAR SubBlock[2]={'\\',0};
985 VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource);
986 VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget);
988 ret = GetFileVersionInfoW(source,0,VersionSizeSource,VersionSource);
990 ret = GetFileVersionInfoW(target, 0, VersionSizeTarget,
995 ret = VerQueryValueW(VersionSource, SubBlock,
996 (LPVOID*)&SourceInfo, &length);
998 ret = VerQueryValueW(VersionTarget, SubBlock,
999 (LPVOID*)&TargetInfo, &length);
1003 FILEPATHS_W filepaths;
1005 TRACE("Versions: Source %i.%i target %i.%i\n",
1006 SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS,
1007 TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS);
1009 /* used in case of notification */
1010 filepaths.Target = target;
1011 filepaths.Source = source;
1012 filepaths.Win32Error = 0;
1013 filepaths.Flags = 0;
1015 if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS)
1018 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1022 else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS)
1023 && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS))
1026 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1030 else if ((style & SP_COPY_NEWER_ONLY) &&
1031 (TargetInfo->dwFileVersionMS ==
1032 SourceInfo->dwFileVersionMS)
1033 &&(TargetInfo->dwFileVersionLS ==
1034 SourceInfo->dwFileVersionLS))
1037 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1043 HeapFree(GetProcessHeap(),0,VersionSource);
1044 HeapFree(GetProcessHeap(),0,VersionTarget);
1047 if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE))
1049 if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES)
1051 FIXME("Notify user target file exists\n");
1055 if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE |
1056 SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP))
1058 ERR("Unsupported style(s) 0x%x\n",style);
1063 rc = CopyFileW(source,target,FALSE);
1064 TRACE("Did copy... rc was %i\n",rc);
1067 /* after copy processing */
1068 if (style & SP_COPY_DELETESOURCE)
1071 DeleteFileW(source);
1077 /***********************************************************************
1078 * SetupCommitFileQueueW (SETUPAPI.@)
1080 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler,
1083 struct file_queue *queue = handle;
1085 BOOL result = FALSE;
1089 paths.Source = paths.Target = NULL;
1091 if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count)
1092 return TRUE; /* nothing to do */
1094 if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE;
1096 /* perform deletes */
1098 if (queue->delete_queue.count)
1100 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE,
1101 queue->delete_queue.count ))) goto done;
1102 for (op = queue->delete_queue.head; op; op = op->next)
1104 build_filepathsW( op, &paths );
1105 op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE);
1106 if (op_result == FILEOP_ABORT) goto done;
1107 while (op_result == FILEOP_DOIT)
1109 TRACE( "deleting file %s\n", debugstr_w(paths.Target) );
1110 if (DeleteFileW( paths.Target )) break; /* success */
1111 paths.Win32Error = GetLastError();
1112 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 );
1113 if (op_result == FILEOP_ABORT) goto done;
1115 handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 );
1117 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 );
1120 /* perform renames */
1122 if (queue->rename_queue.count)
1124 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME,
1125 queue->rename_queue.count ))) goto done;
1126 for (op = queue->rename_queue.head; op; op = op->next)
1128 build_filepathsW( op, &paths );
1129 op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME);
1130 if (op_result == FILEOP_ABORT) goto done;
1131 while (op_result == FILEOP_DOIT)
1133 TRACE( "renaming file %s -> %s\n",
1134 debugstr_w(paths.Source), debugstr_w(paths.Target) );
1135 if (MoveFileW( paths.Source, paths.Target )) break; /* success */
1136 paths.Win32Error = GetLastError();
1137 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 );
1138 if (op_result == FILEOP_ABORT) goto done;
1140 handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 );
1142 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 );
1145 /* perform copies */
1147 if (queue->copy_queue.count)
1149 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY,
1150 queue->copy_queue.count ))) goto done;
1151 for (op = queue->copy_queue.head; op; op = op->next)
1153 WCHAR newpath[MAX_PATH];
1155 build_filepathsW( op, &paths );
1156 op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
1157 if (op_result == FILEOP_ABORT) goto done;
1158 if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT;
1159 while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
1161 TRACE( "copying file %s -> %s\n",
1162 debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ),
1163 debugstr_w(paths.Target) );
1166 if (!create_full_pathW( op->dst_path ))
1168 paths.Win32Error = GetLastError();
1169 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1170 (UINT_PTR)&paths, (UINT_PTR)newpath );
1171 if (op_result == FILEOP_ABORT) goto done;
1174 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
1175 paths.Target, op->style, handler, context )) break; /* success */
1176 /* try to extract it from the cabinet file */
1179 if (extract_cabinet_file( op->src_tag, op->src_root,
1180 paths.Source, paths.Target )) break;
1182 paths.Win32Error = GetLastError();
1183 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1184 (UINT_PTR)&paths, (UINT_PTR)newpath );
1185 if (op_result == FILEOP_ABORT) goto done;
1187 handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
1189 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 );
1196 handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 );
1197 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1198 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1203 /***********************************************************************
1204 * SetupScanFileQueueA (SETUPAPI.@)
1206 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ queue, DWORD flags, HWND window,
1207 PSP_FILE_CALLBACK_A callback, PVOID context, PDWORD result )
1214 /***********************************************************************
1215 * SetupScanFileQueueW (SETUPAPI.@)
1217 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ queue, DWORD flags, HWND window,
1218 PSP_FILE_CALLBACK_W callback, PVOID context, PDWORD result )
1225 /***********************************************************************
1226 * SetupGetFileQueueCount (SETUPAPI.@)
1228 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result )
1230 struct file_queue *queue = handle;
1235 *result = queue->copy_queue.count;
1238 *result = queue->rename_queue.count;
1241 *result = queue->delete_queue.count;
1248 /***********************************************************************
1249 * SetupGetFileQueueFlags (SETUPAPI.@)
1251 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags )
1253 struct file_queue *queue = handle;
1254 *flags = queue->flags;
1259 /***********************************************************************
1260 * SetupSetFileQueueFlags (SETUPAPI.@)
1262 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags )
1264 struct file_queue *queue = handle;
1265 queue->flags = (queue->flags & ~mask) | flags;
1270 /***********************************************************************
1271 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1273 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile)
1275 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile));
1280 /***********************************************************************
1281 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1283 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile)
1285 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile));
1290 /***********************************************************************
1291 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1293 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner )
1295 return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL );
1299 /***********************************************************************
1300 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1302 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg,
1303 DWORD reserved1, PVOID reserved2 )
1305 struct default_callback_context *context;
1307 if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) )))
1309 context->owner = owner;
1310 context->progress = progress;
1311 context->message = msg;
1317 /***********************************************************************
1318 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1320 void WINAPI SetupTermDefaultQueueCallback( PVOID context )
1322 HeapFree( GetProcessHeap(), 0, context );
1326 /***********************************************************************
1327 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1329 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification,
1330 UINT_PTR param1, UINT_PTR param2 )
1332 FILEPATHS_A *paths = (FILEPATHS_A *)param1;
1333 struct default_callback_context *ctx = (struct default_callback_context *)context;
1335 switch(notification)
1337 case SPFILENOTIFY_STARTQUEUE:
1338 TRACE( "start queue\n" );
1340 case SPFILENOTIFY_ENDQUEUE:
1341 TRACE( "end queue\n" );
1343 case SPFILENOTIFY_STARTSUBQUEUE:
1344 TRACE( "start subqueue %d count %d\n", param1, param2 );
1346 case SPFILENOTIFY_ENDSUBQUEUE:
1347 TRACE( "end subqueue %d\n", param1 );
1349 case SPFILENOTIFY_STARTDELETE:
1350 TRACE( "start delete %s\n", debugstr_a(paths->Target) );
1352 case SPFILENOTIFY_ENDDELETE:
1353 TRACE( "end delete %s\n", debugstr_a(paths->Target) );
1355 case SPFILENOTIFY_DELETEERROR:
1356 /*Windows Ignores attempts to delete files / folders which do not exist*/
1357 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1358 SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1360 case SPFILENOTIFY_STARTRENAME:
1361 TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1363 case SPFILENOTIFY_ENDRENAME:
1364 TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1366 case SPFILENOTIFY_RENAMEERROR:
1367 SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1369 case SPFILENOTIFY_STARTCOPY:
1370 TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1372 case SPFILENOTIFY_ENDCOPY:
1373 TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1375 case SPFILENOTIFY_COPYERROR:
1376 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1377 debugstr_a(paths->Source), debugstr_a(paths->Target) );
1379 case SPFILENOTIFY_NEEDMEDIA:
1380 TRACE( "need media\n" );
1383 FIXME( "notification %d params %x,%x\n", notification, param1, param2 );
1390 /***********************************************************************
1391 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1393 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification,
1394 UINT_PTR param1, UINT_PTR param2 )
1396 FILEPATHS_W *paths = (FILEPATHS_W *)param1;
1397 struct default_callback_context *ctx = (struct default_callback_context *)context;
1399 switch(notification)
1401 case SPFILENOTIFY_STARTQUEUE:
1402 TRACE( "start queue\n" );
1404 case SPFILENOTIFY_ENDQUEUE:
1405 TRACE( "end queue\n" );
1407 case SPFILENOTIFY_STARTSUBQUEUE:
1408 TRACE( "start subqueue %d count %d\n", param1, param2 );
1410 case SPFILENOTIFY_ENDSUBQUEUE:
1411 TRACE( "end subqueue %d\n", param1 );
1413 case SPFILENOTIFY_STARTDELETE:
1414 TRACE( "start delete %s\n", debugstr_w(paths->Target) );
1416 case SPFILENOTIFY_ENDDELETE:
1417 TRACE( "end delete %s\n", debugstr_w(paths->Target) );
1419 case SPFILENOTIFY_DELETEERROR:
1420 /*Windows Ignores attempts to delete files / folders which do not exist*/
1421 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1422 SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1424 case SPFILENOTIFY_STARTRENAME:
1425 SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1427 case SPFILENOTIFY_ENDRENAME:
1428 TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1430 case SPFILENOTIFY_RENAMEERROR:
1431 ERR( "rename error %d %s -> %s\n", paths->Win32Error,
1432 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1434 case SPFILENOTIFY_STARTCOPY:
1435 TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1437 case SPFILENOTIFY_ENDCOPY:
1438 TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1440 case SPFILENOTIFY_COPYERROR:
1441 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1442 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1444 case SPFILENOTIFY_NEEDMEDIA:
1445 TRACE( "need media\n" );
1448 FIXME( "notification %d params %x,%x\n", notification, param1, param2 );
1454 /***********************************************************************
1455 * SetupDeleteErrorA (SETUPAPI.@)
1458 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file,
1459 UINT w32error, DWORD style)
1461 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1462 w32error, debugstr_a(file) );
1463 return DPROMPT_SKIPFILE;
1466 /***********************************************************************
1467 * SetupDeleteErrorW (SETUPAPI.@)
1470 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file,
1471 UINT w32error, DWORD style)
1473 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1474 w32error, debugstr_w(file) );
1475 return DPROMPT_SKIPFILE;
1478 /***********************************************************************
1479 * SetupRenameErrorA (SETUPAPI.@)
1482 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source,
1483 PCSTR target, UINT w32error, DWORD style)
1485 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1486 w32error, debugstr_a(source), debugstr_a(target));
1487 return DPROMPT_SKIPFILE;
1490 /***********************************************************************
1491 * SetupRenameErrorW (SETUPAPI.@)
1494 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source,
1495 PCWSTR target, UINT w32error, DWORD style)
1497 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1498 w32error, debugstr_w(source), debugstr_w(target));
1499 return DPROMPT_SKIPFILE;
1503 /***********************************************************************
1504 * SetupCopyErrorA (SETUPAPI.@)
1507 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname,
1508 PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath,
1509 UINT w32error, DWORD style, PSTR pathbuffer,
1510 DWORD buffersize, PDWORD requiredsize)
1512 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1513 w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath));
1514 return DPROMPT_SKIPFILE;
1517 /***********************************************************************
1518 * SetupCopyErrorW (SETUPAPI.@)
1521 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname,
1522 PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath,
1523 UINT w32error, DWORD style, PWSTR pathbuffer,
1524 DWORD buffersize, PDWORD requiredsize)
1526 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1527 w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath));
1528 return DPROMPT_SKIPFILE;