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
strdupW(const WCHAR * str)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
strdupWtoA(const WCHAR * str)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 */
queue_file_op(struct file_op_queue * queue,struct file_op * op)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 */
free_file_op_queue(struct file_op_queue * 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 */
concat_W(WCHAR * buffer,const WCHAR * src1,const WCHAR * src2,const WCHAR * src3)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 */
build_filepathsW(const struct file_op * op,FILEPATHS_W * paths)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 */
QUEUE_callback_WtoA(void * context,UINT notification,UINT_PTR param1,UINT_PTR param2)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 */
get_src_file_info(HINF hinf,struct file_op * op)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 */
get_destination_dir(HINF hinf,const WCHAR * section)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 struct extract_cab_ctx
365 {
366 const WCHAR *src;
367 const WCHAR *dst;
368 };
369
extract_cab_cb(void * arg,UINT message,UINT_PTR param1,UINT_PTR param2)370 static UINT WINAPI extract_cab_cb( void *arg, UINT message, UINT_PTR param1, UINT_PTR param2 )
371 {
372 struct extract_cab_ctx *ctx = arg;
373
374 switch (message)
375 {
376 case SPFILENOTIFY_FILEINCABINET:
377 {
378 FILE_IN_CABINET_INFO_W *info = (FILE_IN_CABINET_INFO_W *)param1;
379 const WCHAR *filename;
380
381 if ((filename = strrchrW( info->NameInCabinet, '\\' )))
382 filename++;
383 else
384 filename = info->NameInCabinet;
385
386 if (lstrcmpiW( filename, ctx->src ))
387 return FILEOP_SKIP;
388
389 strcpyW( info->FullTargetName, ctx->dst );
390 return FILEOP_DOIT;
391 }
392 case SPFILENOTIFY_FILEEXTRACTED:
393 {
394 const FILEPATHS_W *paths = (const FILEPATHS_W *)param1;
395 return paths->Win32Error;
396 }
397 case SPFILENOTIFY_NEEDNEWCABINET:
398 {
399 const CABINET_INFO_W *info = (const CABINET_INFO_W *)param1;
400 strcpyW( (WCHAR *)param2, info->CabinetPath );
401 return ERROR_SUCCESS;
402 }
403 case SPFILENOTIFY_CABINETINFO:
404 return 0;
405 default:
406 FIXME("Unexpected message %#x.\n", message);
407 return 0;
408 }
409 }
410
411 /***********************************************************************
412 * extract_cabinet_file
413 *
414 * Extract a file from a .cab file.
415 */
extract_cabinet_file(const WCHAR * cabinet,const WCHAR * root,const WCHAR * src,const WCHAR * dst)416 static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root,
417 const WCHAR *src, const WCHAR *dst )
418 {
419 #ifndef __REACTOS__
420 static const WCHAR extW[] = {'.','c','a','b',0};
421 #endif
422 static const WCHAR backslashW[] = {'\\',0};
423 WCHAR path[MAX_PATH];
424 struct extract_cab_ctx ctx = {src, dst};
425
426 #ifdef __REACTOS__
427 TRACE("extract_cabinet_file(cab = '%s' ; root = '%s' ; src = '%s' ; dst = '%s')\n",
428 debugstr_w(cabinet), debugstr_w(root), debugstr_w(src), debugstr_w(dst));
429 #else
430 int len = strlenW( cabinet );
431 /* make sure the cabinet file has a .cab extension */
432 if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE;
433 #endif
434 strcpyW(path, root);
435 strcatW(path, backslashW);
436 strcatW(path, cabinet);
437
438 return SetupIterateCabinetW( path, 0, extract_cab_cb, &ctx );
439 }
440
441
442 /***********************************************************************
443 * SetupOpenFileQueue (SETUPAPI.@)
444 */
SetupOpenFileQueue(void)445 HSPFILEQ WINAPI SetupOpenFileQueue(void)
446 {
447 struct file_queue *queue;
448
449 if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue))))
450 return INVALID_HANDLE_VALUE;
451 return queue;
452 }
453
454
455 /***********************************************************************
456 * SetupCloseFileQueue (SETUPAPI.@)
457 */
SetupCloseFileQueue(HSPFILEQ handle)458 BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle )
459 {
460 struct file_queue *queue = handle;
461
462 free_file_op_queue( &queue->copy_queue );
463 free_file_op_queue( &queue->rename_queue );
464 free_file_op_queue( &queue->delete_queue );
465 HeapFree( GetProcessHeap(), 0, queue );
466 return TRUE;
467 }
468
469
470 /***********************************************************************
471 * SetupQueueCopyIndirectA (SETUPAPI.@)
472 */
SetupQueueCopyIndirectA(PSP_FILE_COPY_PARAMS_A params)473 BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params )
474 {
475 struct file_queue *queue = params->QueueHandle;
476 struct file_op *op;
477
478 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
479 op->style = params->CopyStyle;
480 op->src_root = strdupAtoW( params->SourceRootPath );
481 op->src_path = strdupAtoW( params->SourcePath );
482 op->src_file = strdupAtoW( params->SourceFilename );
483 op->src_descr = strdupAtoW( params->SourceDescription );
484 op->src_tag = strdupAtoW( params->SourceTagfile );
485 op->dst_path = strdupAtoW( params->TargetDirectory );
486 op->dst_file = strdupAtoW( params->TargetFilename );
487 op->dst_sd = NULL;
488
489 /* some defaults */
490 if (!op->src_file) op->src_file = op->dst_file;
491 if (params->LayoutInf)
492 {
493 get_src_file_info( params->LayoutInf, op );
494 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
495 }
496
497 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
498 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
499 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
500 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
501
502 queue_file_op( &queue->copy_queue, op );
503 return TRUE;
504 }
505
506
507 /***********************************************************************
508 * SetupQueueCopyIndirectW (SETUPAPI.@)
509 */
SetupQueueCopyIndirectW(PSP_FILE_COPY_PARAMS_W params)510 BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params )
511 {
512 struct file_queue *queue = params->QueueHandle;
513 struct file_op *op;
514
515 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
516 op->style = params->CopyStyle;
517 op->src_root = strdupW( params->SourceRootPath );
518 op->src_path = strdupW( params->SourcePath );
519 op->src_file = strdupW( params->SourceFilename );
520 op->src_descr = strdupW( params->SourceDescription );
521 op->src_tag = strdupW( params->SourceTagfile );
522 op->dst_path = strdupW( params->TargetDirectory );
523 op->dst_file = strdupW( params->TargetFilename );
524 op->dst_sd = NULL;
525 if (params->SecurityDescriptor)
526 ConvertStringSecurityDescriptorToSecurityDescriptorW( params->SecurityDescriptor, SDDL_REVISION_1, &op->dst_sd, NULL );
527
528 /* some defaults */
529 if (!op->src_file) op->src_file = op->dst_file;
530 if (params->LayoutInf)
531 {
532 get_src_file_info( params->LayoutInf, op );
533 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
534 }
535
536 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
537 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
538 debugstr_w(op->dst_path), debugstr_w(op->dst_file),
539 debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
540
541 queue_file_op( &queue->copy_queue, op );
542 return TRUE;
543 }
544
545
546 /***********************************************************************
547 * SetupQueueCopyA (SETUPAPI.@)
548 */
SetupQueueCopyA(HSPFILEQ queue,PCSTR src_root,PCSTR src_path,PCSTR src_file,PCSTR src_descr,PCSTR src_tag,PCSTR dst_dir,PCSTR dst_file,DWORD style)549 BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file,
550 PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file,
551 DWORD style )
552 {
553 SP_FILE_COPY_PARAMS_A params;
554
555 params.cbSize = sizeof(params);
556 params.QueueHandle = queue;
557 params.SourceRootPath = src_root;
558 params.SourcePath = src_path;
559 params.SourceFilename = src_file;
560 params.SourceDescription = src_descr;
561 params.SourceTagfile = src_tag;
562 params.TargetDirectory = dst_dir;
563 params.TargetFilename = dst_file;
564 params.CopyStyle = style;
565 params.LayoutInf = 0;
566 params.SecurityDescriptor = NULL;
567 return SetupQueueCopyIndirectA( ¶ms );
568 }
569
570
571 /***********************************************************************
572 * SetupQueueCopyW (SETUPAPI.@)
573 */
SetupQueueCopyW(HSPFILEQ queue,PCWSTR src_root,PCWSTR src_path,PCWSTR src_file,PCWSTR src_descr,PCWSTR src_tag,PCWSTR dst_dir,PCWSTR dst_file,DWORD style)574 BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file,
575 PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file,
576 DWORD style )
577 {
578 SP_FILE_COPY_PARAMS_W params;
579
580 params.cbSize = sizeof(params);
581 params.QueueHandle = queue;
582 params.SourceRootPath = src_root;
583 params.SourcePath = src_path;
584 params.SourceFilename = src_file;
585 params.SourceDescription = src_descr;
586 params.SourceTagfile = src_tag;
587 params.TargetDirectory = dst_dir;
588 params.TargetFilename = dst_file;
589 params.CopyStyle = style;
590 params.LayoutInf = 0;
591 params.SecurityDescriptor = NULL;
592 return SetupQueueCopyIndirectW( ¶ms );
593 }
594
595
596 /***********************************************************************
597 * SetupQueueDefaultCopyA (SETUPAPI.@)
598 */
SetupQueueDefaultCopyA(HSPFILEQ queue,HINF hinf,PCSTR src_root,PCSTR src_file,PCSTR dst_file,DWORD style)599 BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file,
600 PCSTR dst_file, DWORD style )
601 {
602 SP_FILE_COPY_PARAMS_A params;
603
604 params.cbSize = sizeof(params);
605 params.QueueHandle = queue;
606 params.SourceRootPath = src_root;
607 params.SourcePath = NULL;
608 params.SourceFilename = src_file;
609 params.SourceDescription = NULL;
610 params.SourceTagfile = NULL;
611 params.TargetDirectory = NULL;
612 params.TargetFilename = dst_file;
613 params.CopyStyle = style;
614 params.LayoutInf = hinf;
615 params.SecurityDescriptor = NULL;
616 return SetupQueueCopyIndirectA( ¶ms );
617 }
618
619
620 /***********************************************************************
621 * SetupQueueDefaultCopyW (SETUPAPI.@)
622 */
SetupQueueDefaultCopyW(HSPFILEQ queue,HINF hinf,PCWSTR src_root,PCWSTR src_file,PCWSTR dst_file,DWORD style)623 BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file,
624 PCWSTR dst_file, DWORD style )
625 {
626 SP_FILE_COPY_PARAMS_W params;
627
628 params.cbSize = sizeof(params);
629 params.QueueHandle = queue;
630 params.SourceRootPath = src_root;
631 params.SourcePath = NULL;
632 params.SourceFilename = src_file;
633 params.SourceDescription = NULL;
634 params.SourceTagfile = NULL;
635 params.TargetDirectory = NULL;
636 params.TargetFilename = dst_file;
637 params.CopyStyle = style;
638 params.LayoutInf = hinf;
639 params.SecurityDescriptor = NULL;
640 return SetupQueueCopyIndirectW( ¶ms );
641 }
642
643
644 /***********************************************************************
645 * SetupQueueDeleteA (SETUPAPI.@)
646 */
SetupQueueDeleteA(HSPFILEQ handle,PCSTR part1,PCSTR part2)647 BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 )
648 {
649 struct file_queue *queue = handle;
650 struct file_op *op;
651
652 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
653 op->style = 0;
654 op->src_root = NULL;
655 op->src_path = NULL;
656 op->src_file = NULL;
657 op->src_descr = NULL;
658 op->src_tag = NULL;
659 op->dst_path = strdupAtoW( part1 );
660 op->dst_file = strdupAtoW( part2 );
661 op->dst_sd = NULL;
662 queue_file_op( &queue->delete_queue, op );
663 return TRUE;
664 }
665
666
667 /***********************************************************************
668 * SetupQueueDeleteW (SETUPAPI.@)
669 */
SetupQueueDeleteW(HSPFILEQ handle,PCWSTR part1,PCWSTR part2)670 BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 )
671 {
672 struct file_queue *queue = handle;
673 struct file_op *op;
674
675 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
676 op->style = 0;
677 op->src_root = NULL;
678 op->src_path = NULL;
679 op->src_file = NULL;
680 op->src_descr = NULL;
681 op->src_tag = NULL;
682 op->dst_path = strdupW( part1 );
683 op->dst_file = strdupW( part2 );
684 op->dst_sd = NULL;
685 queue_file_op( &queue->delete_queue, op );
686 return TRUE;
687 }
688
689
690 /***********************************************************************
691 * SetupQueueRenameA (SETUPAPI.@)
692 */
SetupQueueRenameA(HSPFILEQ handle,PCSTR SourcePath,PCSTR SourceFilename,PCSTR TargetPath,PCSTR TargetFilename)693 BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename,
694 PCSTR TargetPath, PCSTR TargetFilename )
695 {
696 struct file_queue *queue = handle;
697 struct file_op *op;
698
699 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
700 op->style = 0;
701 op->src_root = NULL;
702 op->src_path = strdupAtoW( SourcePath );
703 op->src_file = strdupAtoW( SourceFilename );
704 op->src_descr = NULL;
705 op->src_tag = NULL;
706 op->dst_path = strdupAtoW( TargetPath );
707 op->dst_file = strdupAtoW( TargetFilename );
708 op->dst_sd = NULL;
709 queue_file_op( &queue->rename_queue, op );
710 return TRUE;
711 }
712
713
714 /***********************************************************************
715 * SetupQueueRenameW (SETUPAPI.@)
716 */
SetupQueueRenameW(HSPFILEQ handle,PCWSTR SourcePath,PCWSTR SourceFilename,PCWSTR TargetPath,PCWSTR TargetFilename)717 BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename,
718 PCWSTR TargetPath, PCWSTR TargetFilename )
719 {
720 struct file_queue *queue = handle;
721 struct file_op *op;
722
723 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
724 op->style = 0;
725 op->src_root = NULL;
726 op->src_path = strdupW( SourcePath );
727 op->src_file = strdupW( SourceFilename );
728 op->src_descr = NULL;
729 op->src_tag = NULL;
730 op->dst_path = strdupW( TargetPath );
731 op->dst_file = strdupW( TargetFilename );
732 op->dst_sd = NULL;
733 queue_file_op( &queue->rename_queue, op );
734 return TRUE;
735 }
736
737
738 /***********************************************************************
739 * SetupQueueCopySectionA (SETUPAPI.@)
740 */
SetupQueueCopySectionA(HSPFILEQ queue,PCSTR src_root,HINF hinf,HINF hlist,PCSTR section,DWORD style)741 BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist,
742 PCSTR section, DWORD style )
743 {
744 UNICODE_STRING sectionW;
745 BOOL ret = FALSE;
746
747 if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
748 {
749 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
750 return FALSE;
751 }
752 if (!src_root)
753 ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style );
754 else
755 {
756 UNICODE_STRING srcW;
757 if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root ))
758 {
759 ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style );
760 RtlFreeUnicodeString( &srcW );
761 }
762 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
763 }
764 RtlFreeUnicodeString( §ionW );
765 return ret;
766 }
767
768
769 /***********************************************************************
770 * SetupQueueCopySectionW (SETUPAPI.@)
771 */
SetupQueueCopySectionW(HSPFILEQ queue,PCWSTR src_root,HINF hinf,HINF hlist,PCWSTR section,DWORD style)772 BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist,
773 PCWSTR section, DWORD style )
774 {
775 SP_FILE_COPY_PARAMS_W params;
776 LPWSTR security_key, security_descriptor = NULL;
777 INFCONTEXT context, security_context;
778 WCHAR dest[MAX_PATH], src[MAX_PATH];
779 INT flags;
780 DWORD required;
781 BOOL ret;
782
783 TRACE( "hinf=%p/%p section=%s root=%s\n",
784 hinf, hlist, debugstr_w(section), debugstr_w(src_root) );
785
786 /* Check for .Security section */
787 security_key = MyMalloc( (strlenW( section ) + strlenW( DotSecurity )) * sizeof(WCHAR) + sizeof(UNICODE_NULL) );
788 if (!security_key)
789 {
790 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
791 return FALSE;
792 }
793 strcpyW( security_key, section );
794 strcatW( security_key, DotSecurity );
795 ret = SetupFindFirstLineW( hinf, security_key, NULL, &security_context );
796 MyFree(security_key);
797 if (ret)
798 {
799 if (!SetupGetLineTextW( &security_context, NULL, NULL, NULL, NULL, 0, &required ))
800 return FALSE;
801 security_descriptor = MyMalloc( required * sizeof(WCHAR) );
802 if (!security_descriptor)
803 {
804 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
805 return FALSE;
806 }
807 if (!SetupGetLineTextW( &security_context, NULL, NULL, NULL, security_descriptor, required, NULL ))
808 {
809 MyFree( security_descriptor );
810 return FALSE;
811 }
812 }
813
814 params.cbSize = sizeof(params);
815 params.QueueHandle = queue;
816 params.SourceRootPath = src_root;
817 params.SourcePath = NULL;
818 params.SourceDescription = NULL;
819 params.SourceTagfile = NULL;
820 params.TargetFilename = dest;
821 params.CopyStyle = style;
822 params.LayoutInf = hinf;
823 params.SecurityDescriptor = security_descriptor;
824
825 ret = FALSE;
826 if (!hlist) hlist = hinf;
827 if (!hinf) hinf = hlist;
828 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) goto done;
829 if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) goto done;
830 do
831 {
832 if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL ))
833 goto done;
834 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0;
835 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */
836
837 params.SourceFilename = *src ? src : NULL;
838 if (!SetupQueueCopyIndirectW( ¶ms )) goto done;
839 } while (SetupFindNextLine( &context, &context ));
840 ret = TRUE;
841
842 done:
843 if (security_descriptor)
844 MyFree( security_descriptor );
845 return ret;
846 }
847
848
849 /***********************************************************************
850 * SetupQueueDeleteSectionA (SETUPAPI.@)
851 */
SetupQueueDeleteSectionA(HSPFILEQ queue,HINF hinf,HINF hlist,PCSTR section)852 BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
853 {
854 UNICODE_STRING sectionW;
855 BOOL ret = FALSE;
856
857 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
858 {
859 ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer );
860 RtlFreeUnicodeString( §ionW );
861 }
862 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
863 return ret;
864 }
865
866
867 /***********************************************************************
868 * SetupQueueDeleteSectionW (SETUPAPI.@)
869 */
SetupQueueDeleteSectionW(HSPFILEQ queue,HINF hinf,HINF hlist,PCWSTR section)870 BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
871 {
872 INFCONTEXT context;
873 WCHAR *dest_dir;
874 WCHAR buffer[MAX_PATH];
875 BOOL ret = FALSE;
876 INT flags;
877
878 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
879
880 if (!hlist) hlist = hinf;
881 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
882 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
883 do
884 {
885 if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
886 goto done;
887 if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
888 if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done;
889 } while (SetupFindNextLine( &context, &context ));
890
891 ret = TRUE;
892 done:
893 HeapFree( GetProcessHeap(), 0, dest_dir );
894 return ret;
895 }
896
897
898 /***********************************************************************
899 * SetupQueueRenameSectionA (SETUPAPI.@)
900 */
SetupQueueRenameSectionA(HSPFILEQ queue,HINF hinf,HINF hlist,PCSTR section)901 BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
902 {
903 UNICODE_STRING sectionW;
904 BOOL ret = FALSE;
905
906 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
907 {
908 ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer );
909 RtlFreeUnicodeString( §ionW );
910 }
911 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
912 return ret;
913 }
914
915
916 /***********************************************************************
917 * SetupQueueRenameSectionW (SETUPAPI.@)
918 */
SetupQueueRenameSectionW(HSPFILEQ queue,HINF hinf,HINF hlist,PCWSTR section)919 BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
920 {
921 INFCONTEXT context;
922 WCHAR *dest_dir;
923 WCHAR src[MAX_PATH], dst[MAX_PATH];
924 BOOL ret = FALSE;
925
926 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
927
928 if (!hlist) hlist = hinf;
929 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
930 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
931 do
932 {
933 if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL ))
934 goto done;
935 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL ))
936 goto done;
937 if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done;
938 } while (SetupFindNextLine( &context, &context ));
939
940 ret = TRUE;
941 done:
942 HeapFree( GetProcessHeap(), 0, dest_dir );
943 return ret;
944 }
945
946
947 /***********************************************************************
948 * SetupCommitFileQueueA (SETUPAPI.@)
949 */
SetupCommitFileQueueA(HWND owner,HSPFILEQ queue,PSP_FILE_CALLBACK_A handler,PVOID context)950 BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler,
951 PVOID context )
952 {
953 struct callback_WtoA_context ctx;
954
955 ctx.orig_context = context;
956 ctx.orig_handler = handler;
957 return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx );
958 }
959
960
961 /***********************************************************************
962 * create_full_pathW
963 *
964 * Recursively create all directories in the path.
965 */
create_full_pathW(const WCHAR * path)966 static BOOL create_full_pathW(const WCHAR *path)
967 {
968 BOOL ret = TRUE;
969 int len;
970 WCHAR *new_path;
971
972 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
973 strcpyW(new_path, path);
974
975 while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
976 new_path[len - 1] = 0;
977
978 while(!CreateDirectoryW(new_path, NULL))
979 {
980 WCHAR *slash;
981 DWORD last_error = GetLastError();
982
983 if(last_error == ERROR_ALREADY_EXISTS)
984 break;
985
986 if(last_error != ERROR_PATH_NOT_FOUND)
987 {
988 ret = FALSE;
989 break;
990 }
991
992 if(!(slash = strrchrW(new_path, '\\')))
993 {
994 ret = FALSE;
995 break;
996 }
997
998 len = slash - new_path;
999 new_path[len] = 0;
1000 if(!create_full_pathW(new_path))
1001 {
1002 ret = FALSE;
1003 break;
1004 }
1005 new_path[len] = '\\';
1006 }
1007
1008 HeapFree(GetProcessHeap(), 0, new_path);
1009 return ret;
1010 }
1011
do_file_copyW(LPCWSTR source,LPCWSTR target,DWORD style,PSP_FILE_CALLBACK_W handler,PVOID context)1012 static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style,
1013 PSP_FILE_CALLBACK_W handler, PVOID context )
1014 {
1015 BOOL rc = FALSE;
1016 BOOL docopy = TRUE;
1017 #ifdef __REACTOS__
1018 INT hSource, hTemp;
1019 OFSTRUCT OfStruct;
1020 WCHAR TempPath[MAX_PATH];
1021 WCHAR TempFile[MAX_PATH];
1022 LONG lRes;
1023 DWORD dwLastError;
1024 #endif
1025
1026 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source),debugstr_w(target),style);
1027
1028 #ifdef __REACTOS__
1029 /* Get a temp file name */
1030 if (!GetTempPathW(ARRAYSIZE(TempPath), TempPath))
1031 {
1032 ERR("GetTempPathW error\n");
1033 return FALSE;
1034 }
1035
1036 /* Try to open the source file */
1037 hSource = LZOpenFileW((LPWSTR)source, &OfStruct, OF_READ);
1038 if (hSource < 0)
1039 {
1040 TRACE("LZOpenFileW(1) error %d %s\n", (int)hSource, debugstr_w(source));
1041 return FALSE;
1042 }
1043
1044 if (!GetTempFileNameW(TempPath, L"", 0, TempFile))
1045 {
1046 dwLastError = GetLastError();
1047
1048 ERR("GetTempFileNameW(%s) error\n", debugstr_w(TempPath));
1049
1050 /* Close the source handle */
1051 LZClose(hSource);
1052
1053 /* Restore error condition triggered by GetTempFileNameW */
1054 SetLastError(dwLastError);
1055
1056 return FALSE;
1057 }
1058
1059 /* Extract the compressed file to a temp location */
1060 hTemp = LZOpenFileW(TempFile, &OfStruct, OF_CREATE);
1061 if (hTemp < 0)
1062 {
1063 dwLastError = GetLastError();
1064
1065 ERR("LZOpenFileW(2) error %d %s\n", (int)hTemp, debugstr_w(TempFile));
1066
1067 /* Close the source handle */
1068 LZClose(hSource);
1069
1070 /* Delete temp file if an error is signaled */
1071 DeleteFileW(TempFile);
1072
1073 /* Restore error condition triggered by LZOpenFileW */
1074 SetLastError(dwLastError);
1075
1076 return FALSE;
1077 }
1078
1079 lRes = LZCopy(hSource, hTemp);
1080
1081 dwLastError = GetLastError();
1082
1083 LZClose(hSource);
1084 LZClose(hTemp);
1085
1086 if (lRes < 0)
1087 {
1088 ERR("LZCopy error %d (%s, %s)\n", (int)lRes, debugstr_w(source), debugstr_w(TempFile));
1089
1090 /* Delete temp file if copy was not successful */
1091 DeleteFileW(TempFile);
1092
1093 /* Restore error condition triggered by LZCopy */
1094 SetLastError(dwLastError);
1095
1096 return FALSE;
1097 }
1098 #endif
1099
1100 /* before copy processing */
1101 if (style & SP_COPY_REPLACEONLY)
1102 {
1103 if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES)
1104 docopy = FALSE;
1105 }
1106 if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER))
1107 {
1108 DWORD VersionSizeSource=0;
1109 DWORD VersionSizeTarget=0;
1110 DWORD zero=0;
1111
1112 /*
1113 * This is sort of an interesting workaround. You see, calling
1114 * GetVersionInfoSize on a builtin dll loads that dll into memory
1115 * and we do not properly unload builtin dlls.. so we effectively
1116 * lock into memory all the targets we are replacing. This leads
1117 * to problems when we try to register the replaced dlls.
1118 *
1119 * So I will test for the existence of the files first so that
1120 * we just basically unconditionally replace the builtin versions.
1121 */
1122 if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) &&
1123 (GetFileAttributesW(TempFile) != INVALID_FILE_ATTRIBUTES))
1124 {
1125 VersionSizeSource = GetFileVersionInfoSizeW(TempFile,&zero);
1126 VersionSizeTarget = GetFileVersionInfoSizeW((LPWSTR)target,&zero);
1127 }
1128
1129 TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget,
1130 VersionSizeSource);
1131
1132 if (VersionSizeSource && VersionSizeTarget)
1133 {
1134 LPVOID VersionSource;
1135 LPVOID VersionTarget;
1136 VS_FIXEDFILEINFO *TargetInfo;
1137 VS_FIXEDFILEINFO *SourceInfo;
1138 UINT length;
1139 WCHAR SubBlock[2]={'\\',0};
1140 DWORD ret;
1141
1142 VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource);
1143 VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget);
1144
1145 ret = GetFileVersionInfoW(TempFile,0,VersionSizeSource,VersionSource);
1146 if (ret)
1147 ret = GetFileVersionInfoW((LPWSTR)target, 0, VersionSizeTarget,
1148 VersionTarget);
1149
1150 if (ret)
1151 {
1152 ret = VerQueryValueW(VersionSource, SubBlock,
1153 (LPVOID*)&SourceInfo, &length);
1154 if (ret)
1155 ret = VerQueryValueW(VersionTarget, SubBlock,
1156 (LPVOID*)&TargetInfo, &length);
1157
1158 if (ret)
1159 {
1160 FILEPATHS_W filepaths;
1161
1162 TRACE("Versions: Source %i.%i target %i.%i\n",
1163 SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS,
1164 TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS);
1165
1166 /* used in case of notification */
1167 filepaths.Target = target;
1168 filepaths.Source = source;
1169 filepaths.Win32Error = 0;
1170 filepaths.Flags = 0;
1171
1172 if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS)
1173 {
1174 if (handler)
1175 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1176 else
1177 docopy = FALSE;
1178 }
1179 else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS)
1180 && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS))
1181 {
1182 if (handler)
1183 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1184 else
1185 docopy = FALSE;
1186 }
1187 else if ((style & SP_COPY_NEWER_ONLY) &&
1188 (TargetInfo->dwFileVersionMS ==
1189 SourceInfo->dwFileVersionMS)
1190 &&(TargetInfo->dwFileVersionLS ==
1191 SourceInfo->dwFileVersionLS))
1192 {
1193 if (handler)
1194 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
1195 else
1196 docopy = FALSE;
1197 }
1198 }
1199 }
1200 HeapFree(GetProcessHeap(),0,VersionSource);
1201 HeapFree(GetProcessHeap(),0,VersionTarget);
1202 }
1203 }
1204 if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE))
1205 {
1206 if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES)
1207 {
1208 FIXME("Notify user target file exists\n");
1209 docopy = FALSE;
1210 }
1211 }
1212 if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE |
1213 SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP))
1214 {
1215 ERR("Unsupported style(s) 0x%x\n",style);
1216 }
1217
1218 if (docopy)
1219 {
1220 rc = MoveFileExW(TempFile,target,MOVEFILE_REPLACE_EXISTING);
1221 TRACE("Did copy... rc was %i\n",rc);
1222 }
1223
1224 /* after copy processing */
1225 if (style & SP_COPY_DELETESOURCE)
1226 {
1227 if (rc)
1228 DeleteFileW(source);
1229 }
1230
1231 return rc;
1232 }
1233
1234 /***********************************************************************
1235 * SetupInstallFileA (SETUPAPI.@)
1236 */
SetupInstallFileA(HINF hinf,PINFCONTEXT inf_context,PCSTR source,PCSTR root,PCSTR dest,DWORD style,PSP_FILE_CALLBACK_A handler,PVOID context)1237 BOOL WINAPI SetupInstallFileA( HINF hinf, PINFCONTEXT inf_context, PCSTR source, PCSTR root,
1238 PCSTR dest, DWORD style, PSP_FILE_CALLBACK_A handler, PVOID context )
1239 {
1240 BOOL ret = FALSE;
1241 struct callback_WtoA_context ctx;
1242 UNICODE_STRING sourceW, rootW, destW;
1243
1244 TRACE("%p %p %s %s %s %x %p %p\n", hinf, inf_context, debugstr_a(source), debugstr_a(root),
1245 debugstr_a(dest), style, handler, context);
1246
1247 sourceW.Buffer = rootW.Buffer = destW.Buffer = NULL;
1248 if (source && !RtlCreateUnicodeStringFromAsciiz( &sourceW, source ))
1249 {
1250 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1251 return FALSE;
1252 }
1253 if (root && !RtlCreateUnicodeStringFromAsciiz( &rootW, root ))
1254 {
1255 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1256 goto exit;
1257 }
1258 if (dest && !RtlCreateUnicodeStringFromAsciiz( &destW, dest ))
1259 {
1260 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1261 goto exit;
1262 }
1263
1264 ctx.orig_context = context;
1265 ctx.orig_handler = handler;
1266
1267 ret = SetupInstallFileW( hinf, inf_context, sourceW.Buffer, rootW.Buffer, destW.Buffer, style, QUEUE_callback_WtoA, &ctx );
1268
1269 exit:
1270 RtlFreeUnicodeString( &sourceW );
1271 RtlFreeUnicodeString( &rootW );
1272 RtlFreeUnicodeString( &destW );
1273 return ret;
1274 }
1275
1276 /***********************************************************************
1277 * SetupInstallFileW (SETUPAPI.@)
1278 */
SetupInstallFileW(HINF hinf,PINFCONTEXT inf_context,PCWSTR source,PCWSTR root,PCWSTR dest,DWORD style,PSP_FILE_CALLBACK_W handler,PVOID context)1279 BOOL WINAPI SetupInstallFileW( HINF hinf, PINFCONTEXT inf_context, PCWSTR source, PCWSTR root,
1280 PCWSTR dest, DWORD style, PSP_FILE_CALLBACK_W handler, PVOID context )
1281 {
1282 static const WCHAR CopyFiles[] = {'C','o','p','y','F','i','l','e','s',0};
1283
1284 BOOL ret, absolute = (root && *root && !(style & SP_COPY_SOURCE_ABSOLUTE));
1285 WCHAR *buffer, *p, *inf_source = NULL;
1286 unsigned int len;
1287
1288 TRACE("%p %p %s %s %s %x %p %p\n", hinf, inf_context, debugstr_w(source), debugstr_w(root),
1289 debugstr_w(dest), style, handler, context);
1290
1291 if (hinf)
1292 {
1293 INFCONTEXT ctx;
1294
1295 if (!inf_context)
1296 {
1297 inf_context = &ctx;
1298 if (!SetupFindFirstLineW( hinf, CopyFiles, NULL, inf_context )) return FALSE;
1299 }
1300 if (!SetupGetStringFieldW( inf_context, 1, NULL, 0, (PDWORD) &len )) return FALSE;
1301 if (!(inf_source = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1302 {
1303 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1304 return FALSE;
1305 }
1306 if (!SetupGetStringFieldW( inf_context, 1, inf_source, len, NULL ))
1307 {
1308 HeapFree( GetProcessHeap(), 0, inf_source );
1309 return FALSE;
1310 }
1311 source = inf_source;
1312 }
1313 else if (!source)
1314 {
1315 SetLastError( ERROR_INVALID_PARAMETER );
1316 return FALSE;
1317 }
1318
1319 len = strlenW( source ) + 1;
1320 if (absolute) len += strlenW( root ) + 1;
1321
1322 if (!(p = buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1323 {
1324 HeapFree( GetProcessHeap(), 0, inf_source );
1325 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1326 return FALSE;
1327 }
1328
1329 if (absolute)
1330 {
1331 strcpyW( buffer, root );
1332 p += strlenW( buffer );
1333 if (p[-1] != '\\') *p++ = '\\';
1334 }
1335 while (*source == '\\') source++;
1336 strcpyW( p, source );
1337
1338 ret = do_file_copyW( buffer, dest, style, handler, context );
1339
1340 HeapFree( GetProcessHeap(), 0, inf_source );
1341 HeapFree( GetProcessHeap(), 0, buffer );
1342 return ret;
1343 }
1344
1345 /***********************************************************************
1346 * SetupCommitFileQueueW (SETUPAPI.@)
1347 */
SetupCommitFileQueueW(HWND owner,HSPFILEQ handle,PSP_FILE_CALLBACK_W handler,PVOID context)1348 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler,
1349 PVOID context )
1350 {
1351 struct file_queue *queue = handle;
1352 struct file_op *op;
1353 BOOL result = FALSE;
1354 FILEPATHS_W paths;
1355 UINT op_result;
1356
1357 paths.Source = paths.Target = NULL;
1358
1359 if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count)
1360 return TRUE; /* nothing to do */
1361
1362 if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE;
1363
1364 /* perform deletes */
1365
1366 if (queue->delete_queue.count)
1367 {
1368 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE,
1369 queue->delete_queue.count ))) goto done;
1370 for (op = queue->delete_queue.head; op; op = op->next)
1371 {
1372 build_filepathsW( op, &paths );
1373 op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE);
1374 if (op_result == FILEOP_ABORT) goto done;
1375 while (op_result == FILEOP_DOIT)
1376 {
1377 TRACE( "deleting file %s\n", debugstr_w(paths.Target) );
1378 if (DeleteFileW( paths.Target )) break; /* success */
1379 paths.Win32Error = GetLastError();
1380 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 );
1381 if (op_result == FILEOP_ABORT) goto done;
1382 }
1383 handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 );
1384 }
1385 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 );
1386 }
1387
1388 /* perform renames */
1389
1390 if (queue->rename_queue.count)
1391 {
1392 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME,
1393 queue->rename_queue.count ))) goto done;
1394 for (op = queue->rename_queue.head; op; op = op->next)
1395 {
1396 build_filepathsW( op, &paths );
1397 op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME);
1398 if (op_result == FILEOP_ABORT) goto done;
1399 while (op_result == FILEOP_DOIT)
1400 {
1401 TRACE( "renaming file %s -> %s\n",
1402 debugstr_w(paths.Source), debugstr_w(paths.Target) );
1403 if (MoveFileW( paths.Source, paths.Target )) break; /* success */
1404 paths.Win32Error = GetLastError();
1405 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 );
1406 if (op_result == FILEOP_ABORT) goto done;
1407 }
1408 handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 );
1409 }
1410 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 );
1411 }
1412
1413 /* perform copies */
1414
1415 if (queue->copy_queue.count)
1416 {
1417 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY,
1418 queue->copy_queue.count ))) goto done;
1419 for (op = queue->copy_queue.head; op; op = op->next)
1420 {
1421 WCHAR newpath[MAX_PATH];
1422
1423 build_filepathsW( op, &paths );
1424 op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
1425 if (op_result == FILEOP_ABORT) goto done;
1426 if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT;
1427 while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
1428 {
1429 TRACE( "copying file %s -> %s\n",
1430 debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ),
1431 debugstr_w(paths.Target) );
1432 if (op->dst_path)
1433 {
1434 if (!create_full_pathW( op->dst_path ))
1435 {
1436 paths.Win32Error = GetLastError();
1437 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1438 (UINT_PTR)&paths, (UINT_PTR)newpath );
1439 if (op_result == FILEOP_ABORT) goto done;
1440 }
1441 }
1442 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
1443 paths.Target, op->style, handler, context )) break; /* success */
1444 /* try to extract it from the cabinet file */
1445 if (op->src_tag)
1446 {
1447 if (extract_cabinet_file( op->src_tag, op->src_root,
1448 op->src_file, paths.Target )) break;
1449 }
1450 paths.Win32Error = GetLastError();
1451 op_result = handler( context, SPFILENOTIFY_COPYERROR,
1452 (UINT_PTR)&paths, (UINT_PTR)newpath );
1453 if (op_result == FILEOP_ABORT) goto done;
1454 }
1455 if (op->dst_sd)
1456 {
1457 PSID psidOwner = NULL, psidGroup = NULL;
1458 PACL pDacl = NULL, pSacl = NULL;
1459 SECURITY_INFORMATION security_info = 0;
1460 BOOL present, dummy;
1461
1462 if (GetSecurityDescriptorOwner( op->dst_sd, &psidOwner, &dummy ) && psidOwner)
1463 security_info |= OWNER_SECURITY_INFORMATION;
1464 if (GetSecurityDescriptorGroup( op->dst_sd, &psidGroup, &dummy ) && psidGroup)
1465 security_info |= GROUP_SECURITY_INFORMATION;
1466 if (GetSecurityDescriptorDacl( op->dst_sd, &present, &pDacl, &dummy ))
1467 security_info |= DACL_SECURITY_INFORMATION;
1468 if (GetSecurityDescriptorSacl( op->dst_sd, &present, &pSacl, &dummy ))
1469 security_info |= DACL_SECURITY_INFORMATION;
1470 SetNamedSecurityInfoW( (LPWSTR)paths.Target, SE_FILE_OBJECT, security_info,
1471 psidOwner, psidGroup, pDacl, pSacl );
1472 /* Yes, ignore the return code... */
1473 }
1474 handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
1475 }
1476 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 );
1477 }
1478
1479
1480 result = TRUE;
1481
1482 done:
1483 handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 );
1484 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1485 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1486 return result;
1487 }
1488
1489
1490 /***********************************************************************
1491 * SetupScanFileQueueA (SETUPAPI.@)
1492 */
SetupScanFileQueueA(HSPFILEQ handle,DWORD flags,HWND window,PSP_FILE_CALLBACK_A handler,PVOID context,PDWORD result)1493 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ handle, DWORD flags, HWND window,
1494 PSP_FILE_CALLBACK_A handler, PVOID context, PDWORD result )
1495 {
1496 struct callback_WtoA_context ctx;
1497
1498 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
1499
1500 ctx.orig_context = context;
1501 ctx.orig_handler = handler;
1502
1503 return SetupScanFileQueueW( handle, flags, window, QUEUE_callback_WtoA, &ctx, result );
1504 }
1505
1506
1507 /***********************************************************************
1508 * SetupScanFileQueueW (SETUPAPI.@)
1509 */
SetupScanFileQueueW(HSPFILEQ handle,DWORD flags,HWND window,PSP_FILE_CALLBACK_W handler,PVOID context,PDWORD result)1510 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ handle, DWORD flags, HWND window,
1511 PSP_FILE_CALLBACK_W handler, PVOID context, PDWORD result )
1512 {
1513 struct file_queue *queue = handle;
1514 struct file_op *op;
1515 FILEPATHS_W paths;
1516 UINT notification = 0;
1517 BOOL ret = FALSE;
1518
1519 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
1520
1521 *result = FALSE;
1522
1523 if (!queue->copy_queue.count) return TRUE;
1524
1525 if (flags & SPQ_SCAN_USE_CALLBACK) notification = SPFILENOTIFY_QUEUESCAN;
1526 else if (flags & SPQ_SCAN_USE_CALLBACKEX) notification = SPFILENOTIFY_QUEUESCAN_EX;
1527
1528 if (flags & ~(SPQ_SCAN_USE_CALLBACK | SPQ_SCAN_USE_CALLBACKEX))
1529 {
1530 FIXME("flags %x not fully implemented\n", flags);
1531 }
1532
1533 paths.Source = paths.Target = NULL;
1534
1535 for (op = queue->copy_queue.head; op; op = op->next)
1536 {
1537 build_filepathsW( op, &paths );
1538 switch (notification)
1539 {
1540 case SPFILENOTIFY_QUEUESCAN:
1541 /* FIXME: handle delay flag */
1542 if (handler( context, notification, (UINT_PTR)paths.Target, 0 )) goto done;
1543 break;
1544 case SPFILENOTIFY_QUEUESCAN_EX:
1545 if (handler( context, notification, (UINT_PTR)&paths, 0 )) goto done;
1546 break;
1547 default:
1548 ret = TRUE; goto done;
1549 }
1550 }
1551
1552 *result = TRUE;
1553
1554 done:
1555 HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
1556 HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
1557 return ret;
1558 }
1559
1560
1561 /***********************************************************************
1562 * SetupGetFileQueueCount (SETUPAPI.@)
1563 */
SetupGetFileQueueCount(HSPFILEQ handle,UINT op,PUINT result)1564 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result )
1565 {
1566 struct file_queue *queue = handle;
1567
1568 switch(op)
1569 {
1570 case FILEOP_COPY:
1571 *result = queue->copy_queue.count;
1572 return TRUE;
1573 case FILEOP_RENAME:
1574 *result = queue->rename_queue.count;
1575 return TRUE;
1576 case FILEOP_DELETE:
1577 *result = queue->delete_queue.count;
1578 return TRUE;
1579 }
1580 return FALSE;
1581 }
1582
1583
1584 /***********************************************************************
1585 * SetupGetFileQueueFlags (SETUPAPI.@)
1586 */
SetupGetFileQueueFlags(HSPFILEQ handle,PDWORD flags)1587 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags )
1588 {
1589 struct file_queue *queue = handle;
1590 *flags = queue->flags;
1591 return TRUE;
1592 }
1593
1594
1595 /***********************************************************************
1596 * SetupSetFileQueueFlags (SETUPAPI.@)
1597 */
SetupSetFileQueueFlags(HSPFILEQ handle,DWORD mask,DWORD flags)1598 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags )
1599 {
1600 struct file_queue *queue = handle;
1601 queue->flags = (queue->flags & ~mask) | flags;
1602 return TRUE;
1603 }
1604
1605
1606 /***********************************************************************
1607 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1608 */
SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle,PSP_ALTPLATFORM_INFO platform,PCSTR catalogfile)1609 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile)
1610 {
1611 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile));
1612 return FALSE;
1613 }
1614
1615
1616 /***********************************************************************
1617 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1618 */
SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle,PSP_ALTPLATFORM_INFO platform,PCWSTR catalogfile)1619 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile)
1620 {
1621 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile));
1622 return FALSE;
1623 }
1624
1625
1626 /***********************************************************************
1627 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1628 */
SetupInitDefaultQueueCallback(HWND owner)1629 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner )
1630 {
1631 return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL );
1632 }
1633
1634
1635 /***********************************************************************
1636 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1637 */
SetupInitDefaultQueueCallbackEx(HWND owner,HWND progress,UINT msg,DWORD reserved1,PVOID reserved2)1638 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg,
1639 DWORD reserved1, PVOID reserved2 )
1640 {
1641 struct default_callback_context *context;
1642
1643 if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) )))
1644 {
1645 context->owner = owner;
1646 context->progress = progress;
1647 context->message = msg;
1648 }
1649 return context;
1650 }
1651
1652
1653 /***********************************************************************
1654 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1655 */
SetupTermDefaultQueueCallback(PVOID context)1656 void WINAPI SetupTermDefaultQueueCallback( PVOID context )
1657 {
1658 HeapFree( GetProcessHeap(), 0, context );
1659 }
1660
1661
1662 /***********************************************************************
1663 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1664 */
SetupDefaultQueueCallbackA(PVOID context,UINT notification,UINT_PTR param1,UINT_PTR param2)1665 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification,
1666 UINT_PTR param1, UINT_PTR param2 )
1667 {
1668 FILEPATHS_A *paths = (FILEPATHS_A *)param1;
1669 struct default_callback_context *ctx = (struct default_callback_context *)context;
1670
1671 switch(notification)
1672 {
1673 case SPFILENOTIFY_STARTQUEUE:
1674 TRACE( "start queue\n" );
1675 return TRUE;
1676 case SPFILENOTIFY_ENDQUEUE:
1677 TRACE( "end queue\n" );
1678 return 0;
1679 case SPFILENOTIFY_STARTSUBQUEUE:
1680 TRACE( "start subqueue %ld count %ld\n", param1, param2 );
1681 return TRUE;
1682 case SPFILENOTIFY_ENDSUBQUEUE:
1683 TRACE( "end subqueue %ld\n", param1 );
1684 return 0;
1685 case SPFILENOTIFY_STARTDELETE:
1686 TRACE( "start delete %s\n", debugstr_a(paths->Target) );
1687 return FILEOP_DOIT;
1688 case SPFILENOTIFY_ENDDELETE:
1689 TRACE( "end delete %s\n", debugstr_a(paths->Target) );
1690 return 0;
1691 case SPFILENOTIFY_DELETEERROR:
1692 /*Windows Ignores attempts to delete files / folders which do not exist*/
1693 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1694 SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1695 return FILEOP_SKIP;
1696 case SPFILENOTIFY_STARTRENAME:
1697 TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1698 return FILEOP_DOIT;
1699 case SPFILENOTIFY_ENDRENAME:
1700 TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1701 return 0;
1702 case SPFILENOTIFY_RENAMEERROR:
1703 SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1704 return FILEOP_SKIP;
1705 case SPFILENOTIFY_STARTCOPY:
1706 TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1707 return FILEOP_DOIT;
1708 case SPFILENOTIFY_ENDCOPY:
1709 TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
1710 return 0;
1711 case SPFILENOTIFY_COPYERROR:
1712 ERR( "copy error %d %s -> %s\n", paths->Win32Error,
1713 debugstr_a(paths->Source), debugstr_a(paths->Target) );
1714 return FILEOP_SKIP;
1715 case SPFILENOTIFY_NEEDMEDIA:
1716 TRACE( "need media\n" );
1717 return FILEOP_SKIP;
1718 default:
1719 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
1720 break;
1721 }
1722 return 0;
1723 }
1724
1725
1726 /***********************************************************************
1727 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1728 */
SetupDefaultQueueCallbackW(PVOID context,UINT notification,UINT_PTR param1,UINT_PTR param2)1729 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification,
1730 UINT_PTR param1, UINT_PTR param2 )
1731 {
1732 FILEPATHS_W *paths = (FILEPATHS_W *)param1;
1733 struct default_callback_context *ctx = (struct default_callback_context *)context;
1734
1735 switch(notification)
1736 {
1737 case SPFILENOTIFY_STARTQUEUE:
1738 TRACE( "start queue\n" );
1739 return TRUE;
1740 case SPFILENOTIFY_ENDQUEUE:
1741 TRACE( "end queue\n" );
1742 return 0;
1743 case SPFILENOTIFY_STARTSUBQUEUE:
1744 TRACE( "start subqueue %ld count %ld\n", param1, param2 );
1745 return TRUE;
1746 case SPFILENOTIFY_ENDSUBQUEUE:
1747 TRACE( "end subqueue %ld\n", param1 );
1748 return 0;
1749 case SPFILENOTIFY_STARTDELETE:
1750 TRACE( "start delete %s\n", debugstr_w(paths->Target) );
1751 return FILEOP_DOIT;
1752 case SPFILENOTIFY_ENDDELETE:
1753 TRACE( "end delete %s\n", debugstr_w(paths->Target) );
1754 return 0;
1755 case SPFILENOTIFY_DELETEERROR:
1756 /*Windows Ignores attempts to delete files / folders which do not exist*/
1757 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
1758 SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
1759 return FILEOP_SKIP;
1760 case SPFILENOTIFY_STARTRENAME:
1761 SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
1762 return FILEOP_DOIT;
1763 case SPFILENOTIFY_ENDRENAME:
1764 TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1765 return 0;
1766 case SPFILENOTIFY_RENAMEERROR:
1767 ERR( "rename error %d %s -> %s\n", paths->Win32Error,
1768 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1769 return FILEOP_SKIP;
1770 case SPFILENOTIFY_STARTCOPY:
1771 TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1772 return FILEOP_DOIT;
1773 case SPFILENOTIFY_ENDCOPY:
1774 TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
1775 return 0;
1776 case SPFILENOTIFY_COPYERROR:
1777 TRACE( "copy error %d %s -> %s\n", paths->Win32Error,
1778 debugstr_w(paths->Source), debugstr_w(paths->Target) );
1779 return FILEOP_SKIP;
1780 case SPFILENOTIFY_NEEDMEDIA:
1781 TRACE( "need media\n" );
1782 return FILEOP_SKIP;
1783 default:
1784 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
1785 break;
1786 }
1787 return 0;
1788 }
1789
1790 /***********************************************************************
1791 * SetupDeleteErrorA (SETUPAPI.@)
1792 */
1793
SetupDeleteErrorA(HWND parent,PCSTR dialogTitle,PCSTR file,UINT w32error,DWORD style)1794 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file,
1795 UINT w32error, DWORD style)
1796 {
1797 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1798 w32error, debugstr_a(file) );
1799 return DPROMPT_SKIPFILE;
1800 }
1801
1802 /***********************************************************************
1803 * SetupDeleteErrorW (SETUPAPI.@)
1804 */
1805
SetupDeleteErrorW(HWND parent,PCWSTR dialogTitle,PCWSTR file,UINT w32error,DWORD style)1806 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file,
1807 UINT w32error, DWORD style)
1808 {
1809 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1810 w32error, debugstr_w(file) );
1811 return DPROMPT_SKIPFILE;
1812 }
1813
1814 /***********************************************************************
1815 * SetupRenameErrorA (SETUPAPI.@)
1816 */
1817
SetupRenameErrorA(HWND parent,PCSTR dialogTitle,PCSTR source,PCSTR target,UINT w32error,DWORD style)1818 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source,
1819 PCSTR target, UINT w32error, DWORD style)
1820 {
1821 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1822 w32error, debugstr_a(source), debugstr_a(target));
1823 return DPROMPT_SKIPFILE;
1824 }
1825
1826 /***********************************************************************
1827 * SetupRenameErrorW (SETUPAPI.@)
1828 */
1829
SetupRenameErrorW(HWND parent,PCWSTR dialogTitle,PCWSTR source,PCWSTR target,UINT w32error,DWORD style)1830 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source,
1831 PCWSTR target, UINT w32error, DWORD style)
1832 {
1833 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1834 w32error, debugstr_w(source), debugstr_w(target));
1835 return DPROMPT_SKIPFILE;
1836 }
1837
1838
1839 /***********************************************************************
1840 * SetupCopyErrorA (SETUPAPI.@)
1841 */
1842
SetupCopyErrorA(HWND parent,PCSTR dialogTitle,PCSTR diskname,PCSTR sourcepath,PCSTR sourcefile,PCSTR targetpath,UINT w32error,DWORD style,PSTR pathbuffer,DWORD buffersize,PDWORD requiredsize)1843 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname,
1844 PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath,
1845 UINT w32error, DWORD style, PSTR pathbuffer,
1846 DWORD buffersize, PDWORD requiredsize)
1847 {
1848 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1849 w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath));
1850 return DPROMPT_SKIPFILE;
1851 }
1852
1853 /***********************************************************************
1854 * SetupCopyErrorW (SETUPAPI.@)
1855 */
1856
SetupCopyErrorW(HWND parent,PCWSTR dialogTitle,PCWSTR diskname,PCWSTR sourcepath,PCWSTR sourcefile,PCWSTR targetpath,UINT w32error,DWORD style,PWSTR pathbuffer,DWORD buffersize,PDWORD requiredsize)1857 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname,
1858 PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath,
1859 UINT w32error, DWORD style, PWSTR pathbuffer,
1860 DWORD buffersize, PDWORD requiredsize)
1861 {
1862 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1863 w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath));
1864 return DPROMPT_SKIPFILE;
1865 }
1866
1867 /***********************************************************************
1868 * pSetupGetQueueFlags (SETUPAPI.@)
1869 */
pSetupGetQueueFlags(HSPFILEQ handle)1870 DWORD WINAPI pSetupGetQueueFlags( HSPFILEQ handle )
1871 {
1872 struct file_queue *queue = handle;
1873 return queue->flags;
1874 }
1875
1876 /***********************************************************************
1877 * pSetupSetQueueFlags (SETUPAPI.@)
1878 */
pSetupSetQueueFlags(HSPFILEQ handle,DWORD flags)1879 BOOL WINAPI pSetupSetQueueFlags( HSPFILEQ handle, DWORD flags )
1880 {
1881 struct file_queue *queue = handle;
1882 queue->flags = flags;
1883 return TRUE;
1884 }
1885