2 * Setupapi file queue routines
4 * Copyright 2002 Alexandre Julliard for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "setupapi_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
27 /* Unicode constants */
28 static const WCHAR DotSecurity
[] = {'.','S','e','c','u','r','i','t','y',0};
30 /* context structure for the default queue callback */
31 struct default_callback_context
49 PSECURITY_DESCRIPTOR dst_sd
;
61 struct file_op_queue copy_queue
;
62 struct file_op_queue delete_queue
;
63 struct file_op_queue rename_queue
;
68 static inline WCHAR
*strdupW( const WCHAR
*str
)
73 int len
= (strlenW(str
) + 1) * sizeof(WCHAR
);
74 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
))) memcpy( ret
, str
, len
);
79 static inline char *strdupWtoA( const WCHAR
*str
)
84 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, str
, -1, NULL
, 0, NULL
, NULL
);
85 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
86 WideCharToMultiByte( CP_ACP
, 0, str
, -1, ret
, len
, NULL
, NULL
);
91 /* append a file operation to a queue */
92 static inline void queue_file_op( struct file_op_queue
*queue
, struct file_op
*op
)
95 if (queue
->tail
) queue
->tail
->next
= op
;
96 else queue
->head
= op
;
101 /* free all the file operations on a given queue */
102 static void free_file_op_queue( struct file_op_queue
*queue
)
104 struct file_op
*t
, *op
= queue
->head
;
108 HeapFree( GetProcessHeap(), 0, op
->src_root
);
109 HeapFree( GetProcessHeap(), 0, op
->src_path
);
110 HeapFree( GetProcessHeap(), 0, op
->src_file
);
111 HeapFree( GetProcessHeap(), 0, op
->src_descr
);
112 HeapFree( GetProcessHeap(), 0, op
->src_tag
);
113 HeapFree( GetProcessHeap(), 0, op
->dst_path
);
114 if (op
->dst_sd
) LocalFree( op
->dst_sd
);
115 if (op
->dst_file
!= op
->src_file
) HeapFree( GetProcessHeap(), 0, op
->dst_file
);
118 HeapFree( GetProcessHeap(), 0, t
);
122 /* concat 3 strings to make a path, handling separators correctly */
123 static void concat_W( WCHAR
*buffer
, const WCHAR
*src1
, const WCHAR
*src2
, const WCHAR
*src3
)
128 strcpyW( buffer
, src1
);
129 buffer
+= strlenW(buffer
);
130 if (buffer
[-1] != '\\') *buffer
++ = '\\';
131 if (src2
) while (*src2
== '\\') src2
++;
136 strcpyW( buffer
, src2
);
137 buffer
+= strlenW(buffer
);
138 if (buffer
[-1] != '\\') *buffer
++ = '\\';
139 if (src3
) while (*src3
== '\\') src3
++;
143 strcpyW( buffer
, src3
);
144 buffer
+= strlenW(buffer
);
149 /***********************************************************************
152 * Build a FILEPATHS_W structure for a given file operation.
154 static BOOL
build_filepathsW( const struct file_op
*op
, FILEPATHS_W
*paths
)
156 unsigned int src_len
= 1, dst_len
= 1;
157 WCHAR
*source
= (PWSTR
)paths
->Source
, *target
= (PWSTR
)paths
->Target
;
159 if (op
->src_root
) src_len
+= strlenW(op
->src_root
) + 1;
160 if (op
->src_path
) src_len
+= strlenW(op
->src_path
) + 1;
161 if (op
->src_file
) src_len
+= strlenW(op
->src_file
) + 1;
162 if (op
->dst_path
) dst_len
+= strlenW(op
->dst_path
) + 1;
163 if (op
->dst_file
) dst_len
+= strlenW(op
->dst_file
) + 1;
164 src_len
*= sizeof(WCHAR
);
165 dst_len
*= sizeof(WCHAR
);
167 if (!source
|| HeapSize( GetProcessHeap(), 0, source
) < src_len
)
169 HeapFree( GetProcessHeap(), 0, source
);
170 paths
->Source
= source
= HeapAlloc( GetProcessHeap(), 0, src_len
);
172 if (!target
|| HeapSize( GetProcessHeap(), 0, target
) < dst_len
)
174 HeapFree( GetProcessHeap(), 0, target
);
175 paths
->Target
= target
= HeapAlloc( GetProcessHeap(), 0, dst_len
);
177 if (!source
|| !target
) return FALSE
;
178 concat_W( source
, op
->src_root
, op
->src_path
, op
->src_file
);
179 concat_W( target
, NULL
, op
->dst_path
, op
->dst_file
);
180 paths
->Win32Error
= 0;
186 /***********************************************************************
187 * QUEUE_callback_WtoA
189 * Map a file callback parameters from W to A and call the A callback.
191 UINT CALLBACK
QUEUE_callback_WtoA( void *context
, UINT notification
,
192 UINT_PTR param1
, UINT_PTR param2
)
194 struct callback_WtoA_context
*callback_ctx
= context
;
195 char buffer
[MAX_PATH
];
197 UINT_PTR old_param2
= param2
;
201 case SPFILENOTIFY_COPYERROR
:
202 param2
= (UINT_PTR
)&buffer
;
204 case SPFILENOTIFY_STARTDELETE
:
205 case SPFILENOTIFY_ENDDELETE
:
206 case SPFILENOTIFY_DELETEERROR
:
207 case SPFILENOTIFY_STARTRENAME
:
208 case SPFILENOTIFY_ENDRENAME
:
209 case SPFILENOTIFY_RENAMEERROR
:
210 case SPFILENOTIFY_STARTCOPY
:
211 case SPFILENOTIFY_ENDCOPY
:
212 case SPFILENOTIFY_QUEUESCAN_EX
:
214 FILEPATHS_W
*pathsW
= (FILEPATHS_W
*)param1
;
217 pathsA
.Source
= strdupWtoA( pathsW
->Source
);
218 pathsA
.Target
= strdupWtoA( pathsW
->Target
);
219 pathsA
.Win32Error
= pathsW
->Win32Error
;
220 pathsA
.Flags
= pathsW
->Flags
;
221 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
,
222 (UINT_PTR
)&pathsA
, param2
);
223 HeapFree( GetProcessHeap(), 0, (void *)pathsA
.Source
);
224 HeapFree( GetProcessHeap(), 0, (void *)pathsA
.Target
);
226 if (notification
== SPFILENOTIFY_COPYERROR
)
227 MultiByteToWideChar( CP_ACP
, 0, buffer
, -1, (WCHAR
*)old_param2
, MAX_PATH
);
230 case SPFILENOTIFY_STARTREGISTRATION
:
231 case SPFILENOTIFY_ENDREGISTRATION
:
233 SP_REGISTER_CONTROL_STATUSW
*statusW
= (SP_REGISTER_CONTROL_STATUSW
*)param1
;
234 SP_REGISTER_CONTROL_STATUSA statusA
;
236 statusA
.cbSize
= sizeof(statusA
);
237 statusA
.FileName
= strdupWtoA( statusW
->FileName
);
238 statusA
.Win32Error
= statusW
->Win32Error
;
239 statusA
.FailureCode
= statusW
->FailureCode
;
240 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
,
241 (UINT_PTR
)&statusA
, param2
);
242 HeapFree( GetProcessHeap(), 0, (LPSTR
)statusA
.FileName
);
246 case SPFILENOTIFY_QUEUESCAN
:
248 LPWSTR targetW
= (LPWSTR
)param1
;
249 LPSTR target
= strdupWtoA( targetW
);
251 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
,
252 (UINT_PTR
)target
, param2
);
253 HeapFree( GetProcessHeap(), 0, target
);
257 case SPFILENOTIFY_NEEDMEDIA
:
258 FIXME("mapping for %d not implemented\n",notification
);
259 case SPFILENOTIFY_STARTQUEUE
:
260 case SPFILENOTIFY_ENDQUEUE
:
261 case SPFILENOTIFY_STARTSUBQUEUE
:
262 case SPFILENOTIFY_ENDSUBQUEUE
:
264 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
, param1
, param2
);
271 /***********************************************************************
274 * Retrieve the source file information for a given file.
276 static void get_src_file_info( HINF hinf
, struct file_op
*op
)
278 static const WCHAR SourceDisksNames
[] =
279 {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0};
280 static const WCHAR SourceDisksFiles
[] =
281 {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
283 INFCONTEXT file_ctx
, disk_ctx
;
287 /* find the SourceDisksFiles entry */
288 if (!SetupFindFirstLineW( hinf
, SourceDisksFiles
, op
->src_file
, &file_ctx
))
290 if ((op
->style
& (SP_COPY_SOURCE_ABSOLUTE
|SP_COPY_SOURCEPATH_ABSOLUTE
))) return;
291 /* no specific info, use .inf file source directory */
292 if (!op
->src_root
) op
->src_root
= PARSER_get_src_root( hinf
);
295 if (!SetupGetIntField( &file_ctx
, 1, &diskid
)) return;
297 /* now find the diskid in the SourceDisksNames section */
298 if (!SetupFindFirstLineW( hinf
, SourceDisksNames
, NULL
, &disk_ctx
)) return;
301 if (SetupGetIntField( &disk_ctx
, 0, &id
) && (id
== diskid
)) break;
302 if (!SetupFindNextLine( &disk_ctx
, &disk_ctx
)) return;
305 /* and fill in the missing info */
309 if (SetupGetStringFieldW( &disk_ctx
, 1, NULL
, 0, &len
) &&
310 (op
->src_descr
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) )))
311 SetupGetStringFieldW( &disk_ctx
, 1, op
->src_descr
, len
, NULL
);
315 if (SetupGetStringFieldW( &disk_ctx
, 2, NULL
, 0, &len
) &&
316 (op
->src_tag
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) )))
317 SetupGetStringFieldW( &disk_ctx
, 2, op
->src_tag
, len
, NULL
);
319 if (!op
->src_path
&& !(op
->style
& SP_COPY_SOURCE_ABSOLUTE
))
322 if (!(op
->style
& SP_COPY_SOURCEPATH_ABSOLUTE
))
324 /* retrieve relative path for this disk */
325 if (!SetupGetStringFieldW( &disk_ctx
, 4, NULL
, 0, &len
)) len
= 0;
327 /* retrieve relative path for this file */
328 if (!SetupGetStringFieldW( &file_ctx
, 2, NULL
, 0, &len2
)) len2
= 0;
331 (op
->src_path
= HeapAlloc( GetProcessHeap(), 0, (len
+len2
)*sizeof(WCHAR
) )))
333 WCHAR
*ptr
= op
->src_path
;
336 SetupGetStringFieldW( &disk_ctx
, 4, op
->src_path
, len
, NULL
);
337 ptr
= op
->src_path
+ strlenW(op
->src_path
);
338 if (len2
&& ptr
> op
->src_path
&& ptr
[-1] != '\\') *ptr
++ = '\\';
340 if (!SetupGetStringFieldW( &file_ctx
, 2, ptr
, len2
, NULL
)) *ptr
= 0;
343 if (!op
->src_root
) op
->src_root
= PARSER_get_src_root(hinf
);
347 /***********************************************************************
348 * get_destination_dir
350 * Retrieve the destination dir for a given section.
352 static WCHAR
*get_destination_dir( HINF hinf
, const WCHAR
*section
)
354 static const WCHAR Dest
[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
355 static const WCHAR Def
[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
358 if (!SetupFindFirstLineW( hinf
, Dest
, section
, &context
) &&
359 !SetupFindFirstLineW( hinf
, Dest
, Def
, &context
)) return NULL
;
360 return PARSER_get_dest_dir( &context
);
364 static void (WINAPI
*pExtractFiles
)( LPSTR
, LPSTR
, DWORD
, DWORD
, DWORD
, DWORD
);
366 /***********************************************************************
367 * extract_cabinet_file
369 * Extract a file from a .cab file.
371 static BOOL
extract_cabinet_file( const WCHAR
*cabinet
, const WCHAR
*root
,
372 const WCHAR
*src
, const WCHAR
*dst
)
374 static const WCHAR extW
[] = {'.','c','a','b',0};
375 static HMODULE advpack
;
377 char *cab_path
, *cab_file
;
378 int len
= strlenW( cabinet
);
380 /* make sure the cabinet file has a .cab extension */
381 if (len
<= 4 || strcmpiW( cabinet
+ len
- 4, extW
)) return FALSE
;
384 if (!advpack
&& !(advpack
= LoadLibraryA( "advpack.dll" )))
386 ERR( "could not load advpack.dll\n" );
389 if (!(pExtractFiles
= (void *)GetProcAddress( advpack
, "ExtractFiles" )))
391 ERR( "could not find ExtractFiles in advpack.dll\n" );
396 if (!(cab_path
= strdupWtoA( root
))) return FALSE
;
397 len
= WideCharToMultiByte( CP_ACP
, 0, cabinet
, -1, NULL
, 0, NULL
, NULL
);
398 if (!(cab_file
= HeapAlloc( GetProcessHeap(), 0, strlen(cab_path
) + len
+ 1 )))
400 HeapFree( GetProcessHeap(), 0, cab_path
);
403 strcpy( cab_file
, cab_path
);
404 if (cab_file
[0] && cab_file
[strlen(cab_file
)-1] != '\\') strcat( cab_file
, "\\" );
405 WideCharToMultiByte( CP_ACP
, 0, cabinet
, -1, cab_file
+ strlen(cab_file
), len
, NULL
, NULL
);
406 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file
) );
407 pExtractFiles( cab_file
, cab_path
, 0, 0, 0, 0 );
408 HeapFree( GetProcessHeap(), 0, cab_file
);
409 HeapFree( GetProcessHeap(), 0, cab_path
);
410 return CopyFileW( src
, dst
, FALSE
/*FIXME*/ );
414 /***********************************************************************
415 * SetupOpenFileQueue (SETUPAPI.@)
417 HSPFILEQ WINAPI
SetupOpenFileQueue(void)
419 struct file_queue
*queue
;
421 if (!(queue
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*queue
))))
422 return INVALID_HANDLE_VALUE
;
427 /***********************************************************************
428 * SetupCloseFileQueue (SETUPAPI.@)
430 BOOL WINAPI
SetupCloseFileQueue( HSPFILEQ handle
)
432 struct file_queue
*queue
= handle
;
434 free_file_op_queue( &queue
->copy_queue
);
435 free_file_op_queue( &queue
->rename_queue
);
436 free_file_op_queue( &queue
->delete_queue
);
437 HeapFree( GetProcessHeap(), 0, queue
);
442 /***********************************************************************
443 * SetupQueueCopyIndirectA (SETUPAPI.@)
445 BOOL WINAPI
SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params
)
447 struct file_queue
*queue
= params
->QueueHandle
;
450 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
451 op
->style
= params
->CopyStyle
;
452 op
->src_root
= strdupAtoW( params
->SourceRootPath
);
453 op
->src_path
= strdupAtoW( params
->SourcePath
);
454 op
->src_file
= strdupAtoW( params
->SourceFilename
);
455 op
->src_descr
= strdupAtoW( params
->SourceDescription
);
456 op
->src_tag
= strdupAtoW( params
->SourceTagfile
);
457 op
->dst_path
= strdupAtoW( params
->TargetDirectory
);
458 op
->dst_file
= strdupAtoW( params
->TargetFilename
);
461 if (!op
->src_file
) op
->src_file
= op
->dst_file
;
462 if (params
->LayoutInf
)
464 get_src_file_info( params
->LayoutInf
, op
);
465 if (!op
->dst_path
) op
->dst_path
= get_destination_dir( params
->LayoutInf
, op
->dst_file
);
468 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
469 debugstr_w(op
->src_root
), debugstr_w(op
->src_path
), debugstr_w(op
->src_file
),
470 debugstr_w(op
->dst_path
), debugstr_w(op
->dst_file
),
471 debugstr_w(op
->src_descr
), debugstr_w(op
->src_tag
) );
473 queue_file_op( &queue
->copy_queue
, op
);
478 /***********************************************************************
479 * SetupQueueCopyIndirectW (SETUPAPI.@)
481 BOOL WINAPI
SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params
)
483 struct file_queue
*queue
= params
->QueueHandle
;
486 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
487 op
->style
= params
->CopyStyle
;
488 op
->src_root
= strdupW( params
->SourceRootPath
);
489 op
->src_path
= strdupW( params
->SourcePath
);
490 op
->src_file
= strdupW( params
->SourceFilename
);
491 op
->src_descr
= strdupW( params
->SourceDescription
);
492 op
->src_tag
= strdupW( params
->SourceTagfile
);
493 op
->dst_path
= strdupW( params
->TargetDirectory
);
494 op
->dst_file
= strdupW( params
->TargetFilename
);
496 if (params
->SecurityDescriptor
)
497 ConvertStringSecurityDescriptorToSecurityDescriptorW( params
->SecurityDescriptor
, SDDL_REVISION_1
, &op
->dst_sd
, NULL
);
500 if (!op
->src_file
) op
->src_file
= op
->dst_file
;
501 if (params
->LayoutInf
)
503 get_src_file_info( params
->LayoutInf
, op
);
504 if (!op
->dst_path
) op
->dst_path
= get_destination_dir( params
->LayoutInf
, op
->dst_file
);
507 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
508 debugstr_w(op
->src_root
), debugstr_w(op
->src_path
), debugstr_w(op
->src_file
),
509 debugstr_w(op
->dst_path
), debugstr_w(op
->dst_file
),
510 debugstr_w(op
->src_descr
), debugstr_w(op
->src_tag
) );
512 queue_file_op( &queue
->copy_queue
, op
);
517 /***********************************************************************
518 * SetupQueueCopyA (SETUPAPI.@)
520 BOOL WINAPI
SetupQueueCopyA( HSPFILEQ queue
, PCSTR src_root
, PCSTR src_path
, PCSTR src_file
,
521 PCSTR src_descr
, PCSTR src_tag
, PCSTR dst_dir
, PCSTR dst_file
,
524 SP_FILE_COPY_PARAMS_A params
;
526 params
.cbSize
= sizeof(params
);
527 params
.QueueHandle
= queue
;
528 params
.SourceRootPath
= src_root
;
529 params
.SourcePath
= src_path
;
530 params
.SourceFilename
= src_file
;
531 params
.SourceDescription
= src_descr
;
532 params
.SourceTagfile
= src_tag
;
533 params
.TargetDirectory
= dst_dir
;
534 params
.TargetFilename
= dst_file
;
535 params
.CopyStyle
= style
;
536 params
.LayoutInf
= 0;
537 params
.SecurityDescriptor
= NULL
;
538 return SetupQueueCopyIndirectA( ¶ms
);
542 /***********************************************************************
543 * SetupQueueCopyW (SETUPAPI.@)
545 BOOL WINAPI
SetupQueueCopyW( HSPFILEQ queue
, PCWSTR src_root
, PCWSTR src_path
, PCWSTR src_file
,
546 PCWSTR src_descr
, PCWSTR src_tag
, PCWSTR dst_dir
, PCWSTR dst_file
,
549 SP_FILE_COPY_PARAMS_W params
;
551 params
.cbSize
= sizeof(params
);
552 params
.QueueHandle
= queue
;
553 params
.SourceRootPath
= src_root
;
554 params
.SourcePath
= src_path
;
555 params
.SourceFilename
= src_file
;
556 params
.SourceDescription
= src_descr
;
557 params
.SourceTagfile
= src_tag
;
558 params
.TargetDirectory
= dst_dir
;
559 params
.TargetFilename
= dst_file
;
560 params
.CopyStyle
= style
;
561 params
.LayoutInf
= 0;
562 params
.SecurityDescriptor
= NULL
;
563 return SetupQueueCopyIndirectW( ¶ms
);
567 /***********************************************************************
568 * SetupQueueDefaultCopyA (SETUPAPI.@)
570 BOOL WINAPI
SetupQueueDefaultCopyA( HSPFILEQ queue
, HINF hinf
, PCSTR src_root
, PCSTR src_file
,
571 PCSTR dst_file
, DWORD style
)
573 SP_FILE_COPY_PARAMS_A params
;
575 params
.cbSize
= sizeof(params
);
576 params
.QueueHandle
= queue
;
577 params
.SourceRootPath
= src_root
;
578 params
.SourcePath
= NULL
;
579 params
.SourceFilename
= src_file
;
580 params
.SourceDescription
= NULL
;
581 params
.SourceTagfile
= NULL
;
582 params
.TargetDirectory
= NULL
;
583 params
.TargetFilename
= dst_file
;
584 params
.CopyStyle
= style
;
585 params
.LayoutInf
= hinf
;
586 params
.SecurityDescriptor
= NULL
;
587 return SetupQueueCopyIndirectA( ¶ms
);
591 /***********************************************************************
592 * SetupQueueDefaultCopyW (SETUPAPI.@)
594 BOOL WINAPI
SetupQueueDefaultCopyW( HSPFILEQ queue
, HINF hinf
, PCWSTR src_root
, PCWSTR src_file
,
595 PCWSTR dst_file
, DWORD style
)
597 SP_FILE_COPY_PARAMS_W params
;
599 params
.cbSize
= sizeof(params
);
600 params
.QueueHandle
= queue
;
601 params
.SourceRootPath
= src_root
;
602 params
.SourcePath
= NULL
;
603 params
.SourceFilename
= src_file
;
604 params
.SourceDescription
= NULL
;
605 params
.SourceTagfile
= NULL
;
606 params
.TargetDirectory
= NULL
;
607 params
.TargetFilename
= dst_file
;
608 params
.CopyStyle
= style
;
609 params
.LayoutInf
= hinf
;
610 params
.SecurityDescriptor
= NULL
;
611 return SetupQueueCopyIndirectW( ¶ms
);
615 /***********************************************************************
616 * SetupQueueDeleteA (SETUPAPI.@)
618 BOOL WINAPI
SetupQueueDeleteA( HSPFILEQ handle
, PCSTR part1
, PCSTR part2
)
620 struct file_queue
*queue
= handle
;
623 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
628 op
->src_descr
= NULL
;
630 op
->dst_path
= strdupAtoW( part1
);
631 op
->dst_file
= strdupAtoW( part2
);
632 queue_file_op( &queue
->delete_queue
, op
);
637 /***********************************************************************
638 * SetupQueueDeleteW (SETUPAPI.@)
640 BOOL WINAPI
SetupQueueDeleteW( HSPFILEQ handle
, PCWSTR part1
, PCWSTR part2
)
642 struct file_queue
*queue
= handle
;
645 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
650 op
->src_descr
= NULL
;
652 op
->dst_path
= strdupW( part1
);
653 op
->dst_file
= strdupW( part2
);
654 queue_file_op( &queue
->delete_queue
, op
);
659 /***********************************************************************
660 * SetupQueueRenameA (SETUPAPI.@)
662 BOOL WINAPI
SetupQueueRenameA( HSPFILEQ handle
, PCSTR SourcePath
, PCSTR SourceFilename
,
663 PCSTR TargetPath
, PCSTR TargetFilename
)
665 struct file_queue
*queue
= handle
;
668 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
671 op
->src_path
= strdupAtoW( SourcePath
);
672 op
->src_file
= strdupAtoW( SourceFilename
);
673 op
->src_descr
= NULL
;
675 op
->dst_path
= strdupAtoW( TargetPath
);
676 op
->dst_file
= strdupAtoW( TargetFilename
);
677 queue_file_op( &queue
->rename_queue
, op
);
682 /***********************************************************************
683 * SetupQueueRenameW (SETUPAPI.@)
685 BOOL WINAPI
SetupQueueRenameW( HSPFILEQ handle
, PCWSTR SourcePath
, PCWSTR SourceFilename
,
686 PCWSTR TargetPath
, PCWSTR TargetFilename
)
688 struct file_queue
*queue
= handle
;
691 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
694 op
->src_path
= strdupW( SourcePath
);
695 op
->src_file
= strdupW( SourceFilename
);
696 op
->src_descr
= NULL
;
698 op
->dst_path
= strdupW( TargetPath
);
699 op
->dst_file
= strdupW( TargetFilename
);
700 queue_file_op( &queue
->rename_queue
, op
);
705 /***********************************************************************
706 * SetupQueueCopySectionA (SETUPAPI.@)
708 BOOL WINAPI
SetupQueueCopySectionA( HSPFILEQ queue
, PCSTR src_root
, HINF hinf
, HINF hlist
,
709 PCSTR section
, DWORD style
)
711 UNICODE_STRING sectionW
;
714 if (!RtlCreateUnicodeStringFromAsciiz( §ionW
, section
))
716 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
720 ret
= SetupQueueCopySectionW( queue
, NULL
, hinf
, hlist
, sectionW
.Buffer
, style
);
724 if (RtlCreateUnicodeStringFromAsciiz( &srcW
, src_root
))
726 ret
= SetupQueueCopySectionW( queue
, srcW
.Buffer
, hinf
, hlist
, sectionW
.Buffer
, style
);
727 RtlFreeUnicodeString( &srcW
);
729 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
731 RtlFreeUnicodeString( §ionW
);
736 /***********************************************************************
737 * SetupQueueCopySectionW (SETUPAPI.@)
739 BOOL WINAPI
SetupQueueCopySectionW( HSPFILEQ queue
, PCWSTR src_root
, HINF hinf
, HINF hlist
,
740 PCWSTR section
, DWORD style
)
742 SP_FILE_COPY_PARAMS_W params
;
743 LPWSTR security_key
, security_descriptor
= NULL
;
744 INFCONTEXT context
, security_context
;
745 WCHAR dest
[MAX_PATH
], src
[MAX_PATH
];
750 TRACE( "hinf=%p/%p section=%s root=%s\n",
751 hinf
, hlist
, debugstr_w(section
), debugstr_w(src_root
) );
753 /* Check for .Security section */
754 security_key
= MyMalloc( (strlenW( section
) + strlenW( DotSecurity
)) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
) );
757 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
760 strcpyW( security_key
, section
);
761 strcatW( security_key
, DotSecurity
);
762 ret
= SetupFindFirstLineW( hinf
, security_key
, NULL
, &security_context
);
763 MyFree(security_key
);
766 if (!SetupGetLineTextW( &security_context
, NULL
, NULL
, NULL
, NULL
, 0, &required
))
768 security_descriptor
= MyMalloc( required
* sizeof(WCHAR
) );
769 if (!security_descriptor
)
771 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
774 if (!SetupGetLineTextW( &security_context
, NULL
, NULL
, NULL
, security_descriptor
, required
, NULL
))
776 MyFree( security_descriptor
);
781 params
.cbSize
= sizeof(params
);
782 params
.QueueHandle
= queue
;
783 params
.SourceRootPath
= src_root
;
784 params
.SourcePath
= NULL
;
785 params
.SourceDescription
= NULL
;
786 params
.SourceTagfile
= NULL
;
787 params
.TargetFilename
= dest
;
788 params
.CopyStyle
= style
;
789 params
.LayoutInf
= hinf
;
790 params
.SecurityDescriptor
= security_descriptor
;
793 if (!hlist
) hlist
= hinf
;
794 if (!hinf
) hinf
= hlist
;
795 if (!SetupFindFirstLineW( hlist
, section
, NULL
, &context
)) goto done
;
796 if (!(params
.TargetDirectory
= get_destination_dir( hinf
, section
))) goto done
;
799 if (!SetupGetStringFieldW( &context
, 1, dest
, sizeof(dest
)/sizeof(WCHAR
), NULL
))
801 if (!SetupGetStringFieldW( &context
, 2, src
, sizeof(src
)/sizeof(WCHAR
), NULL
)) *src
= 0;
802 if (!SetupGetIntField( &context
, 4, &flags
)) flags
= 0; /* FIXME */
804 params
.SourceFilename
= *src
? src
: NULL
;
805 if (!SetupQueueCopyIndirectW( ¶ms
)) goto done
;
806 } while (SetupFindNextLine( &context
, &context
));
810 if (security_descriptor
)
811 MyFree( security_descriptor
);
816 /***********************************************************************
817 * SetupQueueDeleteSectionA (SETUPAPI.@)
819 BOOL WINAPI
SetupQueueDeleteSectionA( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCSTR section
)
821 UNICODE_STRING sectionW
;
824 if (RtlCreateUnicodeStringFromAsciiz( §ionW
, section
))
826 ret
= SetupQueueDeleteSectionW( queue
, hinf
, hlist
, sectionW
.Buffer
);
827 RtlFreeUnicodeString( §ionW
);
829 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
834 /***********************************************************************
835 * SetupQueueDeleteSectionW (SETUPAPI.@)
837 BOOL WINAPI
SetupQueueDeleteSectionW( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCWSTR section
)
841 WCHAR buffer
[MAX_PATH
];
845 TRACE( "hinf=%p/%p section=%s\n", hinf
, hlist
, debugstr_w(section
) );
847 if (!hlist
) hlist
= hinf
;
848 if (!SetupFindFirstLineW( hlist
, section
, NULL
, &context
)) return FALSE
;
849 if (!(dest_dir
= get_destination_dir( hinf
, section
))) return FALSE
;
852 if (!SetupGetStringFieldW( &context
, 1, buffer
, sizeof(buffer
)/sizeof(WCHAR
), NULL
))
854 if (!SetupGetIntField( &context
, 4, &flags
)) flags
= 0;
855 if (!SetupQueueDeleteW( queue
, dest_dir
, buffer
)) goto done
;
856 } while (SetupFindNextLine( &context
, &context
));
860 HeapFree( GetProcessHeap(), 0, dest_dir
);
865 /***********************************************************************
866 * SetupQueueRenameSectionA (SETUPAPI.@)
868 BOOL WINAPI
SetupQueueRenameSectionA( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCSTR section
)
870 UNICODE_STRING sectionW
;
873 if (RtlCreateUnicodeStringFromAsciiz( §ionW
, section
))
875 ret
= SetupQueueRenameSectionW( queue
, hinf
, hlist
, sectionW
.Buffer
);
876 RtlFreeUnicodeString( §ionW
);
878 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
883 /***********************************************************************
884 * SetupQueueRenameSectionW (SETUPAPI.@)
886 BOOL WINAPI
SetupQueueRenameSectionW( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCWSTR section
)
890 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
893 TRACE( "hinf=%p/%p section=%s\n", hinf
, hlist
, debugstr_w(section
) );
895 if (!hlist
) hlist
= hinf
;
896 if (!SetupFindFirstLineW( hlist
, section
, NULL
, &context
)) return FALSE
;
897 if (!(dest_dir
= get_destination_dir( hinf
, section
))) return FALSE
;
900 if (!SetupGetStringFieldW( &context
, 1, dst
, sizeof(dst
)/sizeof(WCHAR
), NULL
))
902 if (!SetupGetStringFieldW( &context
, 2, src
, sizeof(src
)/sizeof(WCHAR
), NULL
))
904 if (!SetupQueueRenameW( queue
, dest_dir
, src
, NULL
, dst
)) goto done
;
905 } while (SetupFindNextLine( &context
, &context
));
909 HeapFree( GetProcessHeap(), 0, dest_dir
);
914 /***********************************************************************
915 * SetupCommitFileQueueA (SETUPAPI.@)
917 BOOL WINAPI
SetupCommitFileQueueA( HWND owner
, HSPFILEQ queue
, PSP_FILE_CALLBACK_A handler
,
920 struct callback_WtoA_context ctx
;
922 ctx
.orig_context
= context
;
923 ctx
.orig_handler
= handler
;
924 return SetupCommitFileQueueW( owner
, queue
, QUEUE_callback_WtoA
, &ctx
);
928 /***********************************************************************
931 * Recursively create all directories in the path.
933 static BOOL
create_full_pathW(const WCHAR
*path
)
939 new_path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(path
) + 1) * sizeof(WCHAR
));
940 strcpyW(new_path
, path
);
942 while((len
= strlenW(new_path
)) && new_path
[len
- 1] == '\\')
943 new_path
[len
- 1] = 0;
945 while(!CreateDirectoryW(new_path
, NULL
))
948 DWORD last_error
= GetLastError();
950 if(last_error
== ERROR_ALREADY_EXISTS
)
953 if(last_error
!= ERROR_PATH_NOT_FOUND
)
959 if(!(slash
= strrchrW(new_path
, '\\')))
965 len
= slash
- new_path
;
967 if(!create_full_pathW(new_path
))
972 new_path
[len
] = '\\';
975 HeapFree(GetProcessHeap(), 0, new_path
);
979 static BOOL
do_file_copyW( LPCWSTR source
, LPCWSTR target
, DWORD style
,
980 PSP_FILE_CALLBACK_W handler
, PVOID context
)
985 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source
),debugstr_w(target
),style
);
987 /* before copy processing */
988 if (style
& SP_COPY_REPLACEONLY
)
990 if (GetFileAttributesW(target
) == INVALID_FILE_ATTRIBUTES
)
993 if (style
& (SP_COPY_NEWER_OR_SAME
| SP_COPY_NEWER_ONLY
| SP_COPY_FORCE_NEWER
))
995 DWORD VersionSizeSource
=0;
996 DWORD VersionSizeTarget
=0;
1000 * This is sort of an interesting workaround. You see, calling
1001 * GetVersionInfoSize on a builtin dll loads that dll into memory
1002 * and we do not properly unload builtin dlls.. so we effectively
1003 * lock into memory all the targets we are replacing. This leads
1004 * to problems when we try to register the replaced dlls.
1006 * So I will test for the existence of the files first so that
1007 * we just basically unconditionally replace the builtin versions.
1009 if ((GetFileAttributesW(target
) != INVALID_FILE_ATTRIBUTES
) &&
1010 (GetFileAttributesW(source
) != INVALID_FILE_ATTRIBUTES
))
1012 VersionSizeSource
= GetFileVersionInfoSizeW((LPWSTR
)source
,&zero
);
1013 VersionSizeTarget
= GetFileVersionInfoSizeW((LPWSTR
)target
,&zero
);
1016 TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget
,
1019 if (VersionSizeSource
&& VersionSizeTarget
)
1021 LPVOID VersionSource
;
1022 LPVOID VersionTarget
;
1023 VS_FIXEDFILEINFO
*TargetInfo
;
1024 VS_FIXEDFILEINFO
*SourceInfo
;
1026 WCHAR SubBlock
[2]={'\\',0};
1029 VersionSource
= HeapAlloc(GetProcessHeap(),0,VersionSizeSource
);
1030 VersionTarget
= HeapAlloc(GetProcessHeap(),0,VersionSizeTarget
);
1032 ret
= GetFileVersionInfoW((LPWSTR
)source
,0,VersionSizeSource
,VersionSource
);
1034 ret
= GetFileVersionInfoW((LPWSTR
)target
, 0, VersionSizeTarget
,
1039 ret
= VerQueryValueW(VersionSource
, SubBlock
,
1040 (LPVOID
*)&SourceInfo
, &length
);
1042 ret
= VerQueryValueW(VersionTarget
, SubBlock
,
1043 (LPVOID
*)&TargetInfo
, &length
);
1047 FILEPATHS_W filepaths
;
1049 TRACE("Versions: Source %i.%i target %i.%i\n",
1050 SourceInfo
->dwFileVersionMS
, SourceInfo
->dwFileVersionLS
,
1051 TargetInfo
->dwFileVersionMS
, TargetInfo
->dwFileVersionLS
);
1053 /* used in case of notification */
1054 filepaths
.Target
= target
;
1055 filepaths
.Source
= source
;
1056 filepaths
.Win32Error
= 0;
1057 filepaths
.Flags
= 0;
1059 if (TargetInfo
->dwFileVersionMS
> SourceInfo
->dwFileVersionMS
)
1062 docopy
= handler (context
, SPFILENOTIFY_TARGETNEWER
, (UINT_PTR
)&filepaths
, 0);
1066 else if ((TargetInfo
->dwFileVersionMS
== SourceInfo
->dwFileVersionMS
)
1067 && (TargetInfo
->dwFileVersionLS
> SourceInfo
->dwFileVersionLS
))
1070 docopy
= handler (context
, SPFILENOTIFY_TARGETNEWER
, (UINT_PTR
)&filepaths
, 0);
1074 else if ((style
& SP_COPY_NEWER_ONLY
) &&
1075 (TargetInfo
->dwFileVersionMS
==
1076 SourceInfo
->dwFileVersionMS
)
1077 &&(TargetInfo
->dwFileVersionLS
==
1078 SourceInfo
->dwFileVersionLS
))
1081 docopy
= handler (context
, SPFILENOTIFY_TARGETNEWER
, (UINT_PTR
)&filepaths
, 0);
1087 HeapFree(GetProcessHeap(),0,VersionSource
);
1088 HeapFree(GetProcessHeap(),0,VersionTarget
);
1091 if (style
& (SP_COPY_NOOVERWRITE
| SP_COPY_FORCE_NOOVERWRITE
))
1093 if (GetFileAttributesW(target
) != INVALID_FILE_ATTRIBUTES
)
1095 FIXME("Notify user target file exists\n");
1099 if (style
& (SP_COPY_NODECOMP
| SP_COPY_LANGUAGEAWARE
| SP_COPY_FORCE_IN_USE
|
1100 SP_COPY_IN_USE_NEEDS_REBOOT
| SP_COPY_NOSKIP
| SP_COPY_WARNIFSKIP
))
1102 ERR("Unsupported style(s) 0x%x\n",style
);
1107 rc
= CopyFileW(source
,target
,FALSE
);
1108 TRACE("Did copy... rc was %i\n",rc
);
1111 /* after copy processing */
1112 if (style
& SP_COPY_DELETESOURCE
)
1115 DeleteFileW(source
);
1121 /***********************************************************************
1122 * SetupInstallFileA (SETUPAPI.@)
1124 BOOL WINAPI
SetupInstallFileA( HINF hinf
, PINFCONTEXT inf_context
, PCSTR source
, PCSTR root
,
1125 PCSTR dest
, DWORD style
, PSP_FILE_CALLBACK_A handler
, PVOID context
)
1128 struct callback_WtoA_context ctx
;
1129 UNICODE_STRING sourceW
, rootW
, destW
;
1131 TRACE("%p %p %s %s %s %x %p %p\n", hinf
, inf_context
, debugstr_a(source
), debugstr_a(root
),
1132 debugstr_a(dest
), style
, handler
, context
);
1134 sourceW
.Buffer
= rootW
.Buffer
= destW
.Buffer
= NULL
;
1135 if (source
&& !RtlCreateUnicodeStringFromAsciiz( &sourceW
, source
))
1137 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1140 if (root
&& !RtlCreateUnicodeStringFromAsciiz( &rootW
, root
))
1142 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1145 if (dest
&& !RtlCreateUnicodeStringFromAsciiz( &destW
, dest
))
1147 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1151 ctx
.orig_context
= context
;
1152 ctx
.orig_handler
= handler
;
1154 ret
= SetupInstallFileW( hinf
, inf_context
, sourceW
.Buffer
, rootW
.Buffer
, destW
.Buffer
, style
, QUEUE_callback_WtoA
, &ctx
);
1157 RtlFreeUnicodeString( &sourceW
);
1158 RtlFreeUnicodeString( &rootW
);
1159 RtlFreeUnicodeString( &destW
);
1163 /***********************************************************************
1164 * SetupInstallFileW (SETUPAPI.@)
1166 BOOL WINAPI
SetupInstallFileW( HINF hinf
, PINFCONTEXT inf_context
, PCWSTR source
, PCWSTR root
,
1167 PCWSTR dest
, DWORD style
, PSP_FILE_CALLBACK_W handler
, PVOID context
)
1169 static const WCHAR CopyFiles
[] = {'C','o','p','y','F','i','l','e','s',0};
1171 BOOL ret
, absolute
= (root
&& *root
&& !(style
& SP_COPY_SOURCE_ABSOLUTE
));
1172 WCHAR
*buffer
, *p
, *inf_source
= NULL
;
1175 TRACE("%p %p %s %s %s %x %p %p\n", hinf
, inf_context
, debugstr_w(source
), debugstr_w(root
),
1176 debugstr_w(dest
), style
, handler
, context
);
1185 if (!SetupFindFirstLineW( hinf
, CopyFiles
, NULL
, inf_context
)) return FALSE
;
1187 if (!SetupGetStringFieldW( inf_context
, 1, NULL
, 0, (PDWORD
) &len
)) return FALSE
;
1188 if (!(inf_source
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
1190 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1193 if (!SetupGetStringFieldW( inf_context
, 1, inf_source
, len
, NULL
)) return FALSE
;
1194 source
= inf_source
;
1198 SetLastError( ERROR_INVALID_PARAMETER
);
1202 len
= strlenW( source
) + 1;
1203 if (absolute
) len
+= strlenW( root
) + 1;
1205 if (!(p
= buffer
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
1207 HeapFree( GetProcessHeap(), 0, inf_source
);
1208 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1214 strcpyW( buffer
, root
);
1215 p
+= strlenW( buffer
);
1216 if (p
[-1] != '\\') *p
++ = '\\';
1218 while (*source
== '\\') source
++;
1219 strcpyW( p
, source
);
1221 ret
= do_file_copyW( buffer
, dest
, style
, handler
, context
);
1223 HeapFree( GetProcessHeap(), 0, inf_source
);
1224 HeapFree( GetProcessHeap(), 0, buffer
);
1228 /***********************************************************************
1229 * SetupCommitFileQueueW (SETUPAPI.@)
1231 BOOL WINAPI
SetupCommitFileQueueW( HWND owner
, HSPFILEQ handle
, PSP_FILE_CALLBACK_W handler
,
1234 struct file_queue
*queue
= handle
;
1236 BOOL result
= FALSE
;
1240 paths
.Source
= paths
.Target
= NULL
;
1242 if (!queue
->copy_queue
.count
&& !queue
->delete_queue
.count
&& !queue
->rename_queue
.count
)
1243 return TRUE
; /* nothing to do */
1245 if (!handler( context
, SPFILENOTIFY_STARTQUEUE
, (UINT_PTR
)owner
, 0 )) return FALSE
;
1247 /* perform deletes */
1249 if (queue
->delete_queue
.count
)
1251 if (!(handler( context
, SPFILENOTIFY_STARTSUBQUEUE
, FILEOP_DELETE
,
1252 queue
->delete_queue
.count
))) goto done
;
1253 for (op
= queue
->delete_queue
.head
; op
; op
= op
->next
)
1255 build_filepathsW( op
, &paths
);
1256 op_result
= handler( context
, SPFILENOTIFY_STARTDELETE
, (UINT_PTR
)&paths
, FILEOP_DELETE
);
1257 if (op_result
== FILEOP_ABORT
) goto done
;
1258 while (op_result
== FILEOP_DOIT
)
1260 TRACE( "deleting file %s\n", debugstr_w(paths
.Target
) );
1261 if (DeleteFileW( paths
.Target
)) break; /* success */
1262 paths
.Win32Error
= GetLastError();
1263 op_result
= handler( context
, SPFILENOTIFY_DELETEERROR
, (UINT_PTR
)&paths
, 0 );
1264 if (op_result
== FILEOP_ABORT
) goto done
;
1266 handler( context
, SPFILENOTIFY_ENDDELETE
, (UINT_PTR
)&paths
, 0 );
1268 handler( context
, SPFILENOTIFY_ENDSUBQUEUE
, FILEOP_DELETE
, 0 );
1271 /* perform renames */
1273 if (queue
->rename_queue
.count
)
1275 if (!(handler( context
, SPFILENOTIFY_STARTSUBQUEUE
, FILEOP_RENAME
,
1276 queue
->rename_queue
.count
))) goto done
;
1277 for (op
= queue
->rename_queue
.head
; op
; op
= op
->next
)
1279 build_filepathsW( op
, &paths
);
1280 op_result
= handler( context
, SPFILENOTIFY_STARTRENAME
, (UINT_PTR
)&paths
, FILEOP_RENAME
);
1281 if (op_result
== FILEOP_ABORT
) goto done
;
1282 while (op_result
== FILEOP_DOIT
)
1284 TRACE( "renaming file %s -> %s\n",
1285 debugstr_w(paths
.Source
), debugstr_w(paths
.Target
) );
1286 if (MoveFileW( paths
.Source
, paths
.Target
)) break; /* success */
1287 paths
.Win32Error
= GetLastError();
1288 op_result
= handler( context
, SPFILENOTIFY_RENAMEERROR
, (UINT_PTR
)&paths
, 0 );
1289 if (op_result
== FILEOP_ABORT
) goto done
;
1291 handler( context
, SPFILENOTIFY_ENDRENAME
, (UINT_PTR
)&paths
, 0 );
1293 handler( context
, SPFILENOTIFY_ENDSUBQUEUE
, FILEOP_RENAME
, 0 );
1296 /* perform copies */
1298 if (queue
->copy_queue
.count
)
1300 if (!(handler( context
, SPFILENOTIFY_STARTSUBQUEUE
, FILEOP_COPY
,
1301 queue
->copy_queue
.count
))) goto done
;
1302 for (op
= queue
->copy_queue
.head
; op
; op
= op
->next
)
1304 WCHAR newpath
[MAX_PATH
];
1306 build_filepathsW( op
, &paths
);
1307 op_result
= handler( context
, SPFILENOTIFY_STARTCOPY
, (UINT_PTR
)&paths
, FILEOP_COPY
);
1308 if (op_result
== FILEOP_ABORT
) goto done
;
1309 if (op_result
== FILEOP_NEWPATH
) op_result
= FILEOP_DOIT
;
1310 while (op_result
== FILEOP_DOIT
|| op_result
== FILEOP_NEWPATH
)
1312 TRACE( "copying file %s -> %s\n",
1313 debugstr_w( op_result
== FILEOP_NEWPATH
? newpath
: paths
.Source
),
1314 debugstr_w(paths
.Target
) );
1317 if (!create_full_pathW( op
->dst_path
))
1319 paths
.Win32Error
= GetLastError();
1320 op_result
= handler( context
, SPFILENOTIFY_COPYERROR
,
1321 (UINT_PTR
)&paths
, (UINT_PTR
)newpath
);
1322 if (op_result
== FILEOP_ABORT
) goto done
;
1325 if (do_file_copyW( op_result
== FILEOP_NEWPATH
? newpath
: paths
.Source
,
1326 paths
.Target
, op
->style
, handler
, context
)) break; /* success */
1327 /* try to extract it from the cabinet file */
1330 if (extract_cabinet_file( op
->src_tag
, op
->src_root
,
1331 paths
.Source
, paths
.Target
)) break;
1333 paths
.Win32Error
= GetLastError();
1334 op_result
= handler( context
, SPFILENOTIFY_COPYERROR
,
1335 (UINT_PTR
)&paths
, (UINT_PTR
)newpath
);
1336 if (op_result
== FILEOP_ABORT
) goto done
;
1340 PSID psidOwner
= NULL
, psidGroup
= NULL
;
1341 PACL pDacl
= NULL
, pSacl
= NULL
;
1342 SECURITY_INFORMATION security_info
= 0;
1343 BOOL present
, dummy
;
1345 if (GetSecurityDescriptorOwner( op
->dst_sd
, &psidOwner
, &dummy
) && psidOwner
)
1346 security_info
|= OWNER_SECURITY_INFORMATION
;
1347 if (GetSecurityDescriptorGroup( op
->dst_sd
, &psidGroup
, &dummy
) && psidGroup
)
1348 security_info
|= GROUP_SECURITY_INFORMATION
;
1349 if (GetSecurityDescriptorDacl( op
->dst_sd
, &present
, &pDacl
, &dummy
))
1350 security_info
|= DACL_SECURITY_INFORMATION
;
1351 if (GetSecurityDescriptorSacl( op
->dst_sd
, &present
, &pSacl
, &dummy
))
1352 security_info
|= DACL_SECURITY_INFORMATION
;
1353 SetNamedSecurityInfoW( (LPWSTR
)paths
.Target
, SE_FILE_OBJECT
, security_info
,
1354 psidOwner
, psidGroup
, pDacl
, pSacl
);
1355 /* Yes, ignore the return code... */
1357 handler( context
, SPFILENOTIFY_ENDCOPY
, (UINT_PTR
)&paths
, 0 );
1359 handler( context
, SPFILENOTIFY_ENDSUBQUEUE
, FILEOP_COPY
, 0 );
1366 handler( context
, SPFILENOTIFY_ENDQUEUE
, result
, 0 );
1367 HeapFree( GetProcessHeap(), 0, (void *)paths
.Source
);
1368 HeapFree( GetProcessHeap(), 0, (void *)paths
.Target
);
1373 /***********************************************************************
1374 * SetupScanFileQueueA (SETUPAPI.@)
1376 BOOL WINAPI
SetupScanFileQueueA( HSPFILEQ handle
, DWORD flags
, HWND window
,
1377 PSP_FILE_CALLBACK_A handler
, PVOID context
, PDWORD result
)
1379 struct callback_WtoA_context ctx
;
1381 TRACE("%p %x %p %p %p %p\n", handle
, flags
, window
, handler
, context
, result
);
1383 ctx
.orig_context
= context
;
1384 ctx
.orig_handler
= handler
;
1386 return SetupScanFileQueueW( handle
, flags
, window
, QUEUE_callback_WtoA
, &ctx
, result
);
1390 /***********************************************************************
1391 * SetupScanFileQueueW (SETUPAPI.@)
1393 BOOL WINAPI
SetupScanFileQueueW( HSPFILEQ handle
, DWORD flags
, HWND window
,
1394 PSP_FILE_CALLBACK_W handler
, PVOID context
, PDWORD result
)
1396 struct file_queue
*queue
= handle
;
1399 UINT notification
= 0;
1402 TRACE("%p %x %p %p %p %p\n", handle
, flags
, window
, handler
, context
, result
);
1406 if (!queue
->copy_queue
.count
) return TRUE
;
1408 if (flags
& SPQ_SCAN_USE_CALLBACK
) notification
= SPFILENOTIFY_QUEUESCAN
;
1409 else if (flags
& SPQ_SCAN_USE_CALLBACKEX
) notification
= SPFILENOTIFY_QUEUESCAN_EX
;
1411 if (flags
& ~(SPQ_SCAN_USE_CALLBACK
| SPQ_SCAN_USE_CALLBACKEX
))
1413 FIXME("flags %x not fully implemented\n", flags
);
1416 paths
.Source
= paths
.Target
= NULL
;
1418 for (op
= queue
->copy_queue
.head
; op
; op
= op
->next
)
1420 build_filepathsW( op
, &paths
);
1421 switch (notification
)
1423 case SPFILENOTIFY_QUEUESCAN
:
1424 /* FIXME: handle delay flag */
1425 if (handler( context
, notification
, (UINT_PTR
)paths
.Target
, 0 )) goto done
;
1427 case SPFILENOTIFY_QUEUESCAN_EX
:
1428 if (handler( context
, notification
, (UINT_PTR
)&paths
, 0 )) goto done
;
1431 ret
= TRUE
; goto done
;
1438 HeapFree( GetProcessHeap(), 0, (void *)paths
.Source
);
1439 HeapFree( GetProcessHeap(), 0, (void *)paths
.Target
);
1444 /***********************************************************************
1445 * SetupGetFileQueueCount (SETUPAPI.@)
1447 BOOL WINAPI
SetupGetFileQueueCount( HSPFILEQ handle
, UINT op
, PUINT result
)
1449 struct file_queue
*queue
= handle
;
1454 *result
= queue
->copy_queue
.count
;
1457 *result
= queue
->rename_queue
.count
;
1460 *result
= queue
->delete_queue
.count
;
1467 /***********************************************************************
1468 * SetupGetFileQueueFlags (SETUPAPI.@)
1470 BOOL WINAPI
SetupGetFileQueueFlags( HSPFILEQ handle
, PDWORD flags
)
1472 struct file_queue
*queue
= handle
;
1473 *flags
= queue
->flags
;
1478 /***********************************************************************
1479 * SetupSetFileQueueFlags (SETUPAPI.@)
1481 BOOL WINAPI
SetupSetFileQueueFlags( HSPFILEQ handle
, DWORD mask
, DWORD flags
)
1483 struct file_queue
*queue
= handle
;
1484 queue
->flags
= (queue
->flags
& ~mask
) | flags
;
1489 /***********************************************************************
1490 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1492 BOOL WINAPI
SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle
, PSP_ALTPLATFORM_INFO platform
, PCSTR catalogfile
)
1494 FIXME("(%p, %p, %s) stub!\n", handle
, platform
, debugstr_a(catalogfile
));
1499 /***********************************************************************
1500 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1502 BOOL WINAPI
SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle
, PSP_ALTPLATFORM_INFO platform
, PCWSTR catalogfile
)
1504 FIXME("(%p, %p, %s) stub!\n", handle
, platform
, debugstr_w(catalogfile
));
1509 /***********************************************************************
1510 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1512 PVOID WINAPI
SetupInitDefaultQueueCallback( HWND owner
)
1514 return SetupInitDefaultQueueCallbackEx( owner
, 0, 0, 0, NULL
);
1518 /***********************************************************************
1519 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1521 PVOID WINAPI
SetupInitDefaultQueueCallbackEx( HWND owner
, HWND progress
, UINT msg
,
1522 DWORD reserved1
, PVOID reserved2
)
1524 struct default_callback_context
*context
;
1526 if ((context
= HeapAlloc( GetProcessHeap(), 0, sizeof(*context
) )))
1528 context
->owner
= owner
;
1529 context
->progress
= progress
;
1530 context
->message
= msg
;
1536 /***********************************************************************
1537 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1539 void WINAPI
SetupTermDefaultQueueCallback( PVOID context
)
1541 HeapFree( GetProcessHeap(), 0, context
);
1545 /***********************************************************************
1546 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1548 UINT WINAPI
SetupDefaultQueueCallbackA( PVOID context
, UINT notification
,
1549 UINT_PTR param1
, UINT_PTR param2
)
1551 FILEPATHS_A
*paths
= (FILEPATHS_A
*)param1
;
1552 struct default_callback_context
*ctx
= (struct default_callback_context
*)context
;
1554 switch(notification
)
1556 case SPFILENOTIFY_STARTQUEUE
:
1557 TRACE( "start queue\n" );
1559 case SPFILENOTIFY_ENDQUEUE
:
1560 TRACE( "end queue\n" );
1562 case SPFILENOTIFY_STARTSUBQUEUE
:
1563 TRACE( "start subqueue %ld count %ld\n", param1
, param2
);
1565 case SPFILENOTIFY_ENDSUBQUEUE
:
1566 TRACE( "end subqueue %ld\n", param1
);
1568 case SPFILENOTIFY_STARTDELETE
:
1569 TRACE( "start delete %s\n", debugstr_a(paths
->Target
) );
1571 case SPFILENOTIFY_ENDDELETE
:
1572 TRACE( "end delete %s\n", debugstr_a(paths
->Target
) );
1574 case SPFILENOTIFY_DELETEERROR
:
1575 /*Windows Ignores attempts to delete files / folders which do not exist*/
1576 if ((paths
->Win32Error
!= ERROR_FILE_NOT_FOUND
) && (paths
->Win32Error
!= ERROR_PATH_NOT_FOUND
))
1577 SetupDeleteErrorA(ctx
->owner
, NULL
, paths
->Target
, paths
->Win32Error
, 0);
1579 case SPFILENOTIFY_STARTRENAME
:
1580 TRACE( "start rename %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1582 case SPFILENOTIFY_ENDRENAME
:
1583 TRACE( "end rename %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1585 case SPFILENOTIFY_RENAMEERROR
:
1586 SetupRenameErrorA(ctx
->owner
, NULL
, paths
->Source
, paths
->Target
, paths
->Win32Error
, 0);
1588 case SPFILENOTIFY_STARTCOPY
:
1589 TRACE( "start copy %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1591 case SPFILENOTIFY_ENDCOPY
:
1592 TRACE( "end copy %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1594 case SPFILENOTIFY_COPYERROR
:
1595 ERR( "copy error %d %s -> %s\n", paths
->Win32Error
,
1596 debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1598 case SPFILENOTIFY_NEEDMEDIA
:
1599 TRACE( "need media\n" );
1602 FIXME( "notification %d params %lx,%lx\n", notification
, param1
, param2
);
1609 /***********************************************************************
1610 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1612 UINT WINAPI
SetupDefaultQueueCallbackW( PVOID context
, UINT notification
,
1613 UINT_PTR param1
, UINT_PTR param2
)
1615 FILEPATHS_W
*paths
= (FILEPATHS_W
*)param1
;
1616 struct default_callback_context
*ctx
= (struct default_callback_context
*)context
;
1618 switch(notification
)
1620 case SPFILENOTIFY_STARTQUEUE
:
1621 TRACE( "start queue\n" );
1623 case SPFILENOTIFY_ENDQUEUE
:
1624 TRACE( "end queue\n" );
1626 case SPFILENOTIFY_STARTSUBQUEUE
:
1627 TRACE( "start subqueue %ld count %ld\n", param1
, param2
);
1629 case SPFILENOTIFY_ENDSUBQUEUE
:
1630 TRACE( "end subqueue %ld\n", param1
);
1632 case SPFILENOTIFY_STARTDELETE
:
1633 TRACE( "start delete %s\n", debugstr_w(paths
->Target
) );
1635 case SPFILENOTIFY_ENDDELETE
:
1636 TRACE( "end delete %s\n", debugstr_w(paths
->Target
) );
1638 case SPFILENOTIFY_DELETEERROR
:
1639 /*Windows Ignores attempts to delete files / folders which do not exist*/
1640 if ((paths
->Win32Error
!= ERROR_FILE_NOT_FOUND
) && (paths
->Win32Error
!= ERROR_PATH_NOT_FOUND
))
1641 SetupDeleteErrorW(ctx
->owner
, NULL
, paths
->Target
, paths
->Win32Error
, 0);
1643 case SPFILENOTIFY_STARTRENAME
:
1644 SetupRenameErrorW(ctx
->owner
, NULL
, paths
->Source
, paths
->Target
, paths
->Win32Error
, 0);
1646 case SPFILENOTIFY_ENDRENAME
:
1647 TRACE( "end rename %s -> %s\n", debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1649 case SPFILENOTIFY_RENAMEERROR
:
1650 ERR( "rename error %d %s -> %s\n", paths
->Win32Error
,
1651 debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1653 case SPFILENOTIFY_STARTCOPY
:
1654 TRACE( "start copy %s -> %s\n", debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1656 case SPFILENOTIFY_ENDCOPY
:
1657 TRACE( "end copy %s -> %s\n", debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1659 case SPFILENOTIFY_COPYERROR
:
1660 ERR( "copy error %d %s -> %s\n", paths
->Win32Error
,
1661 debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1663 case SPFILENOTIFY_NEEDMEDIA
:
1664 TRACE( "need media\n" );
1667 FIXME( "notification %d params %lx,%lx\n", notification
, param1
, param2
);
1673 /***********************************************************************
1674 * SetupDeleteErrorA (SETUPAPI.@)
1677 UINT WINAPI
SetupDeleteErrorA( HWND parent
, PCSTR dialogTitle
, PCSTR file
,
1678 UINT w32error
, DWORD style
)
1680 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1681 w32error
, debugstr_a(file
) );
1682 return DPROMPT_SKIPFILE
;
1685 /***********************************************************************
1686 * SetupDeleteErrorW (SETUPAPI.@)
1689 UINT WINAPI
SetupDeleteErrorW( HWND parent
, PCWSTR dialogTitle
, PCWSTR file
,
1690 UINT w32error
, DWORD style
)
1692 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1693 w32error
, debugstr_w(file
) );
1694 return DPROMPT_SKIPFILE
;
1697 /***********************************************************************
1698 * SetupRenameErrorA (SETUPAPI.@)
1701 UINT WINAPI
SetupRenameErrorA( HWND parent
, PCSTR dialogTitle
, PCSTR source
,
1702 PCSTR target
, UINT w32error
, DWORD style
)
1704 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1705 w32error
, debugstr_a(source
), debugstr_a(target
));
1706 return DPROMPT_SKIPFILE
;
1709 /***********************************************************************
1710 * SetupRenameErrorW (SETUPAPI.@)
1713 UINT WINAPI
SetupRenameErrorW( HWND parent
, PCWSTR dialogTitle
, PCWSTR source
,
1714 PCWSTR target
, UINT w32error
, DWORD style
)
1716 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1717 w32error
, debugstr_w(source
), debugstr_w(target
));
1718 return DPROMPT_SKIPFILE
;
1722 /***********************************************************************
1723 * SetupCopyErrorA (SETUPAPI.@)
1726 UINT WINAPI
SetupCopyErrorA( HWND parent
, PCSTR dialogTitle
, PCSTR diskname
,
1727 PCSTR sourcepath
, PCSTR sourcefile
, PCSTR targetpath
,
1728 UINT w32error
, DWORD style
, PSTR pathbuffer
,
1729 DWORD buffersize
, PDWORD requiredsize
)
1731 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1732 w32error
, debugstr_a(sourcefile
), debugstr_a(sourcepath
) ,debugstr_a(targetpath
));
1733 return DPROMPT_SKIPFILE
;
1736 /***********************************************************************
1737 * SetupCopyErrorW (SETUPAPI.@)
1740 UINT WINAPI
SetupCopyErrorW( HWND parent
, PCWSTR dialogTitle
, PCWSTR diskname
,
1741 PCWSTR sourcepath
, PCWSTR sourcefile
, PCWSTR targetpath
,
1742 UINT w32error
, DWORD style
, PWSTR pathbuffer
,
1743 DWORD buffersize
, PDWORD requiredsize
)
1745 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1746 w32error
, debugstr_w(sourcefile
), debugstr_w(sourcepath
) ,debugstr_w(targetpath
));
1747 return DPROMPT_SKIPFILE
;
1750 /***********************************************************************
1751 * pSetupGetQueueFlags (SETUPAPI.@)
1753 DWORD WINAPI
pSetupGetQueueFlags( HSPFILEQ handle
)
1755 struct file_queue
*queue
= handle
;
1756 return queue
->flags
;
1759 /***********************************************************************
1760 * pSetupSetQueueFlags (SETUPAPI.@)
1762 BOOL WINAPI
pSetupSetQueueFlags( HSPFILEQ handle
, DWORD flags
)
1764 struct file_queue
*queue
= handle
;
1765 queue
->flags
= flags
;