[SETUPAPI] Add __REACTOS__ guards around our own code; addendum to r68659 and r73442...
[reactos.git] / dll / win32 / setupapi / queue.c
1 /*
2 * Setupapi file queue routines
3 *
4 * Copyright 2002 Alexandre Julliard for CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "setupapi_private.h"
22
23 #include <aclapi.h>
24
25 /* Unicode constants */
26 static const WCHAR DotSecurity[] = {'.','S','e','c','u','r','i','t','y',0};
27
28 /* context structure for the default queue callback */
29 struct default_callback_context
30 {
31 HWND owner;
32 HWND progress;
33 UINT message;
34 };
35
36 struct file_op
37 {
38 struct file_op *next;
39 UINT style;
40 WCHAR *src_root;
41 WCHAR *src_path;
42 WCHAR *src_file;
43 WCHAR *src_descr;
44 WCHAR *src_tag;
45 WCHAR *dst_path;
46 WCHAR *dst_file;
47 PSECURITY_DESCRIPTOR dst_sd;
48 };
49
50 struct file_op_queue
51 {
52 struct file_op *head;
53 struct file_op *tail;
54 unsigned int count;
55 };
56
57 struct file_queue
58 {
59 struct file_op_queue copy_queue;
60 struct file_op_queue delete_queue;
61 struct file_op_queue rename_queue;
62 DWORD flags;
63 };
64
65
66 static inline WCHAR *strdupW( const WCHAR *str )
67 {
68 WCHAR *ret = NULL;
69 if (str)
70 {
71 int len = (strlenW(str) + 1) * sizeof(WCHAR);
72 if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( ret, str, len );
73 }
74 return ret;
75 }
76
77 static inline char *strdupWtoA( const WCHAR *str )
78 {
79 char *ret = NULL;
80 if (str)
81 {
82 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
83 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
84 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
85 }
86 return ret;
87 }
88
89 /* append a file operation to a queue */
90 static inline void queue_file_op( struct file_op_queue *queue, struct file_op *op )
91 {
92 op->next = NULL;
93 if (queue->tail) queue->tail->next = op;
94 else queue->head = op;
95 queue->tail = op;
96 queue->count++;
97 }
98
99 /* free all the file operations on a given queue */
100 static void free_file_op_queue( struct file_op_queue *queue )
101 {
102 struct file_op *t, *op = queue->head;
103
104 while( op )
105 {
106 HeapFree( GetProcessHeap(), 0, op->src_root );
107 HeapFree( GetProcessHeap(), 0, op->src_path );
108 HeapFree( GetProcessHeap(), 0, op->src_file );
109 HeapFree( GetProcessHeap(), 0, op->src_descr );
110 HeapFree( GetProcessHeap(), 0, op->src_tag );
111 HeapFree( GetProcessHeap(), 0, op->dst_path );
112 if (op->dst_sd) LocalFree( op->dst_sd);
113 if (op->dst_file != op->src_file) HeapFree( GetProcessHeap(), 0, op->dst_file );
114 t = op;
115 op = op->next;
116 HeapFree( GetProcessHeap(), 0, t );
117 }
118 }
119
120 /* concat 3 strings to make a path, handling separators correctly */
121 static void concat_W( WCHAR *buffer, const WCHAR *src1, const WCHAR *src2, const WCHAR *src3 )
122 {
123 *buffer = 0;
124 if (src1 && *src1)
125 {
126 strcpyW( buffer, src1 );
127 buffer += strlenW(buffer );
128 if (buffer[-1] != '\\') *buffer++ = '\\';
129 if (src2) while (*src2 == '\\') src2++;
130 }
131
132 if (src2)
133 {
134 strcpyW( buffer, src2 );
135 buffer += strlenW(buffer );
136 if (buffer[-1] != '\\') *buffer++ = '\\';
137 if (src3) while (*src3 == '\\') src3++;
138 }
139
140 if (src3)
141 strcpyW( buffer, src3 );
142 }
143
144
145 /***********************************************************************
146 * build_filepathsW
147 *
148 * Build a FILEPATHS_W structure for a given file operation.
149 */
150 static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths )
151 {
152 unsigned int src_len = 1, dst_len = 1;
153 WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target;
154
155 if (op->src_root) src_len += strlenW(op->src_root) + 1;
156 if (op->src_path) src_len += strlenW(op->src_path) + 1;
157 if (op->src_file) src_len += strlenW(op->src_file) + 1;
158 if (op->dst_path) dst_len += strlenW(op->dst_path) + 1;
159 if (op->dst_file) dst_len += strlenW(op->dst_file) + 1;
160 src_len *= sizeof(WCHAR);
161 dst_len *= sizeof(WCHAR);
162
163 if (!source || HeapSize( GetProcessHeap(), 0, source ) < src_len )
164 {
165 HeapFree( GetProcessHeap(), 0, source );
166 paths->Source = source = HeapAlloc( GetProcessHeap(), 0, src_len );
167 }
168 if (!target || HeapSize( GetProcessHeap(), 0, target ) < dst_len )
169 {
170 HeapFree( GetProcessHeap(), 0, target );
171 paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len );
172 }
173 if (!source || !target) return FALSE;
174 concat_W( source, op->src_root, op->src_path, op->src_file );
175 concat_W( target, NULL, op->dst_path, op->dst_file );
176 paths->Win32Error = 0;
177 paths->Flags = 0;
178 return TRUE;
179 }
180
181
182 /***********************************************************************
183 * QUEUE_callback_WtoA
184 *
185 * Map a file callback parameters from W to A and call the A callback.
186 */
187 UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification,
188 UINT_PTR param1, UINT_PTR param2 )
189 {
190 struct callback_WtoA_context *callback_ctx = context;
191 char buffer[MAX_PATH];
192 UINT ret;
193 UINT_PTR old_param2 = param2;
194
195 switch(notification)
196 {
197 case SPFILENOTIFY_COPYERROR:
198 param2 = (UINT_PTR)&buffer;
199 /* fall through */
200 case SPFILENOTIFY_STARTDELETE:
201 case SPFILENOTIFY_ENDDELETE:
202 case SPFILENOTIFY_DELETEERROR:
203 case SPFILENOTIFY_STARTRENAME:
204 case SPFILENOTIFY_ENDRENAME:
205 case SPFILENOTIFY_RENAMEERROR:
206 case SPFILENOTIFY_STARTCOPY:
207 case SPFILENOTIFY_ENDCOPY:
208 case SPFILENOTIFY_QUEUESCAN_EX:
209 {
210 FILEPATHS_W *pathsW = (FILEPATHS_W *)param1;
211 FILEPATHS_A pathsA;
212
213 pathsA.Source = strdupWtoA( pathsW->Source );
214 pathsA.Target = strdupWtoA( pathsW->Target );
215 pathsA.Win32Error = pathsW->Win32Error;
216 pathsA.Flags = pathsW->Flags;
217 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
218 (UINT_PTR)&pathsA, param2 );
219 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Source );
220 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Target );
221 }
222 if (notification == SPFILENOTIFY_COPYERROR)
223 MultiByteToWideChar( CP_ACP, 0, buffer, -1, (WCHAR *)old_param2, MAX_PATH );
224 break;
225
226 case SPFILENOTIFY_STARTREGISTRATION:
227 case SPFILENOTIFY_ENDREGISTRATION:
228 {
229 SP_REGISTER_CONTROL_STATUSW *statusW = (SP_REGISTER_CONTROL_STATUSW *)param1;
230 SP_REGISTER_CONTROL_STATUSA statusA;
231
232 statusA.cbSize = sizeof(statusA);
233 statusA.FileName = strdupWtoA( statusW->FileName );
234 statusA.Win32Error = statusW->Win32Error;
235 statusA.FailureCode = statusW->FailureCode;
236 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
237 (UINT_PTR)&statusA, param2 );
238 HeapFree( GetProcessHeap(), 0, (LPSTR)statusA.FileName );
239 }
240 break;
241
242 case SPFILENOTIFY_QUEUESCAN:
243 {
244 LPWSTR targetW = (LPWSTR)param1;
245 LPSTR target = strdupWtoA( targetW );
246
247 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
248 (UINT_PTR)target, param2 );
249 HeapFree( GetProcessHeap(), 0, target );
250 }
251 break;
252
253 case SPFILENOTIFY_NEEDMEDIA:
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;
262 }
263 return ret;
264 }
265
266
267 /***********************************************************************
268 * get_src_file_info
269 *
270 * Retrieve the source file information for a given file.
271 */
272 static void get_src_file_info( HINF hinf, struct file_op *op )
273 {
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};
278
279 INFCONTEXT file_ctx, disk_ctx;
280 INT id, diskid;
281 DWORD len, len2;
282 WCHAR SectionName[MAX_PATH];
283
284 /* find the SourceDisksFiles entry */
285 if(!SetupDiGetActualSectionToInstallW(hinf, SourceDisksFiles, SectionName, MAX_PATH, NULL, NULL))
286 return;
287 if (!SetupFindFirstLineW( hinf, SectionName, op->src_file, &file_ctx ))
288 {
289 if ((op->style & (SP_COPY_SOURCE_ABSOLUTE|SP_COPY_SOURCEPATH_ABSOLUTE))) return;
290 /* no specific info, use .inf file source directory */
291 if (!op->src_root) op->src_root = PARSER_get_src_root( hinf );
292 return;
293 }
294 if (!SetupGetIntField( &file_ctx, 1, &diskid )) return;
295
296 /* now find the diskid in the SourceDisksNames section */
297 if(!SetupDiGetActualSectionToInstallW(hinf, SourceDisksNames, SectionName, MAX_PATH, NULL, NULL))
298 return;
299 if (!SetupFindFirstLineW( hinf, SectionName, NULL, &disk_ctx )) return;
300 for (;;)
301 {
302 if (SetupGetIntField( &disk_ctx, 0, &id ) && (id == diskid)) break;
303 if (!SetupFindNextLine( &disk_ctx, &disk_ctx )) return;
304 }
305
306 /* and fill in the missing info */
307
308 if (!op->src_descr)
309 {
310 if (SetupGetStringFieldW( &disk_ctx, 1, NULL, 0, &len ) &&
311 (op->src_descr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
312 SetupGetStringFieldW( &disk_ctx, 1, op->src_descr, len, NULL );
313 }
314 if (!op->src_tag)
315 {
316 if (SetupGetStringFieldW( &disk_ctx, 2, NULL, 0, &len ) &&
317 (op->src_tag = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
318 SetupGetStringFieldW( &disk_ctx, 2, op->src_tag, len, NULL );
319 }
320 if (!op->src_path && !(op->style & SP_COPY_SOURCE_ABSOLUTE))
321 {
322 len = len2 = 0;
323 if (!(op->style & SP_COPY_SOURCEPATH_ABSOLUTE))
324 {
325 /* retrieve relative path for this disk */
326 if (!SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len )) len = 0;
327 }
328 /* retrieve relative path for this file */
329 if (!SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len2 )) len2 = 0;
330
331 if ((len || len2) &&
332 (op->src_path = HeapAlloc( GetProcessHeap(), 0, (len+len2)*sizeof(WCHAR) )))
333 {
334 WCHAR *ptr = op->src_path;
335 if (len)
336 {
337 SetupGetStringFieldW( &disk_ctx, 4, op->src_path, len, NULL );
338 ptr = op->src_path + strlenW(op->src_path);
339 if (len2 && ptr > op->src_path && ptr[-1] != '\\') *ptr++ = '\\';
340 }
341 if (!SetupGetStringFieldW( &file_ctx, 2, ptr, len2, NULL )) *ptr = 0;
342 }
343 }
344 if (!op->src_root) op->src_root = PARSER_get_src_root(hinf);
345 }
346
347
348 /***********************************************************************
349 * get_destination_dir
350 *
351 * Retrieve the destination dir for a given section.
352 */
353 static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
354 {
355 static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
356 static const WCHAR Def[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
357 INFCONTEXT context;
358
359 if (!SetupFindFirstLineW( hinf, Dest, section, &context ) &&
360 !SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL;
361 return PARSER_get_dest_dir( &context );
362 }
363
364
365 static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD );
366
367 /***********************************************************************
368 * extract_cabinet_file
369 *
370 * Extract a file from a .cab file.
371 */
372 static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root,
373 const WCHAR *src, const WCHAR *dst )
374 {
375 static const WCHAR extW[] = {'.','c','a','b',0};
376 static HMODULE advpack;
377
378 char *cab_path, *cab_file;
379 int len = strlenW( cabinet );
380
381 /* make sure the cabinet file has a .cab extension */
382 if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE;
383 if (!pExtractFiles)
384 {
385 if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" )))
386 {
387 ERR( "could not load advpack.dll\n" );
388 return FALSE;
389 }
390 if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" )))
391 {
392 ERR( "could not find ExtractFiles in advpack.dll\n" );
393 return FALSE;
394 }
395 }
396
397 if (!(cab_path = strdupWtoA( root ))) return FALSE;
398 len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL );
399 if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 )))
400 {
401 HeapFree( GetProcessHeap(), 0, cab_path );
402 return FALSE;
403 }
404 strcpy( cab_file, cab_path );
405 if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" );
406 WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL );
407 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) );
408 pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 );
409 HeapFree( GetProcessHeap(), 0, cab_file );
410 HeapFree( GetProcessHeap(), 0, cab_path );
411 return CopyFileW( src, dst, FALSE /*FIXME*/ );
412 }
413
414
415 /***********************************************************************
416 * SetupOpenFileQueue (SETUPAPI.@)
417 */
418 HSPFILEQ WINAPI SetupOpenFileQueue(void)
419 {
420 struct file_queue *queue;
421
422 if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue))))
423 return INVALID_HANDLE_VALUE;
424 return queue;
425 }
426
427
428 /***********************************************************************
429 * SetupCloseFileQueue (SETUPAPI.@)
430 */
431 BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle )
432 {
433 struct file_queue *queue = handle;
434
435 free_file_op_queue( &queue->copy_queue );
436 free_file_op_queue( &queue->rename_queue );
437 free_file_op_queue( &queue->delete_queue );
438 HeapFree( GetProcessHeap(), 0, queue );
439 return TRUE;
440 }
441
442
443 /***********************************************************************
444 * SetupQueueCopyIndirectA (SETUPAPI.@)
445 */
446 BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params )
447 {
448 struct file_queue *queue = params->QueueHandle;
449 struct file_op *op;
450
451 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
452 op->style = params->CopyStyle;
453 op->src_root = strdupAtoW( params->SourceRootPath );
454 op->src_path = strdupAtoW( params->SourcePath );
455 op->src_file = strdupAtoW( params->SourceFilename );
456 op->src_descr = strdupAtoW( params->SourceDescription );
457 op->src_tag = strdupAtoW( params->SourceTagfile );
458 op->dst_path = strdupAtoW( params->TargetDirectory );
459 op->dst_file = strdupAtoW( params->TargetFilename );
460 op->dst_sd = NULL;
461
462 /* some defaults */
463 if (!op->src_file) op->src_file = op->dst_file;
464 if (params->LayoutInf)
465 {
466 get_src_file_info( params->LayoutInf, op );
467 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
468 }
469
470 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
471 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
472 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
473 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
474
475 queue_file_op( &queue->copy_queue, op );
476 return TRUE;
477 }
478
479
480 /***********************************************************************
481 * SetupQueueCopyIndirectW (SETUPAPI.@)
482 */
483 BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params )
484 {
485 struct file_queue *queue = params->QueueHandle;
486 struct file_op *op;
487
488 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
489 op->style = params->CopyStyle;
490 op->src_root = strdupW( params->SourceRootPath );
491 op->src_path = strdupW( params->SourcePath );
492 op->src_file = strdupW( params->SourceFilename );
493 op->src_descr = strdupW( params->SourceDescription );
494 op->src_tag = strdupW( params->SourceTagfile );
495 op->dst_path = strdupW( params->TargetDirectory );
496 op->dst_file = strdupW( params->TargetFilename );
497 op->dst_sd = NULL;
498 if (params->SecurityDescriptor)
499 ConvertStringSecurityDescriptorToSecurityDescriptorW( params->SecurityDescriptor, SDDL_REVISION_1, &op->dst_sd, NULL );
500
501 /* some defaults */
502 if (!op->src_file) op->src_file = op->dst_file;
503 if (params->LayoutInf)
504 {
505 get_src_file_info( params->LayoutInf, op );
506 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
507 }
508
509 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
510 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
511 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
512 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
513
514 queue_file_op( &queue->copy_queue, op );
515 return TRUE;
516 }
517
518
519 /***********************************************************************
520 * SetupQueueCopyA (SETUPAPI.@)
521 */
522 BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file,
523 PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file,
524 DWORD style )
525 {
526 SP_FILE_COPY_PARAMS_A params;
527
528 params.cbSize = sizeof(params);
529 params.QueueHandle = queue;
530 params.SourceRootPath = src_root;
531 params.SourcePath = src_path;
532 params.SourceFilename = src_file;
533 params.SourceDescription = src_descr;
534 params.SourceTagfile = src_tag;
535 params.TargetDirectory = dst_dir;
536 params.TargetFilename = dst_file;
537 params.CopyStyle = style;
538 params.LayoutInf = 0;
539 params.SecurityDescriptor = NULL;
540 return SetupQueueCopyIndirectA( &params );
541 }
542
543
544 /***********************************************************************
545 * SetupQueueCopyW (SETUPAPI.@)
546 */
547 BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file,
548 PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file,
549 DWORD style )
550 {
551 SP_FILE_COPY_PARAMS_W params;
552
553 params.cbSize = sizeof(params);
554 params.QueueHandle = queue;
555 params.SourceRootPath = src_root;
556 params.SourcePath = src_path;
557 params.SourceFilename = src_file;
558 params.SourceDescription = src_descr;
559 params.SourceTagfile = src_tag;
560 params.TargetDirectory = dst_dir;
561 params.TargetFilename = dst_file;
562 params.CopyStyle = style;
563 params.LayoutInf = 0;
564 params.SecurityDescriptor = NULL;
565 return SetupQueueCopyIndirectW( &params );
566 }
567
568
569 /***********************************************************************
570 * SetupQueueDefaultCopyA (SETUPAPI.@)
571 */
572 BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file,
573 PCSTR dst_file, DWORD style )
574 {
575 SP_FILE_COPY_PARAMS_A params;
576
577 params.cbSize = sizeof(params);
578 params.QueueHandle = queue;
579 params.SourceRootPath = src_root;
580 params.SourcePath = NULL;
581 params.SourceFilename = src_file;
582 params.SourceDescription = NULL;
583 params.SourceTagfile = NULL;
584 params.TargetDirectory = NULL;
585 params.TargetFilename = dst_file;
586 params.CopyStyle = style;
587 params.LayoutInf = hinf;
588 params.SecurityDescriptor = NULL;
589 return SetupQueueCopyIndirectA( &params );
590 }
591
592
593 /***********************************************************************
594 * SetupQueueDefaultCopyW (SETUPAPI.@)
595 */
596 BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file,
597 PCWSTR dst_file, DWORD style )
598 {
599 SP_FILE_COPY_PARAMS_W params;
600
601 params.cbSize = sizeof(params);
602 params.QueueHandle = queue;
603 params.SourceRootPath = src_root;
604 params.SourcePath = NULL;
605 params.SourceFilename = src_file;
606 params.SourceDescription = NULL;
607 params.SourceTagfile = NULL;
608 params.TargetDirectory = NULL;
609 params.TargetFilename = dst_file;
610 params.CopyStyle = style;
611 params.LayoutInf = hinf;
612 params.SecurityDescriptor = NULL;
613 return SetupQueueCopyIndirectW( &params );
614 }
615
616
617 /***********************************************************************
618 * SetupQueueDeleteA (SETUPAPI.@)
619 */
620 BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 )
621 {
622 struct file_queue *queue = handle;
623 struct file_op *op;
624
625 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
626 op->style = 0;
627 op->src_root = NULL;
628 op->src_path = NULL;
629 op->src_file = NULL;
630 op->src_descr = NULL;
631 op->src_tag = NULL;
632 op->dst_path = strdupAtoW( part1 );
633 op->dst_file = strdupAtoW( part2 );
634 op->dst_sd = NULL;
635 queue_file_op( &queue->delete_queue, op );
636 return TRUE;
637 }
638
639
640 /***********************************************************************
641 * SetupQueueDeleteW (SETUPAPI.@)
642 */
643 BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 )
644 {
645 struct file_queue *queue = handle;
646 struct file_op *op;
647
648 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
649 op->style = 0;
650 op->src_root = NULL;
651 op->src_path = NULL;
652 op->src_file = NULL;
653 op->src_descr = NULL;
654 op->src_tag = NULL;
655 op->dst_path = strdupW( part1 );
656 op->dst_file = strdupW( part2 );
657 op->dst_sd = NULL;
658 queue_file_op( &queue->delete_queue, op );
659 return TRUE;
660 }
661
662
663 /***********************************************************************
664 * SetupQueueRenameA (SETUPAPI.@)
665 */
666 BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename,
667 PCSTR TargetPath, PCSTR TargetFilename )
668 {
669 struct file_queue *queue = handle;
670 struct file_op *op;
671
672 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
673 op->style = 0;
674 op->src_root = NULL;
675 op->src_path = strdupAtoW( SourcePath );
676 op->src_file = strdupAtoW( SourceFilename );
677 op->src_descr = NULL;
678 op->src_tag = NULL;
679 op->dst_path = strdupAtoW( TargetPath );
680 op->dst_file = strdupAtoW( TargetFilename );
681 op->dst_sd = NULL;
682 queue_file_op( &queue->rename_queue, op );
683 return TRUE;
684 }
685
686
687 /***********************************************************************
688 * SetupQueueRenameW (SETUPAPI.@)
689 */
690 BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename,
691 PCWSTR TargetPath, PCWSTR TargetFilename )
692 {
693 struct file_queue *queue = handle;
694 struct file_op *op;
695
696 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
697 op->style = 0;
698 op->src_root = NULL;
699 op->src_path = strdupW( SourcePath );
700 op->src_file = strdupW( SourceFilename );
701 op->src_descr = NULL;
702 op->src_tag = NULL;
703 op->dst_path = strdupW( TargetPath );
704 op->dst_file = strdupW( TargetFilename );
705 op->dst_sd = NULL;
706 queue_file_op( &queue->rename_queue, op );
707 return TRUE;
708 }
709
710
711 /***********************************************************************
712 * SetupQueueCopySectionA (SETUPAPI.@)
713 */
714 BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist,
715 PCSTR section, DWORD style )
716 {
717 UNICODE_STRING sectionW;
718 BOOL ret = FALSE;
719
720 if (!RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
721 {
722 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
723 return FALSE;
724 }
725 if (!src_root)
726 ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style );
727 else
728 {
729 UNICODE_STRING srcW;
730 if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root ))
731 {
732 ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style );
733 RtlFreeUnicodeString( &srcW );
734 }
735 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
736 }
737 RtlFreeUnicodeString( &sectionW );
738 return ret;
739 }
740
741
742 /***********************************************************************
743 * SetupQueueCopySectionW (SETUPAPI.@)
744 */
745 BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist,
746 PCWSTR section, DWORD style )
747 {
748 SP_FILE_COPY_PARAMS_W params;
749 LPWSTR security_key, security_descriptor = NULL;
750 INFCONTEXT context, security_context;
751 WCHAR dest[MAX_PATH], src[MAX_PATH];
752 INT flags;
753 DWORD required;
754 BOOL ret;
755
756 TRACE( "hinf=%p/%p section=%s root=%s\n",
757 hinf, hlist, debugstr_w(section), debugstr_w(src_root) );
758
759 /* Check for .Security section */
760 security_key = MyMalloc( (strlenW( section ) + strlenW( DotSecurity )) * sizeof(WCHAR) + sizeof(UNICODE_NULL) );
761 if (!security_key)
762 {
763 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
764 return FALSE;
765 }
766 strcpyW( security_key, section );
767 strcatW( security_key, DotSecurity );
768 ret = SetupFindFirstLineW( hinf, security_key, NULL, &security_context );
769 MyFree(security_key);
770 if (ret)
771 {
772 if (!SetupGetLineTextW( &security_context, NULL, NULL, NULL, NULL, 0, &required ))
773 return FALSE;
774 security_descriptor = MyMalloc( required * sizeof(WCHAR) );
775 if (!security_descriptor)
776 {
777 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
778 return FALSE;
779 }
780 if (!SetupGetLineTextW( &security_context, NULL, NULL, NULL, security_descriptor, required, NULL ))
781 {
782 MyFree( security_descriptor );
783 return FALSE;
784 }
785 }
786
787 params.cbSize = sizeof(params);
788 params.QueueHandle = queue;
789 params.SourceRootPath = src_root;
790 params.SourcePath = NULL;
791 params.SourceDescription = NULL;
792 params.SourceTagfile = NULL;
793 params.TargetFilename = dest;
794 params.CopyStyle = style;
795 params.LayoutInf = hinf;
796 params.SecurityDescriptor = security_descriptor;
797
798 ret = FALSE;
799 if (!hlist) hlist = hinf;
800 if (!hinf) hinf = hlist;
801 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) goto done;
802 if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) goto done;
803 do
804 {
805 if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL ))
806 goto done;
807 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0;
808 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */
809
810 params.SourceFilename = *src ? src : NULL;
811 if (!SetupQueueCopyIndirectW( &params )) goto done;
812 } while (SetupFindNextLine( &context, &context ));
813 ret = TRUE;
814
815 done:
816 if (security_descriptor)
817 MyFree( security_descriptor );
818 return ret;
819 }
820
821
822 /***********************************************************************
823 * SetupQueueDeleteSectionA (SETUPAPI.@)
824 */
825 BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
826 {
827 UNICODE_STRING sectionW;
828 BOOL ret = FALSE;
829
830 if (RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
831 {
832 ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer );
833 RtlFreeUnicodeString( &sectionW );
834 }
835 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
836 return ret;
837 }
838
839
840 /***********************************************************************
841 * SetupQueueDeleteSectionW (SETUPAPI.@)
842 */
843 BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
844 {
845 INFCONTEXT context;
846 WCHAR *dest_dir;
847 WCHAR buffer[MAX_PATH];
848 BOOL ret = FALSE;
849 INT flags;
850
851 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
852
853 if (!hlist) hlist = hinf;
854 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
855 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
856 do
857 {
858 if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
859 goto done;
860 if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
861 if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done;
862 } while (SetupFindNextLine( &context, &context ));
863
864 ret = TRUE;
865 done:
866 HeapFree( GetProcessHeap(), 0, dest_dir );
867 return ret;
868 }
869
870
871 /***********************************************************************
872 * SetupQueueRenameSectionA (SETUPAPI.@)
873 */
874 BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
875 {
876 UNICODE_STRING sectionW;
877 BOOL ret = FALSE;
878
879 if (RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
880 {
881 ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer );
882 RtlFreeUnicodeString( &sectionW );
883 }
884 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
885 return ret;
886 }
887
888
889 /***********************************************************************
890 * SetupQueueRenameSectionW (SETUPAPI.@)
891 */
892 BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
893 {
894 INFCONTEXT context;
895 WCHAR *dest_dir;
896 WCHAR src[MAX_PATH], dst[MAX_PATH];
897 BOOL ret = FALSE;
898
899 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
900
901 if (!hlist) hlist = hinf;
902 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
903 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
904 do
905 {
906 if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL ))
907 goto done;
908 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL ))
909 goto done;
910 if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done;
911 } while (SetupFindNextLine( &context, &context ));
912
913 ret = TRUE;
914 done:
915 HeapFree( GetProcessHeap(), 0, dest_dir );
916 return ret;
917 }
918
919
920 /***********************************************************************
921 * SetupCommitFileQueueA (SETUPAPI.@)
922 */
923 BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler,
924 PVOID context )
925 {
926 struct callback_WtoA_context ctx;
927
928 ctx.orig_context = context;
929 ctx.orig_handler = handler;
930 return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx );
931 }
932
933
934 /***********************************************************************
935 * create_full_pathW
936 *
937 * Recursively create all directories in the path.
938 */
939 static BOOL create_full_pathW(const WCHAR *path)
940 {
941 BOOL ret = TRUE;
942 int len;
943 WCHAR *new_path;
944
945 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
946 strcpyW(new_path, path);
947
948 while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
949 new_path[len - 1] = 0;
950
951 while(!CreateDirectoryW(new_path, NULL))
952 {
953 WCHAR *slash;
954 DWORD last_error = GetLastError();
955
956 if(last_error == ERROR_ALREADY_EXISTS)
957 break;
958
959 if(last_error != ERROR_PATH_NOT_FOUND)
960 {
961 ret = FALSE;
962 break;
963 }
964
965 if(!(slash = strrchrW(new_path, '\\')))
966 {
967 ret = FALSE;
968 break;
969 }
970
971 len = slash - new_path;
972 new_path[len] = 0;
973 if(!create_full_pathW(new_path))
974 {
975 ret = FALSE;
976 break;
977 }
978 new_path[len] = '\\';
979 }
980
981 HeapFree(GetProcessHeap(), 0, new_path);
982 return ret;
983 }
984
985 static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style,
986 PSP_FILE_CALLBACK_W handler, PVOID context )
987 {
988 BOOL rc = FALSE;
989 BOOL docopy = TRUE;
990 #ifdef __REACTOS__
991 INT hSource, hTemp;
992 OFSTRUCT OfStruct;
993 WCHAR TempPath[MAX_PATH];
994 WCHAR TempFile[MAX_PATH];
995 #endif
996
997 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source),debugstr_w(target),style);
998
999 #ifdef __REACTOS__
1000 /* Get a temp file name */
1001 if (!GetTempPathW(ARRAYSIZE(TempPath), TempPath))
1002 {
1003 ERR("GetTempPathW error\n");
1004 return FALSE;
1005 }
1006 if (!GetTempFileNameW(TempPath, L"", 0, TempFile))
1007 {
1008 ERR("GetTempFileNameW(%s) error\n", debugstr_w(TempPath));
1009 return FALSE;
1010 }
1011
1012 /* Try to open the source file */
1013 hSource = LZOpenFileW((LPWSTR)source, &OfStruct, OF_READ);
1014 if (hSource < 0)
1015 {
1016 ERR("LZOpenFileW(1) error %d %s\n", (int)hSource, debugstr_w(source));
1017 return FALSE;
1018 }
1019
1020 /* Extract the compressed file to a temp location */
1021 hTemp = LZOpenFileW(TempFile, &OfStruct, OF_CREATE);
1022 if (hTemp < 0)
1023 {
1024 DWORD dwLastError = GetLastError();
1025
1026 ERR("LZOpenFileW(2) error %d %s\n", (int)hTemp, debugstr_w(TempFile));
1027
1028 /* Close the source handle */
1029 LZClose(hSource);
1030
1031 /* Restore error condition triggered by LZOpenFileW */
1032 SetLastError(dwLastError);
1033 return FALSE;
1034 }
1035
1036 LZCopy(hSource, hTemp);
1037 LZClose(hSource);
1038 LZClose(hTemp);
1039 #endif
1040
1041 /* before copy processing */
1042 if (style & SP_COPY_REPLACEONLY)
1043 {
1044 if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES)
1045 docopy = FALSE;
1046 }
1047 if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER))
1048 {
1049 DWORD VersionSizeSource=0;
1050 DWORD VersionSizeTarget=0;
1051 DWORD zero=0;
1052
1053 /*
1054 * This is sort of an interesting workaround. You see, calling
1055 * GetVersionInfoSize on a builtin dll loads that dll into memory
1056 * and we do not properly unload builtin dlls.. so we effectively
1057 * lock into memory all the targets we are replacing. This leads
1058 * to problems when we try to register the replaced dlls.
1059 *
1060 * So I will test for the existence of the files first so that
1061 * we just basically unconditionally replace the builtin versions.
1062 */
1063 if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) &&
1064 (GetFileAttributesW(TempFile) != INVALID_FILE_ATTRIBUTES))
1065 {
1066 VersionSizeSource = GetFileVersionInfoSizeW(TempFile,&zero);
1067 VersionSizeTarget = GetFileVersionInfoSizeW((LPWSTR)target,&zero);
1068 }
1069
1070 TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget,
1071 VersionSizeSource);
1072
1073 if (VersionSizeSource && VersionSizeTarget)
1074 {
1075 LPVOID VersionSource;
1076 LPVOID VersionTarget;
1077 VS_FIXEDFILEINFO *TargetInfo;
1078 VS_FIXEDFILEINFO *SourceInfo;
1079 UINT length;
1080 WCHAR SubBlock[2]={'\\',0};
1081 DWORD ret;
1082
1083 VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource);
1084 VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget);
1085
1086 ret = GetFileVersionInfoW(TempFile,0,VersionSizeSource,VersionSource);
1087 if (ret)
1088 ret = GetFileVersionInfoW((LPWSTR)target, 0, VersionSizeTarget,
1089 VersionTarget);
1090
1091 if (ret)
1092 {
1093 ret = VerQueryValueW(VersionSource, SubBlock,
1094 (LPVOID*)&SourceInfo, &length);
1095 if (ret)
1096 ret = VerQueryValueW(VersionTarget, SubBlock,
1097 (LPVOID*)&TargetInfo, &length);
1098
1099 if (ret)
1100 {
1101 FILEPATHS_W filepaths;
1102
1103 TRACE("Versions: Source %i.%i target %i.%i\n",
1104 SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS,
1105 TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS);
1106
1107 /* used in case of notification */
1108 filepaths.Target = target;
1109 filepaths.Source = source;
1110 filepaths.Win32Error = 0;
1111 filepaths.Flags = 0;
1112
1113 if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS)
1114 {
1115 if (handler)
1116 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1117 else
1118 docopy = FALSE;
1119 }
1120 else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS)
1121 && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS))
1122 {
1123 if (handler)
1124 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1125 else
1126 docopy = FALSE;
1127 }
1128 else if ((style & SP_COPY_NEWER_ONLY) &&
1129 (TargetInfo->dwFileVersionMS ==
1130 SourceInfo->dwFileVersionMS)
1131 &&(TargetInfo->dwFileVersionLS ==
1132 SourceInfo->dwFileVersionLS))
1133 {
1134 if (handler)
1135 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1136 else
1137 docopy = FALSE;
1138 }
1139 }
1140 }
1141 HeapFree(GetProcessHeap(),0,VersionSource);
1142 HeapFree(GetProcessHeap(),0,VersionTarget);
1143 }
1144 }
1145 if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE))
1146 {
1147 if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES)
1148 {
1149 FIXME("Notify user target file exists\n");
1150 docopy = FALSE;
1151 }
1152 }
1153 if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE |
1154 SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP))
1155 {
1156 ERR("Unsupported style(s) 0x%x\n",style);
1157 }
1158
1159 if (docopy)
1160 {
1161 rc = MoveFileExW(TempFile,target,MOVEFILE_REPLACE_EXISTING);
1162 TRACE("Did copy... rc was %i\n",rc);
1163 }
1164
1165 /* after copy processing */
1166 if (style & SP_COPY_DELETESOURCE)
1167 {
1168 if (rc)
1169 DeleteFileW(source);
1170 }
1171
1172 return rc;
1173 }
1174
1175 /***********************************************************************
1176 * SetupInstallFileA (SETUPAPI.@)
1177 */
1178 BOOL WINAPI SetupInstallFileA( HINF hinf, PINFCONTEXT inf_context, PCSTR source, PCSTR root,
1179 PCSTR dest, DWORD style, PSP_FILE_CALLBACK_A handler, PVOID context )
1180 {
1181 BOOL ret = FALSE;
1182 struct callback_WtoA_context ctx;
1183 UNICODE_STRING sourceW, rootW, destW;
1184
1185 TRACE("%p %p %s %s %s %x %p %p\n", hinf, inf_context, debugstr_a(source), debugstr_a(root),
1186 debugstr_a(dest), style, handler, context);
1187
1188 sourceW.Buffer = rootW.Buffer = destW.Buffer = NULL;
1189 if (source && !RtlCreateUnicodeStringFromAsciiz( &sourceW, source ))
1190 {
1191 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1192 return FALSE;
1193 }
1194 if (root && !RtlCreateUnicodeStringFromAsciiz( &rootW, root ))
1195 {
1196 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1197 goto exit;
1198 }
1199 if (dest && !RtlCreateUnicodeStringFromAsciiz( &destW, dest ))
1200 {
1201 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1202 goto exit;
1203 }
1204
1205 ctx.orig_context = context;
1206 ctx.orig_handler = handler;
1207
1208 ret = SetupInstallFileW( hinf, inf_context, sourceW.Buffer, rootW.Buffer, destW.Buffer, style, QUEUE_callback_WtoA, &ctx );
1209
1210 exit:
1211 RtlFreeUnicodeString( &sourceW );
1212 RtlFreeUnicodeString( &rootW );
1213 RtlFreeUnicodeString( &destW );
1214 return ret;
1215 }
1216
1217 /***********************************************************************
1218 * SetupInstallFileW (SETUPAPI.@)
1219 */
1220 BOOL WINAPI SetupInstallFileW( HINF hinf, PINFCONTEXT inf_context, PCWSTR source, PCWSTR root,
1221 PCWSTR dest, DWORD style, PSP_FILE_CALLBACK_W handler, PVOID context )
1222 {
1223 static const WCHAR CopyFiles[] = {'C','o','p','y','F','i','l','e','s',0};
1224
1225 BOOL ret, absolute = (root && *root && !(style & SP_COPY_SOURCE_ABSOLUTE));
1226 WCHAR *buffer, *p, *inf_source = NULL;
1227 unsigned int len;
1228
1229 TRACE("%p %p %s %s %s %x %p %p\n", hinf, inf_context, debugstr_w(source), debugstr_w(root),
1230 debugstr_w(dest), style, handler, context);
1231
1232 if (hinf)
1233 {
1234 INFCONTEXT ctx;
1235
1236 if (!inf_context)
1237 {
1238 inf_context = &ctx;
1239 if (!SetupFindFirstLineW( hinf, CopyFiles, NULL, inf_context )) return FALSE;
1240 }
1241 if (!SetupGetStringFieldW( inf_context, 1, NULL, 0, (PDWORD) &len )) return FALSE;
1242 if (!(inf_source = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1243 {
1244 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1245 return FALSE;
1246 }
1247 if (!SetupGetStringFieldW( inf_context, 1, inf_source, len, NULL ))
1248 {
1249 HeapFree( GetProcessHeap(), 0, inf_source );
1250 return FALSE;
1251 }
1252 source = inf_source;
1253 }
1254 else if (!source)
1255 {
1256 SetLastError( ERROR_INVALID_PARAMETER );
1257 return FALSE;
1258 }
1259
1260 len = strlenW( source ) + 1;
1261 if (absolute) len += strlenW( root ) + 1;
1262
1263 if (!(p = buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1264 {
1265 HeapFree( GetProcessHeap(), 0, inf_source );
1266 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1267 return FALSE;
1268 }
1269
1270 if (absolute)
1271 {
1272 strcpyW( buffer, root );
1273 p += strlenW( buffer );
1274 if (p[-1] != '\\') *p++ = '\\';
1275 }
1276 while (*source == '\\') source++;
1277 strcpyW( p, source );
1278
1279 ret = do_file_copyW( buffer, dest, style, handler, context );
1280
1281 HeapFree( GetProcessHeap(), 0, inf_source );
1282 HeapFree( GetProcessHeap(), 0, buffer );
1283 return ret;
1284 }
1285
1286 /***********************************************************************
1287 * SetupCommitFileQueueW (SETUPAPI.@)
1288 */
1289 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler,
1290 PVOID context )
1291 {
1292 struct file_queue *queue = handle;
1293 struct file_op *op;
1294 BOOL result = FALSE;
1295 FILEPATHS_W paths;
1296 UINT op_result;
1297
1298 paths.Source = paths.Target = NULL;
1299
1300 if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count)
1301 return TRUE; /* nothing to do */
1302
1303 if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE;
1304
1305 /* perform deletes */
1306
1307 if (queue->delete_queue.count)
1308 {
1309 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE,
1310 queue->delete_queue.count ))) goto done;
1311 for (op = queue->delete_queue.head; op; op = op->next)
1312 {
1313 build_filepathsW( op, &paths );
1314 op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE);
1315 if (op_result == FILEOP_ABORT) goto done;
1316 while (op_result == FILEOP_DOIT)
1317 {
1318 TRACE( "deleting file %s\n", debugstr_w(paths.Target) );
1319 if (DeleteFileW( paths.Target )) break; /* success */
1320 paths.Win32Error = GetLastError();
1321 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 );
1322 if (op_result == FILEOP_ABORT) goto done;
1323 }
1324 handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 );
1325 }
1326 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 );
1327 }
1328
1329 /* perform renames */
1330
1331 if (queue->rename_queue.count)
1332 {
1333 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME,
1334 queue->rename_queue.count ))) goto done;
1335 for (op = queue->rename_queue.head; op; op = op->next)
1336 {
1337 build_filepathsW( op, &paths );
1338 op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME);
1339 if (op_result == FILEOP_ABORT) goto done;
1340 while (op_result == FILEOP_DOIT)
1341 {
1342 TRACE( "renaming file %s -> %s\n",
1343 debugstr_w(paths.Source), debugstr_w(paths.Target) );
1344 if (MoveFileW( paths.Source, paths.Target )) break; /* success */
1345 paths.Win32Error = GetLastError();
1346 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 );
1347 if (op_result == FILEOP_ABORT) goto done;
1348 }
1349 handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 );
1350 }
1351 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 );
1352 }
1353
1354 /* perform copies */
1355
1356 if (queue->copy_queue.count)
1357 {
1358 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY,
1359 queue->copy_queue.count ))) goto done;
1360 for (op = queue->copy_queue.head; op; op = op->next)
1361 {
1362 WCHAR newpath[MAX_PATH];
1363
1364 build_filepathsW( op, &paths );
1365 op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
1366 if (op_result == FILEOP_ABORT) goto done;
1367 if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT;
1368 while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
1369 {
1370 TRACE( "copying file %s -> %s\n",
1371 debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ),
1372 debugstr_w(paths.Target) );
1373 if (op->dst_path)
1374 {
1375 if (!create_full_pathW( op->dst_path ))
1376 {
1377 paths.Win32Error = GetLastError();
1378 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1379 (UINT_PTR)&paths, (UINT_PTR)newpath );
1380 if (op_result == FILEOP_ABORT) goto done;
1381 }
1382 }
1383 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
1384 paths.Target, op->style, handler, context )) break; /* success */
1385 /* try to extract it from the cabinet file */
1386 if (op->src_tag)
1387 {
1388 if (extract_cabinet_file( op->src_tag, op->src_root,
1389 paths.Source, paths.Target )) break;
1390 }
1391 paths.Win32Error = GetLastError();
1392 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1393 (UINT_PTR)&paths, (UINT_PTR)newpath );
1394 if (op_result == FILEOP_ABORT) goto done;
1395 }
1396 if (op->dst_sd)
1397 {
1398 PSID psidOwner = NULL, psidGroup = NULL;
1399 PACL pDacl = NULL, pSacl = NULL;
1400 SECURITY_INFORMATION security_info = 0;
1401 BOOL present, dummy;
1402
1403 if (GetSecurityDescriptorOwner( op->dst_sd, &psidOwner, &dummy ) && psidOwner)
1404 security_info |= OWNER_SECURITY_INFORMATION;
1405 if (GetSecurityDescriptorGroup( op->dst_sd, &psidGroup, &dummy ) && psidGroup)
1406 security_info |= GROUP_SECURITY_INFORMATION;
1407 if (GetSecurityDescriptorDacl( op->dst_sd, &present, &pDacl, &dummy ))
1408 security_info |= DACL_SECURITY_INFORMATION;
1409 if (GetSecurityDescriptorSacl( op->dst_sd, &present, &pSacl, &dummy ))
1410 security_info |= DACL_SECURITY_INFORMATION;
1411 SetNamedSecurityInfoW( (LPWSTR)paths.Target, SE_FILE_OBJECT, security_info,
1412 psidOwner, psidGroup, pDacl, pSacl );
1413 /* Yes, ignore the return code... */
1414 }
1415 handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
1416 }
1417 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 );
1418 }
1419
1420
1421 result = TRUE;
1422
1423 done:
1424 handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 );
1425 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1426 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1427 return result;
1428 }
1429
1430
1431 /***********************************************************************
1432 * SetupScanFileQueueA (SETUPAPI.@)
1433 */
1434 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ handle, DWORD flags, HWND window,
1435 PSP_FILE_CALLBACK_A handler, PVOID context, PDWORD result )
1436 {
1437 struct callback_WtoA_context ctx;
1438
1439 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
1440
1441 ctx.orig_context = context;
1442 ctx.orig_handler = handler;
1443
1444 return SetupScanFileQueueW( handle, flags, window, QUEUE_callback_WtoA, &ctx, result );
1445 }
1446
1447
1448 /***********************************************************************
1449 * SetupScanFileQueueW (SETUPAPI.@)
1450 */
1451 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ handle, DWORD flags, HWND window,
1452 PSP_FILE_CALLBACK_W handler, PVOID context, PDWORD result )
1453 {
1454 struct file_queue *queue = handle;
1455 struct file_op *op;
1456 FILEPATHS_W paths;
1457 UINT notification = 0;
1458 BOOL ret = FALSE;
1459
1460 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
1461
1462 *result = FALSE;
1463
1464 if (!queue->copy_queue.count) return TRUE;
1465
1466 if (flags & SPQ_SCAN_USE_CALLBACK) notification = SPFILENOTIFY_QUEUESCAN;
1467 else if (flags & SPQ_SCAN_USE_CALLBACKEX) notification = SPFILENOTIFY_QUEUESCAN_EX;
1468
1469 if (flags & ~(SPQ_SCAN_USE_CALLBACK | SPQ_SCAN_USE_CALLBACKEX))
1470 {
1471 FIXME("flags %x not fully implemented\n", flags);
1472 }
1473
1474 paths.Source = paths.Target = NULL;
1475
1476 for (op = queue->copy_queue.head; op; op = op->next)
1477 {
1478 build_filepathsW( op, &paths );
1479 switch (notification)
1480 {
1481 case SPFILENOTIFY_QUEUESCAN:
1482 /* FIXME: handle delay flag */
1483 if (handler( context, notification, (UINT_PTR)paths.Target, 0 )) goto done;
1484 break;
1485 case SPFILENOTIFY_QUEUESCAN_EX:
1486 if (handler( context, notification, (UINT_PTR)&paths, 0 )) goto done;
1487 break;
1488 default:
1489 ret = TRUE; goto done;
1490 }
1491 }
1492
1493 *result = TRUE;
1494
1495 done:
1496 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1497 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1498 return ret;
1499 }
1500
1501
1502 /***********************************************************************
1503 * SetupGetFileQueueCount (SETUPAPI.@)
1504 */
1505 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result )
1506 {
1507 struct file_queue *queue = handle;
1508
1509 switch(op)
1510 {
1511 case FILEOP_COPY:
1512 *result = queue->copy_queue.count;
1513 return TRUE;
1514 case FILEOP_RENAME:
1515 *result = queue->rename_queue.count;
1516 return TRUE;
1517 case FILEOP_DELETE:
1518 *result = queue->delete_queue.count;
1519 return TRUE;
1520 }
1521 return FALSE;
1522 }
1523
1524
1525 /***********************************************************************
1526 * SetupGetFileQueueFlags (SETUPAPI.@)
1527 */
1528 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags )
1529 {
1530 struct file_queue *queue = handle;
1531 *flags = queue->flags;
1532 return TRUE;
1533 }
1534
1535
1536 /***********************************************************************
1537 * SetupSetFileQueueFlags (SETUPAPI.@)
1538 */
1539 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags )
1540 {
1541 struct file_queue *queue = handle;
1542 queue->flags = (queue->flags & ~mask) | flags;
1543 return TRUE;
1544 }
1545
1546
1547 /***********************************************************************
1548 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1549 */
1550 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile)
1551 {
1552 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile));
1553 return FALSE;
1554 }
1555
1556
1557 /***********************************************************************
1558 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1559 */
1560 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile)
1561 {
1562 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile));
1563 return FALSE;
1564 }
1565
1566
1567 /***********************************************************************
1568 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1569 */
1570 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner )
1571 {
1572 return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL );
1573 }
1574
1575
1576 /***********************************************************************
1577 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1578 */
1579 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg,
1580 DWORD reserved1, PVOID reserved2 )
1581 {
1582 struct default_callback_context *context;
1583
1584 if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) )))
1585 {
1586 context->owner = owner;
1587 context->progress = progress;
1588 context->message = msg;
1589 }
1590 return context;
1591 }
1592
1593
1594 /***********************************************************************
1595 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1596 */
1597 void WINAPI SetupTermDefaultQueueCallback( PVOID context )
1598 {
1599 HeapFree( GetProcessHeap(), 0, context );
1600 }
1601
1602
1603 /***********************************************************************
1604 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1605 */
1606 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification,
1607 UINT_PTR param1, UINT_PTR param2 )
1608 {
1609 FILEPATHS_A *paths = (FILEPATHS_A *)param1;
1610 struct default_callback_context *ctx = (struct default_callback_context *)context;
1611
1612 switch(notification)
1613 {
1614 case SPFILENOTIFY_STARTQUEUE:
1615 TRACE( "start queue\n" );
1616 return TRUE;
1617 case SPFILENOTIFY_ENDQUEUE:
1618 TRACE( "end queue\n" );
1619 return 0;
1620 case SPFILENOTIFY_STARTSUBQUEUE:
1621 TRACE( "start subqueue %ld count %ld\n", param1, param2 );
1622 return TRUE;
1623 case SPFILENOTIFY_ENDSUBQUEUE:
1624 TRACE( "end subqueue %ld\n", param1 );
1625 return 0;
1626 case SPFILENOTIFY_STARTDELETE:
1627 TRACE( "start delete %s\n", debugstr_a(paths->Target) );
1628 return FILEOP_DOIT;
1629 case SPFILENOTIFY_ENDDELETE:
1630 TRACE( "end delete %s\n", debugstr_a(paths->Target) );
1631 return 0;
1632 case SPFILENOTIFY_DELETEERROR:
1633 /*Windows Ignores attempts to delete files / folders which do not exist*/
1634 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1635 SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1636 return FILEOP_SKIP;
1637 case SPFILENOTIFY_STARTRENAME:
1638 TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1639 return FILEOP_DOIT;
1640 case SPFILENOTIFY_ENDRENAME:
1641 TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1642 return 0;
1643 case SPFILENOTIFY_RENAMEERROR:
1644 SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1645 return FILEOP_SKIP;
1646 case SPFILENOTIFY_STARTCOPY:
1647 TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1648 return FILEOP_DOIT;
1649 case SPFILENOTIFY_ENDCOPY:
1650 TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1651 return 0;
1652 case SPFILENOTIFY_COPYERROR:
1653 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1654 debugstr_a(paths->Source), debugstr_a(paths->Target) );
1655 return FILEOP_SKIP;
1656 case SPFILENOTIFY_NEEDMEDIA:
1657 TRACE( "need media\n" );
1658 return FILEOP_SKIP;
1659 default:
1660 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
1661 break;
1662 }
1663 return 0;
1664 }
1665
1666
1667 /***********************************************************************
1668 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1669 */
1670 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification,
1671 UINT_PTR param1, UINT_PTR param2 )
1672 {
1673 FILEPATHS_W *paths = (FILEPATHS_W *)param1;
1674 struct default_callback_context *ctx = (struct default_callback_context *)context;
1675
1676 switch(notification)
1677 {
1678 case SPFILENOTIFY_STARTQUEUE:
1679 TRACE( "start queue\n" );
1680 return TRUE;
1681 case SPFILENOTIFY_ENDQUEUE:
1682 TRACE( "end queue\n" );
1683 return 0;
1684 case SPFILENOTIFY_STARTSUBQUEUE:
1685 TRACE( "start subqueue %ld count %ld\n", param1, param2 );
1686 return TRUE;
1687 case SPFILENOTIFY_ENDSUBQUEUE:
1688 TRACE( "end subqueue %ld\n", param1 );
1689 return 0;
1690 case SPFILENOTIFY_STARTDELETE:
1691 TRACE( "start delete %s\n", debugstr_w(paths->Target) );
1692 return FILEOP_DOIT;
1693 case SPFILENOTIFY_ENDDELETE:
1694 TRACE( "end delete %s\n", debugstr_w(paths->Target) );
1695 return 0;
1696 case SPFILENOTIFY_DELETEERROR:
1697 /*Windows Ignores attempts to delete files / folders which do not exist*/
1698 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1699 SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1700 return FILEOP_SKIP;
1701 case SPFILENOTIFY_STARTRENAME:
1702 SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1703 return FILEOP_DOIT;
1704 case SPFILENOTIFY_ENDRENAME:
1705 TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1706 return 0;
1707 case SPFILENOTIFY_RENAMEERROR:
1708 ERR( "rename error %d %s -> %s\n", paths->Win32Error,
1709 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1710 return FILEOP_SKIP;
1711 case SPFILENOTIFY_STARTCOPY:
1712 TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1713 return FILEOP_DOIT;
1714 case SPFILENOTIFY_ENDCOPY:
1715 TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1716 return 0;
1717 case SPFILENOTIFY_COPYERROR:
1718 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1719 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1720 return FILEOP_SKIP;
1721 case SPFILENOTIFY_NEEDMEDIA:
1722 TRACE( "need media\n" );
1723 return FILEOP_SKIP;
1724 default:
1725 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
1726 break;
1727 }
1728 return 0;
1729 }
1730
1731 /***********************************************************************
1732 * SetupDeleteErrorA (SETUPAPI.@)
1733 */
1734
1735 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file,
1736 UINT w32error, DWORD style)
1737 {
1738 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1739 w32error, debugstr_a(file) );
1740 return DPROMPT_SKIPFILE;
1741 }
1742
1743 /***********************************************************************
1744 * SetupDeleteErrorW (SETUPAPI.@)
1745 */
1746
1747 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file,
1748 UINT w32error, DWORD style)
1749 {
1750 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1751 w32error, debugstr_w(file) );
1752 return DPROMPT_SKIPFILE;
1753 }
1754
1755 /***********************************************************************
1756 * SetupRenameErrorA (SETUPAPI.@)
1757 */
1758
1759 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source,
1760 PCSTR target, UINT w32error, DWORD style)
1761 {
1762 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1763 w32error, debugstr_a(source), debugstr_a(target));
1764 return DPROMPT_SKIPFILE;
1765 }
1766
1767 /***********************************************************************
1768 * SetupRenameErrorW (SETUPAPI.@)
1769 */
1770
1771 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source,
1772 PCWSTR target, UINT w32error, DWORD style)
1773 {
1774 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1775 w32error, debugstr_w(source), debugstr_w(target));
1776 return DPROMPT_SKIPFILE;
1777 }
1778
1779
1780 /***********************************************************************
1781 * SetupCopyErrorA (SETUPAPI.@)
1782 */
1783
1784 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname,
1785 PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath,
1786 UINT w32error, DWORD style, PSTR pathbuffer,
1787 DWORD buffersize, PDWORD requiredsize)
1788 {
1789 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1790 w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath));
1791 return DPROMPT_SKIPFILE;
1792 }
1793
1794 /***********************************************************************
1795 * SetupCopyErrorW (SETUPAPI.@)
1796 */
1797
1798 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname,
1799 PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath,
1800 UINT w32error, DWORD style, PWSTR pathbuffer,
1801 DWORD buffersize, PDWORD requiredsize)
1802 {
1803 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1804 w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath));
1805 return DPROMPT_SKIPFILE;
1806 }
1807
1808 /***********************************************************************
1809 * pSetupGetQueueFlags (SETUPAPI.@)
1810 */
1811 DWORD WINAPI pSetupGetQueueFlags( HSPFILEQ handle )
1812 {
1813 struct file_queue *queue = handle;
1814 return queue->flags;
1815 }
1816
1817 /***********************************************************************
1818 * pSetupSetQueueFlags (SETUPAPI.@)
1819 */
1820 BOOL WINAPI pSetupSetQueueFlags( HSPFILEQ handle, DWORD flags )
1821 {
1822 struct file_queue *queue = handle;
1823 queue->flags = flags;
1824 return TRUE;
1825 }