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