wined3d: Remove fake nvidia card in GetAdapterIdentifier.
[wine/dibdrv.git] / dlls / setupapi / queue.c
blob063e8c0429954aaccf2e72c1a624485167261cd5
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 static inline 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;
87 static inline char *strdupWtoA( const WCHAR *str )
89 char *ret = NULL;
90 if (str)
92 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
93 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
94 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
96 return ret;
99 /* append a file operation to a queue */
100 static inline void queue_file_op( struct file_op_queue *queue, struct file_op *op )
102 op->next = NULL;
103 if (queue->tail) queue->tail->next = op;
104 else queue->head = op;
105 queue->tail = op;
106 queue->count++;
109 /* free all the file operations on a given queue */
110 static void free_file_op_queue( struct file_op_queue *queue )
112 struct file_op *t, *op = queue->head;
114 while( op )
116 HeapFree( GetProcessHeap(), 0, op->src_root );
117 HeapFree( GetProcessHeap(), 0, op->src_path );
118 HeapFree( GetProcessHeap(), 0, op->src_file );
119 HeapFree( GetProcessHeap(), 0, op->src_descr );
120 HeapFree( GetProcessHeap(), 0, op->src_tag );
121 HeapFree( GetProcessHeap(), 0, op->dst_path );
122 if (op->dst_file != op->src_file) HeapFree( GetProcessHeap(), 0, op->dst_file );
123 t = op;
124 op = op->next;
125 HeapFree( GetProcessHeap(), 0, t );
129 /* concat 3 strings to make a path, handling separators correctly */
130 static void concat_W( WCHAR *buffer, const WCHAR *src1, const WCHAR *src2, const WCHAR *src3 )
132 *buffer = 0;
133 if (src1 && *src1)
135 strcpyW( buffer, src1 );
136 buffer += strlenW(buffer );
137 if (buffer[-1] != '\\') *buffer++ = '\\';
138 if (src2) while (*src2 == '\\') src2++;
141 if (src2)
143 strcpyW( buffer, src2 );
144 buffer += strlenW(buffer );
145 if (buffer[-1] != '\\') *buffer++ = '\\';
146 if (src3) while (*src3 == '\\') src3++;
148 if (src3)
150 strcpyW( buffer, src3 );
151 buffer += strlenW(buffer );
156 /***********************************************************************
157 * build_filepathsW
159 * Build a FILEPATHS_W structure for a given file operation.
161 static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths )
163 unsigned int src_len = 1, dst_len = 1;
164 WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target;
166 if (op->src_root) src_len += strlenW(op->src_root) + 1;
167 if (op->src_path) src_len += strlenW(op->src_path) + 1;
168 if (op->src_file) src_len += strlenW(op->src_file) + 1;
169 if (op->dst_path) dst_len += strlenW(op->dst_path) + 1;
170 if (op->dst_file) dst_len += strlenW(op->dst_file) + 1;
171 src_len *= sizeof(WCHAR);
172 dst_len *= sizeof(WCHAR);
174 if (!source || HeapSize( GetProcessHeap(), 0, source ) < src_len )
176 HeapFree( GetProcessHeap(), 0, source );
177 paths->Source = source = HeapAlloc( GetProcessHeap(), 0, src_len );
179 if (!target || HeapSize( GetProcessHeap(), 0, target ) < dst_len )
181 HeapFree( GetProcessHeap(), 0, target );
182 paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len );
184 if (!source || !target) return FALSE;
185 concat_W( source, op->src_root, op->src_path, op->src_file );
186 concat_W( target, NULL, op->dst_path, op->dst_file );
187 paths->Win32Error = 0;
188 paths->Flags = 0;
189 return TRUE;
193 /***********************************************************************
194 * QUEUE_callback_WtoA
196 * Map a file callback parameters from W to A and call the A callback.
198 UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification,
199 UINT_PTR param1, UINT_PTR param2 )
201 struct callback_WtoA_context *callback_ctx = context;
202 char buffer[MAX_PATH];
203 UINT ret;
204 UINT_PTR old_param2 = param2;
206 switch(notification)
208 case SPFILENOTIFY_COPYERROR:
209 param2 = (UINT_PTR)&buffer;
210 /* fall through */
211 case SPFILENOTIFY_STARTDELETE:
212 case SPFILENOTIFY_ENDDELETE:
213 case SPFILENOTIFY_DELETEERROR:
214 case SPFILENOTIFY_STARTRENAME:
215 case SPFILENOTIFY_ENDRENAME:
216 case SPFILENOTIFY_RENAMEERROR:
217 case SPFILENOTIFY_STARTCOPY:
218 case SPFILENOTIFY_ENDCOPY:
220 FILEPATHS_W *pathsW = (FILEPATHS_W *)param1;
221 FILEPATHS_A pathsA;
223 pathsA.Source = strdupWtoA( pathsW->Source );
224 pathsA.Target = strdupWtoA( pathsW->Target );
225 pathsA.Win32Error = pathsW->Win32Error;
226 pathsA.Flags = pathsW->Flags;
227 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
228 (UINT_PTR)&pathsA, param2 );
229 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Source );
230 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Target );
232 if (notification == SPFILENOTIFY_COPYERROR)
233 MultiByteToWideChar( CP_ACP, 0, buffer, -1, (WCHAR *)old_param2, MAX_PATH );
234 break;
236 case SPFILENOTIFY_STARTREGISTRATION:
237 case SPFILENOTIFY_ENDREGISTRATION:
239 SP_REGISTER_CONTROL_STATUSW *statusW = (SP_REGISTER_CONTROL_STATUSW *)param1;
240 SP_REGISTER_CONTROL_STATUSA statusA;
242 statusA.cbSize = sizeof(statusA);
243 statusA.FileName = strdupWtoA( statusW->FileName );
244 statusA.Win32Error = statusW->Win32Error;
245 statusA.FailureCode = statusW->FailureCode;
246 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
247 (UINT_PTR)&statusA, param2 );
248 HeapFree( GetProcessHeap(), 0, (LPSTR)statusA.FileName );
250 break;
252 case SPFILENOTIFY_NEEDMEDIA:
253 case SPFILENOTIFY_QUEUESCAN:
254 FIXME("mapping for %d not implemented\n",notification);
255 case SPFILENOTIFY_STARTQUEUE:
256 case SPFILENOTIFY_ENDQUEUE:
257 case SPFILENOTIFY_STARTSUBQUEUE:
258 case SPFILENOTIFY_ENDSUBQUEUE:
259 default:
260 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, param1, param2 );
261 break;
263 return ret;
267 /***********************************************************************
268 * get_src_file_info
270 * Retrieve the source file information for a given file.
272 static void get_src_file_info( HINF hinf, struct file_op *op )
274 static const WCHAR SourceDisksNames[] =
275 {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0};
276 static const WCHAR SourceDisksFiles[] =
277 {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
279 INFCONTEXT file_ctx, disk_ctx;
280 INT id, diskid;
281 DWORD len, len2;
283 /* find the SourceDisksFiles entry */
284 if (!SetupFindFirstLineW( hinf, SourceDisksFiles, op->src_file, &file_ctx ))
286 if ((op->style & (SP_COPY_SOURCE_ABSOLUTE|SP_COPY_SOURCEPATH_ABSOLUTE))) return;
287 /* no specific info, use .inf file source directory */
288 if (!op->src_root) op->src_root = PARSER_get_src_root( hinf );
289 return;
291 if (!SetupGetIntField( &file_ctx, 1, &diskid )) return;
293 /* now find the diskid in the SourceDisksNames section */
294 if (!SetupFindFirstLineW( hinf, SourceDisksNames, NULL, &disk_ctx )) return;
295 for (;;)
297 if (SetupGetIntField( &disk_ctx, 0, &id ) && (id == diskid)) break;
298 if (!SetupFindNextLine( &disk_ctx, &disk_ctx )) return;
301 /* and fill in the missing info */
303 if (!op->src_descr)
305 if (SetupGetStringFieldW( &disk_ctx, 1, NULL, 0, &len ) &&
306 (op->src_descr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
307 SetupGetStringFieldW( &disk_ctx, 1, op->src_descr, len, NULL );
309 if (!op->src_tag)
311 if (SetupGetStringFieldW( &disk_ctx, 2, NULL, 0, &len ) &&
312 (op->src_tag = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
313 SetupGetStringFieldW( &disk_ctx, 2, op->src_tag, len, NULL );
315 if (!op->src_path && !(op->style & SP_COPY_SOURCE_ABSOLUTE))
317 len = len2 = 0;
318 if (!(op->style & SP_COPY_SOURCEPATH_ABSOLUTE))
320 /* retrieve relative path for this disk */
321 if (!SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len )) len = 0;
323 /* retrieve relative path for this file */
324 if (!SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len2 )) len2 = 0;
326 if ((len || len2) &&
327 (op->src_path = HeapAlloc( GetProcessHeap(), 0, (len+len2)*sizeof(WCHAR) )))
329 WCHAR *ptr = op->src_path;
330 if (len)
332 SetupGetStringFieldW( &disk_ctx, 4, op->src_path, len, NULL );
333 ptr = op->src_path + strlenW(op->src_path);
334 if (len2 && ptr > op->src_path && ptr[-1] != '\\') *ptr++ = '\\';
336 if (!SetupGetStringFieldW( &file_ctx, 2, ptr, len2, NULL )) *ptr = 0;
339 if (!op->src_root) op->src_root = PARSER_get_src_root(hinf);
343 /***********************************************************************
344 * get_destination_dir
346 * Retrieve the destination dir for a given section.
348 static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
350 static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
351 static const WCHAR Def[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
352 INFCONTEXT context;
354 if (!SetupFindFirstLineW( hinf, Dest, section, &context ) &&
355 !SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL;
356 return PARSER_get_dest_dir( &context );
360 static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD );
362 /***********************************************************************
363 * extract_cabinet_file
365 * Extract a file from a .cab file.
367 static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root,
368 const WCHAR *src, const WCHAR *dst )
370 static const WCHAR extW[] = {'.','c','a','b',0};
371 static HMODULE advpack;
373 char *cab_path, *cab_file;
374 int len = strlenW( cabinet );
376 /* make sure the cabinet file has a .cab extension */
377 if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE;
378 if (!pExtractFiles)
380 if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" )))
382 ERR( "could not load advpack.dll\n" );
383 return FALSE;
385 if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" )))
387 ERR( "could not find ExtractFiles in advpack.dll\n" );
388 return FALSE;
392 if (!(cab_path = strdupWtoA( root ))) return FALSE;
393 len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL );
394 if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 )))
396 HeapFree( GetProcessHeap(), 0, cab_path );
397 return FALSE;
399 strcpy( cab_file, cab_path );
400 if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" );
401 WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL );
402 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) );
403 pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 );
404 HeapFree( GetProcessHeap(), 0, cab_file );
405 HeapFree( GetProcessHeap(), 0, cab_path );
406 return CopyFileW( src, dst, FALSE /*FIXME*/ );
410 /***********************************************************************
411 * SetupOpenFileQueue (SETUPAPI.@)
413 HSPFILEQ WINAPI SetupOpenFileQueue(void)
415 struct file_queue *queue;
417 if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue))))
418 return (HSPFILEQ)INVALID_HANDLE_VALUE;
419 return queue;
423 /***********************************************************************
424 * SetupCloseFileQueue (SETUPAPI.@)
426 BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle )
428 struct file_queue *queue = handle;
430 free_file_op_queue( &queue->copy_queue );
431 free_file_op_queue( &queue->rename_queue );
432 free_file_op_queue( &queue->delete_queue );
433 HeapFree( GetProcessHeap(), 0, queue );
434 return TRUE;
438 /***********************************************************************
439 * SetupQueueCopyIndirectA (SETUPAPI.@)
441 BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params )
443 struct file_queue *queue = params->QueueHandle;
444 struct file_op *op;
446 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
447 op->style = params->CopyStyle;
448 op->src_root = strdupAtoW( params->SourceRootPath );
449 op->src_path = strdupAtoW( params->SourcePath );
450 op->src_file = strdupAtoW( params->SourceFilename );
451 op->src_descr = strdupAtoW( params->SourceDescription );
452 op->src_tag = strdupAtoW( params->SourceTagfile );
453 op->dst_path = strdupAtoW( params->TargetDirectory );
454 op->dst_file = strdupAtoW( params->TargetFilename );
456 /* some defaults */
457 if (!op->src_file) op->src_file = op->dst_file;
458 if (params->LayoutInf)
460 get_src_file_info( params->LayoutInf, op );
461 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
464 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
465 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
466 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
467 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
469 queue_file_op( &queue->copy_queue, op );
470 return TRUE;
474 /***********************************************************************
475 * SetupQueueCopyIndirectW (SETUPAPI.@)
477 BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params )
479 struct file_queue *queue = params->QueueHandle;
480 struct file_op *op;
482 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
483 op->style = params->CopyStyle;
484 op->src_root = strdupW( params->SourceRootPath );
485 op->src_path = strdupW( params->SourcePath );
486 op->src_file = strdupW( params->SourceFilename );
487 op->src_descr = strdupW( params->SourceDescription );
488 op->src_tag = strdupW( params->SourceTagfile );
489 op->dst_path = strdupW( params->TargetDirectory );
490 op->dst_file = strdupW( params->TargetFilename );
492 /* some defaults */
493 if (!op->src_file) op->src_file = op->dst_file;
494 if (params->LayoutInf)
496 get_src_file_info( params->LayoutInf, op );
497 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
500 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
501 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
502 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
503 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
505 queue_file_op( &queue->copy_queue, op );
506 return TRUE;
510 /***********************************************************************
511 * SetupQueueCopyA (SETUPAPI.@)
513 BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file,
514 PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file,
515 DWORD style )
517 SP_FILE_COPY_PARAMS_A params;
519 params.cbSize = sizeof(params);
520 params.QueueHandle = queue;
521 params.SourceRootPath = src_root;
522 params.SourcePath = src_path;
523 params.SourceFilename = src_file;
524 params.SourceDescription = src_descr;
525 params.SourceTagfile = src_tag;
526 params.TargetDirectory = dst_dir;
527 params.TargetFilename = dst_file;
528 params.CopyStyle = style;
529 params.LayoutInf = 0;
530 params.SecurityDescriptor = NULL;
531 return SetupQueueCopyIndirectA( &params );
535 /***********************************************************************
536 * SetupQueueCopyW (SETUPAPI.@)
538 BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file,
539 PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file,
540 DWORD style )
542 SP_FILE_COPY_PARAMS_W params;
544 params.cbSize = sizeof(params);
545 params.QueueHandle = queue;
546 params.SourceRootPath = src_root;
547 params.SourcePath = src_path;
548 params.SourceFilename = src_file;
549 params.SourceDescription = src_descr;
550 params.SourceTagfile = src_tag;
551 params.TargetDirectory = dst_dir;
552 params.TargetFilename = dst_file;
553 params.CopyStyle = style;
554 params.LayoutInf = 0;
555 params.SecurityDescriptor = NULL;
556 return SetupQueueCopyIndirectW( &params );
560 /***********************************************************************
561 * SetupQueueDefaultCopyA (SETUPAPI.@)
563 BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file,
564 PCSTR dst_file, DWORD style )
566 SP_FILE_COPY_PARAMS_A params;
568 params.cbSize = sizeof(params);
569 params.QueueHandle = queue;
570 params.SourceRootPath = src_root;
571 params.SourcePath = NULL;
572 params.SourceFilename = src_file;
573 params.SourceDescription = NULL;
574 params.SourceTagfile = NULL;
575 params.TargetDirectory = NULL;
576 params.TargetFilename = dst_file;
577 params.CopyStyle = style;
578 params.LayoutInf = hinf;
579 params.SecurityDescriptor = NULL;
580 return SetupQueueCopyIndirectA( &params );
584 /***********************************************************************
585 * SetupQueueDefaultCopyW (SETUPAPI.@)
587 BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file,
588 PCWSTR dst_file, DWORD style )
590 SP_FILE_COPY_PARAMS_W params;
592 params.cbSize = sizeof(params);
593 params.QueueHandle = queue;
594 params.SourceRootPath = src_root;
595 params.SourcePath = NULL;
596 params.SourceFilename = src_file;
597 params.SourceDescription = NULL;
598 params.SourceTagfile = NULL;
599 params.TargetDirectory = NULL;
600 params.TargetFilename = dst_file;
601 params.CopyStyle = style;
602 params.LayoutInf = hinf;
603 params.SecurityDescriptor = NULL;
604 return SetupQueueCopyIndirectW( &params );
608 /***********************************************************************
609 * SetupQueueDeleteA (SETUPAPI.@)
611 BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 )
613 struct file_queue *queue = handle;
614 struct file_op *op;
616 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
617 op->style = 0;
618 op->src_root = NULL;
619 op->src_path = NULL;
620 op->src_file = NULL;
621 op->src_descr = NULL;
622 op->src_tag = NULL;
623 op->dst_path = strdupAtoW( part1 );
624 op->dst_file = strdupAtoW( part2 );
625 queue_file_op( &queue->delete_queue, op );
626 return TRUE;
630 /***********************************************************************
631 * SetupQueueDeleteW (SETUPAPI.@)
633 BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 )
635 struct file_queue *queue = handle;
636 struct file_op *op;
638 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
639 op->style = 0;
640 op->src_root = NULL;
641 op->src_path = NULL;
642 op->src_file = NULL;
643 op->src_descr = NULL;
644 op->src_tag = NULL;
645 op->dst_path = strdupW( part1 );
646 op->dst_file = strdupW( part2 );
647 queue_file_op( &queue->delete_queue, op );
648 return TRUE;
652 /***********************************************************************
653 * SetupQueueRenameA (SETUPAPI.@)
655 BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename,
656 PCSTR TargetPath, PCSTR TargetFilename )
658 struct file_queue *queue = handle;
659 struct file_op *op;
661 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
662 op->style = 0;
663 op->src_root = NULL;
664 op->src_path = strdupAtoW( SourcePath );
665 op->src_file = strdupAtoW( SourceFilename );
666 op->src_descr = NULL;
667 op->src_tag = NULL;
668 op->dst_path = strdupAtoW( TargetPath );
669 op->dst_file = strdupAtoW( TargetFilename );
670 queue_file_op( &queue->rename_queue, op );
671 return TRUE;
675 /***********************************************************************
676 * SetupQueueRenameW (SETUPAPI.@)
678 BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename,
679 PCWSTR TargetPath, PCWSTR TargetFilename )
681 struct file_queue *queue = handle;
682 struct file_op *op;
684 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
685 op->style = 0;
686 op->src_root = NULL;
687 op->src_path = strdupW( SourcePath );
688 op->src_file = strdupW( SourceFilename );
689 op->src_descr = NULL;
690 op->src_tag = NULL;
691 op->dst_path = strdupW( TargetPath );
692 op->dst_file = strdupW( TargetFilename );
693 queue_file_op( &queue->rename_queue, op );
694 return TRUE;
698 /***********************************************************************
699 * SetupQueueCopySectionA (SETUPAPI.@)
701 BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist,
702 PCSTR section, DWORD style )
704 UNICODE_STRING sectionW;
705 BOOL ret = FALSE;
707 if (!RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
709 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
710 return FALSE;
712 if (!src_root)
713 ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style );
714 else
716 UNICODE_STRING srcW;
717 if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root ))
719 ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style );
720 RtlFreeUnicodeString( &srcW );
722 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
724 RtlFreeUnicodeString( &sectionW );
725 return ret;
729 /***********************************************************************
730 * SetupQueueCopySectionW (SETUPAPI.@)
732 BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist,
733 PCWSTR section, DWORD style )
735 SP_FILE_COPY_PARAMS_W params;
736 INFCONTEXT context;
737 WCHAR dest[MAX_PATH], src[MAX_PATH];
738 INT flags;
740 TRACE( "hinf=%p/%p section=%s root=%s\n",
741 hinf, hlist, debugstr_w(section), debugstr_w(src_root) );
743 params.cbSize = sizeof(params);
744 params.QueueHandle = queue;
745 params.SourceRootPath = src_root;
746 params.SourcePath = NULL;
747 params.SourceDescription = NULL;
748 params.SourceTagfile = NULL;
749 params.TargetFilename = dest;
750 params.CopyStyle = style;
751 params.LayoutInf = hinf;
752 params.SecurityDescriptor = NULL;
754 if (!hlist) hlist = hinf;
755 if (!hinf) hinf = hlist;
756 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
757 if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) return FALSE;
760 if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL ))
761 return FALSE;
762 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0;
763 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */
765 params.SourceFilename = *src ? src : NULL;
766 if (!SetupQueueCopyIndirectW( &params )) return FALSE;
767 } while (SetupFindNextLine( &context, &context ));
768 return TRUE;
772 /***********************************************************************
773 * SetupQueueDeleteSectionA (SETUPAPI.@)
775 BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
777 UNICODE_STRING sectionW;
778 BOOL ret = FALSE;
780 if (RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
782 ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer );
783 RtlFreeUnicodeString( &sectionW );
785 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
786 return ret;
790 /***********************************************************************
791 * SetupQueueDeleteSectionW (SETUPAPI.@)
793 BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
795 INFCONTEXT context;
796 WCHAR *dest_dir;
797 WCHAR buffer[MAX_PATH];
798 BOOL ret = FALSE;
799 INT flags;
801 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
803 if (!hlist) hlist = hinf;
804 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
805 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
808 if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
809 goto done;
810 if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
811 if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done;
812 } while (SetupFindNextLine( &context, &context ));
814 ret = TRUE;
815 done:
816 HeapFree( GetProcessHeap(), 0, dest_dir );
817 return ret;
821 /***********************************************************************
822 * SetupQueueRenameSectionA (SETUPAPI.@)
824 BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
826 UNICODE_STRING sectionW;
827 BOOL ret = FALSE;
829 if (RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
831 ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer );
832 RtlFreeUnicodeString( &sectionW );
834 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
835 return ret;
839 /***********************************************************************
840 * SetupQueueRenameSectionW (SETUPAPI.@)
842 BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
844 INFCONTEXT context;
845 WCHAR *dest_dir;
846 WCHAR src[MAX_PATH], dst[MAX_PATH];
847 BOOL ret = FALSE;
849 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
851 if (!hlist) hlist = hinf;
852 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
853 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
856 if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL ))
857 goto done;
858 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL ))
859 goto done;
860 if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done;
861 } while (SetupFindNextLine( &context, &context ));
863 ret = TRUE;
864 done:
865 HeapFree( GetProcessHeap(), 0, dest_dir );
866 return ret;
870 /***********************************************************************
871 * SetupCommitFileQueueA (SETUPAPI.@)
873 BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler,
874 PVOID context )
876 struct callback_WtoA_context ctx;
878 ctx.orig_context = context;
879 ctx.orig_handler = handler;
880 return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx );
884 /***********************************************************************
885 * create_full_pathW
887 * Recursively create all directories in the path.
889 static BOOL create_full_pathW(const WCHAR *path)
891 BOOL ret = TRUE;
892 int len;
893 WCHAR *new_path;
895 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
896 strcpyW(new_path, path);
898 while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
899 new_path[len - 1] = 0;
901 while(!CreateDirectoryW(new_path, NULL))
903 WCHAR *slash;
904 DWORD last_error = GetLastError();
906 if(last_error == ERROR_ALREADY_EXISTS)
907 break;
909 if(last_error != ERROR_PATH_NOT_FOUND)
911 ret = FALSE;
912 break;
915 if(!(slash = strrchrW(new_path, '\\')))
917 ret = FALSE;
918 break;
921 len = slash - new_path;
922 new_path[len] = 0;
923 if(!create_full_pathW(new_path))
925 ret = FALSE;
926 break;
928 new_path[len] = '\\';
931 HeapFree(GetProcessHeap(), 0, new_path);
932 return ret;
935 static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style,
936 PSP_FILE_CALLBACK_W handler, PVOID context )
938 BOOL rc = FALSE;
939 BOOL docopy = TRUE;
941 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source),debugstr_w(target),style);
943 /* before copy processing */
944 if (style & SP_COPY_REPLACEONLY)
946 if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES)
947 docopy = FALSE;
949 if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER))
951 DWORD VersionSizeSource=0;
952 DWORD VersionSizeTarget=0;
953 DWORD zero=0;
956 * This is sort of an interesting workaround. You see, calling
957 * GetVersionInfoSize on a builtin dll loads that dll into memory
958 * and we do not properly unload builtin dlls.. so we effectively
959 * lock into memory all the targets we are replacing. This leads
960 * to problems when we try to register the replaced dlls.
962 * So I will test for the existence of the files first so that
963 * we just basically unconditionally replace the builtin versions.
965 if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) &&
966 (GetFileAttributesW(source) != INVALID_FILE_ATTRIBUTES))
968 VersionSizeSource = GetFileVersionInfoSizeW(source,&zero);
969 VersionSizeTarget = GetFileVersionInfoSizeW(target,&zero);
972 TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget,
973 VersionSizeSource);
975 if (VersionSizeSource && VersionSizeTarget)
977 LPVOID VersionSource;
978 LPVOID VersionTarget;
979 VS_FIXEDFILEINFO *TargetInfo;
980 VS_FIXEDFILEINFO *SourceInfo;
981 UINT length;
982 WCHAR SubBlock[2]={'\\',0};
983 DWORD ret;
985 VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource);
986 VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget);
988 ret = GetFileVersionInfoW(source,0,VersionSizeSource,VersionSource);
989 if (ret)
990 ret = GetFileVersionInfoW(target, 0, VersionSizeTarget,
991 VersionTarget);
993 if (ret)
995 ret = VerQueryValueW(VersionSource, SubBlock,
996 (LPVOID*)&SourceInfo, &length);
997 if (ret)
998 ret = VerQueryValueW(VersionTarget, SubBlock,
999 (LPVOID*)&TargetInfo, &length);
1001 if (ret)
1003 FILEPATHS_W filepaths;
1005 TRACE("Versions: Source %i.%i target %i.%i\n",
1006 SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS,
1007 TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS);
1009 /* used in case of notification */
1010 filepaths.Target = target;
1011 filepaths.Source = source;
1012 filepaths.Win32Error = 0;
1013 filepaths.Flags = 0;
1015 if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS)
1017 if (handler)
1018 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1019 else
1020 docopy = FALSE;
1022 else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS)
1023 && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS))
1025 if (handler)
1026 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1027 else
1028 docopy = FALSE;
1030 else if ((style & SP_COPY_NEWER_ONLY) &&
1031 (TargetInfo->dwFileVersionMS ==
1032 SourceInfo->dwFileVersionMS)
1033 &&(TargetInfo->dwFileVersionLS ==
1034 SourceInfo->dwFileVersionLS))
1036 if (handler)
1037 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1038 else
1039 docopy = FALSE;
1043 HeapFree(GetProcessHeap(),0,VersionSource);
1044 HeapFree(GetProcessHeap(),0,VersionTarget);
1047 if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE))
1049 if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES)
1051 FIXME("Notify user target file exists\n");
1052 docopy = FALSE;
1055 if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE |
1056 SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP))
1058 ERR("Unsupported style(s) 0x%x\n",style);
1061 if (docopy)
1063 rc = CopyFileW(source,target,FALSE);
1064 TRACE("Did copy... rc was %i\n",rc);
1067 /* after copy processing */
1068 if (style & SP_COPY_DELETESOURCE)
1070 if (rc)
1071 DeleteFileW(source);
1074 return rc;
1077 /***********************************************************************
1078 * SetupCommitFileQueueW (SETUPAPI.@)
1080 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler,
1081 PVOID context )
1083 struct file_queue *queue = handle;
1084 struct file_op *op;
1085 BOOL result = FALSE;
1086 FILEPATHS_W paths;
1087 UINT op_result;
1089 paths.Source = paths.Target = NULL;
1091 if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count)
1092 return TRUE; /* nothing to do */
1094 if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE;
1096 /* perform deletes */
1098 if (queue->delete_queue.count)
1100 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE,
1101 queue->delete_queue.count ))) goto done;
1102 for (op = queue->delete_queue.head; op; op = op->next)
1104 build_filepathsW( op, &paths );
1105 op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE);
1106 if (op_result == FILEOP_ABORT) goto done;
1107 while (op_result == FILEOP_DOIT)
1109 TRACE( "deleting file %s\n", debugstr_w(paths.Target) );
1110 if (DeleteFileW( paths.Target )) break; /* success */
1111 paths.Win32Error = GetLastError();
1112 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 );
1113 if (op_result == FILEOP_ABORT) goto done;
1115 handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 );
1117 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 );
1120 /* perform renames */
1122 if (queue->rename_queue.count)
1124 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME,
1125 queue->rename_queue.count ))) goto done;
1126 for (op = queue->rename_queue.head; op; op = op->next)
1128 build_filepathsW( op, &paths );
1129 op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME);
1130 if (op_result == FILEOP_ABORT) goto done;
1131 while (op_result == FILEOP_DOIT)
1133 TRACE( "renaming file %s -> %s\n",
1134 debugstr_w(paths.Source), debugstr_w(paths.Target) );
1135 if (MoveFileW( paths.Source, paths.Target )) break; /* success */
1136 paths.Win32Error = GetLastError();
1137 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 );
1138 if (op_result == FILEOP_ABORT) goto done;
1140 handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 );
1142 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 );
1145 /* perform copies */
1147 if (queue->copy_queue.count)
1149 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY,
1150 queue->copy_queue.count ))) goto done;
1151 for (op = queue->copy_queue.head; op; op = op->next)
1153 WCHAR newpath[MAX_PATH];
1155 build_filepathsW( op, &paths );
1156 op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
1157 if (op_result == FILEOP_ABORT) goto done;
1158 if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT;
1159 while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
1161 TRACE( "copying file %s -> %s\n",
1162 debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ),
1163 debugstr_w(paths.Target) );
1164 if (op->dst_path)
1166 if (!create_full_pathW( op->dst_path ))
1168 paths.Win32Error = GetLastError();
1169 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1170 (UINT_PTR)&paths, (UINT_PTR)newpath );
1171 if (op_result == FILEOP_ABORT) goto done;
1174 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
1175 paths.Target, op->style, handler, context )) break; /* success */
1176 /* try to extract it from the cabinet file */
1177 if (op->src_tag)
1179 if (extract_cabinet_file( op->src_tag, op->src_root,
1180 paths.Source, paths.Target )) break;
1182 paths.Win32Error = GetLastError();
1183 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1184 (UINT_PTR)&paths, (UINT_PTR)newpath );
1185 if (op_result == FILEOP_ABORT) goto done;
1187 handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
1189 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 );
1193 result = TRUE;
1195 done:
1196 handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 );
1197 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1198 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1199 return result;
1203 /***********************************************************************
1204 * SetupScanFileQueueA (SETUPAPI.@)
1206 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ queue, DWORD flags, HWND window,
1207 PSP_FILE_CALLBACK_A callback, PVOID context, PDWORD result )
1209 FIXME("stub\n");
1210 return FALSE;
1214 /***********************************************************************
1215 * SetupScanFileQueueW (SETUPAPI.@)
1217 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ queue, DWORD flags, HWND window,
1218 PSP_FILE_CALLBACK_W callback, PVOID context, PDWORD result )
1220 FIXME("stub\n");
1221 return FALSE;
1225 /***********************************************************************
1226 * SetupGetFileQueueCount (SETUPAPI.@)
1228 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result )
1230 struct file_queue *queue = handle;
1232 switch(op)
1234 case FILEOP_COPY:
1235 *result = queue->copy_queue.count;
1236 return TRUE;
1237 case FILEOP_RENAME:
1238 *result = queue->rename_queue.count;
1239 return TRUE;
1240 case FILEOP_DELETE:
1241 *result = queue->delete_queue.count;
1242 return TRUE;
1244 return FALSE;
1248 /***********************************************************************
1249 * SetupGetFileQueueFlags (SETUPAPI.@)
1251 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags )
1253 struct file_queue *queue = handle;
1254 *flags = queue->flags;
1255 return TRUE;
1259 /***********************************************************************
1260 * SetupSetFileQueueFlags (SETUPAPI.@)
1262 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags )
1264 struct file_queue *queue = handle;
1265 queue->flags = (queue->flags & ~mask) | flags;
1266 return TRUE;
1270 /***********************************************************************
1271 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1273 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile)
1275 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile));
1276 return FALSE;
1280 /***********************************************************************
1281 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1283 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile)
1285 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile));
1286 return FALSE;
1290 /***********************************************************************
1291 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1293 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner )
1295 return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL );
1299 /***********************************************************************
1300 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1302 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg,
1303 DWORD reserved1, PVOID reserved2 )
1305 struct default_callback_context *context;
1307 if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) )))
1309 context->owner = owner;
1310 context->progress = progress;
1311 context->message = msg;
1313 return context;
1317 /***********************************************************************
1318 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1320 void WINAPI SetupTermDefaultQueueCallback( PVOID context )
1322 HeapFree( GetProcessHeap(), 0, context );
1326 /***********************************************************************
1327 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1329 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification,
1330 UINT_PTR param1, UINT_PTR param2 )
1332 FILEPATHS_A *paths = (FILEPATHS_A *)param1;
1333 struct default_callback_context *ctx = (struct default_callback_context *)context;
1335 switch(notification)
1337 case SPFILENOTIFY_STARTQUEUE:
1338 TRACE( "start queue\n" );
1339 return TRUE;
1340 case SPFILENOTIFY_ENDQUEUE:
1341 TRACE( "end queue\n" );
1342 return 0;
1343 case SPFILENOTIFY_STARTSUBQUEUE:
1344 TRACE( "start subqueue %d count %d\n", param1, param2 );
1345 return TRUE;
1346 case SPFILENOTIFY_ENDSUBQUEUE:
1347 TRACE( "end subqueue %d\n", param1 );
1348 return 0;
1349 case SPFILENOTIFY_STARTDELETE:
1350 TRACE( "start delete %s\n", debugstr_a(paths->Target) );
1351 return FILEOP_DOIT;
1352 case SPFILENOTIFY_ENDDELETE:
1353 TRACE( "end delete %s\n", debugstr_a(paths->Target) );
1354 return 0;
1355 case SPFILENOTIFY_DELETEERROR:
1356 /*Windows Ignores attempts to delete files / folders which do not exist*/
1357 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1358 SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1359 return FILEOP_SKIP;
1360 case SPFILENOTIFY_STARTRENAME:
1361 TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1362 return FILEOP_DOIT;
1363 case SPFILENOTIFY_ENDRENAME:
1364 TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1365 return 0;
1366 case SPFILENOTIFY_RENAMEERROR:
1367 SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1368 return FILEOP_SKIP;
1369 case SPFILENOTIFY_STARTCOPY:
1370 TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1371 return FILEOP_DOIT;
1372 case SPFILENOTIFY_ENDCOPY:
1373 TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1374 return 0;
1375 case SPFILENOTIFY_COPYERROR:
1376 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1377 debugstr_a(paths->Source), debugstr_a(paths->Target) );
1378 return FILEOP_SKIP;
1379 case SPFILENOTIFY_NEEDMEDIA:
1380 TRACE( "need media\n" );
1381 return FILEOP_SKIP;
1382 default:
1383 FIXME( "notification %d params %x,%x\n", notification, param1, param2 );
1384 break;
1386 return 0;
1390 /***********************************************************************
1391 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1393 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification,
1394 UINT_PTR param1, UINT_PTR param2 )
1396 FILEPATHS_W *paths = (FILEPATHS_W *)param1;
1397 struct default_callback_context *ctx = (struct default_callback_context *)context;
1399 switch(notification)
1401 case SPFILENOTIFY_STARTQUEUE:
1402 TRACE( "start queue\n" );
1403 return TRUE;
1404 case SPFILENOTIFY_ENDQUEUE:
1405 TRACE( "end queue\n" );
1406 return 0;
1407 case SPFILENOTIFY_STARTSUBQUEUE:
1408 TRACE( "start subqueue %d count %d\n", param1, param2 );
1409 return TRUE;
1410 case SPFILENOTIFY_ENDSUBQUEUE:
1411 TRACE( "end subqueue %d\n", param1 );
1412 return 0;
1413 case SPFILENOTIFY_STARTDELETE:
1414 TRACE( "start delete %s\n", debugstr_w(paths->Target) );
1415 return FILEOP_DOIT;
1416 case SPFILENOTIFY_ENDDELETE:
1417 TRACE( "end delete %s\n", debugstr_w(paths->Target) );
1418 return 0;
1419 case SPFILENOTIFY_DELETEERROR:
1420 /*Windows Ignores attempts to delete files / folders which do not exist*/
1421 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1422 SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1423 return FILEOP_SKIP;
1424 case SPFILENOTIFY_STARTRENAME:
1425 SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1426 return FILEOP_DOIT;
1427 case SPFILENOTIFY_ENDRENAME:
1428 TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1429 return 0;
1430 case SPFILENOTIFY_RENAMEERROR:
1431 ERR( "rename error %d %s -> %s\n", paths->Win32Error,
1432 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1433 return FILEOP_SKIP;
1434 case SPFILENOTIFY_STARTCOPY:
1435 TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1436 return FILEOP_DOIT;
1437 case SPFILENOTIFY_ENDCOPY:
1438 TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1439 return 0;
1440 case SPFILENOTIFY_COPYERROR:
1441 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1442 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1443 return FILEOP_SKIP;
1444 case SPFILENOTIFY_NEEDMEDIA:
1445 TRACE( "need media\n" );
1446 return FILEOP_SKIP;
1447 default:
1448 FIXME( "notification %d params %x,%x\n", notification, param1, param2 );
1449 break;
1451 return 0;
1454 /***********************************************************************
1455 * SetupDeleteErrorA (SETUPAPI.@)
1458 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file,
1459 UINT w32error, DWORD style)
1461 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1462 w32error, debugstr_a(file) );
1463 return DPROMPT_SKIPFILE;
1466 /***********************************************************************
1467 * SetupDeleteErrorW (SETUPAPI.@)
1470 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file,
1471 UINT w32error, DWORD style)
1473 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1474 w32error, debugstr_w(file) );
1475 return DPROMPT_SKIPFILE;
1478 /***********************************************************************
1479 * SetupRenameErrorA (SETUPAPI.@)
1482 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source,
1483 PCSTR target, UINT w32error, DWORD style)
1485 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1486 w32error, debugstr_a(source), debugstr_a(target));
1487 return DPROMPT_SKIPFILE;
1490 /***********************************************************************
1491 * SetupRenameErrorW (SETUPAPI.@)
1494 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source,
1495 PCWSTR target, UINT w32error, DWORD style)
1497 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1498 w32error, debugstr_w(source), debugstr_w(target));
1499 return DPROMPT_SKIPFILE;
1503 /***********************************************************************
1504 * SetupCopyErrorA (SETUPAPI.@)
1507 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname,
1508 PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath,
1509 UINT w32error, DWORD style, PSTR pathbuffer,
1510 DWORD buffersize, PDWORD requiredsize)
1512 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1513 w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath));
1514 return DPROMPT_SKIPFILE;
1517 /***********************************************************************
1518 * SetupCopyErrorW (SETUPAPI.@)
1521 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname,
1522 PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath,
1523 UINT w32error, DWORD style, PWSTR pathbuffer,
1524 DWORD buffersize, PDWORD requiredsize)
1526 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1527 w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath));
1528 return DPROMPT_SKIPFILE;