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 /* append a file operation to a queue */
77 static inline void queue_file_op( struct file_op_queue *queue, struct file_op *op )
80 if (queue->tail) queue->tail->next = op;
81 else queue->head = op;
86 /* free all the file operations on a given queue */
87 static void free_file_op_queue( struct file_op_queue *queue )
89 struct file_op *t, *op = queue->head;
93 HeapFree( GetProcessHeap(), 0, op->src_root );
94 HeapFree( GetProcessHeap(), 0, op->src_path );
95 HeapFree( GetProcessHeap(), 0, op->src_file );
96 HeapFree( GetProcessHeap(), 0, op->src_descr );
97 HeapFree( GetProcessHeap(), 0, op->src_tag );
98 HeapFree( GetProcessHeap(), 0, op->dst_path );
99 if (op->dst_file != op->src_file) HeapFree( GetProcessHeap(), 0, op->dst_file );
102 HeapFree( GetProcessHeap(), 0, t );
106 /* concat 3 strings to make a path, handling separators correctly */
107 static void concat_W( WCHAR *buffer, const WCHAR *src1, const WCHAR *src2, const WCHAR *src3 )
112 strcpyW( buffer, src1 );
113 buffer += strlenW(buffer );
114 if (buffer[-1] != '\\') *buffer++ = '\\';
115 if (src2) while (*src2 == '\\') src2++;
120 strcpyW( buffer, src2 );
121 buffer += strlenW(buffer );
122 if (buffer[-1] != '\\') *buffer++ = '\\';
123 if (src3) while (*src3 == '\\') src3++;
127 strcpyW( buffer, src3 );
128 buffer += strlenW(buffer );
133 /***********************************************************************
136 * Build a FILEPATHS_W structure for a given file operation.
138 static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths )
140 unsigned int src_len = 1, dst_len = 1;
141 WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target;
143 if (op->src_root) src_len += strlenW(op->src_root) + 1;
144 if (op->src_path) src_len += strlenW(op->src_path) + 1;
145 if (op->src_file) src_len += strlenW(op->src_file) + 1;
146 if (op->dst_path) dst_len += strlenW(op->dst_path) + 1;
147 if (op->dst_file) dst_len += strlenW(op->dst_file) + 1;
148 src_len *= sizeof(WCHAR);
149 dst_len *= sizeof(WCHAR);
151 if (!source || HeapSize( GetProcessHeap(), 0, source ) < src_len )
153 HeapFree( GetProcessHeap(), 0, source );
154 paths->Source = source = HeapAlloc( GetProcessHeap(), 0, src_len );
156 if (!target || HeapSize( GetProcessHeap(), 0, target ) < dst_len )
158 HeapFree( GetProcessHeap(), 0, target );
159 paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len );
161 if (!source || !target) return FALSE;
162 concat_W( source, op->src_root, op->src_path, op->src_file );
163 concat_W( target, NULL, op->dst_path, op->dst_file );
164 paths->Win32Error = 0;
170 /***********************************************************************
171 * QUEUE_callback_WtoA
173 * Map a file callback parameters from W to A and call the A callback.
175 UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification,
176 UINT_PTR param1, UINT_PTR param2 )
178 struct callback_WtoA_context *callback_ctx = context;
179 char buffer[MAX_PATH];
181 UINT_PTR old_param2 = param2;
185 case SPFILENOTIFY_COPYERROR:
186 param2 = (UINT_PTR)buffer;
188 case SPFILENOTIFY_STARTDELETE:
189 case SPFILENOTIFY_ENDDELETE:
190 case SPFILENOTIFY_DELETEERROR:
191 case SPFILENOTIFY_STARTRENAME:
192 case SPFILENOTIFY_ENDRENAME:
193 case SPFILENOTIFY_RENAMEERROR:
194 case SPFILENOTIFY_STARTCOPY:
195 case SPFILENOTIFY_ENDCOPY:
196 case SPFILENOTIFY_QUEUESCAN_EX:
198 FILEPATHS_W *pathsW = (FILEPATHS_W *)param1;
201 pathsA.Source = strdupWtoA( pathsW->Source );
202 pathsA.Target = strdupWtoA( pathsW->Target );
203 pathsA.Win32Error = pathsW->Win32Error;
204 pathsA.Flags = pathsW->Flags;
205 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
206 (UINT_PTR)&pathsA, param2 );
207 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Source );
208 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Target );
210 if (notification == SPFILENOTIFY_COPYERROR)
211 MultiByteToWideChar( CP_ACP, 0, buffer, -1, (WCHAR *)old_param2, MAX_PATH );
214 case SPFILENOTIFY_STARTREGISTRATION:
215 case SPFILENOTIFY_ENDREGISTRATION:
217 SP_REGISTER_CONTROL_STATUSW *statusW = (SP_REGISTER_CONTROL_STATUSW *)param1;
218 SP_REGISTER_CONTROL_STATUSA statusA;
220 statusA.cbSize = sizeof(statusA);
221 statusA.FileName = strdupWtoA( statusW->FileName );
222 statusA.Win32Error = statusW->Win32Error;
223 statusA.FailureCode = statusW->FailureCode;
224 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
225 (UINT_PTR)&statusA, param2 );
226 HeapFree( GetProcessHeap(), 0, (LPSTR)statusA.FileName );
230 case SPFILENOTIFY_QUEUESCAN:
232 LPWSTR targetW = (LPWSTR)param1;
233 LPSTR target = strdupWtoA( targetW );
235 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
236 (UINT_PTR)target, param2 );
237 HeapFree( GetProcessHeap(), 0, target );
241 case SPFILENOTIFY_NEEDMEDIA:
242 FIXME("mapping for %d not implemented\n",notification);
243 case SPFILENOTIFY_STARTQUEUE:
244 case SPFILENOTIFY_ENDQUEUE:
245 case SPFILENOTIFY_STARTSUBQUEUE:
246 case SPFILENOTIFY_ENDSUBQUEUE:
248 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, param1, param2 );
255 /***********************************************************************
258 * Retrieve the source file information for a given file.
260 static void get_src_file_info( HINF hinf, struct file_op *op )
262 static const WCHAR SourceDisksNames[] =
263 {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0};
264 static const WCHAR SourceDisksFiles[] =
265 {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
267 INFCONTEXT file_ctx, disk_ctx;
271 /* find the SourceDisksFiles entry */
272 if (!SetupFindFirstLineW( hinf, SourceDisksFiles, op->src_file, &file_ctx ))
274 if ((op->style & (SP_COPY_SOURCE_ABSOLUTE|SP_COPY_SOURCEPATH_ABSOLUTE))) return;
275 /* no specific info, use .inf file source directory */
276 if (!op->src_root) op->src_root = PARSER_get_src_root( hinf );
279 if (!SetupGetIntField( &file_ctx, 1, &diskid )) return;
281 /* now find the diskid in the SourceDisksNames section */
282 if (!SetupFindFirstLineW( hinf, SourceDisksNames, NULL, &disk_ctx )) return;
285 if (SetupGetIntField( &disk_ctx, 0, &id ) && (id == diskid)) break;
286 if (!SetupFindNextLine( &disk_ctx, &disk_ctx )) return;
289 /* and fill in the missing info */
293 if (SetupGetStringFieldW( &disk_ctx, 1, NULL, 0, &len ) &&
294 (op->src_descr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
295 SetupGetStringFieldW( &disk_ctx, 1, op->src_descr, len, NULL );
299 if (SetupGetStringFieldW( &disk_ctx, 2, NULL, 0, &len ) &&
300 (op->src_tag = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
301 SetupGetStringFieldW( &disk_ctx, 2, op->src_tag, len, NULL );
303 if (!op->src_path && !(op->style & SP_COPY_SOURCE_ABSOLUTE))
306 if (!(op->style & SP_COPY_SOURCEPATH_ABSOLUTE))
308 /* retrieve relative path for this disk */
309 if (!SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len )) len = 0;
311 /* retrieve relative path for this file */
312 if (!SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len2 )) len2 = 0;
315 (op->src_path = HeapAlloc( GetProcessHeap(), 0, (len+len2)*sizeof(WCHAR) )))
317 WCHAR *ptr = op->src_path;
320 SetupGetStringFieldW( &disk_ctx, 4, op->src_path, len, NULL );
321 ptr = op->src_path + strlenW(op->src_path);
322 if (len2 && ptr > op->src_path && ptr[-1] != '\\') *ptr++ = '\\';
324 if (!SetupGetStringFieldW( &file_ctx, 2, ptr, len2, NULL )) *ptr = 0;
327 if (!op->src_root) op->src_root = PARSER_get_src_root(hinf);
331 /***********************************************************************
332 * get_destination_dir
334 * Retrieve the destination dir for a given section.
336 static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
338 static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
339 static const WCHAR Def[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
342 if (!SetupFindFirstLineW( hinf, Dest, section, &context ) &&
343 !SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL;
344 return PARSER_get_dest_dir( &context );
348 static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD );
350 /***********************************************************************
351 * extract_cabinet_file
353 * Extract a file from a .cab file.
355 static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root,
356 const WCHAR *src, const WCHAR *dst )
358 static const WCHAR extW[] = {'.','c','a','b',0};
359 static HMODULE advpack;
361 char *cab_path, *cab_file;
362 int len = strlenW( cabinet );
364 /* make sure the cabinet file has a .cab extension */
365 if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE;
368 if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" )))
370 ERR( "could not load advpack.dll\n" );
373 if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" )))
375 ERR( "could not find ExtractFiles in advpack.dll\n" );
380 if (!(cab_path = strdupWtoA( root ))) return FALSE;
381 len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL );
382 if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 )))
384 HeapFree( GetProcessHeap(), 0, cab_path );
387 strcpy( cab_file, cab_path );
388 if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" );
389 WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL );
390 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) );
391 pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 );
392 HeapFree( GetProcessHeap(), 0, cab_file );
393 HeapFree( GetProcessHeap(), 0, cab_path );
394 return CopyFileW( src, dst, FALSE /*FIXME*/ );
398 /***********************************************************************
399 * SetupOpenFileQueue (SETUPAPI.@)
401 HSPFILEQ WINAPI SetupOpenFileQueue(void)
403 struct file_queue *queue;
405 if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue))))
406 return INVALID_HANDLE_VALUE;
411 /***********************************************************************
412 * SetupCloseFileQueue (SETUPAPI.@)
414 BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle )
416 struct file_queue *queue = handle;
418 free_file_op_queue( &queue->copy_queue );
419 free_file_op_queue( &queue->rename_queue );
420 free_file_op_queue( &queue->delete_queue );
421 HeapFree( GetProcessHeap(), 0, queue );
426 /***********************************************************************
427 * SetupQueueCopyIndirectA (SETUPAPI.@)
429 BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params )
431 struct file_queue *queue = params->QueueHandle;
434 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
435 op->style = params->CopyStyle;
436 op->src_root = strdupAtoW( params->SourceRootPath );
437 op->src_path = strdupAtoW( params->SourcePath );
438 op->src_file = strdupAtoW( params->SourceFilename );
439 op->src_descr = strdupAtoW( params->SourceDescription );
440 op->src_tag = strdupAtoW( params->SourceTagfile );
441 op->dst_path = strdupAtoW( params->TargetDirectory );
442 op->dst_file = strdupAtoW( params->TargetFilename );
445 if (!op->src_file) op->src_file = op->dst_file;
446 if (params->LayoutInf)
448 get_src_file_info( params->LayoutInf, op );
449 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
452 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
453 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
454 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
455 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
457 queue_file_op( &queue->copy_queue, op );
462 /***********************************************************************
463 * SetupQueueCopyIndirectW (SETUPAPI.@)
465 BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params )
467 struct file_queue *queue = params->QueueHandle;
470 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
471 op->style = params->CopyStyle;
472 op->src_root = strdupW( params->SourceRootPath );
473 op->src_path = strdupW( params->SourcePath );
474 op->src_file = strdupW( params->SourceFilename );
475 op->src_descr = strdupW( params->SourceDescription );
476 op->src_tag = strdupW( params->SourceTagfile );
477 op->dst_path = strdupW( params->TargetDirectory );
478 op->dst_file = strdupW( params->TargetFilename );
481 if (!op->src_file) op->src_file = op->dst_file;
482 if (params->LayoutInf)
484 get_src_file_info( params->LayoutInf, op );
485 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
488 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
489 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
490 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
491 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
493 queue_file_op( &queue->copy_queue, op );
498 /***********************************************************************
499 * SetupQueueCopyA (SETUPAPI.@)
501 BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file,
502 PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file,
505 SP_FILE_COPY_PARAMS_A params;
507 params.cbSize = sizeof(params);
508 params.QueueHandle = queue;
509 params.SourceRootPath = src_root;
510 params.SourcePath = src_path;
511 params.SourceFilename = src_file;
512 params.SourceDescription = src_descr;
513 params.SourceTagfile = src_tag;
514 params.TargetDirectory = dst_dir;
515 params.TargetFilename = dst_file;
516 params.CopyStyle = style;
517 params.LayoutInf = 0;
518 params.SecurityDescriptor = NULL;
519 return SetupQueueCopyIndirectA( ¶ms );
523 /***********************************************************************
524 * SetupQueueCopyW (SETUPAPI.@)
526 BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file,
527 PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file,
530 SP_FILE_COPY_PARAMS_W params;
532 params.cbSize = sizeof(params);
533 params.QueueHandle = queue;
534 params.SourceRootPath = src_root;
535 params.SourcePath = src_path;
536 params.SourceFilename = src_file;
537 params.SourceDescription = src_descr;
538 params.SourceTagfile = src_tag;
539 params.TargetDirectory = dst_dir;
540 params.TargetFilename = dst_file;
541 params.CopyStyle = style;
542 params.LayoutInf = 0;
543 params.SecurityDescriptor = NULL;
544 return SetupQueueCopyIndirectW( ¶ms );
548 /***********************************************************************
549 * SetupQueueDefaultCopyA (SETUPAPI.@)
551 BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file,
552 PCSTR dst_file, DWORD style )
554 SP_FILE_COPY_PARAMS_A params;
556 params.cbSize = sizeof(params);
557 params.QueueHandle = queue;
558 params.SourceRootPath = src_root;
559 params.SourcePath = NULL;
560 params.SourceFilename = src_file;
561 params.SourceDescription = NULL;
562 params.SourceTagfile = NULL;
563 params.TargetDirectory = NULL;
564 params.TargetFilename = dst_file;
565 params.CopyStyle = style;
566 params.LayoutInf = hinf;
567 params.SecurityDescriptor = NULL;
568 return SetupQueueCopyIndirectA( ¶ms );
572 /***********************************************************************
573 * SetupQueueDefaultCopyW (SETUPAPI.@)
575 BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file,
576 PCWSTR dst_file, DWORD style )
578 SP_FILE_COPY_PARAMS_W 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 SetupQueueCopyIndirectW( ¶ms );
596 /***********************************************************************
597 * SetupQueueDeleteA (SETUPAPI.@)
599 BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 )
601 struct file_queue *queue = handle;
604 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
609 op->src_descr = NULL;
611 op->dst_path = strdupAtoW( part1 );
612 op->dst_file = strdupAtoW( part2 );
613 queue_file_op( &queue->delete_queue, op );
618 /***********************************************************************
619 * SetupQueueDeleteW (SETUPAPI.@)
621 BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 )
623 struct file_queue *queue = handle;
626 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
631 op->src_descr = NULL;
633 op->dst_path = strdupW( part1 );
634 op->dst_file = strdupW( part2 );
635 queue_file_op( &queue->delete_queue, op );
640 /***********************************************************************
641 * SetupQueueRenameA (SETUPAPI.@)
643 BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename,
644 PCSTR TargetPath, PCSTR TargetFilename )
646 struct file_queue *queue = handle;
649 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
652 op->src_path = strdupAtoW( SourcePath );
653 op->src_file = strdupAtoW( SourceFilename );
654 op->src_descr = NULL;
656 op->dst_path = strdupAtoW( TargetPath );
657 op->dst_file = strdupAtoW( TargetFilename );
658 queue_file_op( &queue->rename_queue, op );
663 /***********************************************************************
664 * SetupQueueRenameW (SETUPAPI.@)
666 BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename,
667 PCWSTR TargetPath, PCWSTR TargetFilename )
669 struct file_queue *queue = handle;
672 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
675 op->src_path = strdupW( SourcePath );
676 op->src_file = strdupW( SourceFilename );
677 op->src_descr = NULL;
679 op->dst_path = strdupW( TargetPath );
680 op->dst_file = strdupW( TargetFilename );
681 queue_file_op( &queue->rename_queue, op );
686 /***********************************************************************
687 * SetupQueueCopySectionA (SETUPAPI.@)
689 BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist,
690 PCSTR section, DWORD style )
692 UNICODE_STRING sectionW;
695 if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
697 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
701 ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style );
705 if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root ))
707 ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style );
708 RtlFreeUnicodeString( &srcW );
710 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
712 RtlFreeUnicodeString( §ionW );
717 /***********************************************************************
718 * SetupQueueCopySectionW (SETUPAPI.@)
720 BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist,
721 PCWSTR section, DWORD style )
723 SP_FILE_COPY_PARAMS_W params;
725 WCHAR dest[MAX_PATH], src[MAX_PATH];
728 TRACE( "hinf=%p/%p section=%s root=%s\n",
729 hinf, hlist, debugstr_w(section), debugstr_w(src_root) );
731 params.cbSize = sizeof(params);
732 params.QueueHandle = queue;
733 params.SourceRootPath = src_root;
734 params.SourcePath = NULL;
735 params.SourceDescription = NULL;
736 params.SourceTagfile = NULL;
737 params.TargetFilename = dest;
738 params.CopyStyle = style;
739 params.LayoutInf = hinf;
740 params.SecurityDescriptor = NULL;
742 if (!hlist) hlist = hinf;
743 if (!hinf) hinf = hlist;
744 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
745 if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) return FALSE;
748 if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL ))
750 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0;
751 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */
753 params.SourceFilename = *src ? src : NULL;
754 if (!SetupQueueCopyIndirectW( ¶ms )) return FALSE;
755 } while (SetupFindNextLine( &context, &context ));
760 /***********************************************************************
761 * SetupQueueDeleteSectionA (SETUPAPI.@)
763 BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
765 UNICODE_STRING sectionW;
768 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
770 ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer );
771 RtlFreeUnicodeString( §ionW );
773 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
778 /***********************************************************************
779 * SetupQueueDeleteSectionW (SETUPAPI.@)
781 BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
785 WCHAR buffer[MAX_PATH];
789 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
791 if (!hlist) hlist = hinf;
792 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
793 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
796 if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
798 if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
799 if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done;
800 } while (SetupFindNextLine( &context, &context ));
804 HeapFree( GetProcessHeap(), 0, dest_dir );
809 /***********************************************************************
810 * SetupQueueRenameSectionA (SETUPAPI.@)
812 BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
814 UNICODE_STRING sectionW;
817 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
819 ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer );
820 RtlFreeUnicodeString( §ionW );
822 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
827 /***********************************************************************
828 * SetupQueueRenameSectionW (SETUPAPI.@)
830 BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
834 WCHAR src[MAX_PATH], dst[MAX_PATH];
837 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
839 if (!hlist) hlist = hinf;
840 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
841 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
844 if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL ))
846 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL ))
848 if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done;
849 } while (SetupFindNextLine( &context, &context ));
853 HeapFree( GetProcessHeap(), 0, dest_dir );
858 /***********************************************************************
859 * SetupCommitFileQueueA (SETUPAPI.@)
861 BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler,
864 struct callback_WtoA_context ctx;
866 ctx.orig_context = context;
867 ctx.orig_handler = handler;
868 return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx );
872 /***********************************************************************
875 * Recursively create all directories in the path.
877 static BOOL create_full_pathW(const WCHAR *path)
883 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
884 strcpyW(new_path, path);
886 while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
887 new_path[len - 1] = 0;
889 while(!CreateDirectoryW(new_path, NULL))
892 DWORD last_error = GetLastError();
894 if(last_error == ERROR_ALREADY_EXISTS)
897 if(last_error != ERROR_PATH_NOT_FOUND)
903 if(!(slash = strrchrW(new_path, '\\')))
909 len = slash - new_path;
911 if(!create_full_pathW(new_path))
916 new_path[len] = '\\';
919 HeapFree(GetProcessHeap(), 0, new_path);
923 static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style,
924 PSP_FILE_CALLBACK_W handler, PVOID context )
929 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source),debugstr_w(target),style);
931 /* before copy processing */
932 if (style & SP_COPY_REPLACEONLY)
934 if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES)
937 if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER))
939 DWORD VersionSizeSource=0;
940 DWORD VersionSizeTarget=0;
944 * This is sort of an interesting workaround. You see, calling
945 * GetVersionInfoSize on a builtin dll loads that dll into memory
946 * and we do not properly unload builtin dlls.. so we effectively
947 * lock into memory all the targets we are replacing. This leads
948 * to problems when we try to register the replaced dlls.
950 * So I will test for the existence of the files first so that
951 * we just basically unconditionally replace the builtin versions.
953 if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) &&
954 (GetFileAttributesW(source) != INVALID_FILE_ATTRIBUTES))
956 VersionSizeSource = GetFileVersionInfoSizeW(source,&zero);
957 VersionSizeTarget = GetFileVersionInfoSizeW(target,&zero);
960 TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget,
963 if (VersionSizeSource && VersionSizeTarget)
965 LPVOID VersionSource;
966 LPVOID VersionTarget;
967 VS_FIXEDFILEINFO *TargetInfo;
968 VS_FIXEDFILEINFO *SourceInfo;
970 WCHAR SubBlock[2]={'\\',0};
973 VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource);
974 VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget);
976 ret = GetFileVersionInfoW(source,0,VersionSizeSource,VersionSource);
978 ret = GetFileVersionInfoW(target, 0, VersionSizeTarget,
983 ret = VerQueryValueW(VersionSource, SubBlock,
984 (LPVOID*)&SourceInfo, &length);
986 ret = VerQueryValueW(VersionTarget, SubBlock,
987 (LPVOID*)&TargetInfo, &length);
991 FILEPATHS_W filepaths;
993 TRACE("Versions: Source %i.%i target %i.%i\n",
994 SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS,
995 TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS);
997 /* used in case of notification */
998 filepaths.Target = target;
999 filepaths.Source = source;
1000 filepaths.Win32Error = 0;
1001 filepaths.Flags = 0;
1003 if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS)
1006 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1010 else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS)
1011 && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS))
1014 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1018 else if ((style & SP_COPY_NEWER_ONLY) &&
1019 (TargetInfo->dwFileVersionMS ==
1020 SourceInfo->dwFileVersionMS)
1021 &&(TargetInfo->dwFileVersionLS ==
1022 SourceInfo->dwFileVersionLS))
1025 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1031 HeapFree(GetProcessHeap(),0,VersionSource);
1032 HeapFree(GetProcessHeap(),0,VersionTarget);
1035 if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE))
1037 if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES)
1039 FIXME("Notify user target file exists\n");
1043 if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE |
1044 SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP))
1046 ERR("Unsupported style(s) 0x%x\n",style);
1051 rc = CopyFileW(source,target,FALSE);
1052 TRACE("Did copy... rc was %i\n",rc);
1055 /* after copy processing */
1056 if (style & SP_COPY_DELETESOURCE)
1059 DeleteFileW(source);
1065 /***********************************************************************
1066 * SetupInstallFileExA (SETUPAPI.@)
1068 BOOL WINAPI SetupInstallFileExA( HINF hinf, PINFCONTEXT inf_context, PCSTR source, PCSTR root,
1069 PCSTR dest, DWORD style, PSP_FILE_CALLBACK_A handler, PVOID context, PBOOL in_use )
1072 struct callback_WtoA_context ctx;
1073 UNICODE_STRING sourceW, rootW, destW;
1075 TRACE("%p %p %s %s %s %x %p %p %p\n", hinf, inf_context, debugstr_a(source), debugstr_a(root),
1076 debugstr_a(dest), style, handler, context, in_use);
1078 sourceW.Buffer = rootW.Buffer = destW.Buffer = NULL;
1079 if (source && !RtlCreateUnicodeStringFromAsciiz( &sourceW, source ))
1081 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1084 if (root && !RtlCreateUnicodeStringFromAsciiz( &rootW, root ))
1086 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1089 if (dest && !RtlCreateUnicodeStringFromAsciiz( &destW, dest ))
1091 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1095 ctx.orig_context = context;
1096 ctx.orig_handler = handler;
1098 ret = SetupInstallFileExW( hinf, inf_context, sourceW.Buffer, rootW.Buffer, destW.Buffer, style, QUEUE_callback_WtoA, &ctx, in_use );
1101 RtlFreeUnicodeString( &sourceW );
1102 RtlFreeUnicodeString( &rootW );
1103 RtlFreeUnicodeString( &destW );
1107 /***********************************************************************
1108 * SetupInstallFileA (SETUPAPI.@)
1110 BOOL WINAPI SetupInstallFileA( HINF hinf, PINFCONTEXT inf_context, PCSTR source, PCSTR root,
1111 PCSTR dest, DWORD style, PSP_FILE_CALLBACK_A handler, PVOID context )
1113 return SetupInstallFileExA( hinf, inf_context, source, root, dest, style, handler, context, NULL );
1116 /***********************************************************************
1117 * SetupInstallFileExW (SETUPAPI.@)
1119 BOOL WINAPI SetupInstallFileExW( HINF hinf, PINFCONTEXT inf_context, PCWSTR source, PCWSTR root,
1120 PCWSTR dest, DWORD style, PSP_FILE_CALLBACK_W handler, PVOID context, PBOOL in_use )
1122 static const WCHAR CopyFiles[] = {'C','o','p','y','F','i','l','e','s',0};
1124 BOOL ret, absolute = (root && *root && !(style & SP_COPY_SOURCE_ABSOLUTE));
1125 WCHAR *buffer, *p, *inf_source = NULL;
1128 TRACE("%p %p %s %s %s %x %p %p %p\n", hinf, inf_context, debugstr_w(source), debugstr_w(root),
1129 debugstr_w(dest), style, handler, context, in_use);
1131 if (in_use) FIXME("no file in use support\n");
1140 if (!SetupFindFirstLineW( hinf, CopyFiles, NULL, inf_context )) return FALSE;
1142 if (!SetupGetStringFieldW( inf_context, 1, NULL, 0, &len )) return FALSE;
1143 if (!(inf_source = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1145 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1148 if (!SetupGetStringFieldW( inf_context, 1, inf_source, len, NULL )) return FALSE;
1149 source = inf_source;
1153 SetLastError( ERROR_INVALID_PARAMETER );
1157 len = strlenW( source ) + 1;
1158 if (absolute) len += strlenW( root ) + 1;
1160 if (!(p = buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1162 HeapFree( GetProcessHeap(), 0, inf_source );
1163 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1169 strcpyW( buffer, root );
1170 p += strlenW( buffer );
1171 if (p[-1] != '\\') *p++ = '\\';
1173 while (*source == '\\') source++;
1174 strcpyW( p, source );
1176 ret = do_file_copyW( buffer, dest, style, handler, context );
1178 HeapFree( GetProcessHeap(), 0, inf_source );
1179 HeapFree( GetProcessHeap(), 0, buffer );
1183 /***********************************************************************
1184 * SetupInstallFileW (SETUPAPI.@)
1186 BOOL WINAPI SetupInstallFileW( HINF hinf, PINFCONTEXT inf_context, PCWSTR source, PCWSTR root,
1187 PCWSTR dest, DWORD style, PSP_FILE_CALLBACK_W handler, PVOID context )
1189 return SetupInstallFileExW( hinf, inf_context, source, root, dest, style, handler, context, NULL );
1192 /***********************************************************************
1193 * SetupCommitFileQueueW (SETUPAPI.@)
1195 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler,
1198 struct file_queue *queue = handle;
1200 BOOL result = FALSE;
1204 paths.Source = paths.Target = NULL;
1206 if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count)
1207 return TRUE; /* nothing to do */
1209 if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE;
1211 /* perform deletes */
1213 if (queue->delete_queue.count)
1215 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE,
1216 queue->delete_queue.count ))) goto done;
1217 for (op = queue->delete_queue.head; op; op = op->next)
1219 build_filepathsW( op, &paths );
1220 op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE);
1221 if (op_result == FILEOP_ABORT) goto done;
1222 while (op_result == FILEOP_DOIT)
1224 TRACE( "deleting file %s\n", debugstr_w(paths.Target) );
1225 if (DeleteFileW( paths.Target )) break; /* success */
1226 paths.Win32Error = GetLastError();
1227 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 );
1228 if (op_result == FILEOP_ABORT) goto done;
1230 handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 );
1232 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 );
1235 /* perform renames */
1237 if (queue->rename_queue.count)
1239 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME,
1240 queue->rename_queue.count ))) goto done;
1241 for (op = queue->rename_queue.head; op; op = op->next)
1243 build_filepathsW( op, &paths );
1244 op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME);
1245 if (op_result == FILEOP_ABORT) goto done;
1246 while (op_result == FILEOP_DOIT)
1248 TRACE( "renaming file %s -> %s\n",
1249 debugstr_w(paths.Source), debugstr_w(paths.Target) );
1250 if (MoveFileW( paths.Source, paths.Target )) break; /* success */
1251 paths.Win32Error = GetLastError();
1252 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 );
1253 if (op_result == FILEOP_ABORT) goto done;
1255 handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 );
1257 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 );
1260 /* perform copies */
1262 if (queue->copy_queue.count)
1264 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY,
1265 queue->copy_queue.count ))) goto done;
1266 for (op = queue->copy_queue.head; op; op = op->next)
1268 WCHAR newpath[MAX_PATH];
1270 build_filepathsW( op, &paths );
1271 op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
1272 if (op_result == FILEOP_ABORT) goto done;
1273 if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT;
1274 while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
1276 TRACE( "copying file %s -> %s\n",
1277 debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ),
1278 debugstr_w(paths.Target) );
1281 if (!create_full_pathW( op->dst_path ))
1283 paths.Win32Error = GetLastError();
1284 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1285 (UINT_PTR)&paths, (UINT_PTR)newpath );
1286 if (op_result == FILEOP_ABORT) goto done;
1289 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
1290 paths.Target, op->style, handler, context )) break; /* success */
1291 /* try to extract it from the cabinet file */
1294 if (extract_cabinet_file( op->src_tag, op->src_root,
1295 paths.Source, paths.Target )) break;
1297 paths.Win32Error = GetLastError();
1298 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1299 (UINT_PTR)&paths, (UINT_PTR)newpath );
1300 if (op_result == FILEOP_ABORT) goto done;
1302 handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
1304 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 );
1311 handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 );
1312 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1313 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1318 /***********************************************************************
1319 * SetupScanFileQueueA (SETUPAPI.@)
1321 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ handle, DWORD flags, HWND window,
1322 PSP_FILE_CALLBACK_A handler, PVOID context, PDWORD result )
1324 struct callback_WtoA_context ctx;
1326 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
1328 ctx.orig_context = context;
1329 ctx.orig_handler = handler;
1331 return SetupScanFileQueueW( handle, flags, window, QUEUE_callback_WtoA, &ctx, result );
1335 /***********************************************************************
1336 * SetupScanFileQueueW (SETUPAPI.@)
1338 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ handle, DWORD flags, HWND window,
1339 PSP_FILE_CALLBACK_W handler, PVOID context, PDWORD result )
1341 struct file_queue *queue = handle;
1344 UINT notification = 0;
1347 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
1349 if (!queue->copy_queue.count) return TRUE;
1351 if (flags & SPQ_SCAN_USE_CALLBACK) notification = SPFILENOTIFY_QUEUESCAN;
1352 else if (flags & SPQ_SCAN_USE_CALLBACKEX) notification = SPFILENOTIFY_QUEUESCAN_EX;
1354 if (flags & ~(SPQ_SCAN_USE_CALLBACK | SPQ_SCAN_USE_CALLBACKEX))
1356 FIXME("flags %x not fully implemented\n", flags);
1359 paths.Source = paths.Target = NULL;
1361 for (op = queue->copy_queue.head; op; op = op->next)
1363 build_filepathsW( op, &paths );
1364 switch (notification)
1366 case SPFILENOTIFY_QUEUESCAN:
1367 /* FIXME: handle delay flag */
1368 if (handler( context, notification, (UINT_PTR)paths.Target, 0 )) goto done;
1370 case SPFILENOTIFY_QUEUESCAN_EX:
1371 if (handler( context, notification, (UINT_PTR)&paths, 0 )) goto done;
1374 ret = TRUE; goto done;
1381 if (result) *result = 0;
1382 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1383 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1388 /***********************************************************************
1389 * SetupGetFileQueueCount (SETUPAPI.@)
1391 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result )
1393 struct file_queue *queue = handle;
1398 *result = queue->copy_queue.count;
1401 *result = queue->rename_queue.count;
1404 *result = queue->delete_queue.count;
1411 /***********************************************************************
1412 * SetupGetFileQueueFlags (SETUPAPI.@)
1414 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags )
1416 struct file_queue *queue = handle;
1417 *flags = queue->flags;
1422 /***********************************************************************
1423 * SetupSetFileQueueFlags (SETUPAPI.@)
1425 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags )
1427 struct file_queue *queue = handle;
1428 queue->flags = (queue->flags & ~mask) | flags;
1433 /***********************************************************************
1434 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1436 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile)
1438 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile));
1443 /***********************************************************************
1444 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1446 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile)
1448 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile));
1453 /***********************************************************************
1454 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1456 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner )
1458 return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL );
1462 /***********************************************************************
1463 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1465 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg,
1466 DWORD reserved1, PVOID reserved2 )
1468 struct default_callback_context *context;
1470 if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) )))
1472 context->owner = owner;
1473 context->progress = progress;
1474 context->message = msg;
1480 /***********************************************************************
1481 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1483 void WINAPI SetupTermDefaultQueueCallback( PVOID context )
1485 HeapFree( GetProcessHeap(), 0, context );
1489 /***********************************************************************
1490 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1492 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification,
1493 UINT_PTR param1, UINT_PTR param2 )
1495 FILEPATHS_A *paths = (FILEPATHS_A *)param1;
1496 struct default_callback_context *ctx = context;
1498 switch(notification)
1500 case SPFILENOTIFY_STARTQUEUE:
1501 TRACE( "start queue\n" );
1503 case SPFILENOTIFY_ENDQUEUE:
1504 TRACE( "end queue\n" );
1506 case SPFILENOTIFY_STARTSUBQUEUE:
1507 TRACE( "start subqueue %ld count %ld\n", param1, param2 );
1509 case SPFILENOTIFY_ENDSUBQUEUE:
1510 TRACE( "end subqueue %ld\n", param1 );
1512 case SPFILENOTIFY_STARTDELETE:
1513 TRACE( "start delete %s\n", debugstr_a(paths->Target) );
1515 case SPFILENOTIFY_ENDDELETE:
1516 TRACE( "end delete %s\n", debugstr_a(paths->Target) );
1518 case SPFILENOTIFY_DELETEERROR:
1519 /*Windows Ignores attempts to delete files / folders which do not exist*/
1520 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1521 SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1523 case SPFILENOTIFY_STARTRENAME:
1524 TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1526 case SPFILENOTIFY_ENDRENAME:
1527 TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1529 case SPFILENOTIFY_RENAMEERROR:
1530 SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1532 case SPFILENOTIFY_STARTCOPY:
1533 TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1535 case SPFILENOTIFY_ENDCOPY:
1536 TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1538 case SPFILENOTIFY_COPYERROR:
1539 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1540 debugstr_a(paths->Source), debugstr_a(paths->Target) );
1542 case SPFILENOTIFY_NEEDMEDIA:
1543 TRACE( "need media\n" );
1546 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
1553 /***********************************************************************
1554 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1556 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification,
1557 UINT_PTR param1, UINT_PTR param2 )
1559 FILEPATHS_W *paths = (FILEPATHS_W *)param1;
1560 struct default_callback_context *ctx = context;
1562 switch(notification)
1564 case SPFILENOTIFY_STARTQUEUE:
1565 TRACE( "start queue\n" );
1567 case SPFILENOTIFY_ENDQUEUE:
1568 TRACE( "end queue\n" );
1570 case SPFILENOTIFY_STARTSUBQUEUE:
1571 TRACE( "start subqueue %ld count %ld\n", param1, param2 );
1573 case SPFILENOTIFY_ENDSUBQUEUE:
1574 TRACE( "end subqueue %ld\n", param1 );
1576 case SPFILENOTIFY_STARTDELETE:
1577 TRACE( "start delete %s\n", debugstr_w(paths->Target) );
1579 case SPFILENOTIFY_ENDDELETE:
1580 TRACE( "end delete %s\n", debugstr_w(paths->Target) );
1582 case SPFILENOTIFY_DELETEERROR:
1583 /*Windows Ignores attempts to delete files / folders which do not exist*/
1584 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1585 SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1587 case SPFILENOTIFY_STARTRENAME:
1588 SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1590 case SPFILENOTIFY_ENDRENAME:
1591 TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1593 case SPFILENOTIFY_RENAMEERROR:
1594 ERR( "rename error %d %s -> %s\n", paths->Win32Error,
1595 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1597 case SPFILENOTIFY_STARTCOPY:
1598 TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1600 case SPFILENOTIFY_ENDCOPY:
1601 TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1603 case SPFILENOTIFY_COPYERROR:
1604 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1605 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1607 case SPFILENOTIFY_NEEDMEDIA:
1608 TRACE( "need media\n" );
1611 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
1617 /***********************************************************************
1618 * SetupDeleteErrorA (SETUPAPI.@)
1621 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file,
1622 UINT w32error, DWORD style)
1624 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1625 w32error, debugstr_a(file) );
1626 return DPROMPT_SKIPFILE;
1629 /***********************************************************************
1630 * SetupDeleteErrorW (SETUPAPI.@)
1633 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file,
1634 UINT w32error, DWORD style)
1636 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1637 w32error, debugstr_w(file) );
1638 return DPROMPT_SKIPFILE;
1641 /***********************************************************************
1642 * SetupRenameErrorA (SETUPAPI.@)
1645 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source,
1646 PCSTR target, UINT w32error, DWORD style)
1648 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1649 w32error, debugstr_a(source), debugstr_a(target));
1650 return DPROMPT_SKIPFILE;
1653 /***********************************************************************
1654 * SetupRenameErrorW (SETUPAPI.@)
1657 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source,
1658 PCWSTR target, UINT w32error, DWORD style)
1660 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1661 w32error, debugstr_w(source), debugstr_w(target));
1662 return DPROMPT_SKIPFILE;
1666 /***********************************************************************
1667 * SetupCopyErrorA (SETUPAPI.@)
1670 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname,
1671 PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath,
1672 UINT w32error, DWORD style, PSTR pathbuffer,
1673 DWORD buffersize, PDWORD requiredsize)
1675 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1676 w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath));
1677 return DPROMPT_SKIPFILE;
1680 /***********************************************************************
1681 * SetupCopyErrorW (SETUPAPI.@)
1684 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname,
1685 PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath,
1686 UINT w32error, DWORD style, PWSTR pathbuffer,
1687 DWORD buffersize, PDWORD requiredsize)
1689 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1690 w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath));
1691 return DPROMPT_SKIPFILE;
1694 /***********************************************************************
1695 * pSetupGetQueueFlags (SETUPAPI.@)
1697 DWORD WINAPI pSetupGetQueueFlags( HSPFILEQ handle )
1699 struct file_queue *queue = handle;
1700 return queue->flags;
1703 /***********************************************************************
1704 * pSetupSetQueueFlags (SETUPAPI.@)
1706 BOOL WINAPI pSetupSetQueueFlags( HSPFILEQ handle, DWORD flags )
1708 struct file_queue *queue = handle;
1709 queue->flags = flags;