user32: Add a test showing a problem in GetClassNameA.
[wine/wine64.git] / dlls / setupapi / queue.c
blob3ddb55216006c8e4cbca88b3b32f8cfe750e4aa6
1 /*
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
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winreg.h"
26 #include "winternl.h"
27 #include "winerror.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "setupapi.h"
32 #include "wine/unicode.h"
33 #include "setupapi_private.h"
34 #include "winver.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
42 HWND owner;
43 HWND progress;
44 UINT message;
47 struct file_op
49 struct file_op *next;
50 UINT style;
51 WCHAR *src_root;
52 WCHAR *src_path;
53 WCHAR *src_file;
54 WCHAR *src_descr;
55 WCHAR *src_tag;
56 WCHAR *dst_path;
57 WCHAR *dst_file;
60 struct file_op_queue
62 struct file_op *head;
63 struct file_op *tail;
64 unsigned int count;
67 struct file_queue
69 struct file_op_queue copy_queue;
70 struct file_op_queue delete_queue;
71 struct file_op_queue rename_queue;
72 DWORD flags;
76 inline static WCHAR *strdupW( const WCHAR *str )
78 WCHAR *ret = NULL;
79 if (str)
81 int len = (strlenW(str) + 1) * sizeof(WCHAR);
82 if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( ret, str, len );
84 return ret;
88 inline static WCHAR *strdupAtoW( const char *str )
90 WCHAR *ret = NULL;
91 if (str)
93 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
94 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
95 MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
97 return ret;
100 inline static char *strdupWtoA( const WCHAR *str )
102 char *ret = NULL;
103 if (str)
105 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
106 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
107 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
109 return ret;
112 /* append a file operation to a queue */
113 inline static void queue_file_op( struct file_op_queue *queue, struct file_op *op )
115 op->next = NULL;
116 if (queue->tail) queue->tail->next = op;
117 else queue->head = op;
118 queue->tail = op;
119 queue->count++;
122 /* free all the file operations on a given queue */
123 static void free_file_op_queue( struct file_op_queue *queue )
125 struct file_op *t, *op = queue->head;
127 while( op )
129 HeapFree( GetProcessHeap(), 0, op->src_root );
130 HeapFree( GetProcessHeap(), 0, op->src_path );
131 HeapFree( GetProcessHeap(), 0, op->src_file );
132 HeapFree( GetProcessHeap(), 0, op->src_descr );
133 HeapFree( GetProcessHeap(), 0, op->src_tag );
134 HeapFree( GetProcessHeap(), 0, op->dst_path );
135 if (op->dst_file != op->src_file) HeapFree( GetProcessHeap(), 0, op->dst_file );
136 t = op;
137 op = op->next;
138 HeapFree( GetProcessHeap(), 0, t );
142 /* concat 3 strings to make a path, handling separators correctly */
143 static void concat_W( WCHAR *buffer, const WCHAR *src1, const WCHAR *src2, const WCHAR *src3 )
145 *buffer = 0;
146 if (src1 && *src1)
148 strcpyW( buffer, src1 );
149 buffer += strlenW(buffer );
150 if (buffer[-1] != '\\') *buffer++ = '\\';
151 if (src2) while (*src2 == '\\') src2++;
154 if (src2)
156 strcpyW( buffer, src2 );
157 buffer += strlenW(buffer );
158 if (buffer[-1] != '\\') *buffer++ = '\\';
159 if (src3) while (*src3 == '\\') src3++;
161 if (src3)
163 strcpyW( buffer, src3 );
164 buffer += strlenW(buffer );
169 /***********************************************************************
170 * build_filepathsW
172 * Build a FILEPATHS_W structure for a given file operation.
174 static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths )
176 unsigned int src_len = 1, dst_len = 1;
177 WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target;
179 if (op->src_root) src_len += strlenW(op->src_root) + 1;
180 if (op->src_path) src_len += strlenW(op->src_path) + 1;
181 if (op->src_file) src_len += strlenW(op->src_file) + 1;
182 if (op->dst_path) dst_len += strlenW(op->dst_path) + 1;
183 if (op->dst_file) dst_len += strlenW(op->dst_file) + 1;
184 src_len *= sizeof(WCHAR);
185 dst_len *= sizeof(WCHAR);
187 if (!source || HeapSize( GetProcessHeap(), 0, source ) < src_len )
189 HeapFree( GetProcessHeap(), 0, source );
190 paths->Source = source = HeapAlloc( GetProcessHeap(), 0, src_len );
192 if (!target || HeapSize( GetProcessHeap(), 0, target ) < dst_len )
194 HeapFree( GetProcessHeap(), 0, target );
195 paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len );
197 if (!source || !target) return FALSE;
198 concat_W( source, op->src_root, op->src_path, op->src_file );
199 concat_W( target, NULL, op->dst_path, op->dst_file );
200 paths->Win32Error = 0;
201 paths->Flags = 0;
202 return TRUE;
206 /***********************************************************************
207 * QUEUE_callback_WtoA
209 * Map a file callback parameters from W to A and call the A callback.
211 UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification,
212 UINT_PTR param1, UINT_PTR param2 )
214 struct callback_WtoA_context *callback_ctx = context;
215 char buffer[MAX_PATH];
216 UINT ret;
217 UINT_PTR old_param2 = param2;
219 switch(notification)
221 case SPFILENOTIFY_COPYERROR:
222 param2 = (UINT_PTR)&buffer;
223 /* fall through */
224 case SPFILENOTIFY_STARTDELETE:
225 case SPFILENOTIFY_ENDDELETE:
226 case SPFILENOTIFY_DELETEERROR:
227 case SPFILENOTIFY_STARTRENAME:
228 case SPFILENOTIFY_ENDRENAME:
229 case SPFILENOTIFY_RENAMEERROR:
230 case SPFILENOTIFY_STARTCOPY:
231 case SPFILENOTIFY_ENDCOPY:
233 FILEPATHS_W *pathsW = (FILEPATHS_W *)param1;
234 FILEPATHS_A pathsA;
236 pathsA.Source = strdupWtoA( pathsW->Source );
237 pathsA.Target = strdupWtoA( pathsW->Target );
238 pathsA.Win32Error = pathsW->Win32Error;
239 pathsA.Flags = pathsW->Flags;
240 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
241 (UINT_PTR)&pathsA, param2 );
242 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Source );
243 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Target );
245 if (notification == SPFILENOTIFY_COPYERROR)
246 MultiByteToWideChar( CP_ACP, 0, buffer, -1, (WCHAR *)old_param2, MAX_PATH );
247 break;
249 case SPFILENOTIFY_STARTREGISTRATION:
250 case SPFILENOTIFY_ENDREGISTRATION:
252 SP_REGISTER_CONTROL_STATUSW *statusW = (SP_REGISTER_CONTROL_STATUSW *)param1;
253 SP_REGISTER_CONTROL_STATUSA statusA;
255 statusA.cbSize = sizeof(statusA);
256 statusA.FileName = strdupWtoA( statusW->FileName );
257 statusA.Win32Error = statusW->Win32Error;
258 statusA.FailureCode = statusW->FailureCode;
259 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
260 (UINT_PTR)&statusA, param2 );
261 HeapFree( GetProcessHeap(), 0, (LPSTR)statusA.FileName );
263 break;
265 case SPFILENOTIFY_NEEDMEDIA:
266 case SPFILENOTIFY_QUEUESCAN:
267 FIXME("mapping for %d not implemented\n",notification);
268 case SPFILENOTIFY_STARTQUEUE:
269 case SPFILENOTIFY_ENDQUEUE:
270 case SPFILENOTIFY_STARTSUBQUEUE:
271 case SPFILENOTIFY_ENDSUBQUEUE:
272 default:
273 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, param1, param2 );
274 break;
276 return ret;
280 /***********************************************************************
281 * get_src_file_info
283 * Retrieve the source file information for a given file.
285 static void get_src_file_info( HINF hinf, struct file_op *op )
287 static const WCHAR SourceDisksNames[] =
288 {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0};
289 static const WCHAR SourceDisksFiles[] =
290 {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
292 INFCONTEXT file_ctx, disk_ctx;
293 INT id, diskid;
294 DWORD len, len2;
296 /* find the SourceDisksFiles entry */
297 if (!SetupFindFirstLineW( hinf, SourceDisksFiles, op->src_file, &file_ctx ))
299 if ((op->style & (SP_COPY_SOURCE_ABSOLUTE|SP_COPY_SOURCEPATH_ABSOLUTE))) return;
300 /* no specific info, use .inf file source directory */
301 if (!op->src_root) op->src_root = PARSER_get_src_root( hinf );
302 return;
304 if (!SetupGetIntField( &file_ctx, 1, &diskid )) return;
306 /* now find the diskid in the SourceDisksNames section */
307 if (!SetupFindFirstLineW( hinf, SourceDisksNames, NULL, &disk_ctx )) return;
308 for (;;)
310 if (SetupGetIntField( &disk_ctx, 0, &id ) && (id == diskid)) break;
311 if (!SetupFindNextLine( &disk_ctx, &disk_ctx )) return;
314 /* and fill in the missing info */
316 if (!op->src_descr)
318 if (SetupGetStringFieldW( &disk_ctx, 1, NULL, 0, &len ) &&
319 (op->src_descr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
320 SetupGetStringFieldW( &disk_ctx, 1, op->src_descr, len, NULL );
322 if (!op->src_tag)
324 if (SetupGetStringFieldW( &disk_ctx, 2, NULL, 0, &len ) &&
325 (op->src_tag = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
326 SetupGetStringFieldW( &disk_ctx, 2, op->src_tag, len, NULL );
328 if (!op->src_path && !(op->style & SP_COPY_SOURCE_ABSOLUTE))
330 len = len2 = 0;
331 if (!(op->style & SP_COPY_SOURCEPATH_ABSOLUTE))
333 /* retrieve relative path for this disk */
334 if (!SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len )) len = 0;
336 /* retrieve relative path for this file */
337 if (!SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len2 )) len2 = 0;
339 if ((len || len2) &&
340 (op->src_path = HeapAlloc( GetProcessHeap(), 0, (len+len2)*sizeof(WCHAR) )))
342 WCHAR *ptr = op->src_path;
343 if (len)
345 SetupGetStringFieldW( &disk_ctx, 4, op->src_path, len, NULL );
346 ptr = op->src_path + strlenW(op->src_path);
347 if (len2 && ptr > op->src_path && ptr[-1] != '\\') *ptr++ = '\\';
349 if (!SetupGetStringFieldW( &file_ctx, 2, ptr, len2, NULL )) *ptr = 0;
352 if (!op->src_root) op->src_root = PARSER_get_src_root(hinf);
356 /***********************************************************************
357 * get_destination_dir
359 * Retrieve the destination dir for a given section.
361 static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
363 static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
364 static const WCHAR Def[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
365 INFCONTEXT context;
367 if (!SetupFindFirstLineW( hinf, Dest, section, &context ) &&
368 !SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL;
369 return PARSER_get_dest_dir( &context );
373 static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD );
375 /***********************************************************************
376 * extract_cabinet_file
378 * Extract a file from a .cab file.
380 static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root,
381 const WCHAR *src, const WCHAR *dst )
383 static const WCHAR extW[] = {'.','c','a','b',0};
384 static HMODULE advpack;
386 char *cab_path, *cab_file;
387 int len = strlenW( cabinet );
389 /* make sure the cabinet file has a .cab extension */
390 if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE;
391 if (!pExtractFiles)
393 if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" )))
395 ERR( "could not load advpack.dll\n" );
396 return FALSE;
398 if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" )))
400 ERR( "could not find ExtractFiles in advpack.dll\n" );
401 return FALSE;
405 if (!(cab_path = strdupWtoA( root ))) return FALSE;
406 len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL );
407 if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 )))
409 HeapFree( GetProcessHeap(), 0, cab_path );
410 return FALSE;
412 strcpy( cab_file, cab_path );
413 if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" );
414 WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL );
415 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) );
416 pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 );
417 HeapFree( GetProcessHeap(), 0, cab_file );
418 HeapFree( GetProcessHeap(), 0, cab_path );
419 return CopyFileW( src, dst, FALSE /*FIXME*/ );
423 /***********************************************************************
424 * SetupOpenFileQueue (SETUPAPI.@)
426 HSPFILEQ WINAPI SetupOpenFileQueue(void)
428 struct file_queue *queue;
430 if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue))))
431 return (HSPFILEQ)INVALID_HANDLE_VALUE;
432 return queue;
436 /***********************************************************************
437 * SetupCloseFileQueue (SETUPAPI.@)
439 BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle )
441 struct file_queue *queue = handle;
443 free_file_op_queue( &queue->copy_queue );
444 free_file_op_queue( &queue->rename_queue );
445 free_file_op_queue( &queue->delete_queue );
446 HeapFree( GetProcessHeap(), 0, queue );
447 return TRUE;
451 /***********************************************************************
452 * SetupQueueCopyIndirectA (SETUPAPI.@)
454 BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params )
456 struct file_queue *queue = params->QueueHandle;
457 struct file_op *op;
459 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
460 op->style = params->CopyStyle;
461 op->src_root = strdupAtoW( params->SourceRootPath );
462 op->src_path = strdupAtoW( params->SourcePath );
463 op->src_file = strdupAtoW( params->SourceFilename );
464 op->src_descr = strdupAtoW( params->SourceDescription );
465 op->src_tag = strdupAtoW( params->SourceTagfile );
466 op->dst_path = strdupAtoW( params->TargetDirectory );
467 op->dst_file = strdupAtoW( params->TargetFilename );
469 /* some defaults */
470 if (!op->src_file) op->src_file = op->dst_file;
471 if (params->LayoutInf)
473 get_src_file_info( params->LayoutInf, op );
474 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
477 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
478 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
479 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
480 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
482 queue_file_op( &queue->copy_queue, op );
483 return TRUE;
487 /***********************************************************************
488 * SetupQueueCopyIndirectW (SETUPAPI.@)
490 BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params )
492 struct file_queue *queue = params->QueueHandle;
493 struct file_op *op;
495 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
496 op->style = params->CopyStyle;
497 op->src_root = strdupW( params->SourceRootPath );
498 op->src_path = strdupW( params->SourcePath );
499 op->src_file = strdupW( params->SourceFilename );
500 op->src_descr = strdupW( params->SourceDescription );
501 op->src_tag = strdupW( params->SourceTagfile );
502 op->dst_path = strdupW( params->TargetDirectory );
503 op->dst_file = strdupW( params->TargetFilename );
505 /* some defaults */
506 if (!op->src_file) op->src_file = op->dst_file;
507 if (params->LayoutInf)
509 get_src_file_info( params->LayoutInf, op );
510 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
513 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
514 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
515 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
516 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
518 queue_file_op( &queue->copy_queue, op );
519 return TRUE;
523 /***********************************************************************
524 * SetupQueueCopyA (SETUPAPI.@)
526 BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file,
527 PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file,
528 DWORD style )
530 SP_FILE_COPY_PARAMS_A params;
532 params.cbSize = sizeof(params);
533 params.QueueHandle = queue;
534 params.SourceRootPath = src_root;
535 params.SourcePath = src_path;
536 params.SourceFilename = src_file;
537 params.SourceDescription = src_descr;
538 params.SourceTagfile = src_tag;
539 params.TargetDirectory = dst_dir;
540 params.TargetFilename = dst_file;
541 params.CopyStyle = style;
542 params.LayoutInf = 0;
543 params.SecurityDescriptor = NULL;
544 return SetupQueueCopyIndirectA( &params );
548 /***********************************************************************
549 * SetupQueueCopyW (SETUPAPI.@)
551 BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file,
552 PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file,
553 DWORD style )
555 SP_FILE_COPY_PARAMS_W params;
557 params.cbSize = sizeof(params);
558 params.QueueHandle = queue;
559 params.SourceRootPath = src_root;
560 params.SourcePath = src_path;
561 params.SourceFilename = src_file;
562 params.SourceDescription = src_descr;
563 params.SourceTagfile = src_tag;
564 params.TargetDirectory = dst_dir;
565 params.TargetFilename = dst_file;
566 params.CopyStyle = style;
567 params.LayoutInf = 0;
568 params.SecurityDescriptor = NULL;
569 return SetupQueueCopyIndirectW( &params );
573 /***********************************************************************
574 * SetupQueueDefaultCopyA (SETUPAPI.@)
576 BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file,
577 PCSTR dst_file, DWORD style )
579 SP_FILE_COPY_PARAMS_A params;
581 params.cbSize = sizeof(params);
582 params.QueueHandle = queue;
583 params.SourceRootPath = src_root;
584 params.SourcePath = NULL;
585 params.SourceFilename = src_file;
586 params.SourceDescription = NULL;
587 params.SourceTagfile = NULL;
588 params.TargetDirectory = NULL;
589 params.TargetFilename = dst_file;
590 params.CopyStyle = style;
591 params.LayoutInf = hinf;
592 params.SecurityDescriptor = NULL;
593 return SetupQueueCopyIndirectA( &params );
597 /***********************************************************************
598 * SetupQueueDefaultCopyW (SETUPAPI.@)
600 BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file,
601 PCWSTR dst_file, DWORD style )
603 SP_FILE_COPY_PARAMS_W params;
605 params.cbSize = sizeof(params);
606 params.QueueHandle = queue;
607 params.SourceRootPath = src_root;
608 params.SourcePath = NULL;
609 params.SourceFilename = src_file;
610 params.SourceDescription = NULL;
611 params.SourceTagfile = NULL;
612 params.TargetDirectory = NULL;
613 params.TargetFilename = dst_file;
614 params.CopyStyle = style;
615 params.LayoutInf = hinf;
616 params.SecurityDescriptor = NULL;
617 return SetupQueueCopyIndirectW( &params );
621 /***********************************************************************
622 * SetupQueueDeleteA (SETUPAPI.@)
624 BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 )
626 struct file_queue *queue = handle;
627 struct file_op *op;
629 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
630 op->style = 0;
631 op->src_root = NULL;
632 op->src_path = NULL;
633 op->src_file = NULL;
634 op->src_descr = NULL;
635 op->src_tag = NULL;
636 op->dst_path = strdupAtoW( part1 );
637 op->dst_file = strdupAtoW( part2 );
638 queue_file_op( &queue->delete_queue, op );
639 return TRUE;
643 /***********************************************************************
644 * SetupQueueDeleteW (SETUPAPI.@)
646 BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 )
648 struct file_queue *queue = handle;
649 struct file_op *op;
651 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
652 op->style = 0;
653 op->src_root = NULL;
654 op->src_path = NULL;
655 op->src_file = NULL;
656 op->src_descr = NULL;
657 op->src_tag = NULL;
658 op->dst_path = strdupW( part1 );
659 op->dst_file = strdupW( part2 );
660 queue_file_op( &queue->delete_queue, op );
661 return TRUE;
665 /***********************************************************************
666 * SetupQueueRenameA (SETUPAPI.@)
668 BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename,
669 PCSTR TargetPath, PCSTR TargetFilename )
671 struct file_queue *queue = handle;
672 struct file_op *op;
674 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
675 op->style = 0;
676 op->src_root = NULL;
677 op->src_path = strdupAtoW( SourcePath );
678 op->src_file = strdupAtoW( SourceFilename );
679 op->src_descr = NULL;
680 op->src_tag = NULL;
681 op->dst_path = strdupAtoW( TargetPath );
682 op->dst_file = strdupAtoW( TargetFilename );
683 queue_file_op( &queue->rename_queue, op );
684 return TRUE;
688 /***********************************************************************
689 * SetupQueueRenameW (SETUPAPI.@)
691 BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename,
692 PCWSTR TargetPath, PCWSTR TargetFilename )
694 struct file_queue *queue = handle;
695 struct file_op *op;
697 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
698 op->style = 0;
699 op->src_root = NULL;
700 op->src_path = strdupW( SourcePath );
701 op->src_file = strdupW( SourceFilename );
702 op->src_descr = NULL;
703 op->src_tag = NULL;
704 op->dst_path = strdupW( TargetPath );
705 op->dst_file = strdupW( TargetFilename );
706 queue_file_op( &queue->rename_queue, op );
707 return TRUE;
711 /***********************************************************************
712 * SetupQueueCopySectionA (SETUPAPI.@)
714 BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist,
715 PCSTR section, DWORD style )
717 UNICODE_STRING sectionW;
718 BOOL ret = FALSE;
720 if (!RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
722 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
723 return FALSE;
725 if (!src_root)
726 ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style );
727 else
729 UNICODE_STRING srcW;
730 if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root ))
732 ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style );
733 RtlFreeUnicodeString( &srcW );
735 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
737 RtlFreeUnicodeString( &sectionW );
738 return ret;
742 /***********************************************************************
743 * SetupQueueCopySectionW (SETUPAPI.@)
745 BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist,
746 PCWSTR section, DWORD style )
748 SP_FILE_COPY_PARAMS_W params;
749 INFCONTEXT context;
750 WCHAR dest[MAX_PATH], src[MAX_PATH];
751 INT flags;
753 TRACE( "hinf=%p/%p section=%s root=%s\n",
754 hinf, hlist, debugstr_w(section), debugstr_w(src_root) );
756 params.cbSize = sizeof(params);
757 params.QueueHandle = queue;
758 params.SourceRootPath = src_root;
759 params.SourcePath = NULL;
760 params.SourceDescription = NULL;
761 params.SourceTagfile = NULL;
762 params.TargetFilename = dest;
763 params.CopyStyle = style;
764 params.LayoutInf = hinf;
765 params.SecurityDescriptor = NULL;
767 if (!hlist) hlist = hinf;
768 if (!hinf) hinf = hlist;
769 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
770 if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) return FALSE;
773 if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL ))
774 return FALSE;
775 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0;
776 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */
778 params.SourceFilename = *src ? src : NULL;
779 if (!SetupQueueCopyIndirectW( &params )) return FALSE;
780 } while (SetupFindNextLine( &context, &context ));
781 return TRUE;
785 /***********************************************************************
786 * SetupQueueDeleteSectionA (SETUPAPI.@)
788 BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
790 UNICODE_STRING sectionW;
791 BOOL ret = FALSE;
793 if (RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
795 ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer );
796 RtlFreeUnicodeString( &sectionW );
798 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
799 return ret;
803 /***********************************************************************
804 * SetupQueueDeleteSectionW (SETUPAPI.@)
806 BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
808 INFCONTEXT context;
809 WCHAR *dest_dir;
810 WCHAR buffer[MAX_PATH];
811 BOOL ret = FALSE;
812 INT flags;
814 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
816 if (!hlist) hlist = hinf;
817 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
818 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
821 if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
822 goto done;
823 if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
824 if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done;
825 } while (SetupFindNextLine( &context, &context ));
827 ret = TRUE;
828 done:
829 HeapFree( GetProcessHeap(), 0, dest_dir );
830 return ret;
834 /***********************************************************************
835 * SetupQueueRenameSectionA (SETUPAPI.@)
837 BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
839 UNICODE_STRING sectionW;
840 BOOL ret = FALSE;
842 if (RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
844 ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer );
845 RtlFreeUnicodeString( &sectionW );
847 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
848 return ret;
852 /***********************************************************************
853 * SetupQueueRenameSectionW (SETUPAPI.@)
855 BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
857 INFCONTEXT context;
858 WCHAR *dest_dir;
859 WCHAR src[MAX_PATH], dst[MAX_PATH];
860 BOOL ret = FALSE;
862 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
864 if (!hlist) hlist = hinf;
865 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
866 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
869 if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL ))
870 goto done;
871 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL ))
872 goto done;
873 if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done;
874 } while (SetupFindNextLine( &context, &context ));
876 ret = TRUE;
877 done:
878 HeapFree( GetProcessHeap(), 0, dest_dir );
879 return ret;
883 /***********************************************************************
884 * SetupCommitFileQueueA (SETUPAPI.@)
886 BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler,
887 PVOID context )
889 struct callback_WtoA_context ctx;
891 ctx.orig_context = context;
892 ctx.orig_handler = handler;
893 return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx );
897 /***********************************************************************
898 * create_full_pathW
900 * Recursively create all directories in the path.
902 static BOOL create_full_pathW(const WCHAR *path)
904 BOOL ret = TRUE;
905 int len;
906 WCHAR *new_path;
908 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
909 strcpyW(new_path, path);
911 while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
912 new_path[len - 1] = 0;
914 while(!CreateDirectoryW(new_path, NULL))
916 WCHAR *slash;
917 DWORD last_error = GetLastError();
919 if(last_error == ERROR_ALREADY_EXISTS)
920 break;
922 if(last_error != ERROR_PATH_NOT_FOUND)
924 ret = FALSE;
925 break;
928 if(!(slash = strrchrW(new_path, '\\')))
930 ret = FALSE;
931 break;
934 len = slash - new_path;
935 new_path[len] = 0;
936 if(!create_full_pathW(new_path))
938 ret = FALSE;
939 break;
941 new_path[len] = '\\';
944 HeapFree(GetProcessHeap(), 0, new_path);
945 return ret;
948 static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style,
949 PSP_FILE_CALLBACK_W handler, PVOID context )
951 BOOL rc = FALSE;
952 BOOL docopy = TRUE;
954 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source),debugstr_w(target),style);
956 /* before copy processing */
957 if (style & SP_COPY_REPLACEONLY)
959 if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES)
960 docopy = FALSE;
962 if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER))
964 DWORD VersionSizeSource=0;
965 DWORD VersionSizeTarget=0;
966 DWORD zero=0;
969 * This is sort of an interesting workaround. You see, calling
970 * GetVersionInfoSize on a builtin dll loads that dll into memory
971 * and we do not properly unload builtin dlls.. so we effectively
972 * lock into memory all the targets we are replacing. This leads
973 * to problems when we try to register the replaced dlls.
975 * So I will test for the existence of the files first so that
976 * we just basically unconditionally replace the builtin versions.
978 if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) &&
979 (GetFileAttributesW(source) != INVALID_FILE_ATTRIBUTES))
981 VersionSizeSource = GetFileVersionInfoSizeW(source,&zero);
982 VersionSizeTarget = GetFileVersionInfoSizeW(target,&zero);
985 TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget,
986 VersionSizeSource);
988 if (VersionSizeSource && VersionSizeTarget)
990 LPVOID VersionSource;
991 LPVOID VersionTarget;
992 VS_FIXEDFILEINFO *TargetInfo;
993 VS_FIXEDFILEINFO *SourceInfo;
994 UINT length;
995 WCHAR SubBlock[2]={'\\',0};
996 DWORD ret;
998 VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource);
999 VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget);
1001 ret = GetFileVersionInfoW(source,0,VersionSizeSource,VersionSource);
1002 if (ret)
1003 ret = GetFileVersionInfoW(target, 0, VersionSizeTarget,
1004 VersionTarget);
1006 if (ret)
1008 ret = VerQueryValueW(VersionSource, SubBlock,
1009 (LPVOID*)&SourceInfo, &length);
1010 if (ret)
1011 ret = VerQueryValueW(VersionTarget, SubBlock,
1012 (LPVOID*)&TargetInfo, &length);
1014 if (ret)
1016 FILEPATHS_W filepaths;
1018 TRACE("Versions: Source %i.%i target %i.%i\n",
1019 SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS,
1020 TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS);
1022 /* used in case of notification */
1023 filepaths.Target = target;
1024 filepaths.Source = source;
1025 filepaths.Win32Error = 0;
1026 filepaths.Flags = 0;
1028 if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS)
1030 if (handler)
1031 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1032 else
1033 docopy = FALSE;
1035 else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS)
1036 && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS))
1038 if (handler)
1039 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1040 else
1041 docopy = FALSE;
1043 else if ((style & SP_COPY_NEWER_ONLY) &&
1044 (TargetInfo->dwFileVersionMS ==
1045 SourceInfo->dwFileVersionMS)
1046 &&(TargetInfo->dwFileVersionLS ==
1047 SourceInfo->dwFileVersionLS))
1049 if (handler)
1050 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1051 else
1052 docopy = FALSE;
1056 HeapFree(GetProcessHeap(),0,VersionSource);
1057 HeapFree(GetProcessHeap(),0,VersionTarget);
1060 if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE))
1062 if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES)
1064 FIXME("Notify user target file exists\n");
1065 docopy = FALSE;
1068 if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE |
1069 SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP))
1071 ERR("Unsupported style(s) 0x%x\n",style);
1074 if (docopy)
1076 rc = CopyFileW(source,target,FALSE);
1077 TRACE("Did copy... rc was %i\n",rc);
1080 /* after copy processing */
1081 if (style & SP_COPY_DELETESOURCE)
1083 if (rc)
1084 DeleteFileW(source);
1087 return rc;
1090 /***********************************************************************
1091 * SetupCommitFileQueueW (SETUPAPI.@)
1093 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler,
1094 PVOID context )
1096 struct file_queue *queue = handle;
1097 struct file_op *op;
1098 BOOL result = FALSE;
1099 FILEPATHS_W paths;
1100 UINT op_result;
1102 paths.Source = paths.Target = NULL;
1104 if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count)
1105 return TRUE; /* nothing to do */
1107 if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE;
1109 /* perform deletes */
1111 if (queue->delete_queue.count)
1113 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE,
1114 queue->delete_queue.count ))) goto done;
1115 for (op = queue->delete_queue.head; op; op = op->next)
1117 build_filepathsW( op, &paths );
1118 op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE);
1119 if (op_result == FILEOP_ABORT) goto done;
1120 while (op_result == FILEOP_DOIT)
1122 TRACE( "deleting file %s\n", debugstr_w(paths.Target) );
1123 if (DeleteFileW( paths.Target )) break; /* success */
1124 paths.Win32Error = GetLastError();
1125 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 );
1126 if (op_result == FILEOP_ABORT) goto done;
1128 handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 );
1130 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 );
1133 /* perform renames */
1135 if (queue->rename_queue.count)
1137 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME,
1138 queue->rename_queue.count ))) goto done;
1139 for (op = queue->rename_queue.head; op; op = op->next)
1141 build_filepathsW( op, &paths );
1142 op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME);
1143 if (op_result == FILEOP_ABORT) goto done;
1144 while (op_result == FILEOP_DOIT)
1146 TRACE( "renaming file %s -> %s\n",
1147 debugstr_w(paths.Source), debugstr_w(paths.Target) );
1148 if (MoveFileW( paths.Source, paths.Target )) break; /* success */
1149 paths.Win32Error = GetLastError();
1150 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 );
1151 if (op_result == FILEOP_ABORT) goto done;
1153 handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 );
1155 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 );
1158 /* perform copies */
1160 if (queue->copy_queue.count)
1162 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY,
1163 queue->copy_queue.count ))) goto done;
1164 for (op = queue->copy_queue.head; op; op = op->next)
1166 WCHAR newpath[MAX_PATH];
1168 build_filepathsW( op, &paths );
1169 op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
1170 if (op_result == FILEOP_ABORT) goto done;
1171 if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT;
1172 while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
1174 TRACE( "copying file %s -> %s\n",
1175 debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ),
1176 debugstr_w(paths.Target) );
1177 if (op->dst_path)
1179 if (!create_full_pathW( op->dst_path ))
1181 paths.Win32Error = GetLastError();
1182 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1183 (UINT_PTR)&paths, (UINT_PTR)newpath );
1184 if (op_result == FILEOP_ABORT) goto done;
1187 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
1188 paths.Target, op->style, handler, context )) break; /* success */
1189 /* try to extract it from the cabinet file */
1190 if (op->src_tag)
1192 if (extract_cabinet_file( op->src_tag, op->src_root,
1193 paths.Source, paths.Target )) break;
1195 paths.Win32Error = GetLastError();
1196 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1197 (UINT_PTR)&paths, (UINT_PTR)newpath );
1198 if (op_result == FILEOP_ABORT) goto done;
1200 handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
1202 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 );
1206 result = TRUE;
1208 done:
1209 handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 );
1210 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1211 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1212 return result;
1216 /***********************************************************************
1217 * SetupScanFileQueueA (SETUPAPI.@)
1219 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ queue, DWORD flags, HWND window,
1220 PSP_FILE_CALLBACK_A callback, PVOID context, PDWORD result )
1222 FIXME("stub\n");
1223 return FALSE;
1227 /***********************************************************************
1228 * SetupScanFileQueueW (SETUPAPI.@)
1230 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ queue, DWORD flags, HWND window,
1231 PSP_FILE_CALLBACK_W callback, PVOID context, PDWORD result )
1233 FIXME("stub\n");
1234 return FALSE;
1238 /***********************************************************************
1239 * SetupGetFileQueueCount (SETUPAPI.@)
1241 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result )
1243 struct file_queue *queue = handle;
1245 switch(op)
1247 case FILEOP_COPY:
1248 *result = queue->copy_queue.count;
1249 return TRUE;
1250 case FILEOP_RENAME:
1251 *result = queue->rename_queue.count;
1252 return TRUE;
1253 case FILEOP_DELETE:
1254 *result = queue->delete_queue.count;
1255 return TRUE;
1257 return FALSE;
1261 /***********************************************************************
1262 * SetupGetFileQueueFlags (SETUPAPI.@)
1264 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags )
1266 struct file_queue *queue = handle;
1267 *flags = queue->flags;
1268 return TRUE;
1272 /***********************************************************************
1273 * SetupSetFileQueueFlags (SETUPAPI.@)
1275 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags )
1277 struct file_queue *queue = handle;
1278 queue->flags = (queue->flags & ~mask) | flags;
1279 return TRUE;
1283 /***********************************************************************
1284 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1286 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile)
1288 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile));
1289 return FALSE;
1293 /***********************************************************************
1294 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1296 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile)
1298 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile));
1299 return FALSE;
1303 /***********************************************************************
1304 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1306 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner )
1308 return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL );
1312 /***********************************************************************
1313 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1315 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg,
1316 DWORD reserved1, PVOID reserved2 )
1318 struct default_callback_context *context;
1320 if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) )))
1322 context->owner = owner;
1323 context->progress = progress;
1324 context->message = msg;
1326 return context;
1330 /***********************************************************************
1331 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1333 void WINAPI SetupTermDefaultQueueCallback( PVOID context )
1335 HeapFree( GetProcessHeap(), 0, context );
1339 /***********************************************************************
1340 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1342 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification,
1343 UINT_PTR param1, UINT_PTR param2 )
1345 FILEPATHS_A *paths = (FILEPATHS_A *)param1;
1346 struct default_callback_context *ctx = (struct default_callback_context *)context;
1348 switch(notification)
1350 case SPFILENOTIFY_STARTQUEUE:
1351 TRACE( "start queue\n" );
1352 return TRUE;
1353 case SPFILENOTIFY_ENDQUEUE:
1354 TRACE( "end queue\n" );
1355 return 0;
1356 case SPFILENOTIFY_STARTSUBQUEUE:
1357 TRACE( "start subqueue %d count %d\n", param1, param2 );
1358 return TRUE;
1359 case SPFILENOTIFY_ENDSUBQUEUE:
1360 TRACE( "end subqueue %d\n", param1 );
1361 return 0;
1362 case SPFILENOTIFY_STARTDELETE:
1363 TRACE( "start delete %s\n", debugstr_a(paths->Target) );
1364 return FILEOP_DOIT;
1365 case SPFILENOTIFY_ENDDELETE:
1366 TRACE( "end delete %s\n", debugstr_a(paths->Target) );
1367 return 0;
1368 case SPFILENOTIFY_DELETEERROR:
1369 /*Windows Ignores attempts to delete files / folders which do not exist*/
1370 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1371 SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1372 return FILEOP_SKIP;
1373 case SPFILENOTIFY_STARTRENAME:
1374 TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1375 return FILEOP_DOIT;
1376 case SPFILENOTIFY_ENDRENAME:
1377 TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1378 return 0;
1379 case SPFILENOTIFY_RENAMEERROR:
1380 SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1381 return FILEOP_SKIP;
1382 case SPFILENOTIFY_STARTCOPY:
1383 TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1384 return FILEOP_DOIT;
1385 case SPFILENOTIFY_ENDCOPY:
1386 TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1387 return 0;
1388 case SPFILENOTIFY_COPYERROR:
1389 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1390 debugstr_a(paths->Source), debugstr_a(paths->Target) );
1391 return FILEOP_SKIP;
1392 case SPFILENOTIFY_NEEDMEDIA:
1393 TRACE( "need media\n" );
1394 return FILEOP_SKIP;
1395 default:
1396 FIXME( "notification %d params %x,%x\n", notification, param1, param2 );
1397 break;
1399 return 0;
1403 /***********************************************************************
1404 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1406 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification,
1407 UINT_PTR param1, UINT_PTR param2 )
1409 FILEPATHS_W *paths = (FILEPATHS_W *)param1;
1410 struct default_callback_context *ctx = (struct default_callback_context *)context;
1412 switch(notification)
1414 case SPFILENOTIFY_STARTQUEUE:
1415 TRACE( "start queue\n" );
1416 return TRUE;
1417 case SPFILENOTIFY_ENDQUEUE:
1418 TRACE( "end queue\n" );
1419 return 0;
1420 case SPFILENOTIFY_STARTSUBQUEUE:
1421 TRACE( "start subqueue %d count %d\n", param1, param2 );
1422 return TRUE;
1423 case SPFILENOTIFY_ENDSUBQUEUE:
1424 TRACE( "end subqueue %d\n", param1 );
1425 return 0;
1426 case SPFILENOTIFY_STARTDELETE:
1427 TRACE( "start delete %s\n", debugstr_w(paths->Target) );
1428 return FILEOP_DOIT;
1429 case SPFILENOTIFY_ENDDELETE:
1430 TRACE( "end delete %s\n", debugstr_w(paths->Target) );
1431 return 0;
1432 case SPFILENOTIFY_DELETEERROR:
1433 /*Windows Ignores attempts to delete files / folders which do not exist*/
1434 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1435 SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1436 return FILEOP_SKIP;
1437 case SPFILENOTIFY_STARTRENAME:
1438 SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1439 return FILEOP_DOIT;
1440 case SPFILENOTIFY_ENDRENAME:
1441 TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1442 return 0;
1443 case SPFILENOTIFY_RENAMEERROR:
1444 ERR( "rename error %d %s -> %s\n", paths->Win32Error,
1445 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1446 return FILEOP_SKIP;
1447 case SPFILENOTIFY_STARTCOPY:
1448 TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1449 return FILEOP_DOIT;
1450 case SPFILENOTIFY_ENDCOPY:
1451 TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1452 return 0;
1453 case SPFILENOTIFY_COPYERROR:
1454 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1455 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1456 return FILEOP_SKIP;
1457 case SPFILENOTIFY_NEEDMEDIA:
1458 TRACE( "need media\n" );
1459 return FILEOP_SKIP;
1460 default:
1461 FIXME( "notification %d params %x,%x\n", notification, param1, param2 );
1462 break;
1464 return 0;
1467 /***********************************************************************
1468 * SetupDeleteErrorA (SETUPAPI.@)
1471 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file,
1472 UINT w32error, DWORD style)
1474 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1475 w32error, debugstr_a(file) );
1476 return DPROMPT_SKIPFILE;
1479 /***********************************************************************
1480 * SetupDeleteErrorW (SETUPAPI.@)
1483 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file,
1484 UINT w32error, DWORD style)
1486 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1487 w32error, debugstr_w(file) );
1488 return DPROMPT_SKIPFILE;
1491 /***********************************************************************
1492 * SetupRenameErrorA (SETUPAPI.@)
1495 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source,
1496 PCSTR target, UINT w32error, DWORD style)
1498 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1499 w32error, debugstr_a(source), debugstr_a(target));
1500 return DPROMPT_SKIPFILE;
1503 /***********************************************************************
1504 * SetupRenameErrorW (SETUPAPI.@)
1507 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source,
1508 PCWSTR target, UINT w32error, DWORD style)
1510 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1511 w32error, debugstr_w(source), debugstr_w(target));
1512 return DPROMPT_SKIPFILE;
1516 /***********************************************************************
1517 * SetupCopyErrorA (SETUPAPI.@)
1520 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname,
1521 PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath,
1522 UINT w32error, DWORD style, PSTR pathbuffer,
1523 DWORD buffersize, PDWORD requiredsize)
1525 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1526 w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath));
1527 return DPROMPT_SKIPFILE;
1530 /***********************************************************************
1531 * SetupCopyErrorW (SETUPAPI.@)
1534 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname,
1535 PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath,
1536 UINT w32error, DWORD style, PWSTR pathbuffer,
1537 DWORD buffersize, PDWORD requiredsize)
1539 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1540 w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath));
1541 return DPROMPT_SKIPFILE;