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 static const WCHAR SubBlock[]={'\\',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 ))
1161 HeapFree( GetProcessHeap(), 0, inf_source );
1164 source = inf_source;
1168 SetLastError( ERROR_INVALID_PARAMETER );
1172 len = strlenW( source ) + 1;
1173 if (absolute) len += strlenW( root ) + 1;
1175 if (!(p = buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1177 HeapFree( GetProcessHeap(), 0, inf_source );
1178 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1184 strcpyW( buffer, root );
1185 p += strlenW( buffer );
1186 if (p[-1] != '\\') *p++ = '\\';
1188 while (*source == '\\') source++;
1189 strcpyW( p, source );
1191 ret = do_file_copyW( buffer, dest, style, handler, context );
1193 HeapFree( GetProcessHeap(), 0, inf_source );
1194 HeapFree( GetProcessHeap(), 0, buffer );
1198 /***********************************************************************
1199 * SetupInstallFileW (SETUPAPI.@)
1201 BOOL WINAPI SetupInstallFileW( HINF hinf, PINFCONTEXT inf_context, PCWSTR source, PCWSTR root,
1202 PCWSTR dest, DWORD style, PSP_FILE_CALLBACK_W handler, PVOID context )
1204 return SetupInstallFileExW( hinf, inf_context, source, root, dest, style, handler, context, NULL );
1207 /***********************************************************************
1208 * SetupCommitFileQueueW (SETUPAPI.@)
1210 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler,
1213 struct file_queue *queue = handle;
1215 BOOL result = FALSE;
1219 paths.Source = paths.Target = NULL;
1221 if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count)
1222 return TRUE; /* nothing to do */
1224 if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE;
1226 /* perform deletes */
1228 if (queue->delete_queue.count)
1230 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE,
1231 queue->delete_queue.count ))) goto done;
1232 for (op = queue->delete_queue.head; op; op = op->next)
1234 build_filepathsW( op, &paths );
1235 op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE);
1236 if (op_result == FILEOP_ABORT) goto done;
1237 while (op_result == FILEOP_DOIT)
1239 TRACE( "deleting file %s\n", debugstr_w(paths.Target) );
1240 if (DeleteFileW( paths.Target )) break; /* success */
1241 paths.Win32Error = GetLastError();
1242 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 );
1243 if (op_result == FILEOP_ABORT) goto done;
1245 handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 );
1247 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 );
1250 /* perform renames */
1252 if (queue->rename_queue.count)
1254 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME,
1255 queue->rename_queue.count ))) goto done;
1256 for (op = queue->rename_queue.head; op; op = op->next)
1258 build_filepathsW( op, &paths );
1259 op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME);
1260 if (op_result == FILEOP_ABORT) goto done;
1261 while (op_result == FILEOP_DOIT)
1263 TRACE( "renaming file %s -> %s\n",
1264 debugstr_w(paths.Source), debugstr_w(paths.Target) );
1265 if (MoveFileW( paths.Source, paths.Target )) break; /* success */
1266 paths.Win32Error = GetLastError();
1267 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 );
1268 if (op_result == FILEOP_ABORT) goto done;
1270 handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 );
1272 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 );
1275 /* perform copies */
1277 if (queue->copy_queue.count)
1279 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY,
1280 queue->copy_queue.count ))) goto done;
1281 for (op = queue->copy_queue.head; op; op = op->next)
1283 WCHAR newpath[MAX_PATH];
1285 build_filepathsW( op, &paths );
1286 op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
1287 if (op_result == FILEOP_ABORT) goto done;
1288 if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT;
1289 while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
1291 TRACE( "copying file %s -> %s\n",
1292 debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ),
1293 debugstr_w(paths.Target) );
1296 if (!create_full_pathW( op->dst_path ))
1298 paths.Win32Error = GetLastError();
1299 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1300 (UINT_PTR)&paths, (UINT_PTR)newpath );
1301 if (op_result == FILEOP_ABORT) goto done;
1304 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
1305 paths.Target, op->style, handler, context )) break; /* success */
1306 /* try to extract it from the cabinet file */
1309 if (extract_cabinet_file( op->src_tag, op->src_root,
1310 paths.Source, paths.Target )) break;
1312 paths.Win32Error = GetLastError();
1313 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1314 (UINT_PTR)&paths, (UINT_PTR)newpath );
1315 if (op_result == FILEOP_ABORT) goto done;
1317 handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
1319 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 );
1326 handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 );
1327 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1328 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1333 /***********************************************************************
1334 * SetupScanFileQueueA (SETUPAPI.@)
1336 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ handle, DWORD flags, HWND window,
1337 PSP_FILE_CALLBACK_A handler, PVOID context, PDWORD result )
1339 struct callback_WtoA_context ctx;
1341 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
1343 ctx.orig_context = context;
1344 ctx.orig_handler = handler;
1346 return SetupScanFileQueueW( handle, flags, window, QUEUE_callback_WtoA, &ctx, result );
1350 /***********************************************************************
1351 * SetupScanFileQueueW (SETUPAPI.@)
1353 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ handle, DWORD flags, HWND window,
1354 PSP_FILE_CALLBACK_W handler, PVOID context, PDWORD result )
1356 struct file_queue *queue = handle;
1359 UINT notification = 0;
1362 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
1364 if (!queue->copy_queue.count) return TRUE;
1366 if (flags & SPQ_SCAN_USE_CALLBACK) notification = SPFILENOTIFY_QUEUESCAN;
1367 else if (flags & SPQ_SCAN_USE_CALLBACKEX) notification = SPFILENOTIFY_QUEUESCAN_EX;
1369 if (flags & ~(SPQ_SCAN_USE_CALLBACK | SPQ_SCAN_USE_CALLBACKEX))
1371 FIXME("flags %x not fully implemented\n", flags);
1374 paths.Source = paths.Target = NULL;
1376 for (op = queue->copy_queue.head; op; op = op->next)
1378 build_filepathsW( op, &paths );
1379 switch (notification)
1381 case SPFILENOTIFY_QUEUESCAN:
1382 /* FIXME: handle delay flag */
1383 if (handler( context, notification, (UINT_PTR)paths.Target, 0 )) goto done;
1385 case SPFILENOTIFY_QUEUESCAN_EX:
1386 if (handler( context, notification, (UINT_PTR)&paths, 0 )) goto done;
1389 ret = TRUE; goto done;
1396 if (result) *result = 0;
1397 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1398 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1403 /***********************************************************************
1404 * SetupGetFileQueueCount (SETUPAPI.@)
1406 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result )
1408 struct file_queue *queue = handle;
1413 *result = queue->copy_queue.count;
1416 *result = queue->rename_queue.count;
1419 *result = queue->delete_queue.count;
1426 /***********************************************************************
1427 * SetupGetFileQueueFlags (SETUPAPI.@)
1429 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags )
1431 struct file_queue *queue = handle;
1432 *flags = queue->flags;
1437 /***********************************************************************
1438 * SetupSetFileQueueFlags (SETUPAPI.@)
1440 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags )
1442 struct file_queue *queue = handle;
1443 queue->flags = (queue->flags & ~mask) | flags;
1448 /***********************************************************************
1449 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1451 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile)
1453 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile));
1458 /***********************************************************************
1459 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1461 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile)
1463 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile));
1468 /***********************************************************************
1469 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1471 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner )
1473 return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL );
1477 /***********************************************************************
1478 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1480 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg,
1481 DWORD reserved1, PVOID reserved2 )
1483 struct default_callback_context *context;
1485 if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) )))
1487 context->owner = owner;
1488 context->progress = progress;
1489 context->message = msg;
1495 /***********************************************************************
1496 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1498 void WINAPI SetupTermDefaultQueueCallback( PVOID context )
1500 HeapFree( GetProcessHeap(), 0, context );
1504 /***********************************************************************
1505 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1507 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification,
1508 UINT_PTR param1, UINT_PTR param2 )
1510 FILEPATHS_A *paths = (FILEPATHS_A *)param1;
1511 struct default_callback_context *ctx = context;
1513 switch(notification)
1515 case SPFILENOTIFY_STARTQUEUE:
1516 TRACE( "start queue\n" );
1518 case SPFILENOTIFY_ENDQUEUE:
1519 TRACE( "end queue\n" );
1521 case SPFILENOTIFY_STARTSUBQUEUE:
1522 TRACE( "start subqueue %ld count %ld\n", param1, param2 );
1524 case SPFILENOTIFY_ENDSUBQUEUE:
1525 TRACE( "end subqueue %ld\n", param1 );
1527 case SPFILENOTIFY_STARTDELETE:
1528 TRACE( "start delete %s\n", debugstr_a(paths->Target) );
1530 case SPFILENOTIFY_ENDDELETE:
1531 TRACE( "end delete %s\n", debugstr_a(paths->Target) );
1533 case SPFILENOTIFY_DELETEERROR:
1534 /*Windows Ignores attempts to delete files / folders which do not exist*/
1535 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1536 SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1538 case SPFILENOTIFY_STARTRENAME:
1539 TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1541 case SPFILENOTIFY_ENDRENAME:
1542 TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1544 case SPFILENOTIFY_RENAMEERROR:
1545 SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1547 case SPFILENOTIFY_STARTCOPY:
1548 TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1550 case SPFILENOTIFY_ENDCOPY:
1551 TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1553 case SPFILENOTIFY_COPYERROR:
1554 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1555 debugstr_a(paths->Source), debugstr_a(paths->Target) );
1557 case SPFILENOTIFY_NEEDMEDIA:
1558 TRACE( "need media\n" );
1561 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
1568 /***********************************************************************
1569 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1571 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification,
1572 UINT_PTR param1, UINT_PTR param2 )
1574 FILEPATHS_W *paths = (FILEPATHS_W *)param1;
1575 struct default_callback_context *ctx = context;
1577 switch(notification)
1579 case SPFILENOTIFY_STARTQUEUE:
1580 TRACE( "start queue\n" );
1582 case SPFILENOTIFY_ENDQUEUE:
1583 TRACE( "end queue\n" );
1585 case SPFILENOTIFY_STARTSUBQUEUE:
1586 TRACE( "start subqueue %ld count %ld\n", param1, param2 );
1588 case SPFILENOTIFY_ENDSUBQUEUE:
1589 TRACE( "end subqueue %ld\n", param1 );
1591 case SPFILENOTIFY_STARTDELETE:
1592 TRACE( "start delete %s\n", debugstr_w(paths->Target) );
1594 case SPFILENOTIFY_ENDDELETE:
1595 TRACE( "end delete %s\n", debugstr_w(paths->Target) );
1597 case SPFILENOTIFY_DELETEERROR:
1598 /*Windows Ignores attempts to delete files / folders which do not exist*/
1599 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1600 SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1602 case SPFILENOTIFY_STARTRENAME:
1603 SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1605 case SPFILENOTIFY_ENDRENAME:
1606 TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1608 case SPFILENOTIFY_RENAMEERROR:
1609 ERR( "rename error %d %s -> %s\n", paths->Win32Error,
1610 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1612 case SPFILENOTIFY_STARTCOPY:
1613 TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1615 case SPFILENOTIFY_ENDCOPY:
1616 TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1618 case SPFILENOTIFY_COPYERROR:
1619 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1620 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1622 case SPFILENOTIFY_NEEDMEDIA:
1623 TRACE( "need media\n" );
1626 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
1632 /***********************************************************************
1633 * SetupDeleteErrorA (SETUPAPI.@)
1636 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file,
1637 UINT w32error, DWORD style)
1639 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1640 w32error, debugstr_a(file) );
1641 return DPROMPT_SKIPFILE;
1644 /***********************************************************************
1645 * SetupDeleteErrorW (SETUPAPI.@)
1648 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file,
1649 UINT w32error, DWORD style)
1651 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1652 w32error, debugstr_w(file) );
1653 return DPROMPT_SKIPFILE;
1656 /***********************************************************************
1657 * SetupRenameErrorA (SETUPAPI.@)
1660 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source,
1661 PCSTR target, UINT w32error, DWORD style)
1663 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1664 w32error, debugstr_a(source), debugstr_a(target));
1665 return DPROMPT_SKIPFILE;
1668 /***********************************************************************
1669 * SetupRenameErrorW (SETUPAPI.@)
1672 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source,
1673 PCWSTR target, UINT w32error, DWORD style)
1675 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1676 w32error, debugstr_w(source), debugstr_w(target));
1677 return DPROMPT_SKIPFILE;
1681 /***********************************************************************
1682 * SetupCopyErrorA (SETUPAPI.@)
1685 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname,
1686 PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath,
1687 UINT w32error, DWORD style, PSTR pathbuffer,
1688 DWORD buffersize, PDWORD requiredsize)
1690 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1691 w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath));
1692 return DPROMPT_SKIPFILE;
1695 /***********************************************************************
1696 * SetupCopyErrorW (SETUPAPI.@)
1699 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname,
1700 PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath,
1701 UINT w32error, DWORD style, PWSTR pathbuffer,
1702 DWORD buffersize, PDWORD requiredsize)
1704 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1705 w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath));
1706 return DPROMPT_SKIPFILE;
1709 /***********************************************************************
1710 * pSetupGetQueueFlags (SETUPAPI.@)
1712 DWORD WINAPI pSetupGetQueueFlags( HSPFILEQ handle )
1714 struct file_queue *queue = handle;
1715 return queue->flags;
1718 /***********************************************************************
1719 * pSetupSetQueueFlags (SETUPAPI.@)
1721 BOOL WINAPI pSetupSetQueueFlags( HSPFILEQ handle, DWORD flags )
1723 struct file_queue *queue = handle;
1724 queue->flags = flags;