push 6fe5edf8439c19d3885814583531c2f2b1495177
[wine/hacks.git] / dlls / setupapi / queue.c
blob3212d5a546c8bce8aae362097e60283f3e3b7a84
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 /* append a file operation to a queue */
77 static inline void queue_file_op( struct file_op_queue *queue, struct file_op *op )
79 op->next = NULL;
80 if (queue->tail) queue->tail->next = op;
81 else queue->head = op;
82 queue->tail = op;
83 queue->count++;
86 /* free all the file operations on a given queue */
87 static void free_file_op_queue( struct file_op_queue *queue )
89 struct file_op *t, *op = queue->head;
91 while( op )
93 HeapFree( GetProcessHeap(), 0, op->src_root );
94 HeapFree( GetProcessHeap(), 0, op->src_path );
95 HeapFree( GetProcessHeap(), 0, op->src_file );
96 HeapFree( GetProcessHeap(), 0, op->src_descr );
97 HeapFree( GetProcessHeap(), 0, op->src_tag );
98 HeapFree( GetProcessHeap(), 0, op->dst_path );
99 if (op->dst_file != op->src_file) HeapFree( GetProcessHeap(), 0, op->dst_file );
100 t = op;
101 op = op->next;
102 HeapFree( GetProcessHeap(), 0, t );
106 /* concat 3 strings to make a path, handling separators correctly */
107 static void concat_W( WCHAR *buffer, const WCHAR *src1, const WCHAR *src2, const WCHAR *src3 )
109 *buffer = 0;
110 if (src1 && *src1)
112 strcpyW( buffer, src1 );
113 buffer += strlenW(buffer );
114 if (buffer[-1] != '\\') *buffer++ = '\\';
115 if (src2) while (*src2 == '\\') src2++;
118 if (src2)
120 strcpyW( buffer, src2 );
121 buffer += strlenW(buffer );
122 if (buffer[-1] != '\\') *buffer++ = '\\';
123 if (src3) while (*src3 == '\\') src3++;
125 if (src3)
127 strcpyW( buffer, src3 );
128 buffer += strlenW(buffer );
133 /***********************************************************************
134 * build_filepathsW
136 * Build a FILEPATHS_W structure for a given file operation.
138 static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths )
140 unsigned int src_len = 1, dst_len = 1;
141 WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target;
143 if (op->src_root) src_len += strlenW(op->src_root) + 1;
144 if (op->src_path) src_len += strlenW(op->src_path) + 1;
145 if (op->src_file) src_len += strlenW(op->src_file) + 1;
146 if (op->dst_path) dst_len += strlenW(op->dst_path) + 1;
147 if (op->dst_file) dst_len += strlenW(op->dst_file) + 1;
148 src_len *= sizeof(WCHAR);
149 dst_len *= sizeof(WCHAR);
151 if (!source || HeapSize( GetProcessHeap(), 0, source ) < src_len )
153 HeapFree( GetProcessHeap(), 0, source );
154 paths->Source = source = HeapAlloc( GetProcessHeap(), 0, src_len );
156 if (!target || HeapSize( GetProcessHeap(), 0, target ) < dst_len )
158 HeapFree( GetProcessHeap(), 0, target );
159 paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len );
161 if (!source || !target) return FALSE;
162 concat_W( source, op->src_root, op->src_path, op->src_file );
163 concat_W( target, NULL, op->dst_path, op->dst_file );
164 paths->Win32Error = 0;
165 paths->Flags = 0;
166 return TRUE;
170 /***********************************************************************
171 * QUEUE_callback_WtoA
173 * Map a file callback parameters from W to A and call the A callback.
175 UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification,
176 UINT_PTR param1, UINT_PTR param2 )
178 struct callback_WtoA_context *callback_ctx = context;
179 char buffer[MAX_PATH];
180 UINT ret;
181 UINT_PTR old_param2 = param2;
183 switch(notification)
185 case SPFILENOTIFY_COPYERROR:
186 param2 = (UINT_PTR)&buffer;
187 /* fall through */
188 case SPFILENOTIFY_STARTDELETE:
189 case SPFILENOTIFY_ENDDELETE:
190 case SPFILENOTIFY_DELETEERROR:
191 case SPFILENOTIFY_STARTRENAME:
192 case SPFILENOTIFY_ENDRENAME:
193 case SPFILENOTIFY_RENAMEERROR:
194 case SPFILENOTIFY_STARTCOPY:
195 case SPFILENOTIFY_ENDCOPY:
196 case SPFILENOTIFY_QUEUESCAN_EX:
198 FILEPATHS_W *pathsW = (FILEPATHS_W *)param1;
199 FILEPATHS_A pathsA;
201 pathsA.Source = strdupWtoA( pathsW->Source );
202 pathsA.Target = strdupWtoA( pathsW->Target );
203 pathsA.Win32Error = pathsW->Win32Error;
204 pathsA.Flags = pathsW->Flags;
205 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
206 (UINT_PTR)&pathsA, param2 );
207 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Source );
208 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Target );
210 if (notification == SPFILENOTIFY_COPYERROR)
211 MultiByteToWideChar( CP_ACP, 0, buffer, -1, (WCHAR *)old_param2, MAX_PATH );
212 break;
214 case SPFILENOTIFY_STARTREGISTRATION:
215 case SPFILENOTIFY_ENDREGISTRATION:
217 SP_REGISTER_CONTROL_STATUSW *statusW = (SP_REGISTER_CONTROL_STATUSW *)param1;
218 SP_REGISTER_CONTROL_STATUSA statusA;
220 statusA.cbSize = sizeof(statusA);
221 statusA.FileName = strdupWtoA( statusW->FileName );
222 statusA.Win32Error = statusW->Win32Error;
223 statusA.FailureCode = statusW->FailureCode;
224 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
225 (UINT_PTR)&statusA, param2 );
226 HeapFree( GetProcessHeap(), 0, (LPSTR)statusA.FileName );
228 break;
230 case SPFILENOTIFY_QUEUESCAN:
232 LPWSTR targetW = (LPWSTR)param1;
233 LPSTR target = strdupWtoA( targetW );
235 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
236 (UINT_PTR)target, param2 );
237 HeapFree( GetProcessHeap(), 0, target );
239 break;
241 case SPFILENOTIFY_NEEDMEDIA:
242 FIXME("mapping for %d not implemented\n",notification);
243 case SPFILENOTIFY_STARTQUEUE:
244 case SPFILENOTIFY_ENDQUEUE:
245 case SPFILENOTIFY_STARTSUBQUEUE:
246 case SPFILENOTIFY_ENDSUBQUEUE:
247 default:
248 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, param1, param2 );
249 break;
251 return ret;
255 /***********************************************************************
256 * get_src_file_info
258 * Retrieve the source file information for a given file.
260 static void get_src_file_info( HINF hinf, struct file_op *op )
262 static const WCHAR SourceDisksNames[] =
263 {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0};
264 static const WCHAR SourceDisksFiles[] =
265 {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
267 INFCONTEXT file_ctx, disk_ctx;
268 INT id, diskid;
269 DWORD len, len2;
271 /* find the SourceDisksFiles entry */
272 if (!SetupFindFirstLineW( hinf, SourceDisksFiles, op->src_file, &file_ctx ))
274 if ((op->style & (SP_COPY_SOURCE_ABSOLUTE|SP_COPY_SOURCEPATH_ABSOLUTE))) return;
275 /* no specific info, use .inf file source directory */
276 if (!op->src_root) op->src_root = PARSER_get_src_root( hinf );
277 return;
279 if (!SetupGetIntField( &file_ctx, 1, &diskid )) return;
281 /* now find the diskid in the SourceDisksNames section */
282 if (!SetupFindFirstLineW( hinf, SourceDisksNames, NULL, &disk_ctx )) return;
283 for (;;)
285 if (SetupGetIntField( &disk_ctx, 0, &id ) && (id == diskid)) break;
286 if (!SetupFindNextLine( &disk_ctx, &disk_ctx )) return;
289 /* and fill in the missing info */
291 if (!op->src_descr)
293 if (SetupGetStringFieldW( &disk_ctx, 1, NULL, 0, &len ) &&
294 (op->src_descr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
295 SetupGetStringFieldW( &disk_ctx, 1, op->src_descr, len, NULL );
297 if (!op->src_tag)
299 if (SetupGetStringFieldW( &disk_ctx, 2, NULL, 0, &len ) &&
300 (op->src_tag = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
301 SetupGetStringFieldW( &disk_ctx, 2, op->src_tag, len, NULL );
303 if (!op->src_path && !(op->style & SP_COPY_SOURCE_ABSOLUTE))
305 len = len2 = 0;
306 if (!(op->style & SP_COPY_SOURCEPATH_ABSOLUTE))
308 /* retrieve relative path for this disk */
309 if (!SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len )) len = 0;
311 /* retrieve relative path for this file */
312 if (!SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len2 )) len2 = 0;
314 if ((len || len2) &&
315 (op->src_path = HeapAlloc( GetProcessHeap(), 0, (len+len2)*sizeof(WCHAR) )))
317 WCHAR *ptr = op->src_path;
318 if (len)
320 SetupGetStringFieldW( &disk_ctx, 4, op->src_path, len, NULL );
321 ptr = op->src_path + strlenW(op->src_path);
322 if (len2 && ptr > op->src_path && ptr[-1] != '\\') *ptr++ = '\\';
324 if (!SetupGetStringFieldW( &file_ctx, 2, ptr, len2, NULL )) *ptr = 0;
327 if (!op->src_root) op->src_root = PARSER_get_src_root(hinf);
331 /***********************************************************************
332 * get_destination_dir
334 * Retrieve the destination dir for a given section.
336 static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
338 static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
339 static const WCHAR Def[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
340 INFCONTEXT context;
342 if (!SetupFindFirstLineW( hinf, Dest, section, &context ) &&
343 !SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL;
344 return PARSER_get_dest_dir( &context );
348 static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD );
350 /***********************************************************************
351 * extract_cabinet_file
353 * Extract a file from a .cab file.
355 static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root,
356 const WCHAR *src, const WCHAR *dst )
358 static const WCHAR extW[] = {'.','c','a','b',0};
359 static HMODULE advpack;
361 char *cab_path, *cab_file;
362 int len = strlenW( cabinet );
364 /* make sure the cabinet file has a .cab extension */
365 if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE;
366 if (!pExtractFiles)
368 if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" )))
370 ERR( "could not load advpack.dll\n" );
371 return FALSE;
373 if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" )))
375 ERR( "could not find ExtractFiles in advpack.dll\n" );
376 return FALSE;
380 if (!(cab_path = strdupWtoA( root ))) return FALSE;
381 len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL );
382 if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 )))
384 HeapFree( GetProcessHeap(), 0, cab_path );
385 return FALSE;
387 strcpy( cab_file, cab_path );
388 if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" );
389 WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL );
390 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) );
391 pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 );
392 HeapFree( GetProcessHeap(), 0, cab_file );
393 HeapFree( GetProcessHeap(), 0, cab_path );
394 return CopyFileW( src, dst, FALSE /*FIXME*/ );
398 /***********************************************************************
399 * SetupOpenFileQueue (SETUPAPI.@)
401 HSPFILEQ WINAPI SetupOpenFileQueue(void)
403 struct file_queue *queue;
405 if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue))))
406 return INVALID_HANDLE_VALUE;
407 return queue;
411 /***********************************************************************
412 * SetupCloseFileQueue (SETUPAPI.@)
414 BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle )
416 struct file_queue *queue = handle;
418 free_file_op_queue( &queue->copy_queue );
419 free_file_op_queue( &queue->rename_queue );
420 free_file_op_queue( &queue->delete_queue );
421 HeapFree( GetProcessHeap(), 0, queue );
422 return TRUE;
426 /***********************************************************************
427 * SetupQueueCopyIndirectA (SETUPAPI.@)
429 BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params )
431 struct file_queue *queue = params->QueueHandle;
432 struct file_op *op;
434 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
435 op->style = params->CopyStyle;
436 op->src_root = strdupAtoW( params->SourceRootPath );
437 op->src_path = strdupAtoW( params->SourcePath );
438 op->src_file = strdupAtoW( params->SourceFilename );
439 op->src_descr = strdupAtoW( params->SourceDescription );
440 op->src_tag = strdupAtoW( params->SourceTagfile );
441 op->dst_path = strdupAtoW( params->TargetDirectory );
442 op->dst_file = strdupAtoW( params->TargetFilename );
444 /* some defaults */
445 if (!op->src_file) op->src_file = op->dst_file;
446 if (params->LayoutInf)
448 get_src_file_info( params->LayoutInf, op );
449 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
452 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
453 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
454 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
455 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
457 queue_file_op( &queue->copy_queue, op );
458 return TRUE;
462 /***********************************************************************
463 * SetupQueueCopyIndirectW (SETUPAPI.@)
465 BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params )
467 struct file_queue *queue = params->QueueHandle;
468 struct file_op *op;
470 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
471 op->style = params->CopyStyle;
472 op->src_root = strdupW( params->SourceRootPath );
473 op->src_path = strdupW( params->SourcePath );
474 op->src_file = strdupW( params->SourceFilename );
475 op->src_descr = strdupW( params->SourceDescription );
476 op->src_tag = strdupW( params->SourceTagfile );
477 op->dst_path = strdupW( params->TargetDirectory );
478 op->dst_file = strdupW( params->TargetFilename );
480 /* some defaults */
481 if (!op->src_file) op->src_file = op->dst_file;
482 if (params->LayoutInf)
484 get_src_file_info( params->LayoutInf, op );
485 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
488 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
489 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
490 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
491 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
493 queue_file_op( &queue->copy_queue, op );
494 return TRUE;
498 /***********************************************************************
499 * SetupQueueCopyA (SETUPAPI.@)
501 BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file,
502 PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file,
503 DWORD style )
505 SP_FILE_COPY_PARAMS_A params;
507 params.cbSize = sizeof(params);
508 params.QueueHandle = queue;
509 params.SourceRootPath = src_root;
510 params.SourcePath = src_path;
511 params.SourceFilename = src_file;
512 params.SourceDescription = src_descr;
513 params.SourceTagfile = src_tag;
514 params.TargetDirectory = dst_dir;
515 params.TargetFilename = dst_file;
516 params.CopyStyle = style;
517 params.LayoutInf = 0;
518 params.SecurityDescriptor = NULL;
519 return SetupQueueCopyIndirectA( &params );
523 /***********************************************************************
524 * SetupQueueCopyW (SETUPAPI.@)
526 BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file,
527 PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file,
528 DWORD style )
530 SP_FILE_COPY_PARAMS_W params;
532 params.cbSize = sizeof(params);
533 params.QueueHandle = queue;
534 params.SourceRootPath = src_root;
535 params.SourcePath = src_path;
536 params.SourceFilename = src_file;
537 params.SourceDescription = src_descr;
538 params.SourceTagfile = src_tag;
539 params.TargetDirectory = dst_dir;
540 params.TargetFilename = dst_file;
541 params.CopyStyle = style;
542 params.LayoutInf = 0;
543 params.SecurityDescriptor = NULL;
544 return SetupQueueCopyIndirectW( &params );
548 /***********************************************************************
549 * SetupQueueDefaultCopyA (SETUPAPI.@)
551 BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file,
552 PCSTR dst_file, DWORD style )
554 SP_FILE_COPY_PARAMS_A params;
556 params.cbSize = sizeof(params);
557 params.QueueHandle = queue;
558 params.SourceRootPath = src_root;
559 params.SourcePath = NULL;
560 params.SourceFilename = src_file;
561 params.SourceDescription = NULL;
562 params.SourceTagfile = NULL;
563 params.TargetDirectory = NULL;
564 params.TargetFilename = dst_file;
565 params.CopyStyle = style;
566 params.LayoutInf = hinf;
567 params.SecurityDescriptor = NULL;
568 return SetupQueueCopyIndirectA( &params );
572 /***********************************************************************
573 * SetupQueueDefaultCopyW (SETUPAPI.@)
575 BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file,
576 PCWSTR dst_file, DWORD style )
578 SP_FILE_COPY_PARAMS_W params;
580 params.cbSize = sizeof(params);
581 params.QueueHandle = queue;
582 params.SourceRootPath = src_root;
583 params.SourcePath = NULL;
584 params.SourceFilename = src_file;
585 params.SourceDescription = NULL;
586 params.SourceTagfile = NULL;
587 params.TargetDirectory = NULL;
588 params.TargetFilename = dst_file;
589 params.CopyStyle = style;
590 params.LayoutInf = hinf;
591 params.SecurityDescriptor = NULL;
592 return SetupQueueCopyIndirectW( &params );
596 /***********************************************************************
597 * SetupQueueDeleteA (SETUPAPI.@)
599 BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 )
601 struct file_queue *queue = handle;
602 struct file_op *op;
604 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
605 op->style = 0;
606 op->src_root = NULL;
607 op->src_path = NULL;
608 op->src_file = NULL;
609 op->src_descr = NULL;
610 op->src_tag = NULL;
611 op->dst_path = strdupAtoW( part1 );
612 op->dst_file = strdupAtoW( part2 );
613 queue_file_op( &queue->delete_queue, op );
614 return TRUE;
618 /***********************************************************************
619 * SetupQueueDeleteW (SETUPAPI.@)
621 BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 )
623 struct file_queue *queue = handle;
624 struct file_op *op;
626 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
627 op->style = 0;
628 op->src_root = NULL;
629 op->src_path = NULL;
630 op->src_file = NULL;
631 op->src_descr = NULL;
632 op->src_tag = NULL;
633 op->dst_path = strdupW( part1 );
634 op->dst_file = strdupW( part2 );
635 queue_file_op( &queue->delete_queue, op );
636 return TRUE;
640 /***********************************************************************
641 * SetupQueueRenameA (SETUPAPI.@)
643 BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename,
644 PCSTR TargetPath, PCSTR TargetFilename )
646 struct file_queue *queue = handle;
647 struct file_op *op;
649 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
650 op->style = 0;
651 op->src_root = NULL;
652 op->src_path = strdupAtoW( SourcePath );
653 op->src_file = strdupAtoW( SourceFilename );
654 op->src_descr = NULL;
655 op->src_tag = NULL;
656 op->dst_path = strdupAtoW( TargetPath );
657 op->dst_file = strdupAtoW( TargetFilename );
658 queue_file_op( &queue->rename_queue, op );
659 return TRUE;
663 /***********************************************************************
664 * SetupQueueRenameW (SETUPAPI.@)
666 BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename,
667 PCWSTR TargetPath, PCWSTR TargetFilename )
669 struct file_queue *queue = handle;
670 struct file_op *op;
672 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
673 op->style = 0;
674 op->src_root = NULL;
675 op->src_path = strdupW( SourcePath );
676 op->src_file = strdupW( SourceFilename );
677 op->src_descr = NULL;
678 op->src_tag = NULL;
679 op->dst_path = strdupW( TargetPath );
680 op->dst_file = strdupW( TargetFilename );
681 queue_file_op( &queue->rename_queue, op );
682 return TRUE;
686 /***********************************************************************
687 * SetupQueueCopySectionA (SETUPAPI.@)
689 BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist,
690 PCSTR section, DWORD style )
692 UNICODE_STRING sectionW;
693 BOOL ret = FALSE;
695 if (!RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
697 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
698 return FALSE;
700 if (!src_root)
701 ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style );
702 else
704 UNICODE_STRING srcW;
705 if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root ))
707 ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style );
708 RtlFreeUnicodeString( &srcW );
710 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
712 RtlFreeUnicodeString( &sectionW );
713 return ret;
717 /***********************************************************************
718 * SetupQueueCopySectionW (SETUPAPI.@)
720 BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist,
721 PCWSTR section, DWORD style )
723 SP_FILE_COPY_PARAMS_W params;
724 INFCONTEXT context;
725 WCHAR dest[MAX_PATH], src[MAX_PATH];
726 INT flags;
728 TRACE( "hinf=%p/%p section=%s root=%s\n",
729 hinf, hlist, debugstr_w(section), debugstr_w(src_root) );
731 params.cbSize = sizeof(params);
732 params.QueueHandle = queue;
733 params.SourceRootPath = src_root;
734 params.SourcePath = NULL;
735 params.SourceDescription = NULL;
736 params.SourceTagfile = NULL;
737 params.TargetFilename = dest;
738 params.CopyStyle = style;
739 params.LayoutInf = hinf;
740 params.SecurityDescriptor = NULL;
742 if (!hlist) hlist = hinf;
743 if (!hinf) hinf = hlist;
744 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
745 if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) return FALSE;
748 if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL ))
749 return FALSE;
750 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0;
751 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */
753 params.SourceFilename = *src ? src : NULL;
754 if (!SetupQueueCopyIndirectW( &params )) return FALSE;
755 } while (SetupFindNextLine( &context, &context ));
756 return TRUE;
760 /***********************************************************************
761 * SetupQueueDeleteSectionA (SETUPAPI.@)
763 BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
765 UNICODE_STRING sectionW;
766 BOOL ret = FALSE;
768 if (RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
770 ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer );
771 RtlFreeUnicodeString( &sectionW );
773 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
774 return ret;
778 /***********************************************************************
779 * SetupQueueDeleteSectionW (SETUPAPI.@)
781 BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
783 INFCONTEXT context;
784 WCHAR *dest_dir;
785 WCHAR buffer[MAX_PATH];
786 BOOL ret = FALSE;
787 INT flags;
789 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
791 if (!hlist) hlist = hinf;
792 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
793 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
796 if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
797 goto done;
798 if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
799 if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done;
800 } while (SetupFindNextLine( &context, &context ));
802 ret = TRUE;
803 done:
804 HeapFree( GetProcessHeap(), 0, dest_dir );
805 return ret;
809 /***********************************************************************
810 * SetupQueueRenameSectionA (SETUPAPI.@)
812 BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
814 UNICODE_STRING sectionW;
815 BOOL ret = FALSE;
817 if (RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
819 ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer );
820 RtlFreeUnicodeString( &sectionW );
822 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
823 return ret;
827 /***********************************************************************
828 * SetupQueueRenameSectionW (SETUPAPI.@)
830 BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
832 INFCONTEXT context;
833 WCHAR *dest_dir;
834 WCHAR src[MAX_PATH], dst[MAX_PATH];
835 BOOL ret = FALSE;
837 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
839 if (!hlist) hlist = hinf;
840 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
841 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
844 if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL ))
845 goto done;
846 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL ))
847 goto done;
848 if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done;
849 } while (SetupFindNextLine( &context, &context ));
851 ret = TRUE;
852 done:
853 HeapFree( GetProcessHeap(), 0, dest_dir );
854 return ret;
858 /***********************************************************************
859 * SetupCommitFileQueueA (SETUPAPI.@)
861 BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler,
862 PVOID context )
864 struct callback_WtoA_context ctx;
866 ctx.orig_context = context;
867 ctx.orig_handler = handler;
868 return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx );
872 /***********************************************************************
873 * create_full_pathW
875 * Recursively create all directories in the path.
877 static BOOL create_full_pathW(const WCHAR *path)
879 BOOL ret = TRUE;
880 int len;
881 WCHAR *new_path;
883 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
884 strcpyW(new_path, path);
886 while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
887 new_path[len - 1] = 0;
889 while(!CreateDirectoryW(new_path, NULL))
891 WCHAR *slash;
892 DWORD last_error = GetLastError();
894 if(last_error == ERROR_ALREADY_EXISTS)
895 break;
897 if(last_error != ERROR_PATH_NOT_FOUND)
899 ret = FALSE;
900 break;
903 if(!(slash = strrchrW(new_path, '\\')))
905 ret = FALSE;
906 break;
909 len = slash - new_path;
910 new_path[len] = 0;
911 if(!create_full_pathW(new_path))
913 ret = FALSE;
914 break;
916 new_path[len] = '\\';
919 HeapFree(GetProcessHeap(), 0, new_path);
920 return ret;
923 static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style,
924 PSP_FILE_CALLBACK_W handler, PVOID context )
926 BOOL rc = FALSE;
927 BOOL docopy = TRUE;
929 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source),debugstr_w(target),style);
931 /* before copy processing */
932 if (style & SP_COPY_REPLACEONLY)
934 if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES)
935 docopy = FALSE;
937 if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER))
939 DWORD VersionSizeSource=0;
940 DWORD VersionSizeTarget=0;
941 DWORD zero=0;
944 * This is sort of an interesting workaround. You see, calling
945 * GetVersionInfoSize on a builtin dll loads that dll into memory
946 * and we do not properly unload builtin dlls.. so we effectively
947 * lock into memory all the targets we are replacing. This leads
948 * to problems when we try to register the replaced dlls.
950 * So I will test for the existence of the files first so that
951 * we just basically unconditionally replace the builtin versions.
953 if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) &&
954 (GetFileAttributesW(source) != INVALID_FILE_ATTRIBUTES))
956 VersionSizeSource = GetFileVersionInfoSizeW(source,&zero);
957 VersionSizeTarget = GetFileVersionInfoSizeW(target,&zero);
960 TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget,
961 VersionSizeSource);
963 if (VersionSizeSource && VersionSizeTarget)
965 LPVOID VersionSource;
966 LPVOID VersionTarget;
967 VS_FIXEDFILEINFO *TargetInfo;
968 VS_FIXEDFILEINFO *SourceInfo;
969 UINT length;
970 WCHAR SubBlock[2]={'\\',0};
971 DWORD ret;
973 VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource);
974 VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget);
976 ret = GetFileVersionInfoW(source,0,VersionSizeSource,VersionSource);
977 if (ret)
978 ret = GetFileVersionInfoW(target, 0, VersionSizeTarget,
979 VersionTarget);
981 if (ret)
983 ret = VerQueryValueW(VersionSource, SubBlock,
984 (LPVOID*)&SourceInfo, &length);
985 if (ret)
986 ret = VerQueryValueW(VersionTarget, SubBlock,
987 (LPVOID*)&TargetInfo, &length);
989 if (ret)
991 FILEPATHS_W filepaths;
993 TRACE("Versions: Source %i.%i target %i.%i\n",
994 SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS,
995 TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS);
997 /* used in case of notification */
998 filepaths.Target = target;
999 filepaths.Source = source;
1000 filepaths.Win32Error = 0;
1001 filepaths.Flags = 0;
1003 if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS)
1005 if (handler)
1006 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1007 else
1008 docopy = FALSE;
1010 else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS)
1011 && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS))
1013 if (handler)
1014 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1015 else
1016 docopy = FALSE;
1018 else if ((style & SP_COPY_NEWER_ONLY) &&
1019 (TargetInfo->dwFileVersionMS ==
1020 SourceInfo->dwFileVersionMS)
1021 &&(TargetInfo->dwFileVersionLS ==
1022 SourceInfo->dwFileVersionLS))
1024 if (handler)
1025 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1026 else
1027 docopy = FALSE;
1031 HeapFree(GetProcessHeap(),0,VersionSource);
1032 HeapFree(GetProcessHeap(),0,VersionTarget);
1035 if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE))
1037 if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES)
1039 FIXME("Notify user target file exists\n");
1040 docopy = FALSE;
1043 if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE |
1044 SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP))
1046 ERR("Unsupported style(s) 0x%x\n",style);
1049 if (docopy)
1051 rc = CopyFileW(source,target,FALSE);
1052 TRACE("Did copy... rc was %i\n",rc);
1055 /* after copy processing */
1056 if (style & SP_COPY_DELETESOURCE)
1058 if (rc)
1059 DeleteFileW(source);
1062 return rc;
1065 /***********************************************************************
1066 * SetupCommitFileQueueW (SETUPAPI.@)
1068 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler,
1069 PVOID context )
1071 struct file_queue *queue = handle;
1072 struct file_op *op;
1073 BOOL result = FALSE;
1074 FILEPATHS_W paths;
1075 UINT op_result;
1077 paths.Source = paths.Target = NULL;
1079 if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count)
1080 return TRUE; /* nothing to do */
1082 if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE;
1084 /* perform deletes */
1086 if (queue->delete_queue.count)
1088 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE,
1089 queue->delete_queue.count ))) goto done;
1090 for (op = queue->delete_queue.head; op; op = op->next)
1092 build_filepathsW( op, &paths );
1093 op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE);
1094 if (op_result == FILEOP_ABORT) goto done;
1095 while (op_result == FILEOP_DOIT)
1097 TRACE( "deleting file %s\n", debugstr_w(paths.Target) );
1098 if (DeleteFileW( paths.Target )) break; /* success */
1099 paths.Win32Error = GetLastError();
1100 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 );
1101 if (op_result == FILEOP_ABORT) goto done;
1103 handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 );
1105 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 );
1108 /* perform renames */
1110 if (queue->rename_queue.count)
1112 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME,
1113 queue->rename_queue.count ))) goto done;
1114 for (op = queue->rename_queue.head; op; op = op->next)
1116 build_filepathsW( op, &paths );
1117 op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME);
1118 if (op_result == FILEOP_ABORT) goto done;
1119 while (op_result == FILEOP_DOIT)
1121 TRACE( "renaming file %s -> %s\n",
1122 debugstr_w(paths.Source), debugstr_w(paths.Target) );
1123 if (MoveFileW( paths.Source, paths.Target )) break; /* success */
1124 paths.Win32Error = GetLastError();
1125 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 );
1126 if (op_result == FILEOP_ABORT) goto done;
1128 handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 );
1130 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 );
1133 /* perform copies */
1135 if (queue->copy_queue.count)
1137 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY,
1138 queue->copy_queue.count ))) goto done;
1139 for (op = queue->copy_queue.head; op; op = op->next)
1141 WCHAR newpath[MAX_PATH];
1143 build_filepathsW( op, &paths );
1144 op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
1145 if (op_result == FILEOP_ABORT) goto done;
1146 if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT;
1147 while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
1149 TRACE( "copying file %s -> %s\n",
1150 debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ),
1151 debugstr_w(paths.Target) );
1152 if (op->dst_path)
1154 if (!create_full_pathW( op->dst_path ))
1156 paths.Win32Error = GetLastError();
1157 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1158 (UINT_PTR)&paths, (UINT_PTR)newpath );
1159 if (op_result == FILEOP_ABORT) goto done;
1162 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
1163 paths.Target, op->style, handler, context )) break; /* success */
1164 /* try to extract it from the cabinet file */
1165 if (op->src_tag)
1167 if (extract_cabinet_file( op->src_tag, op->src_root,
1168 paths.Source, paths.Target )) break;
1170 paths.Win32Error = GetLastError();
1171 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1172 (UINT_PTR)&paths, (UINT_PTR)newpath );
1173 if (op_result == FILEOP_ABORT) goto done;
1175 handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
1177 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 );
1181 result = TRUE;
1183 done:
1184 handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 );
1185 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1186 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1187 return result;
1191 /***********************************************************************
1192 * SetupScanFileQueueA (SETUPAPI.@)
1194 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ handle, DWORD flags, HWND window,
1195 PSP_FILE_CALLBACK_A handler, PVOID context, PDWORD result )
1197 struct callback_WtoA_context ctx;
1199 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
1201 ctx.orig_context = context;
1202 ctx.orig_handler = handler;
1204 return SetupScanFileQueueW( handle, flags, window, QUEUE_callback_WtoA, &ctx, result );
1208 /***********************************************************************
1209 * SetupScanFileQueueW (SETUPAPI.@)
1211 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ handle, DWORD flags, HWND window,
1212 PSP_FILE_CALLBACK_W handler, PVOID context, PDWORD result )
1214 struct file_queue *queue = handle;
1215 struct file_op *op;
1216 FILEPATHS_W paths;
1217 UINT notification = 0;
1218 BOOL ret = FALSE;
1220 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
1222 if (!queue->copy_queue.count) return TRUE;
1224 if (flags & SPQ_SCAN_USE_CALLBACK) notification = SPFILENOTIFY_QUEUESCAN;
1225 else if (flags & SPQ_SCAN_USE_CALLBACKEX) notification = SPFILENOTIFY_QUEUESCAN_EX;
1227 if (flags & ~(SPQ_SCAN_USE_CALLBACK | SPQ_SCAN_USE_CALLBACKEX))
1229 FIXME("flags %x not fully implemented\n", flags);
1232 paths.Source = paths.Target = NULL;
1234 for (op = queue->copy_queue.head; op; op = op->next)
1236 build_filepathsW( op, &paths );
1237 switch (notification)
1239 case SPFILENOTIFY_QUEUESCAN:
1240 /* FIXME: handle delay flag */
1241 if (handler( context, notification, (UINT_PTR)paths.Target, 0 )) goto done;
1242 break;
1243 case SPFILENOTIFY_QUEUESCAN_EX:
1244 if (handler( context, notification, (UINT_PTR)&paths, 0 )) goto done;
1245 break;
1246 default:
1247 ret = TRUE; goto done;
1251 ret = TRUE;
1253 done:
1254 if (result) *result = 0;
1255 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1256 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1257 return ret;
1261 /***********************************************************************
1262 * SetupGetFileQueueCount (SETUPAPI.@)
1264 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result )
1266 struct file_queue *queue = handle;
1268 switch(op)
1270 case FILEOP_COPY:
1271 *result = queue->copy_queue.count;
1272 return TRUE;
1273 case FILEOP_RENAME:
1274 *result = queue->rename_queue.count;
1275 return TRUE;
1276 case FILEOP_DELETE:
1277 *result = queue->delete_queue.count;
1278 return TRUE;
1280 return FALSE;
1284 /***********************************************************************
1285 * SetupGetFileQueueFlags (SETUPAPI.@)
1287 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags )
1289 struct file_queue *queue = handle;
1290 *flags = queue->flags;
1291 return TRUE;
1295 /***********************************************************************
1296 * SetupSetFileQueueFlags (SETUPAPI.@)
1298 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags )
1300 struct file_queue *queue = handle;
1301 queue->flags = (queue->flags & ~mask) | flags;
1302 return TRUE;
1306 /***********************************************************************
1307 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1309 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile)
1311 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile));
1312 return FALSE;
1316 /***********************************************************************
1317 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1319 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile)
1321 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile));
1322 return FALSE;
1326 /***********************************************************************
1327 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1329 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner )
1331 return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL );
1335 /***********************************************************************
1336 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1338 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg,
1339 DWORD reserved1, PVOID reserved2 )
1341 struct default_callback_context *context;
1343 if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) )))
1345 context->owner = owner;
1346 context->progress = progress;
1347 context->message = msg;
1349 return context;
1353 /***********************************************************************
1354 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1356 void WINAPI SetupTermDefaultQueueCallback( PVOID context )
1358 HeapFree( GetProcessHeap(), 0, context );
1362 /***********************************************************************
1363 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1365 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification,
1366 UINT_PTR param1, UINT_PTR param2 )
1368 FILEPATHS_A *paths = (FILEPATHS_A *)param1;
1369 struct default_callback_context *ctx = (struct default_callback_context *)context;
1371 switch(notification)
1373 case SPFILENOTIFY_STARTQUEUE:
1374 TRACE( "start queue\n" );
1375 return TRUE;
1376 case SPFILENOTIFY_ENDQUEUE:
1377 TRACE( "end queue\n" );
1378 return 0;
1379 case SPFILENOTIFY_STARTSUBQUEUE:
1380 TRACE( "start subqueue %ld count %ld\n", param1, param2 );
1381 return TRUE;
1382 case SPFILENOTIFY_ENDSUBQUEUE:
1383 TRACE( "end subqueue %ld\n", param1 );
1384 return 0;
1385 case SPFILENOTIFY_STARTDELETE:
1386 TRACE( "start delete %s\n", debugstr_a(paths->Target) );
1387 return FILEOP_DOIT;
1388 case SPFILENOTIFY_ENDDELETE:
1389 TRACE( "end delete %s\n", debugstr_a(paths->Target) );
1390 return 0;
1391 case SPFILENOTIFY_DELETEERROR:
1392 /*Windows Ignores attempts to delete files / folders which do not exist*/
1393 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1394 SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1395 return FILEOP_SKIP;
1396 case SPFILENOTIFY_STARTRENAME:
1397 TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1398 return FILEOP_DOIT;
1399 case SPFILENOTIFY_ENDRENAME:
1400 TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1401 return 0;
1402 case SPFILENOTIFY_RENAMEERROR:
1403 SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1404 return FILEOP_SKIP;
1405 case SPFILENOTIFY_STARTCOPY:
1406 TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1407 return FILEOP_DOIT;
1408 case SPFILENOTIFY_ENDCOPY:
1409 TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1410 return 0;
1411 case SPFILENOTIFY_COPYERROR:
1412 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1413 debugstr_a(paths->Source), debugstr_a(paths->Target) );
1414 return FILEOP_SKIP;
1415 case SPFILENOTIFY_NEEDMEDIA:
1416 TRACE( "need media\n" );
1417 return FILEOP_SKIP;
1418 default:
1419 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
1420 break;
1422 return 0;
1426 /***********************************************************************
1427 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1429 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification,
1430 UINT_PTR param1, UINT_PTR param2 )
1432 FILEPATHS_W *paths = (FILEPATHS_W *)param1;
1433 struct default_callback_context *ctx = (struct default_callback_context *)context;
1435 switch(notification)
1437 case SPFILENOTIFY_STARTQUEUE:
1438 TRACE( "start queue\n" );
1439 return TRUE;
1440 case SPFILENOTIFY_ENDQUEUE:
1441 TRACE( "end queue\n" );
1442 return 0;
1443 case SPFILENOTIFY_STARTSUBQUEUE:
1444 TRACE( "start subqueue %ld count %ld\n", param1, param2 );
1445 return TRUE;
1446 case SPFILENOTIFY_ENDSUBQUEUE:
1447 TRACE( "end subqueue %ld\n", param1 );
1448 return 0;
1449 case SPFILENOTIFY_STARTDELETE:
1450 TRACE( "start delete %s\n", debugstr_w(paths->Target) );
1451 return FILEOP_DOIT;
1452 case SPFILENOTIFY_ENDDELETE:
1453 TRACE( "end delete %s\n", debugstr_w(paths->Target) );
1454 return 0;
1455 case SPFILENOTIFY_DELETEERROR:
1456 /*Windows Ignores attempts to delete files / folders which do not exist*/
1457 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1458 SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1459 return FILEOP_SKIP;
1460 case SPFILENOTIFY_STARTRENAME:
1461 SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1462 return FILEOP_DOIT;
1463 case SPFILENOTIFY_ENDRENAME:
1464 TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1465 return 0;
1466 case SPFILENOTIFY_RENAMEERROR:
1467 ERR( "rename error %d %s -> %s\n", paths->Win32Error,
1468 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1469 return FILEOP_SKIP;
1470 case SPFILENOTIFY_STARTCOPY:
1471 TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1472 return FILEOP_DOIT;
1473 case SPFILENOTIFY_ENDCOPY:
1474 TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1475 return 0;
1476 case SPFILENOTIFY_COPYERROR:
1477 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1478 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1479 return FILEOP_SKIP;
1480 case SPFILENOTIFY_NEEDMEDIA:
1481 TRACE( "need media\n" );
1482 return FILEOP_SKIP;
1483 default:
1484 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
1485 break;
1487 return 0;
1490 /***********************************************************************
1491 * SetupDeleteErrorA (SETUPAPI.@)
1494 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file,
1495 UINT w32error, DWORD style)
1497 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1498 w32error, debugstr_a(file) );
1499 return DPROMPT_SKIPFILE;
1502 /***********************************************************************
1503 * SetupDeleteErrorW (SETUPAPI.@)
1506 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file,
1507 UINT w32error, DWORD style)
1509 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1510 w32error, debugstr_w(file) );
1511 return DPROMPT_SKIPFILE;
1514 /***********************************************************************
1515 * SetupRenameErrorA (SETUPAPI.@)
1518 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source,
1519 PCSTR target, UINT w32error, DWORD style)
1521 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1522 w32error, debugstr_a(source), debugstr_a(target));
1523 return DPROMPT_SKIPFILE;
1526 /***********************************************************************
1527 * SetupRenameErrorW (SETUPAPI.@)
1530 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source,
1531 PCWSTR target, UINT w32error, DWORD style)
1533 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1534 w32error, debugstr_w(source), debugstr_w(target));
1535 return DPROMPT_SKIPFILE;
1539 /***********************************************************************
1540 * SetupCopyErrorA (SETUPAPI.@)
1543 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname,
1544 PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath,
1545 UINT w32error, DWORD style, PSTR pathbuffer,
1546 DWORD buffersize, PDWORD requiredsize)
1548 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1549 w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath));
1550 return DPROMPT_SKIPFILE;
1553 /***********************************************************************
1554 * SetupCopyErrorW (SETUPAPI.@)
1557 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname,
1558 PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath,
1559 UINT w32error, DWORD style, PWSTR pathbuffer,
1560 DWORD buffersize, PDWORD requiredsize)
1562 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1563 w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath));
1564 return DPROMPT_SKIPFILE;
1567 /***********************************************************************
1568 * pSetupGetQueueFlags (SETUPAPI.@)
1570 DWORD WINAPI pSetupGetQueueFlags( HSPFILEQ handle )
1572 struct file_queue *queue = handle;
1573 return queue->flags;
1576 /***********************************************************************
1577 * pSetupSetQueueFlags (SETUPAPI.@)
1579 BOOL WINAPI pSetupSetQueueFlags( HSPFILEQ handle, DWORD flags )
1581 struct file_queue *queue = handle;
1582 queue->flags = flags;
1583 return TRUE;