rpcss: Don't use sizeof in traces to avoid printf format warnings.
[wine/testsucceed.git] / dlls / setupapi / queue.c
blobf7d3c5e064aa4aae923fbe1fced7dbf58c2573e4
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 if (!(op->style & SP_COPY_SOURCEPATH_ABSOLUTE))
332 /* retrieve relative path for this disk */
333 if (!SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len )) len = 0;
335 /* retrieve relative path for this file */
336 if (!SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len2 )) len2 = 0;
338 if ((len || len2) &&
339 (op->src_path = HeapAlloc( GetProcessHeap(), 0, (len+len2)*sizeof(WCHAR) )))
341 WCHAR *ptr = op->src_path;
342 if (len)
344 SetupGetStringFieldW( &disk_ctx, 4, op->src_path, len, NULL );
345 ptr = op->src_path + strlenW(op->src_path);
346 if (len2 && ptr > op->src_path && ptr[-1] != '\\') *ptr++ = '\\';
348 if (!SetupGetStringFieldW( &disk_ctx, 4, ptr, len2, NULL )) *ptr = 0;
351 if (!op->src_root) op->src_root = PARSER_get_src_root(hinf);
355 /***********************************************************************
356 * get_destination_dir
358 * Retrieve the destination dir for a given section.
360 static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
362 static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
363 static const WCHAR Def[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
364 INFCONTEXT context;
366 if (!SetupFindFirstLineW( hinf, Dest, section, &context ) &&
367 !SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL;
368 return PARSER_get_dest_dir( &context );
372 static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD );
374 /***********************************************************************
375 * extract_cabinet_file
377 * Extract a file from a .cab file.
379 static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root,
380 const WCHAR *src, const WCHAR *dst )
382 static const WCHAR extW[] = {'.','c','a','b',0};
383 static HMODULE advpack;
385 char *cab_path, *cab_file;
386 int len = strlenW( cabinet );
388 /* make sure the cabinet file has a .cab extension */
389 if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE;
390 if (!pExtractFiles)
392 if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" )))
394 ERR( "could not load advpack.dll\n" );
395 return FALSE;
397 if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" )))
399 ERR( "could not find ExtractFiles in advpack.dll\n" );
400 return FALSE;
404 if (!(cab_path = strdupWtoA( root ))) return FALSE;
405 len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL );
406 if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 )))
408 HeapFree( GetProcessHeap(), 0, cab_path );
409 return FALSE;
411 strcpy( cab_file, cab_path );
412 if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" );
413 WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL );
414 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) );
415 pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 );
416 HeapFree( GetProcessHeap(), 0, cab_file );
417 HeapFree( GetProcessHeap(), 0, cab_path );
418 return CopyFileW( src, dst, FALSE /*FIXME*/ );
422 /***********************************************************************
423 * SetupOpenFileQueue (SETUPAPI.@)
425 HSPFILEQ WINAPI SetupOpenFileQueue(void)
427 struct file_queue *queue;
429 if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue))))
430 return (HSPFILEQ)INVALID_HANDLE_VALUE;
431 return queue;
435 /***********************************************************************
436 * SetupCloseFileQueue (SETUPAPI.@)
438 BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle )
440 struct file_queue *queue = handle;
442 free_file_op_queue( &queue->copy_queue );
443 free_file_op_queue( &queue->rename_queue );
444 free_file_op_queue( &queue->delete_queue );
445 HeapFree( GetProcessHeap(), 0, queue );
446 return TRUE;
450 /***********************************************************************
451 * SetupQueueCopyIndirectA (SETUPAPI.@)
453 BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params )
455 struct file_queue *queue = params->QueueHandle;
456 struct file_op *op;
458 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
459 op->style = params->CopyStyle;
460 op->src_root = strdupAtoW( params->SourceRootPath );
461 op->src_path = strdupAtoW( params->SourcePath );
462 op->src_file = strdupAtoW( params->SourceFilename );
463 op->src_descr = strdupAtoW( params->SourceDescription );
464 op->src_tag = strdupAtoW( params->SourceTagfile );
465 op->dst_path = strdupAtoW( params->TargetDirectory );
466 op->dst_file = strdupAtoW( params->TargetFilename );
468 /* some defaults */
469 if (!op->src_file) op->src_file = op->dst_file;
470 if (params->LayoutInf)
472 get_src_file_info( params->LayoutInf, op );
473 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
476 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
477 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
478 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
479 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
481 queue_file_op( &queue->copy_queue, op );
482 return TRUE;
486 /***********************************************************************
487 * SetupQueueCopyIndirectW (SETUPAPI.@)
489 BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params )
491 struct file_queue *queue = params->QueueHandle;
492 struct file_op *op;
494 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
495 op->style = params->CopyStyle;
496 op->src_root = strdupW( params->SourceRootPath );
497 op->src_path = strdupW( params->SourcePath );
498 op->src_file = strdupW( params->SourceFilename );
499 op->src_descr = strdupW( params->SourceDescription );
500 op->src_tag = strdupW( params->SourceTagfile );
501 op->dst_path = strdupW( params->TargetDirectory );
502 op->dst_file = strdupW( params->TargetFilename );
504 /* some defaults */
505 if (!op->src_file) op->src_file = op->dst_file;
506 if (params->LayoutInf)
508 get_src_file_info( params->LayoutInf, op );
509 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
512 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
513 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
514 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
515 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
517 queue_file_op( &queue->copy_queue, op );
518 return TRUE;
522 /***********************************************************************
523 * SetupQueueCopyA (SETUPAPI.@)
525 BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file,
526 PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file,
527 DWORD style )
529 SP_FILE_COPY_PARAMS_A params;
531 params.cbSize = sizeof(params);
532 params.QueueHandle = queue;
533 params.SourceRootPath = src_root;
534 params.SourcePath = src_path;
535 params.SourceFilename = src_file;
536 params.SourceDescription = src_descr;
537 params.SourceTagfile = src_tag;
538 params.TargetDirectory = dst_dir;
539 params.TargetFilename = dst_file;
540 params.CopyStyle = style;
541 params.LayoutInf = 0;
542 params.SecurityDescriptor = NULL;
543 return SetupQueueCopyIndirectA( &params );
547 /***********************************************************************
548 * SetupQueueCopyW (SETUPAPI.@)
550 BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file,
551 PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file,
552 DWORD style )
554 SP_FILE_COPY_PARAMS_W params;
556 params.cbSize = sizeof(params);
557 params.QueueHandle = queue;
558 params.SourceRootPath = src_root;
559 params.SourcePath = src_path;
560 params.SourceFilename = src_file;
561 params.SourceDescription = src_descr;
562 params.SourceTagfile = src_tag;
563 params.TargetDirectory = dst_dir;
564 params.TargetFilename = dst_file;
565 params.CopyStyle = style;
566 params.LayoutInf = 0;
567 params.SecurityDescriptor = NULL;
568 return SetupQueueCopyIndirectW( &params );
572 /***********************************************************************
573 * SetupQueueDefaultCopyA (SETUPAPI.@)
575 BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file,
576 PCSTR dst_file, DWORD style )
578 SP_FILE_COPY_PARAMS_A params;
580 params.cbSize = sizeof(params);
581 params.QueueHandle = queue;
582 params.SourceRootPath = src_root;
583 params.SourcePath = NULL;
584 params.SourceFilename = src_file;
585 params.SourceDescription = NULL;
586 params.SourceTagfile = NULL;
587 params.TargetDirectory = NULL;
588 params.TargetFilename = dst_file;
589 params.CopyStyle = style;
590 params.LayoutInf = hinf;
591 params.SecurityDescriptor = NULL;
592 return SetupQueueCopyIndirectA( &params );
596 /***********************************************************************
597 * SetupQueueDefaultCopyW (SETUPAPI.@)
599 BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file,
600 PCWSTR dst_file, DWORD style )
602 SP_FILE_COPY_PARAMS_W params;
604 params.cbSize = sizeof(params);
605 params.QueueHandle = queue;
606 params.SourceRootPath = src_root;
607 params.SourcePath = NULL;
608 params.SourceFilename = src_file;
609 params.SourceDescription = NULL;
610 params.SourceTagfile = NULL;
611 params.TargetDirectory = NULL;
612 params.TargetFilename = dst_file;
613 params.CopyStyle = style;
614 params.LayoutInf = hinf;
615 params.SecurityDescriptor = NULL;
616 return SetupQueueCopyIndirectW( &params );
620 /***********************************************************************
621 * SetupQueueDeleteA (SETUPAPI.@)
623 BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 )
625 struct file_queue *queue = handle;
626 struct file_op *op;
628 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
629 op->style = 0;
630 op->src_root = NULL;
631 op->src_path = NULL;
632 op->src_file = NULL;
633 op->src_descr = NULL;
634 op->src_tag = NULL;
635 op->dst_path = strdupAtoW( part1 );
636 op->dst_file = strdupAtoW( part2 );
637 queue_file_op( &queue->delete_queue, op );
638 return TRUE;
642 /***********************************************************************
643 * SetupQueueDeleteW (SETUPAPI.@)
645 BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 )
647 struct file_queue *queue = handle;
648 struct file_op *op;
650 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
651 op->style = 0;
652 op->src_root = NULL;
653 op->src_path = NULL;
654 op->src_file = NULL;
655 op->src_descr = NULL;
656 op->src_tag = NULL;
657 op->dst_path = strdupW( part1 );
658 op->dst_file = strdupW( part2 );
659 queue_file_op( &queue->delete_queue, op );
660 return TRUE;
664 /***********************************************************************
665 * SetupQueueRenameA (SETUPAPI.@)
667 BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename,
668 PCSTR TargetPath, PCSTR TargetFilename )
670 struct file_queue *queue = handle;
671 struct file_op *op;
673 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
674 op->style = 0;
675 op->src_root = NULL;
676 op->src_path = strdupAtoW( SourcePath );
677 op->src_file = strdupAtoW( SourceFilename );
678 op->src_descr = NULL;
679 op->src_tag = NULL;
680 op->dst_path = strdupAtoW( TargetPath );
681 op->dst_file = strdupAtoW( TargetFilename );
682 queue_file_op( &queue->rename_queue, op );
683 return TRUE;
687 /***********************************************************************
688 * SetupQueueRenameW (SETUPAPI.@)
690 BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename,
691 PCWSTR TargetPath, PCWSTR TargetFilename )
693 struct file_queue *queue = handle;
694 struct file_op *op;
696 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
697 op->style = 0;
698 op->src_root = NULL;
699 op->src_path = strdupW( SourcePath );
700 op->src_file = strdupW( SourceFilename );
701 op->src_descr = NULL;
702 op->src_tag = NULL;
703 op->dst_path = strdupW( TargetPath );
704 op->dst_file = strdupW( TargetFilename );
705 queue_file_op( &queue->rename_queue, op );
706 return TRUE;
710 /***********************************************************************
711 * SetupQueueCopySectionA (SETUPAPI.@)
713 BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist,
714 PCSTR section, DWORD style )
716 UNICODE_STRING sectionW;
717 BOOL ret = FALSE;
719 if (!RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
721 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
722 return FALSE;
724 if (!src_root)
725 ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style );
726 else
728 UNICODE_STRING srcW;
729 if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root ))
731 ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style );
732 RtlFreeUnicodeString( &srcW );
734 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
736 RtlFreeUnicodeString( &sectionW );
737 return ret;
741 /***********************************************************************
742 * SetupQueueCopySectionW (SETUPAPI.@)
744 BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist,
745 PCWSTR section, DWORD style )
747 SP_FILE_COPY_PARAMS_W params;
748 INFCONTEXT context;
749 WCHAR dest[MAX_PATH], src[MAX_PATH];
750 INT flags;
752 TRACE( "hinf=%p/%p section=%s root=%s\n",
753 hinf, hlist, debugstr_w(section), debugstr_w(src_root) );
755 params.cbSize = sizeof(params);
756 params.QueueHandle = queue;
757 params.SourceRootPath = src_root;
758 params.SourcePath = NULL;
759 params.SourceDescription = NULL;
760 params.SourceTagfile = NULL;
761 params.TargetFilename = dest;
762 params.CopyStyle = style;
763 params.LayoutInf = hinf;
764 params.SecurityDescriptor = NULL;
766 if (!hlist) hlist = hinf;
767 if (!hinf) hinf = hlist;
768 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
769 if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) return FALSE;
772 if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL ))
773 return FALSE;
774 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0;
775 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */
777 params.SourceFilename = *src ? src : NULL;
778 if (!SetupQueueCopyIndirectW( &params )) return FALSE;
779 } while (SetupFindNextLine( &context, &context ));
780 return TRUE;
784 /***********************************************************************
785 * SetupQueueDeleteSectionA (SETUPAPI.@)
787 BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
789 UNICODE_STRING sectionW;
790 BOOL ret = FALSE;
792 if (RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
794 ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer );
795 RtlFreeUnicodeString( &sectionW );
797 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
798 return ret;
802 /***********************************************************************
803 * SetupQueueDeleteSectionW (SETUPAPI.@)
805 BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
807 INFCONTEXT context;
808 WCHAR *dest_dir;
809 WCHAR buffer[MAX_PATH];
810 BOOL ret = FALSE;
811 INT flags;
813 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
815 if (!hlist) hlist = hinf;
816 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
817 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
820 if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
821 goto done;
822 if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
823 if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done;
824 } while (SetupFindNextLine( &context, &context ));
826 ret = TRUE;
827 done:
828 HeapFree( GetProcessHeap(), 0, dest_dir );
829 return ret;
833 /***********************************************************************
834 * SetupQueueRenameSectionA (SETUPAPI.@)
836 BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
838 UNICODE_STRING sectionW;
839 BOOL ret = FALSE;
841 if (RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
843 ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer );
844 RtlFreeUnicodeString( &sectionW );
846 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
847 return ret;
851 /***********************************************************************
852 * SetupQueueRenameSectionW (SETUPAPI.@)
854 BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
856 INFCONTEXT context;
857 WCHAR *dest_dir;
858 WCHAR src[MAX_PATH], dst[MAX_PATH];
859 BOOL ret = FALSE;
861 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
863 if (!hlist) hlist = hinf;
864 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
865 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
868 if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL ))
869 goto done;
870 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL ))
871 goto done;
872 if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done;
873 } while (SetupFindNextLine( &context, &context ));
875 ret = TRUE;
876 done:
877 HeapFree( GetProcessHeap(), 0, dest_dir );
878 return ret;
882 /***********************************************************************
883 * SetupCommitFileQueueA (SETUPAPI.@)
885 BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler,
886 PVOID context )
888 struct callback_WtoA_context ctx;
890 ctx.orig_context = context;
891 ctx.orig_handler = handler;
892 return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx );
896 /***********************************************************************
897 * create_full_pathW
899 * Recursively create all directories in the path.
901 static BOOL create_full_pathW(const WCHAR *path)
903 BOOL ret = TRUE;
904 int len;
905 WCHAR *new_path;
907 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
908 strcpyW(new_path, path);
910 while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
911 new_path[len - 1] = 0;
913 while(!CreateDirectoryW(new_path, NULL))
915 WCHAR *slash;
916 DWORD last_error = GetLastError();
918 if(last_error == ERROR_ALREADY_EXISTS)
919 break;
921 if(last_error != ERROR_PATH_NOT_FOUND)
923 ret = FALSE;
924 break;
927 if(!(slash = strrchrW(new_path, '\\')))
929 ret = FALSE;
930 break;
933 len = slash - new_path;
934 new_path[len] = 0;
935 if(!create_full_pathW(new_path))
937 ret = FALSE;
938 break;
940 new_path[len] = '\\';
943 HeapFree(GetProcessHeap(), 0, new_path);
944 return ret;
947 static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style)
949 BOOL rc = FALSE;
950 BOOL docopy = TRUE;
952 TRACE("copy %s to %s style 0x%lx\n",debugstr_w(source),debugstr_w(target),style);
954 /* before copy processing */
955 if (style & SP_COPY_REPLACEONLY)
957 if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES)
958 docopy = FALSE;
960 if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER))
962 DWORD VersionSizeSource=0;
963 DWORD VersionSizeTarget=0;
964 DWORD zero=0;
967 * This is sort of an interesting workaround. You see, calling
968 * GetVersionInfoSize on a builtin dll loads that dll into memory
969 * and we do not properly unload builtin dlls.. so we effectively
970 * lock into memory all the targets we are replacing. This leads
971 * to problems when we try to register the replaced dlls.
973 * So I will test for the existence of the files first so that
974 * we just basically unconditionally replace the builtin versions.
976 if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) &&
977 (GetFileAttributesW(source) != INVALID_FILE_ATTRIBUTES))
979 VersionSizeSource = GetFileVersionInfoSizeW(source,&zero);
980 VersionSizeTarget = GetFileVersionInfoSizeW(target,&zero);
983 TRACE("SizeTarget %li ... SizeSource %li\n",VersionSizeTarget,
984 VersionSizeSource);
986 if (VersionSizeSource && VersionSizeTarget)
988 LPVOID VersionSource;
989 LPVOID VersionTarget;
990 VS_FIXEDFILEINFO *TargetInfo;
991 VS_FIXEDFILEINFO *SourceInfo;
992 UINT length;
993 WCHAR SubBlock[2]={'\\',0};
994 DWORD ret;
996 VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource);
997 VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget);
999 ret = GetFileVersionInfoW(source,0,VersionSizeSource,VersionSource);
1000 if (ret)
1001 ret = GetFileVersionInfoW(target, 0, VersionSizeTarget,
1002 VersionTarget);
1004 if (ret)
1006 ret = VerQueryValueW(VersionSource, SubBlock,
1007 (LPVOID*)&SourceInfo, &length);
1008 if (ret)
1009 ret = VerQueryValueW(VersionTarget, SubBlock,
1010 (LPVOID*)&TargetInfo, &length);
1012 if (ret)
1014 TRACE("Versions: Source %li.%li target %li.%li\n",
1015 SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS,
1016 TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS);
1018 if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS)
1020 FIXME("Notify that target version is greater..\n");
1021 docopy = FALSE;
1023 else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS)
1024 && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS))
1026 FIXME("Notify that target version is greater..\n");
1027 docopy = FALSE;
1029 else if ((style & SP_COPY_NEWER_ONLY) &&
1030 (TargetInfo->dwFileVersionMS ==
1031 SourceInfo->dwFileVersionMS)
1032 &&(TargetInfo->dwFileVersionLS ==
1033 SourceInfo->dwFileVersionLS))
1035 FIXME("Notify that target version is greater..\n");
1036 docopy = FALSE;
1040 HeapFree(GetProcessHeap(),0,VersionSource);
1041 HeapFree(GetProcessHeap(),0,VersionTarget);
1044 if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE))
1046 if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES)
1048 FIXME("Notify user target file exists\n");
1049 docopy = FALSE;
1052 if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE |
1053 SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP))
1055 ERR("Unsupported style(s) 0x%lx\n",style);
1058 if (docopy)
1060 rc = CopyFileW(source,target,FALSE);
1061 TRACE("Did copy... rc was %i\n",rc);
1064 /* after copy processing */
1065 if (style & SP_COPY_DELETESOURCE)
1067 if (rc)
1068 DeleteFileW(source);
1071 return rc;
1074 /***********************************************************************
1075 * SetupCommitFileQueueW (SETUPAPI.@)
1077 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler,
1078 PVOID context )
1080 struct file_queue *queue = handle;
1081 struct file_op *op;
1082 BOOL result = FALSE;
1083 FILEPATHS_W paths;
1084 UINT op_result;
1086 paths.Source = paths.Target = NULL;
1088 if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count)
1089 return TRUE; /* nothing to do */
1091 if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE;
1093 /* perform deletes */
1095 if (queue->delete_queue.count)
1097 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE,
1098 queue->delete_queue.count ))) goto done;
1099 for (op = queue->delete_queue.head; op; op = op->next)
1101 build_filepathsW( op, &paths );
1102 op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE);
1103 if (op_result == FILEOP_ABORT) goto done;
1104 while (op_result == FILEOP_DOIT)
1106 TRACE( "deleting file %s\n", debugstr_w(paths.Target) );
1107 if (DeleteFileW( paths.Target )) break; /* success */
1108 paths.Win32Error = GetLastError();
1109 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 );
1110 if (op_result == FILEOP_ABORT) goto done;
1112 handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 );
1114 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 );
1117 /* perform renames */
1119 if (queue->rename_queue.count)
1121 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME,
1122 queue->rename_queue.count ))) goto done;
1123 for (op = queue->rename_queue.head; op; op = op->next)
1125 build_filepathsW( op, &paths );
1126 op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME);
1127 if (op_result == FILEOP_ABORT) goto done;
1128 while (op_result == FILEOP_DOIT)
1130 TRACE( "renaming file %s -> %s\n",
1131 debugstr_w(paths.Source), debugstr_w(paths.Target) );
1132 if (MoveFileW( paths.Source, paths.Target )) break; /* success */
1133 paths.Win32Error = GetLastError();
1134 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 );
1135 if (op_result == FILEOP_ABORT) goto done;
1137 handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 );
1139 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 );
1142 /* perform copies */
1144 if (queue->copy_queue.count)
1146 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY,
1147 queue->copy_queue.count ))) goto done;
1148 for (op = queue->copy_queue.head; op; op = op->next)
1150 WCHAR newpath[MAX_PATH];
1152 build_filepathsW( op, &paths );
1153 op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
1154 if (op_result == FILEOP_ABORT) goto done;
1155 if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT;
1156 while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
1158 TRACE( "copying file %s -> %s\n",
1159 debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ),
1160 debugstr_w(paths.Target) );
1161 if (op->dst_path)
1163 if (!create_full_pathW( op->dst_path ))
1165 paths.Win32Error = GetLastError();
1166 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1167 (UINT_PTR)&paths, (UINT_PTR)newpath );
1168 if (op_result == FILEOP_ABORT) goto done;
1171 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
1172 paths.Target, op->style )) break; /* success */
1173 /* try to extract it from the cabinet file */
1174 if (op->src_tag)
1176 if (extract_cabinet_file( op->src_tag, op->src_root,
1177 paths.Source, paths.Target )) break;
1179 paths.Win32Error = GetLastError();
1180 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1181 (UINT_PTR)&paths, (UINT_PTR)newpath );
1182 if (op_result == FILEOP_ABORT) goto done;
1184 handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
1186 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 );
1190 result = TRUE;
1192 done:
1193 handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 );
1194 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1195 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1196 return result;
1200 /***********************************************************************
1201 * SetupScanFileQueueA (SETUPAPI.@)
1203 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ queue, DWORD flags, HWND window,
1204 PSP_FILE_CALLBACK_A callback, PVOID context, PDWORD result )
1206 FIXME("stub\n");
1207 return FALSE;
1211 /***********************************************************************
1212 * SetupScanFileQueueW (SETUPAPI.@)
1214 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ queue, DWORD flags, HWND window,
1215 PSP_FILE_CALLBACK_W callback, PVOID context, PDWORD result )
1217 FIXME("stub\n");
1218 return FALSE;
1222 /***********************************************************************
1223 * SetupGetFileQueueCount (SETUPAPI.@)
1225 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result )
1227 struct file_queue *queue = handle;
1229 switch(op)
1231 case FILEOP_COPY:
1232 *result = queue->copy_queue.count;
1233 return TRUE;
1234 case FILEOP_RENAME:
1235 *result = queue->rename_queue.count;
1236 return TRUE;
1237 case FILEOP_DELETE:
1238 *result = queue->delete_queue.count;
1239 return TRUE;
1241 return FALSE;
1245 /***********************************************************************
1246 * SetupGetFileQueueFlags (SETUPAPI.@)
1248 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags )
1250 struct file_queue *queue = handle;
1251 *flags = queue->flags;
1252 return TRUE;
1256 /***********************************************************************
1257 * SetupSetFileQueueFlags (SETUPAPI.@)
1259 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags )
1261 struct file_queue *queue = handle;
1262 queue->flags = (queue->flags & ~mask) | flags;
1263 return TRUE;
1267 /***********************************************************************
1268 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1270 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile)
1272 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile));
1273 return FALSE;
1277 /***********************************************************************
1278 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1280 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile)
1282 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile));
1283 return FALSE;
1287 /***********************************************************************
1288 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1290 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner )
1292 return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL );
1296 /***********************************************************************
1297 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1299 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg,
1300 DWORD reserved1, PVOID reserved2 )
1302 struct default_callback_context *context;
1304 if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) )))
1306 context->owner = owner;
1307 context->progress = progress;
1308 context->message = msg;
1310 return context;
1314 /***********************************************************************
1315 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1317 void WINAPI SetupTermDefaultQueueCallback( PVOID context )
1319 HeapFree( GetProcessHeap(), 0, context );
1323 /***********************************************************************
1324 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1326 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification,
1327 UINT_PTR param1, UINT_PTR param2 )
1329 FILEPATHS_A *paths = (FILEPATHS_A *)param1;
1330 struct default_callback_context *ctx = (struct default_callback_context *)context;
1332 switch(notification)
1334 case SPFILENOTIFY_STARTQUEUE:
1335 TRACE( "start queue\n" );
1336 return TRUE;
1337 case SPFILENOTIFY_ENDQUEUE:
1338 TRACE( "end queue\n" );
1339 return 0;
1340 case SPFILENOTIFY_STARTSUBQUEUE:
1341 TRACE( "start subqueue %d count %d\n", param1, param2 );
1342 return TRUE;
1343 case SPFILENOTIFY_ENDSUBQUEUE:
1344 TRACE( "end subqueue %d\n", param1 );
1345 return 0;
1346 case SPFILENOTIFY_STARTDELETE:
1347 TRACE( "start delete %s\n", debugstr_a(paths->Target) );
1348 return FILEOP_DOIT;
1349 case SPFILENOTIFY_ENDDELETE:
1350 TRACE( "end delete %s\n", debugstr_a(paths->Target) );
1351 return 0;
1352 case SPFILENOTIFY_DELETEERROR:
1353 /*Windows Ignores attempts to delete files / folders which do not exist*/
1354 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1355 SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1356 return FILEOP_SKIP;
1357 case SPFILENOTIFY_STARTRENAME:
1358 TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1359 return FILEOP_DOIT;
1360 case SPFILENOTIFY_ENDRENAME:
1361 TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1362 return 0;
1363 case SPFILENOTIFY_RENAMEERROR:
1364 SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1365 return FILEOP_SKIP;
1366 case SPFILENOTIFY_STARTCOPY:
1367 TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1368 return FILEOP_DOIT;
1369 case SPFILENOTIFY_ENDCOPY:
1370 TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1371 return 0;
1372 case SPFILENOTIFY_COPYERROR:
1373 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1374 debugstr_a(paths->Source), debugstr_a(paths->Target) );
1375 return FILEOP_SKIP;
1376 case SPFILENOTIFY_NEEDMEDIA:
1377 TRACE( "need media\n" );
1378 return FILEOP_SKIP;
1379 default:
1380 FIXME( "notification %d params %x,%x\n", notification, param1, param2 );
1381 break;
1383 return 0;
1387 /***********************************************************************
1388 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1390 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification,
1391 UINT_PTR param1, UINT_PTR param2 )
1393 FILEPATHS_W *paths = (FILEPATHS_W *)param1;
1394 struct default_callback_context *ctx = (struct default_callback_context *)context;
1396 switch(notification)
1398 case SPFILENOTIFY_STARTQUEUE:
1399 TRACE( "start queue\n" );
1400 return TRUE;
1401 case SPFILENOTIFY_ENDQUEUE:
1402 TRACE( "end queue\n" );
1403 return 0;
1404 case SPFILENOTIFY_STARTSUBQUEUE:
1405 TRACE( "start subqueue %d count %d\n", param1, param2 );
1406 return TRUE;
1407 case SPFILENOTIFY_ENDSUBQUEUE:
1408 TRACE( "end subqueue %d\n", param1 );
1409 return 0;
1410 case SPFILENOTIFY_STARTDELETE:
1411 TRACE( "start delete %s\n", debugstr_w(paths->Target) );
1412 return FILEOP_DOIT;
1413 case SPFILENOTIFY_ENDDELETE:
1414 TRACE( "end delete %s\n", debugstr_w(paths->Target) );
1415 return 0;
1416 case SPFILENOTIFY_DELETEERROR:
1417 /*Windows Ignores attempts to delete files / folders which do not exist*/
1418 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1419 SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1420 return FILEOP_SKIP;
1421 case SPFILENOTIFY_STARTRENAME:
1422 SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1423 return FILEOP_DOIT;
1424 case SPFILENOTIFY_ENDRENAME:
1425 TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1426 return 0;
1427 case SPFILENOTIFY_RENAMEERROR:
1428 ERR( "rename error %d %s -> %s\n", paths->Win32Error,
1429 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1430 return FILEOP_SKIP;
1431 case SPFILENOTIFY_STARTCOPY:
1432 TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1433 return FILEOP_DOIT;
1434 case SPFILENOTIFY_ENDCOPY:
1435 TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1436 return 0;
1437 case SPFILENOTIFY_COPYERROR:
1438 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1439 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1440 return FILEOP_SKIP;
1441 case SPFILENOTIFY_NEEDMEDIA:
1442 TRACE( "need media\n" );
1443 return FILEOP_SKIP;
1444 default:
1445 FIXME( "notification %d params %x,%x\n", notification, param1, param2 );
1446 break;
1448 return 0;
1451 /***********************************************************************
1452 * SetupDeleteErrorA (SETUPAPI.@)
1455 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file,
1456 UINT w32error, DWORD style)
1458 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1459 w32error, debugstr_a(file) );
1460 return DPROMPT_SKIPFILE;
1463 /***********************************************************************
1464 * SetupDeleteErrorW (SETUPAPI.@)
1467 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file,
1468 UINT w32error, DWORD style)
1470 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1471 w32error, debugstr_w(file) );
1472 return DPROMPT_SKIPFILE;
1475 /***********************************************************************
1476 * SetupRenameErrorA (SETUPAPI.@)
1479 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source,
1480 PCSTR target, UINT w32error, DWORD style)
1482 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1483 w32error, debugstr_a(source), debugstr_a(target));
1484 return DPROMPT_SKIPFILE;
1487 /***********************************************************************
1488 * SetupRenameErrorW (SETUPAPI.@)
1491 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source,
1492 PCWSTR target, UINT w32error, DWORD style)
1494 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1495 w32error, debugstr_w(source), debugstr_w(target));
1496 return DPROMPT_SKIPFILE;
1500 /***********************************************************************
1501 * SetupCopyErrorA (SETUPAPI.@)
1504 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname,
1505 PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath,
1506 UINT w32error, DWORD style, PSTR pathbuffer,
1507 DWORD buffersize, PDWORD requiredsize)
1509 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1510 w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath));
1511 return DPROMPT_SKIPFILE;
1514 /***********************************************************************
1515 * SetupCopyErrorW (SETUPAPI.@)
1518 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname,
1519 PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath,
1520 UINT w32error, DWORD style, PWSTR pathbuffer,
1521 DWORD buffersize, PDWORD requiredsize)
1523 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1524 w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath));
1525 return DPROMPT_SKIPFILE;