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};
341 WCHAR systemdir[MAX_PATH], *dir;
344 if (!(ret = SetupFindFirstLineW( hinf, Dest, section, &context )))
345 ret = SetupFindFirstLineW( hinf, Dest, Def, &context );
347 if (ret && (dir = PARSER_get_dest_dir( &context )))
350 GetSystemDirectoryW( systemdir, MAX_PATH );
351 return strdupW( systemdir );
355 static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD );
357 /***********************************************************************
358 * extract_cabinet_file
360 * Extract a file from a .cab file.
362 static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root,
363 const WCHAR *src, const WCHAR *dst )
365 static const WCHAR extW[] = {'.','c','a','b',0};
366 static HMODULE advpack;
368 char *cab_path, *cab_file;
369 int len = strlenW( cabinet );
371 /* make sure the cabinet file has a .cab extension */
372 if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE;
375 if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" )))
377 ERR( "could not load advpack.dll\n" );
380 if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" )))
382 ERR( "could not find ExtractFiles in advpack.dll\n" );
387 if (!(cab_path = strdupWtoA( root ))) return FALSE;
388 len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL );
389 if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 )))
391 HeapFree( GetProcessHeap(), 0, cab_path );
394 strcpy( cab_file, cab_path );
395 if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" );
396 WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL );
397 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) );
398 pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 );
399 HeapFree( GetProcessHeap(), 0, cab_file );
400 HeapFree( GetProcessHeap(), 0, cab_path );
401 return CopyFileW( src, dst, FALSE /*FIXME*/ );
405 /***********************************************************************
406 * SetupOpenFileQueue (SETUPAPI.@)
408 HSPFILEQ WINAPI SetupOpenFileQueue(void)
410 struct file_queue *queue;
412 if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue))))
413 return INVALID_HANDLE_VALUE;
418 /***********************************************************************
419 * SetupCloseFileQueue (SETUPAPI.@)
421 BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle )
423 struct file_queue *queue = handle;
425 free_file_op_queue( &queue->copy_queue );
426 free_file_op_queue( &queue->rename_queue );
427 free_file_op_queue( &queue->delete_queue );
428 HeapFree( GetProcessHeap(), 0, queue );
433 /***********************************************************************
434 * SetupQueueCopyIndirectA (SETUPAPI.@)
436 BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params )
438 struct file_queue *queue = params->QueueHandle;
441 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
442 op->style = params->CopyStyle;
443 op->src_root = strdupAtoW( params->SourceRootPath );
444 op->src_path = strdupAtoW( params->SourcePath );
445 op->src_file = strdupAtoW( params->SourceFilename );
446 op->src_descr = strdupAtoW( params->SourceDescription );
447 op->src_tag = strdupAtoW( params->SourceTagfile );
448 op->dst_path = strdupAtoW( params->TargetDirectory );
449 op->dst_file = strdupAtoW( params->TargetFilename );
452 if (!op->src_file) op->src_file = op->dst_file;
453 if (params->LayoutInf)
455 get_src_file_info( params->LayoutInf, op );
456 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
459 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
460 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
461 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
462 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
464 queue_file_op( &queue->copy_queue, op );
469 /***********************************************************************
470 * SetupQueueCopyIndirectW (SETUPAPI.@)
472 BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params )
474 struct file_queue *queue = params->QueueHandle;
477 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
478 op->style = params->CopyStyle;
479 op->src_root = strdupW( params->SourceRootPath );
480 op->src_path = strdupW( params->SourcePath );
481 op->src_file = strdupW( params->SourceFilename );
482 op->src_descr = strdupW( params->SourceDescription );
483 op->src_tag = strdupW( params->SourceTagfile );
484 op->dst_path = strdupW( params->TargetDirectory );
485 op->dst_file = strdupW( params->TargetFilename );
488 if (!op->src_file) op->src_file = op->dst_file;
489 if (params->LayoutInf)
491 get_src_file_info( params->LayoutInf, op );
492 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
495 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
496 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
497 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
498 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
500 queue_file_op( &queue->copy_queue, op );
505 /***********************************************************************
506 * SetupQueueCopyA (SETUPAPI.@)
508 BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file,
509 PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file,
512 SP_FILE_COPY_PARAMS_A params;
514 params.cbSize = sizeof(params);
515 params.QueueHandle = queue;
516 params.SourceRootPath = src_root;
517 params.SourcePath = src_path;
518 params.SourceFilename = src_file;
519 params.SourceDescription = src_descr;
520 params.SourceTagfile = src_tag;
521 params.TargetDirectory = dst_dir;
522 params.TargetFilename = dst_file;
523 params.CopyStyle = style;
524 params.LayoutInf = 0;
525 params.SecurityDescriptor = NULL;
526 return SetupQueueCopyIndirectA( ¶ms );
530 /***********************************************************************
531 * SetupQueueCopyW (SETUPAPI.@)
533 BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file,
534 PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file,
537 SP_FILE_COPY_PARAMS_W params;
539 params.cbSize = sizeof(params);
540 params.QueueHandle = queue;
541 params.SourceRootPath = src_root;
542 params.SourcePath = src_path;
543 params.SourceFilename = src_file;
544 params.SourceDescription = src_descr;
545 params.SourceTagfile = src_tag;
546 params.TargetDirectory = dst_dir;
547 params.TargetFilename = dst_file;
548 params.CopyStyle = style;
549 params.LayoutInf = 0;
550 params.SecurityDescriptor = NULL;
551 return SetupQueueCopyIndirectW( ¶ms );
555 /***********************************************************************
556 * SetupQueueDefaultCopyA (SETUPAPI.@)
558 BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file,
559 PCSTR dst_file, DWORD style )
561 SP_FILE_COPY_PARAMS_A params;
563 params.cbSize = sizeof(params);
564 params.QueueHandle = queue;
565 params.SourceRootPath = src_root;
566 params.SourcePath = NULL;
567 params.SourceFilename = src_file;
568 params.SourceDescription = NULL;
569 params.SourceTagfile = NULL;
570 params.TargetDirectory = NULL;
571 params.TargetFilename = dst_file;
572 params.CopyStyle = style;
573 params.LayoutInf = hinf;
574 params.SecurityDescriptor = NULL;
575 return SetupQueueCopyIndirectA( ¶ms );
579 /***********************************************************************
580 * SetupQueueDefaultCopyW (SETUPAPI.@)
582 BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file,
583 PCWSTR dst_file, DWORD style )
585 SP_FILE_COPY_PARAMS_W params;
587 params.cbSize = sizeof(params);
588 params.QueueHandle = queue;
589 params.SourceRootPath = src_root;
590 params.SourcePath = NULL;
591 params.SourceFilename = src_file;
592 params.SourceDescription = NULL;
593 params.SourceTagfile = NULL;
594 params.TargetDirectory = NULL;
595 params.TargetFilename = dst_file;
596 params.CopyStyle = style;
597 params.LayoutInf = hinf;
598 params.SecurityDescriptor = NULL;
599 return SetupQueueCopyIndirectW( ¶ms );
603 /***********************************************************************
604 * SetupQueueDeleteA (SETUPAPI.@)
606 BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 )
608 struct file_queue *queue = handle;
611 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
616 op->src_descr = NULL;
618 op->dst_path = strdupAtoW( part1 );
619 op->dst_file = strdupAtoW( part2 );
620 queue_file_op( &queue->delete_queue, op );
625 /***********************************************************************
626 * SetupQueueDeleteW (SETUPAPI.@)
628 BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 )
630 struct file_queue *queue = handle;
633 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
638 op->src_descr = NULL;
640 op->dst_path = strdupW( part1 );
641 op->dst_file = strdupW( part2 );
642 queue_file_op( &queue->delete_queue, op );
647 /***********************************************************************
648 * SetupQueueRenameA (SETUPAPI.@)
650 BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename,
651 PCSTR TargetPath, PCSTR TargetFilename )
653 struct file_queue *queue = handle;
656 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
659 op->src_path = strdupAtoW( SourcePath );
660 op->src_file = strdupAtoW( SourceFilename );
661 op->src_descr = NULL;
663 op->dst_path = strdupAtoW( TargetPath );
664 op->dst_file = strdupAtoW( TargetFilename );
665 queue_file_op( &queue->rename_queue, op );
670 /***********************************************************************
671 * SetupQueueRenameW (SETUPAPI.@)
673 BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename,
674 PCWSTR TargetPath, PCWSTR TargetFilename )
676 struct file_queue *queue = handle;
679 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
682 op->src_path = strdupW( SourcePath );
683 op->src_file = strdupW( SourceFilename );
684 op->src_descr = NULL;
686 op->dst_path = strdupW( TargetPath );
687 op->dst_file = strdupW( TargetFilename );
688 queue_file_op( &queue->rename_queue, op );
693 /***********************************************************************
694 * SetupQueueCopySectionA (SETUPAPI.@)
696 BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist,
697 PCSTR section, DWORD style )
699 UNICODE_STRING sectionW;
702 if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
704 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
708 ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style );
712 if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root ))
714 ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style );
715 RtlFreeUnicodeString( &srcW );
717 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
719 RtlFreeUnicodeString( §ionW );
724 /***********************************************************************
725 * SetupQueueCopySectionW (SETUPAPI.@)
727 BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist,
728 PCWSTR section, DWORD style )
730 SP_FILE_COPY_PARAMS_W params;
732 WCHAR dest[MAX_PATH], src[MAX_PATH], *dest_dir;
736 TRACE( "hinf=%p/%p section=%s root=%s\n",
737 hinf, hlist, debugstr_w(section), debugstr_w(src_root) );
739 params.cbSize = sizeof(params);
740 params.QueueHandle = queue;
741 params.SourceRootPath = src_root;
742 params.SourcePath = NULL;
743 params.SourceDescription = NULL;
744 params.SourceTagfile = NULL;
745 params.TargetFilename = dest;
746 params.CopyStyle = style;
747 params.LayoutInf = hinf;
748 params.SecurityDescriptor = NULL;
750 if (!hlist) hlist = hinf;
751 if (!hinf) hinf = hlist;
752 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
753 if (!(params.TargetDirectory = dest_dir = get_destination_dir( hinf, section ))) return FALSE;
756 if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL ))
758 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0;
759 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */
761 params.SourceFilename = *src ? src : NULL;
762 if (!SetupQueueCopyIndirectW( ¶ms )) goto end;
763 } while (SetupFindNextLine( &context, &context ));
766 HeapFree(GetProcessHeap(), 0, dest_dir);
771 /***********************************************************************
772 * SetupQueueDeleteSectionA (SETUPAPI.@)
774 BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
776 UNICODE_STRING sectionW;
779 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
781 ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer );
782 RtlFreeUnicodeString( §ionW );
784 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
789 /***********************************************************************
790 * SetupQueueDeleteSectionW (SETUPAPI.@)
792 BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
796 WCHAR buffer[MAX_PATH];
800 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
802 if (!hlist) hlist = hinf;
803 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
804 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
807 if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
809 if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
810 if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done;
811 } while (SetupFindNextLine( &context, &context ));
815 HeapFree( GetProcessHeap(), 0, dest_dir );
820 /***********************************************************************
821 * SetupQueueRenameSectionA (SETUPAPI.@)
823 BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
825 UNICODE_STRING sectionW;
828 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
830 ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer );
831 RtlFreeUnicodeString( §ionW );
833 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
838 /***********************************************************************
839 * SetupQueueRenameSectionW (SETUPAPI.@)
841 BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
845 WCHAR src[MAX_PATH], dst[MAX_PATH];
848 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
850 if (!hlist) hlist = hinf;
851 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
852 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
855 if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL ))
857 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL ))
859 if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done;
860 } while (SetupFindNextLine( &context, &context ));
864 HeapFree( GetProcessHeap(), 0, dest_dir );
869 /***********************************************************************
870 * SetupCommitFileQueueA (SETUPAPI.@)
872 BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler,
875 struct callback_WtoA_context ctx;
877 ctx.orig_context = context;
878 ctx.orig_handler = handler;
879 return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx );
883 /***********************************************************************
886 * Recursively create all directories in the path.
888 static BOOL create_full_pathW(const WCHAR *path)
894 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
895 strcpyW(new_path, path);
897 while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
898 new_path[len - 1] = 0;
900 while(!CreateDirectoryW(new_path, NULL))
903 DWORD last_error = GetLastError();
905 if(last_error == ERROR_ALREADY_EXISTS)
908 if(last_error != ERROR_PATH_NOT_FOUND)
914 if(!(slash = strrchrW(new_path, '\\')))
920 len = slash - new_path;
922 if(!create_full_pathW(new_path))
927 new_path[len] = '\\';
930 HeapFree(GetProcessHeap(), 0, new_path);
934 static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style,
935 PSP_FILE_CALLBACK_W handler, PVOID context )
940 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source),debugstr_w(target),style);
942 /* before copy processing */
943 if (style & SP_COPY_REPLACEONLY)
945 if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES)
948 if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER))
950 DWORD VersionSizeSource=0;
951 DWORD VersionSizeTarget=0;
955 * This is sort of an interesting workaround. You see, calling
956 * GetVersionInfoSize on a builtin dll loads that dll into memory
957 * and we do not properly unload builtin dlls.. so we effectively
958 * lock into memory all the targets we are replacing. This leads
959 * to problems when we try to register the replaced dlls.
961 * So I will test for the existence of the files first so that
962 * we just basically unconditionally replace the builtin versions.
964 if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) &&
965 (GetFileAttributesW(source) != INVALID_FILE_ATTRIBUTES))
967 VersionSizeSource = GetFileVersionInfoSizeW(source,&zero);
968 VersionSizeTarget = GetFileVersionInfoSizeW(target,&zero);
971 TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget,
974 if (VersionSizeSource && VersionSizeTarget)
976 LPVOID VersionSource;
977 LPVOID VersionTarget;
978 VS_FIXEDFILEINFO *TargetInfo;
979 VS_FIXEDFILEINFO *SourceInfo;
981 WCHAR SubBlock[2]={'\\',0};
984 VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource);
985 VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget);
987 ret = GetFileVersionInfoW(source,0,VersionSizeSource,VersionSource);
989 ret = GetFileVersionInfoW(target, 0, VersionSizeTarget,
994 ret = VerQueryValueW(VersionSource, SubBlock,
995 (LPVOID*)&SourceInfo, &length);
997 ret = VerQueryValueW(VersionTarget, SubBlock,
998 (LPVOID*)&TargetInfo, &length);
1002 FILEPATHS_W filepaths;
1004 TRACE("Versions: Source %i.%i target %i.%i\n",
1005 SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS,
1006 TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS);
1008 /* used in case of notification */
1009 filepaths.Target = target;
1010 filepaths.Source = source;
1011 filepaths.Win32Error = 0;
1012 filepaths.Flags = 0;
1014 if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS)
1017 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1021 else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS)
1022 && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS))
1025 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1029 else if ((style & SP_COPY_NEWER_ONLY) &&
1030 (TargetInfo->dwFileVersionMS ==
1031 SourceInfo->dwFileVersionMS)
1032 &&(TargetInfo->dwFileVersionLS ==
1033 SourceInfo->dwFileVersionLS))
1036 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1042 HeapFree(GetProcessHeap(),0,VersionSource);
1043 HeapFree(GetProcessHeap(),0,VersionTarget);
1046 if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE))
1048 if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES)
1050 FIXME("Notify user target file exists\n");
1054 if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE |
1055 SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP))
1057 ERR("Unsupported style(s) 0x%x\n",style);
1062 rc = CopyFileW(source,target,FALSE);
1063 TRACE("Did copy... rc was %i\n",rc);
1066 /* after copy processing */
1067 if (style & SP_COPY_DELETESOURCE)
1070 DeleteFileW(source);
1076 /***********************************************************************
1077 * SetupInstallFileExA (SETUPAPI.@)
1079 BOOL WINAPI SetupInstallFileExA( HINF hinf, PINFCONTEXT inf_context, PCSTR source, PCSTR root,
1080 PCSTR dest, DWORD style, PSP_FILE_CALLBACK_A handler, PVOID context, PBOOL in_use )
1083 struct callback_WtoA_context ctx;
1084 UNICODE_STRING sourceW, rootW, destW;
1086 TRACE("%p %p %s %s %s %x %p %p %p\n", hinf, inf_context, debugstr_a(source), debugstr_a(root),
1087 debugstr_a(dest), style, handler, context, in_use);
1089 sourceW.Buffer = rootW.Buffer = destW.Buffer = NULL;
1090 if (source && !RtlCreateUnicodeStringFromAsciiz( &sourceW, source ))
1092 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1095 if (root && !RtlCreateUnicodeStringFromAsciiz( &rootW, root ))
1097 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1100 if (dest && !RtlCreateUnicodeStringFromAsciiz( &destW, dest ))
1102 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1106 ctx.orig_context = context;
1107 ctx.orig_handler = handler;
1109 ret = SetupInstallFileExW( hinf, inf_context, sourceW.Buffer, rootW.Buffer, destW.Buffer, style, QUEUE_callback_WtoA, &ctx, in_use );
1112 RtlFreeUnicodeString( &sourceW );
1113 RtlFreeUnicodeString( &rootW );
1114 RtlFreeUnicodeString( &destW );
1118 /***********************************************************************
1119 * SetupInstallFileA (SETUPAPI.@)
1121 BOOL WINAPI SetupInstallFileA( HINF hinf, PINFCONTEXT inf_context, PCSTR source, PCSTR root,
1122 PCSTR dest, DWORD style, PSP_FILE_CALLBACK_A handler, PVOID context )
1124 return SetupInstallFileExA( hinf, inf_context, source, root, dest, style, handler, context, NULL );
1127 /***********************************************************************
1128 * SetupInstallFileExW (SETUPAPI.@)
1130 BOOL WINAPI SetupInstallFileExW( HINF hinf, PINFCONTEXT inf_context, PCWSTR source, PCWSTR root,
1131 PCWSTR dest, DWORD style, PSP_FILE_CALLBACK_W handler, PVOID context, PBOOL in_use )
1133 static const WCHAR CopyFiles[] = {'C','o','p','y','F','i','l','e','s',0};
1135 BOOL ret, absolute = (root && *root && !(style & SP_COPY_SOURCE_ABSOLUTE));
1136 WCHAR *buffer, *p, *inf_source = NULL;
1139 TRACE("%p %p %s %s %s %x %p %p %p\n", hinf, inf_context, debugstr_w(source), debugstr_w(root),
1140 debugstr_w(dest), style, handler, context, in_use);
1142 if (in_use) FIXME("no file in use support\n");
1151 if (!SetupFindFirstLineW( hinf, CopyFiles, NULL, inf_context )) return FALSE;
1153 if (!SetupGetStringFieldW( inf_context, 1, NULL, 0, &len )) return FALSE;
1154 if (!(inf_source = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1156 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1159 if (!SetupGetStringFieldW( inf_context, 1, inf_source, len, NULL )) return FALSE;
1160 source = inf_source;
1164 SetLastError( ERROR_INVALID_PARAMETER );
1168 len = strlenW( source ) + 1;
1169 if (absolute) len += strlenW( root ) + 1;
1171 if (!(p = buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1173 HeapFree( GetProcessHeap(), 0, inf_source );
1174 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1180 strcpyW( buffer, root );
1181 p += strlenW( buffer );
1182 if (p[-1] != '\\') *p++ = '\\';
1184 while (*source == '\\') source++;
1185 strcpyW( p, source );
1187 ret = do_file_copyW( buffer, dest, style, handler, context );
1189 HeapFree( GetProcessHeap(), 0, inf_source );
1190 HeapFree( GetProcessHeap(), 0, buffer );
1194 /***********************************************************************
1195 * SetupInstallFileW (SETUPAPI.@)
1197 BOOL WINAPI SetupInstallFileW( HINF hinf, PINFCONTEXT inf_context, PCWSTR source, PCWSTR root,
1198 PCWSTR dest, DWORD style, PSP_FILE_CALLBACK_W handler, PVOID context )
1200 return SetupInstallFileExW( hinf, inf_context, source, root, dest, style, handler, context, NULL );
1203 /***********************************************************************
1204 * SetupCommitFileQueueW (SETUPAPI.@)
1206 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler,
1209 struct file_queue *queue = handle;
1211 BOOL result = FALSE;
1215 paths.Source = paths.Target = NULL;
1217 if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count)
1218 return TRUE; /* nothing to do */
1220 if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE;
1222 /* perform deletes */
1224 if (queue->delete_queue.count)
1226 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE,
1227 queue->delete_queue.count ))) goto done;
1228 for (op = queue->delete_queue.head; op; op = op->next)
1230 build_filepathsW( op, &paths );
1231 op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE);
1232 if (op_result == FILEOP_ABORT) goto done;
1233 while (op_result == FILEOP_DOIT)
1235 TRACE( "deleting file %s\n", debugstr_w(paths.Target) );
1236 if (DeleteFileW( paths.Target )) break; /* success */
1237 paths.Win32Error = GetLastError();
1238 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 );
1239 if (op_result == FILEOP_ABORT) goto done;
1241 handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 );
1243 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 );
1246 /* perform renames */
1248 if (queue->rename_queue.count)
1250 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME,
1251 queue->rename_queue.count ))) goto done;
1252 for (op = queue->rename_queue.head; op; op = op->next)
1254 build_filepathsW( op, &paths );
1255 op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME);
1256 if (op_result == FILEOP_ABORT) goto done;
1257 while (op_result == FILEOP_DOIT)
1259 TRACE( "renaming file %s -> %s\n",
1260 debugstr_w(paths.Source), debugstr_w(paths.Target) );
1261 if (MoveFileW( paths.Source, paths.Target )) break; /* success */
1262 paths.Win32Error = GetLastError();
1263 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 );
1264 if (op_result == FILEOP_ABORT) goto done;
1266 handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 );
1268 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 );
1271 /* perform copies */
1273 if (queue->copy_queue.count)
1275 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY,
1276 queue->copy_queue.count ))) goto done;
1277 for (op = queue->copy_queue.head; op; op = op->next)
1279 WCHAR newpath[MAX_PATH];
1281 build_filepathsW( op, &paths );
1282 op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
1283 if (op_result == FILEOP_ABORT) goto done;
1284 if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT;
1285 while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
1287 TRACE( "copying file %s -> %s\n",
1288 debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ),
1289 debugstr_w(paths.Target) );
1292 if (!create_full_pathW( op->dst_path ))
1294 paths.Win32Error = GetLastError();
1295 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1296 (UINT_PTR)&paths, (UINT_PTR)newpath );
1297 if (op_result == FILEOP_ABORT) goto done;
1300 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
1301 paths.Target, op->style, handler, context )) break; /* success */
1302 /* try to extract it from the cabinet file */
1305 if (extract_cabinet_file( op->src_tag, op->src_root,
1306 paths.Source, paths.Target )) break;
1308 paths.Win32Error = GetLastError();
1309 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1310 (UINT_PTR)&paths, (UINT_PTR)newpath );
1311 if (op_result == FILEOP_ABORT) goto done;
1313 handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
1315 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 );
1322 handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 );
1323 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1324 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1329 /***********************************************************************
1330 * SetupScanFileQueueA (SETUPAPI.@)
1332 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ handle, DWORD flags, HWND window,
1333 PSP_FILE_CALLBACK_A handler, PVOID context, PDWORD result )
1335 struct callback_WtoA_context ctx;
1337 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
1339 ctx.orig_context = context;
1340 ctx.orig_handler = handler;
1342 return SetupScanFileQueueW( handle, flags, window, QUEUE_callback_WtoA, &ctx, result );
1346 /***********************************************************************
1347 * SetupScanFileQueueW (SETUPAPI.@)
1349 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ handle, DWORD flags, HWND window,
1350 PSP_FILE_CALLBACK_W handler, PVOID context, PDWORD result )
1352 struct file_queue *queue = handle;
1355 UINT notification = 0;
1358 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
1360 if (!queue->copy_queue.count) return TRUE;
1362 if (flags & SPQ_SCAN_USE_CALLBACK) notification = SPFILENOTIFY_QUEUESCAN;
1363 else if (flags & SPQ_SCAN_USE_CALLBACKEX) notification = SPFILENOTIFY_QUEUESCAN_EX;
1365 if (flags & ~(SPQ_SCAN_USE_CALLBACK | SPQ_SCAN_USE_CALLBACKEX))
1367 FIXME("flags %x not fully implemented\n", flags);
1370 paths.Source = paths.Target = NULL;
1372 for (op = queue->copy_queue.head; op; op = op->next)
1374 build_filepathsW( op, &paths );
1375 switch (notification)
1377 case SPFILENOTIFY_QUEUESCAN:
1378 /* FIXME: handle delay flag */
1379 if (handler( context, notification, (UINT_PTR)paths.Target, 0 )) goto done;
1381 case SPFILENOTIFY_QUEUESCAN_EX:
1382 if (handler( context, notification, (UINT_PTR)&paths, 0 )) goto done;
1385 ret = TRUE; goto done;
1392 if (result) *result = 0;
1393 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1394 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1399 /***********************************************************************
1400 * SetupGetFileQueueCount (SETUPAPI.@)
1402 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result )
1404 struct file_queue *queue = handle;
1409 *result = queue->copy_queue.count;
1412 *result = queue->rename_queue.count;
1415 *result = queue->delete_queue.count;
1422 /***********************************************************************
1423 * SetupGetFileQueueFlags (SETUPAPI.@)
1425 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags )
1427 struct file_queue *queue = handle;
1428 *flags = queue->flags;
1433 /***********************************************************************
1434 * SetupSetFileQueueFlags (SETUPAPI.@)
1436 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags )
1438 struct file_queue *queue = handle;
1439 queue->flags = (queue->flags & ~mask) | flags;
1444 /***********************************************************************
1445 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1447 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile)
1449 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile));
1454 /***********************************************************************
1455 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1457 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile)
1459 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile));
1464 /***********************************************************************
1465 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1467 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner )
1469 return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL );
1473 /***********************************************************************
1474 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1476 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg,
1477 DWORD reserved1, PVOID reserved2 )
1479 struct default_callback_context *context;
1481 if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) )))
1483 context->owner = owner;
1484 context->progress = progress;
1485 context->message = msg;
1491 /***********************************************************************
1492 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1494 void WINAPI SetupTermDefaultQueueCallback( PVOID context )
1496 HeapFree( GetProcessHeap(), 0, context );
1500 /***********************************************************************
1501 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1503 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification,
1504 UINT_PTR param1, UINT_PTR param2 )
1506 FILEPATHS_A *paths = (FILEPATHS_A *)param1;
1507 struct default_callback_context *ctx = context;
1509 switch(notification)
1511 case SPFILENOTIFY_STARTQUEUE:
1512 TRACE( "start queue\n" );
1514 case SPFILENOTIFY_ENDQUEUE:
1515 TRACE( "end queue\n" );
1517 case SPFILENOTIFY_STARTSUBQUEUE:
1518 TRACE( "start subqueue %ld count %ld\n", param1, param2 );
1520 case SPFILENOTIFY_ENDSUBQUEUE:
1521 TRACE( "end subqueue %ld\n", param1 );
1523 case SPFILENOTIFY_STARTDELETE:
1524 TRACE( "start delete %s\n", debugstr_a(paths->Target) );
1526 case SPFILENOTIFY_ENDDELETE:
1527 TRACE( "end delete %s\n", debugstr_a(paths->Target) );
1529 case SPFILENOTIFY_DELETEERROR:
1530 /*Windows Ignores attempts to delete files / folders which do not exist*/
1531 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1532 SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1534 case SPFILENOTIFY_STARTRENAME:
1535 TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1537 case SPFILENOTIFY_ENDRENAME:
1538 TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1540 case SPFILENOTIFY_RENAMEERROR:
1541 SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1543 case SPFILENOTIFY_STARTCOPY:
1544 TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1546 case SPFILENOTIFY_ENDCOPY:
1547 TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1549 case SPFILENOTIFY_COPYERROR:
1550 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1551 debugstr_a(paths->Source), debugstr_a(paths->Target) );
1553 case SPFILENOTIFY_NEEDMEDIA:
1554 TRACE( "need media\n" );
1557 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
1564 /***********************************************************************
1565 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1567 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification,
1568 UINT_PTR param1, UINT_PTR param2 )
1570 FILEPATHS_W *paths = (FILEPATHS_W *)param1;
1571 struct default_callback_context *ctx = context;
1573 switch(notification)
1575 case SPFILENOTIFY_STARTQUEUE:
1576 TRACE( "start queue\n" );
1578 case SPFILENOTIFY_ENDQUEUE:
1579 TRACE( "end queue\n" );
1581 case SPFILENOTIFY_STARTSUBQUEUE:
1582 TRACE( "start subqueue %ld count %ld\n", param1, param2 );
1584 case SPFILENOTIFY_ENDSUBQUEUE:
1585 TRACE( "end subqueue %ld\n", param1 );
1587 case SPFILENOTIFY_STARTDELETE:
1588 TRACE( "start delete %s\n", debugstr_w(paths->Target) );
1590 case SPFILENOTIFY_ENDDELETE:
1591 TRACE( "end delete %s\n", debugstr_w(paths->Target) );
1593 case SPFILENOTIFY_DELETEERROR:
1594 /*Windows Ignores attempts to delete files / folders which do not exist*/
1595 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1596 SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1598 case SPFILENOTIFY_STARTRENAME:
1599 SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1601 case SPFILENOTIFY_ENDRENAME:
1602 TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1604 case SPFILENOTIFY_RENAMEERROR:
1605 ERR( "rename error %d %s -> %s\n", paths->Win32Error,
1606 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1608 case SPFILENOTIFY_STARTCOPY:
1609 TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1611 case SPFILENOTIFY_ENDCOPY:
1612 TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1614 case SPFILENOTIFY_COPYERROR:
1615 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1616 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1618 case SPFILENOTIFY_NEEDMEDIA:
1619 TRACE( "need media\n" );
1622 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
1628 /***********************************************************************
1629 * SetupDeleteErrorA (SETUPAPI.@)
1632 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file,
1633 UINT w32error, DWORD style)
1635 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1636 w32error, debugstr_a(file) );
1637 return DPROMPT_SKIPFILE;
1640 /***********************************************************************
1641 * SetupDeleteErrorW (SETUPAPI.@)
1644 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file,
1645 UINT w32error, DWORD style)
1647 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1648 w32error, debugstr_w(file) );
1649 return DPROMPT_SKIPFILE;
1652 /***********************************************************************
1653 * SetupRenameErrorA (SETUPAPI.@)
1656 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source,
1657 PCSTR target, UINT w32error, DWORD style)
1659 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1660 w32error, debugstr_a(source), debugstr_a(target));
1661 return DPROMPT_SKIPFILE;
1664 /***********************************************************************
1665 * SetupRenameErrorW (SETUPAPI.@)
1668 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source,
1669 PCWSTR target, UINT w32error, DWORD style)
1671 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1672 w32error, debugstr_w(source), debugstr_w(target));
1673 return DPROMPT_SKIPFILE;
1677 /***********************************************************************
1678 * SetupCopyErrorA (SETUPAPI.@)
1681 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname,
1682 PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath,
1683 UINT w32error, DWORD style, PSTR pathbuffer,
1684 DWORD buffersize, PDWORD requiredsize)
1686 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1687 w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath));
1688 return DPROMPT_SKIPFILE;
1691 /***********************************************************************
1692 * SetupCopyErrorW (SETUPAPI.@)
1695 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname,
1696 PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath,
1697 UINT w32error, DWORD style, PWSTR pathbuffer,
1698 DWORD buffersize, PDWORD requiredsize)
1700 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1701 w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath));
1702 return DPROMPT_SKIPFILE;
1705 /***********************************************************************
1706 * pSetupGetQueueFlags (SETUPAPI.@)
1708 DWORD WINAPI pSetupGetQueueFlags( HSPFILEQ handle )
1710 struct file_queue *queue = handle;
1711 return queue->flags;
1714 /***********************************************************************
1715 * pSetupSetQueueFlags (SETUPAPI.@)
1717 BOOL WINAPI pSetupSetQueueFlags( HSPFILEQ handle, DWORD flags )
1719 struct file_queue *queue = handle;
1720 queue->flags = flags;