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
32 #include "wine/unicode.h"
33 #include "setupapi_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
39 /* context structure for the default queue callback */
40 struct default_callback_context
69 struct file_op_queue copy_queue
;
70 struct file_op_queue delete_queue
;
71 struct file_op_queue rename_queue
;
76 /* append a file operation to a queue */
77 static inline void queue_file_op( struct file_op_queue
*queue
, struct file_op
*op
)
80 if (queue
->tail
) queue
->tail
->next
= op
;
81 else queue
->head
= op
;
86 /* free all the file operations on a given queue */
87 static void free_file_op_queue( struct file_op_queue
*queue
)
89 struct file_op
*t
, *op
= queue
->head
;
93 HeapFree( GetProcessHeap(), 0, op
->src_root
);
94 HeapFree( GetProcessHeap(), 0, op
->src_path
);
95 HeapFree( GetProcessHeap(), 0, op
->src_file
);
96 HeapFree( GetProcessHeap(), 0, op
->src_descr
);
97 HeapFree( GetProcessHeap(), 0, op
->src_tag
);
98 HeapFree( GetProcessHeap(), 0, op
->dst_path
);
99 if (op
->dst_file
!= op
->src_file
) HeapFree( GetProcessHeap(), 0, op
->dst_file
);
102 HeapFree( GetProcessHeap(), 0, t
);
106 /* concat 3 strings to make a path, handling separators correctly */
107 static void concat_W( WCHAR
*buffer
, const WCHAR
*src1
, const WCHAR
*src2
, const WCHAR
*src3
)
112 strcpyW( buffer
, src1
);
113 buffer
+= strlenW(buffer
);
114 if (buffer
[-1] != '\\') *buffer
++ = '\\';
115 if (src2
) while (*src2
== '\\') src2
++;
120 strcpyW( buffer
, src2
);
121 buffer
+= strlenW(buffer
);
122 if (buffer
[-1] != '\\') *buffer
++ = '\\';
123 if (src3
) while (*src3
== '\\') src3
++;
127 strcpyW( buffer
, src3
);
128 buffer
+= strlenW(buffer
);
133 /***********************************************************************
136 * Build a FILEPATHS_W structure for a given file operation.
138 static BOOL
build_filepathsW( const struct file_op
*op
, FILEPATHS_W
*paths
)
140 unsigned int src_len
= 1, dst_len
= 1;
141 WCHAR
*source
= (PWSTR
)paths
->Source
, *target
= (PWSTR
)paths
->Target
;
143 if (op
->src_root
) src_len
+= strlenW(op
->src_root
) + 1;
144 if (op
->src_path
) src_len
+= strlenW(op
->src_path
) + 1;
145 if (op
->src_file
) src_len
+= strlenW(op
->src_file
) + 1;
146 if (op
->dst_path
) dst_len
+= strlenW(op
->dst_path
) + 1;
147 if (op
->dst_file
) dst_len
+= strlenW(op
->dst_file
) + 1;
148 src_len
*= sizeof(WCHAR
);
149 dst_len
*= sizeof(WCHAR
);
151 if (!source
|| HeapSize( GetProcessHeap(), 0, source
) < src_len
)
153 HeapFree( GetProcessHeap(), 0, source
);
154 paths
->Source
= source
= HeapAlloc( GetProcessHeap(), 0, src_len
);
156 if (!target
|| HeapSize( GetProcessHeap(), 0, target
) < dst_len
)
158 HeapFree( GetProcessHeap(), 0, target
);
159 paths
->Target
= target
= HeapAlloc( GetProcessHeap(), 0, dst_len
);
161 if (!source
|| !target
) return FALSE
;
162 concat_W( source
, op
->src_root
, op
->src_path
, op
->src_file
);
163 concat_W( target
, NULL
, op
->dst_path
, op
->dst_file
);
164 paths
->Win32Error
= 0;
170 /***********************************************************************
171 * QUEUE_callback_WtoA
173 * Map a file callback parameters from W to A and call the A callback.
175 UINT CALLBACK
QUEUE_callback_WtoA( void *context
, UINT notification
,
176 UINT_PTR param1
, UINT_PTR param2
)
178 struct callback_WtoA_context
*callback_ctx
= context
;
179 char buffer
[MAX_PATH
];
181 UINT_PTR old_param2
= param2
;
185 case SPFILENOTIFY_COPYERROR
:
186 param2
= (UINT_PTR
)buffer
;
188 case SPFILENOTIFY_STARTDELETE
:
189 case SPFILENOTIFY_ENDDELETE
:
190 case SPFILENOTIFY_DELETEERROR
:
191 case SPFILENOTIFY_STARTRENAME
:
192 case SPFILENOTIFY_ENDRENAME
:
193 case SPFILENOTIFY_RENAMEERROR
:
194 case SPFILENOTIFY_STARTCOPY
:
195 case SPFILENOTIFY_ENDCOPY
:
196 case SPFILENOTIFY_QUEUESCAN_EX
:
198 FILEPATHS_W
*pathsW
= (FILEPATHS_W
*)param1
;
201 pathsA
.Source
= strdupWtoA( pathsW
->Source
);
202 pathsA
.Target
= strdupWtoA( pathsW
->Target
);
203 pathsA
.Win32Error
= pathsW
->Win32Error
;
204 pathsA
.Flags
= pathsW
->Flags
;
205 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
,
206 (UINT_PTR
)&pathsA
, param2
);
207 HeapFree( GetProcessHeap(), 0, (void *)pathsA
.Source
);
208 HeapFree( GetProcessHeap(), 0, (void *)pathsA
.Target
);
210 if (notification
== SPFILENOTIFY_COPYERROR
)
211 MultiByteToWideChar( CP_ACP
, 0, buffer
, -1, (WCHAR
*)old_param2
, MAX_PATH
);
214 case SPFILENOTIFY_STARTREGISTRATION
:
215 case SPFILENOTIFY_ENDREGISTRATION
:
217 SP_REGISTER_CONTROL_STATUSW
*statusW
= (SP_REGISTER_CONTROL_STATUSW
*)param1
;
218 SP_REGISTER_CONTROL_STATUSA statusA
;
220 statusA
.cbSize
= sizeof(statusA
);
221 statusA
.FileName
= strdupWtoA( statusW
->FileName
);
222 statusA
.Win32Error
= statusW
->Win32Error
;
223 statusA
.FailureCode
= statusW
->FailureCode
;
224 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
,
225 (UINT_PTR
)&statusA
, param2
);
226 HeapFree( GetProcessHeap(), 0, (LPSTR
)statusA
.FileName
);
230 case SPFILENOTIFY_QUEUESCAN
:
232 LPWSTR targetW
= (LPWSTR
)param1
;
233 LPSTR target
= strdupWtoA( targetW
);
235 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
,
236 (UINT_PTR
)target
, param2
);
237 HeapFree( GetProcessHeap(), 0, target
);
241 case SPFILENOTIFY_NEEDMEDIA
:
242 FIXME("mapping for %d not implemented\n",notification
);
243 case SPFILENOTIFY_STARTQUEUE
:
244 case SPFILENOTIFY_ENDQUEUE
:
245 case SPFILENOTIFY_STARTSUBQUEUE
:
246 case SPFILENOTIFY_ENDSUBQUEUE
:
248 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
, param1
, param2
);
255 /***********************************************************************
258 * Retrieve the source file information for a given file.
260 static void get_src_file_info( HINF hinf
, struct file_op
*op
)
262 static const WCHAR SourceDisksNames
[] =
263 {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0};
264 static const WCHAR SourceDisksFiles
[] =
265 {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
267 INFCONTEXT file_ctx
, disk_ctx
;
271 /* find the SourceDisksFiles entry */
272 if (!SetupFindFirstLineW( hinf
, SourceDisksFiles
, op
->src_file
, &file_ctx
))
274 if ((op
->style
& (SP_COPY_SOURCE_ABSOLUTE
|SP_COPY_SOURCEPATH_ABSOLUTE
))) return;
275 /* no specific info, use .inf file source directory */
276 if (!op
->src_root
) op
->src_root
= PARSER_get_src_root( hinf
);
279 if (!SetupGetIntField( &file_ctx
, 1, &diskid
)) return;
281 /* now find the diskid in the SourceDisksNames section */
282 if (!SetupFindFirstLineW( hinf
, SourceDisksNames
, NULL
, &disk_ctx
)) return;
285 if (SetupGetIntField( &disk_ctx
, 0, &id
) && (id
== diskid
)) break;
286 if (!SetupFindNextLine( &disk_ctx
, &disk_ctx
)) return;
289 /* and fill in the missing info */
293 if (SetupGetStringFieldW( &disk_ctx
, 1, NULL
, 0, &len
) &&
294 (op
->src_descr
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) )))
295 SetupGetStringFieldW( &disk_ctx
, 1, op
->src_descr
, len
, NULL
);
299 if (SetupGetStringFieldW( &disk_ctx
, 2, NULL
, 0, &len
) &&
300 (op
->src_tag
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) )))
301 SetupGetStringFieldW( &disk_ctx
, 2, op
->src_tag
, len
, NULL
);
303 if (!op
->src_path
&& !(op
->style
& SP_COPY_SOURCE_ABSOLUTE
))
306 if (!(op
->style
& SP_COPY_SOURCEPATH_ABSOLUTE
))
308 /* retrieve relative path for this disk */
309 if (!SetupGetStringFieldW( &disk_ctx
, 4, NULL
, 0, &len
)) len
= 0;
311 /* retrieve relative path for this file */
312 if (!SetupGetStringFieldW( &file_ctx
, 2, NULL
, 0, &len2
)) len2
= 0;
315 (op
->src_path
= HeapAlloc( GetProcessHeap(), 0, (len
+len2
)*sizeof(WCHAR
) )))
317 WCHAR
*ptr
= op
->src_path
;
320 SetupGetStringFieldW( &disk_ctx
, 4, op
->src_path
, len
, NULL
);
321 ptr
= op
->src_path
+ strlenW(op
->src_path
);
322 if (len2
&& ptr
> op
->src_path
&& ptr
[-1] != '\\') *ptr
++ = '\\';
324 if (!SetupGetStringFieldW( &file_ctx
, 2, ptr
, len2
, NULL
)) *ptr
= 0;
327 if (!op
->src_root
) op
->src_root
= PARSER_get_src_root(hinf
);
331 /***********************************************************************
332 * get_destination_dir
334 * Retrieve the destination dir for a given section.
336 static WCHAR
*get_destination_dir( HINF hinf
, const WCHAR
*section
)
338 static const WCHAR Dest
[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
339 static const WCHAR Def
[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
342 if (!SetupFindFirstLineW( hinf
, Dest
, section
, &context
) &&
343 !SetupFindFirstLineW( hinf
, Dest
, Def
, &context
)) return NULL
;
344 return PARSER_get_dest_dir( &context
);
348 static void (WINAPI
*pExtractFiles
)( LPSTR
, LPSTR
, DWORD
, DWORD
, DWORD
, DWORD
);
350 /***********************************************************************
351 * extract_cabinet_file
353 * Extract a file from a .cab file.
355 static BOOL
extract_cabinet_file( const WCHAR
*cabinet
, const WCHAR
*root
,
356 const WCHAR
*src
, const WCHAR
*dst
)
358 static const WCHAR extW
[] = {'.','c','a','b',0};
359 static HMODULE advpack
;
361 char *cab_path
, *cab_file
;
362 int len
= strlenW( cabinet
);
364 /* make sure the cabinet file has a .cab extension */
365 if (len
<= 4 || strcmpiW( cabinet
+ len
- 4, extW
)) return FALSE
;
368 if (!advpack
&& !(advpack
= LoadLibraryA( "advpack.dll" )))
370 ERR( "could not load advpack.dll\n" );
373 if (!(pExtractFiles
= (void *)GetProcAddress( advpack
, "ExtractFiles" )))
375 ERR( "could not find ExtractFiles in advpack.dll\n" );
380 if (!(cab_path
= strdupWtoA( root
))) return FALSE
;
381 len
= WideCharToMultiByte( CP_ACP
, 0, cabinet
, -1, NULL
, 0, NULL
, NULL
);
382 if (!(cab_file
= HeapAlloc( GetProcessHeap(), 0, strlen(cab_path
) + len
+ 1 )))
384 HeapFree( GetProcessHeap(), 0, cab_path
);
387 strcpy( cab_file
, cab_path
);
388 if (cab_file
[0] && cab_file
[strlen(cab_file
)-1] != '\\') strcat( cab_file
, "\\" );
389 WideCharToMultiByte( CP_ACP
, 0, cabinet
, -1, cab_file
+ strlen(cab_file
), len
, NULL
, NULL
);
390 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file
) );
391 pExtractFiles( cab_file
, cab_path
, 0, 0, 0, 0 );
392 HeapFree( GetProcessHeap(), 0, cab_file
);
393 HeapFree( GetProcessHeap(), 0, cab_path
);
394 return CopyFileW( src
, dst
, FALSE
/*FIXME*/ );
398 /***********************************************************************
399 * SetupOpenFileQueue (SETUPAPI.@)
401 HSPFILEQ WINAPI
SetupOpenFileQueue(void)
403 struct file_queue
*queue
;
405 if (!(queue
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*queue
))))
406 return INVALID_HANDLE_VALUE
;
411 /***********************************************************************
412 * SetupCloseFileQueue (SETUPAPI.@)
414 BOOL WINAPI
SetupCloseFileQueue( HSPFILEQ handle
)
416 struct file_queue
*queue
= handle
;
418 free_file_op_queue( &queue
->copy_queue
);
419 free_file_op_queue( &queue
->rename_queue
);
420 free_file_op_queue( &queue
->delete_queue
);
421 HeapFree( GetProcessHeap(), 0, queue
);
426 /***********************************************************************
427 * SetupQueueCopyIndirectA (SETUPAPI.@)
429 BOOL WINAPI
SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params
)
431 struct file_queue
*queue
= params
->QueueHandle
;
434 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
435 op
->style
= params
->CopyStyle
;
436 op
->src_root
= strdupAtoW( params
->SourceRootPath
);
437 op
->src_path
= strdupAtoW( params
->SourcePath
);
438 op
->src_file
= strdupAtoW( params
->SourceFilename
);
439 op
->src_descr
= strdupAtoW( params
->SourceDescription
);
440 op
->src_tag
= strdupAtoW( params
->SourceTagfile
);
441 op
->dst_path
= strdupAtoW( params
->TargetDirectory
);
442 op
->dst_file
= strdupAtoW( params
->TargetFilename
);
445 if (!op
->src_file
) op
->src_file
= op
->dst_file
;
446 if (params
->LayoutInf
)
448 get_src_file_info( params
->LayoutInf
, op
);
449 if (!op
->dst_path
) op
->dst_path
= get_destination_dir( params
->LayoutInf
, op
->dst_file
);
452 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
453 debugstr_w(op
->src_root
), debugstr_w(op
->src_path
), debugstr_w(op
->src_file
),
454 debugstr_w(op
->dst_path
), debugstr_w(op
->dst_file
),
455 debugstr_w(op
->src_descr
), debugstr_w(op
->src_tag
) );
457 queue_file_op( &queue
->copy_queue
, op
);
462 /***********************************************************************
463 * SetupQueueCopyIndirectW (SETUPAPI.@)
465 BOOL WINAPI
SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params
)
467 struct file_queue
*queue
= params
->QueueHandle
;
470 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
471 op
->style
= params
->CopyStyle
;
472 op
->src_root
= strdupW( params
->SourceRootPath
);
473 op
->src_path
= strdupW( params
->SourcePath
);
474 op
->src_file
= strdupW( params
->SourceFilename
);
475 op
->src_descr
= strdupW( params
->SourceDescription
);
476 op
->src_tag
= strdupW( params
->SourceTagfile
);
477 op
->dst_path
= strdupW( params
->TargetDirectory
);
478 op
->dst_file
= strdupW( params
->TargetFilename
);
481 if (!op
->src_file
) op
->src_file
= op
->dst_file
;
482 if (params
->LayoutInf
)
484 get_src_file_info( params
->LayoutInf
, op
);
485 if (!op
->dst_path
) op
->dst_path
= get_destination_dir( params
->LayoutInf
, op
->dst_file
);
488 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
489 debugstr_w(op
->src_root
), debugstr_w(op
->src_path
), debugstr_w(op
->src_file
),
490 debugstr_w(op
->dst_path
), debugstr_w(op
->dst_file
),
491 debugstr_w(op
->src_descr
), debugstr_w(op
->src_tag
) );
493 queue_file_op( &queue
->copy_queue
, op
);
498 /***********************************************************************
499 * SetupQueueCopyA (SETUPAPI.@)
501 BOOL WINAPI
SetupQueueCopyA( HSPFILEQ queue
, PCSTR src_root
, PCSTR src_path
, PCSTR src_file
,
502 PCSTR src_descr
, PCSTR src_tag
, PCSTR dst_dir
, PCSTR dst_file
,
505 SP_FILE_COPY_PARAMS_A params
;
507 params
.cbSize
= sizeof(params
);
508 params
.QueueHandle
= queue
;
509 params
.SourceRootPath
= src_root
;
510 params
.SourcePath
= src_path
;
511 params
.SourceFilename
= src_file
;
512 params
.SourceDescription
= src_descr
;
513 params
.SourceTagfile
= src_tag
;
514 params
.TargetDirectory
= dst_dir
;
515 params
.TargetFilename
= dst_file
;
516 params
.CopyStyle
= style
;
517 params
.LayoutInf
= 0;
518 params
.SecurityDescriptor
= NULL
;
519 return SetupQueueCopyIndirectA( ¶ms
);
523 /***********************************************************************
524 * SetupQueueCopyW (SETUPAPI.@)
526 BOOL WINAPI
SetupQueueCopyW( HSPFILEQ queue
, PCWSTR src_root
, PCWSTR src_path
, PCWSTR src_file
,
527 PCWSTR src_descr
, PCWSTR src_tag
, PCWSTR dst_dir
, PCWSTR dst_file
,
530 SP_FILE_COPY_PARAMS_W params
;
532 params
.cbSize
= sizeof(params
);
533 params
.QueueHandle
= queue
;
534 params
.SourceRootPath
= src_root
;
535 params
.SourcePath
= src_path
;
536 params
.SourceFilename
= src_file
;
537 params
.SourceDescription
= src_descr
;
538 params
.SourceTagfile
= src_tag
;
539 params
.TargetDirectory
= dst_dir
;
540 params
.TargetFilename
= dst_file
;
541 params
.CopyStyle
= style
;
542 params
.LayoutInf
= 0;
543 params
.SecurityDescriptor
= NULL
;
544 return SetupQueueCopyIndirectW( ¶ms
);
548 /***********************************************************************
549 * SetupQueueDefaultCopyA (SETUPAPI.@)
551 BOOL WINAPI
SetupQueueDefaultCopyA( HSPFILEQ queue
, HINF hinf
, PCSTR src_root
, PCSTR src_file
,
552 PCSTR dst_file
, DWORD style
)
554 SP_FILE_COPY_PARAMS_A params
;
556 params
.cbSize
= sizeof(params
);
557 params
.QueueHandle
= queue
;
558 params
.SourceRootPath
= src_root
;
559 params
.SourcePath
= NULL
;
560 params
.SourceFilename
= src_file
;
561 params
.SourceDescription
= NULL
;
562 params
.SourceTagfile
= NULL
;
563 params
.TargetDirectory
= NULL
;
564 params
.TargetFilename
= dst_file
;
565 params
.CopyStyle
= style
;
566 params
.LayoutInf
= hinf
;
567 params
.SecurityDescriptor
= NULL
;
568 return SetupQueueCopyIndirectA( ¶ms
);
572 /***********************************************************************
573 * SetupQueueDefaultCopyW (SETUPAPI.@)
575 BOOL WINAPI
SetupQueueDefaultCopyW( HSPFILEQ queue
, HINF hinf
, PCWSTR src_root
, PCWSTR src_file
,
576 PCWSTR dst_file
, DWORD style
)
578 SP_FILE_COPY_PARAMS_W params
;
580 params
.cbSize
= sizeof(params
);
581 params
.QueueHandle
= queue
;
582 params
.SourceRootPath
= src_root
;
583 params
.SourcePath
= NULL
;
584 params
.SourceFilename
= src_file
;
585 params
.SourceDescription
= NULL
;
586 params
.SourceTagfile
= NULL
;
587 params
.TargetDirectory
= NULL
;
588 params
.TargetFilename
= dst_file
;
589 params
.CopyStyle
= style
;
590 params
.LayoutInf
= hinf
;
591 params
.SecurityDescriptor
= NULL
;
592 return SetupQueueCopyIndirectW( ¶ms
);
596 /***********************************************************************
597 * SetupQueueDeleteA (SETUPAPI.@)
599 BOOL WINAPI
SetupQueueDeleteA( HSPFILEQ handle
, PCSTR part1
, PCSTR part2
)
601 struct file_queue
*queue
= handle
;
604 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
609 op
->src_descr
= NULL
;
611 op
->dst_path
= strdupAtoW( part1
);
612 op
->dst_file
= strdupAtoW( part2
);
613 queue_file_op( &queue
->delete_queue
, op
);
618 /***********************************************************************
619 * SetupQueueDeleteW (SETUPAPI.@)
621 BOOL WINAPI
SetupQueueDeleteW( HSPFILEQ handle
, PCWSTR part1
, PCWSTR part2
)
623 struct file_queue
*queue
= handle
;
626 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
631 op
->src_descr
= NULL
;
633 op
->dst_path
= strdupW( part1
);
634 op
->dst_file
= strdupW( part2
);
635 queue_file_op( &queue
->delete_queue
, op
);
640 /***********************************************************************
641 * SetupQueueRenameA (SETUPAPI.@)
643 BOOL WINAPI
SetupQueueRenameA( HSPFILEQ handle
, PCSTR SourcePath
, PCSTR SourceFilename
,
644 PCSTR TargetPath
, PCSTR TargetFilename
)
646 struct file_queue
*queue
= handle
;
649 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
652 op
->src_path
= strdupAtoW( SourcePath
);
653 op
->src_file
= strdupAtoW( SourceFilename
);
654 op
->src_descr
= NULL
;
656 op
->dst_path
= strdupAtoW( TargetPath
);
657 op
->dst_file
= strdupAtoW( TargetFilename
);
658 queue_file_op( &queue
->rename_queue
, op
);
663 /***********************************************************************
664 * SetupQueueRenameW (SETUPAPI.@)
666 BOOL WINAPI
SetupQueueRenameW( HSPFILEQ handle
, PCWSTR SourcePath
, PCWSTR SourceFilename
,
667 PCWSTR TargetPath
, PCWSTR TargetFilename
)
669 struct file_queue
*queue
= handle
;
672 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
675 op
->src_path
= strdupW( SourcePath
);
676 op
->src_file
= strdupW( SourceFilename
);
677 op
->src_descr
= NULL
;
679 op
->dst_path
= strdupW( TargetPath
);
680 op
->dst_file
= strdupW( TargetFilename
);
681 queue_file_op( &queue
->rename_queue
, op
);
686 /***********************************************************************
687 * SetupQueueCopySectionA (SETUPAPI.@)
689 BOOL WINAPI
SetupQueueCopySectionA( HSPFILEQ queue
, PCSTR src_root
, HINF hinf
, HINF hlist
,
690 PCSTR section
, DWORD style
)
692 UNICODE_STRING sectionW
;
695 if (!RtlCreateUnicodeStringFromAsciiz( §ionW
, section
))
697 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
701 ret
= SetupQueueCopySectionW( queue
, NULL
, hinf
, hlist
, sectionW
.Buffer
, style
);
705 if (RtlCreateUnicodeStringFromAsciiz( &srcW
, src_root
))
707 ret
= SetupQueueCopySectionW( queue
, srcW
.Buffer
, hinf
, hlist
, sectionW
.Buffer
, style
);
708 RtlFreeUnicodeString( &srcW
);
710 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
712 RtlFreeUnicodeString( §ionW
);
717 /***********************************************************************
718 * SetupQueueCopySectionW (SETUPAPI.@)
720 BOOL WINAPI
SetupQueueCopySectionW( HSPFILEQ queue
, PCWSTR src_root
, HINF hinf
, HINF hlist
,
721 PCWSTR section
, DWORD style
)
723 SP_FILE_COPY_PARAMS_W params
;
725 WCHAR dest
[MAX_PATH
], src
[MAX_PATH
];
728 TRACE( "hinf=%p/%p section=%s root=%s\n",
729 hinf
, hlist
, debugstr_w(section
), debugstr_w(src_root
) );
731 params
.cbSize
= sizeof(params
);
732 params
.QueueHandle
= queue
;
733 params
.SourceRootPath
= src_root
;
734 params
.SourcePath
= NULL
;
735 params
.SourceDescription
= NULL
;
736 params
.SourceTagfile
= NULL
;
737 params
.TargetFilename
= dest
;
738 params
.CopyStyle
= style
;
739 params
.LayoutInf
= hinf
;
740 params
.SecurityDescriptor
= NULL
;
742 if (!hlist
) hlist
= hinf
;
743 if (!hinf
) hinf
= hlist
;
744 if (!SetupFindFirstLineW( hlist
, section
, NULL
, &context
)) return FALSE
;
745 if (!(params
.TargetDirectory
= get_destination_dir( hinf
, section
))) return FALSE
;
748 if (!SetupGetStringFieldW( &context
, 1, dest
, sizeof(dest
)/sizeof(WCHAR
), NULL
))
750 if (!SetupGetStringFieldW( &context
, 2, src
, sizeof(src
)/sizeof(WCHAR
), NULL
)) *src
= 0;
751 if (!SetupGetIntField( &context
, 4, &flags
)) flags
= 0; /* FIXME */
753 params
.SourceFilename
= *src
? src
: NULL
;
754 if (!SetupQueueCopyIndirectW( ¶ms
)) return FALSE
;
755 } while (SetupFindNextLine( &context
, &context
));
760 /***********************************************************************
761 * SetupQueueDeleteSectionA (SETUPAPI.@)
763 BOOL WINAPI
SetupQueueDeleteSectionA( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCSTR section
)
765 UNICODE_STRING sectionW
;
768 if (RtlCreateUnicodeStringFromAsciiz( §ionW
, section
))
770 ret
= SetupQueueDeleteSectionW( queue
, hinf
, hlist
, sectionW
.Buffer
);
771 RtlFreeUnicodeString( §ionW
);
773 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
778 /***********************************************************************
779 * SetupQueueDeleteSectionW (SETUPAPI.@)
781 BOOL WINAPI
SetupQueueDeleteSectionW( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCWSTR section
)
785 WCHAR buffer
[MAX_PATH
];
789 TRACE( "hinf=%p/%p section=%s\n", hinf
, hlist
, debugstr_w(section
) );
791 if (!hlist
) hlist
= hinf
;
792 if (!SetupFindFirstLineW( hlist
, section
, NULL
, &context
)) return FALSE
;
793 if (!(dest_dir
= get_destination_dir( hinf
, section
))) return FALSE
;
796 if (!SetupGetStringFieldW( &context
, 1, buffer
, sizeof(buffer
)/sizeof(WCHAR
), NULL
))
798 if (!SetupGetIntField( &context
, 4, &flags
)) flags
= 0;
799 if (!SetupQueueDeleteW( queue
, dest_dir
, buffer
)) goto done
;
800 } while (SetupFindNextLine( &context
, &context
));
804 HeapFree( GetProcessHeap(), 0, dest_dir
);
809 /***********************************************************************
810 * SetupQueueRenameSectionA (SETUPAPI.@)
812 BOOL WINAPI
SetupQueueRenameSectionA( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCSTR section
)
814 UNICODE_STRING sectionW
;
817 if (RtlCreateUnicodeStringFromAsciiz( §ionW
, section
))
819 ret
= SetupQueueRenameSectionW( queue
, hinf
, hlist
, sectionW
.Buffer
);
820 RtlFreeUnicodeString( §ionW
);
822 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
827 /***********************************************************************
828 * SetupQueueRenameSectionW (SETUPAPI.@)
830 BOOL WINAPI
SetupQueueRenameSectionW( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCWSTR section
)
834 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
837 TRACE( "hinf=%p/%p section=%s\n", hinf
, hlist
, debugstr_w(section
) );
839 if (!hlist
) hlist
= hinf
;
840 if (!SetupFindFirstLineW( hlist
, section
, NULL
, &context
)) return FALSE
;
841 if (!(dest_dir
= get_destination_dir( hinf
, section
))) return FALSE
;
844 if (!SetupGetStringFieldW( &context
, 1, dst
, sizeof(dst
)/sizeof(WCHAR
), NULL
))
846 if (!SetupGetStringFieldW( &context
, 2, src
, sizeof(src
)/sizeof(WCHAR
), NULL
))
848 if (!SetupQueueRenameW( queue
, dest_dir
, src
, NULL
, dst
)) goto done
;
849 } while (SetupFindNextLine( &context
, &context
));
853 HeapFree( GetProcessHeap(), 0, dest_dir
);
858 /***********************************************************************
859 * SetupCommitFileQueueA (SETUPAPI.@)
861 BOOL WINAPI
SetupCommitFileQueueA( HWND owner
, HSPFILEQ queue
, PSP_FILE_CALLBACK_A handler
,
864 struct callback_WtoA_context ctx
;
866 ctx
.orig_context
= context
;
867 ctx
.orig_handler
= handler
;
868 return SetupCommitFileQueueW( owner
, queue
, QUEUE_callback_WtoA
, &ctx
);
872 /***********************************************************************
875 * Recursively create all directories in the path.
877 static BOOL
create_full_pathW(const WCHAR
*path
)
883 new_path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(path
) + 1) * sizeof(WCHAR
));
884 strcpyW(new_path
, path
);
886 while((len
= strlenW(new_path
)) && new_path
[len
- 1] == '\\')
887 new_path
[len
- 1] = 0;
889 while(!CreateDirectoryW(new_path
, NULL
))
892 DWORD last_error
= GetLastError();
894 if(last_error
== ERROR_ALREADY_EXISTS
)
897 if(last_error
!= ERROR_PATH_NOT_FOUND
)
903 if(!(slash
= strrchrW(new_path
, '\\')))
909 len
= slash
- new_path
;
911 if(!create_full_pathW(new_path
))
916 new_path
[len
] = '\\';
919 HeapFree(GetProcessHeap(), 0, new_path
);
923 static BOOL
do_file_copyW( LPCWSTR source
, LPCWSTR target
, DWORD style
,
924 PSP_FILE_CALLBACK_W handler
, PVOID context
)
929 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source
),debugstr_w(target
),style
);
931 /* before copy processing */
932 if (style
& SP_COPY_REPLACEONLY
)
934 if (GetFileAttributesW(target
) == INVALID_FILE_ATTRIBUTES
)
937 if (style
& (SP_COPY_NEWER_OR_SAME
| SP_COPY_NEWER_ONLY
| SP_COPY_FORCE_NEWER
))
939 DWORD VersionSizeSource
=0;
940 DWORD VersionSizeTarget
=0;
944 * This is sort of an interesting workaround. You see, calling
945 * GetVersionInfoSize on a builtin dll loads that dll into memory
946 * and we do not properly unload builtin dlls.. so we effectively
947 * lock into memory all the targets we are replacing. This leads
948 * to problems when we try to register the replaced dlls.
950 * So I will test for the existence of the files first so that
951 * we just basically unconditionally replace the builtin versions.
953 if ((GetFileAttributesW(target
) != INVALID_FILE_ATTRIBUTES
) &&
954 (GetFileAttributesW(source
) != INVALID_FILE_ATTRIBUTES
))
956 VersionSizeSource
= GetFileVersionInfoSizeW(source
,&zero
);
957 VersionSizeTarget
= GetFileVersionInfoSizeW(target
,&zero
);
960 TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget
,
963 if (VersionSizeSource
&& VersionSizeTarget
)
965 LPVOID VersionSource
;
966 LPVOID VersionTarget
;
967 VS_FIXEDFILEINFO
*TargetInfo
;
968 VS_FIXEDFILEINFO
*SourceInfo
;
970 WCHAR SubBlock
[2]={'\\',0};
973 VersionSource
= HeapAlloc(GetProcessHeap(),0,VersionSizeSource
);
974 VersionTarget
= HeapAlloc(GetProcessHeap(),0,VersionSizeTarget
);
976 ret
= GetFileVersionInfoW(source
,0,VersionSizeSource
,VersionSource
);
978 ret
= GetFileVersionInfoW(target
, 0, VersionSizeTarget
,
983 ret
= VerQueryValueW(VersionSource
, SubBlock
,
984 (LPVOID
*)&SourceInfo
, &length
);
986 ret
= VerQueryValueW(VersionTarget
, SubBlock
,
987 (LPVOID
*)&TargetInfo
, &length
);
991 FILEPATHS_W filepaths
;
993 TRACE("Versions: Source %i.%i target %i.%i\n",
994 SourceInfo
->dwFileVersionMS
, SourceInfo
->dwFileVersionLS
,
995 TargetInfo
->dwFileVersionMS
, TargetInfo
->dwFileVersionLS
);
997 /* used in case of notification */
998 filepaths
.Target
= target
;
999 filepaths
.Source
= source
;
1000 filepaths
.Win32Error
= 0;
1001 filepaths
.Flags
= 0;
1003 if (TargetInfo
->dwFileVersionMS
> SourceInfo
->dwFileVersionMS
)
1006 docopy
= handler (context
, SPFILENOTIFY_TARGETNEWER
, (UINT_PTR
)&filepaths
, 0);
1010 else if ((TargetInfo
->dwFileVersionMS
== SourceInfo
->dwFileVersionMS
)
1011 && (TargetInfo
->dwFileVersionLS
> SourceInfo
->dwFileVersionLS
))
1014 docopy
= handler (context
, SPFILENOTIFY_TARGETNEWER
, (UINT_PTR
)&filepaths
, 0);
1018 else if ((style
& SP_COPY_NEWER_ONLY
) &&
1019 (TargetInfo
->dwFileVersionMS
==
1020 SourceInfo
->dwFileVersionMS
)
1021 &&(TargetInfo
->dwFileVersionLS
==
1022 SourceInfo
->dwFileVersionLS
))
1025 docopy
= handler (context
, SPFILENOTIFY_TARGETNEWER
, (UINT_PTR
)&filepaths
, 0);
1031 HeapFree(GetProcessHeap(),0,VersionSource
);
1032 HeapFree(GetProcessHeap(),0,VersionTarget
);
1035 if (style
& (SP_COPY_NOOVERWRITE
| SP_COPY_FORCE_NOOVERWRITE
))
1037 if (GetFileAttributesW(target
) != INVALID_FILE_ATTRIBUTES
)
1039 FIXME("Notify user target file exists\n");
1043 if (style
& (SP_COPY_NODECOMP
| SP_COPY_LANGUAGEAWARE
| SP_COPY_FORCE_IN_USE
|
1044 SP_COPY_IN_USE_NEEDS_REBOOT
| SP_COPY_NOSKIP
| SP_COPY_WARNIFSKIP
))
1046 ERR("Unsupported style(s) 0x%x\n",style
);
1051 rc
= CopyFileW(source
,target
,FALSE
);
1052 TRACE("Did copy... rc was %i\n",rc
);
1055 /* after copy processing */
1056 if (style
& SP_COPY_DELETESOURCE
)
1059 DeleteFileW(source
);
1065 /***********************************************************************
1066 * SetupInstallFileA (SETUPAPI.@)
1068 BOOL WINAPI
SetupInstallFileA( HINF hinf
, PINFCONTEXT inf_context
, PCSTR source
, PCSTR root
,
1069 PCSTR dest
, DWORD style
, PSP_FILE_CALLBACK_A handler
, PVOID context
)
1072 struct callback_WtoA_context ctx
;
1073 UNICODE_STRING sourceW
, rootW
, destW
;
1075 TRACE("%p %p %s %s %s %x %p %p\n", hinf
, inf_context
, debugstr_a(source
), debugstr_a(root
),
1076 debugstr_a(dest
), style
, handler
, context
);
1078 sourceW
.Buffer
= rootW
.Buffer
= destW
.Buffer
= NULL
;
1079 if (source
&& !RtlCreateUnicodeStringFromAsciiz( &sourceW
, source
))
1081 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1084 if (root
&& !RtlCreateUnicodeStringFromAsciiz( &rootW
, root
))
1086 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1089 if (dest
&& !RtlCreateUnicodeStringFromAsciiz( &destW
, dest
))
1091 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1095 ctx
.orig_context
= context
;
1096 ctx
.orig_handler
= handler
;
1098 ret
= SetupInstallFileW( hinf
, inf_context
, sourceW
.Buffer
, rootW
.Buffer
, destW
.Buffer
, style
, QUEUE_callback_WtoA
, &ctx
);
1101 RtlFreeUnicodeString( &sourceW
);
1102 RtlFreeUnicodeString( &rootW
);
1103 RtlFreeUnicodeString( &destW
);
1107 /***********************************************************************
1108 * SetupInstallFileW (SETUPAPI.@)
1110 BOOL WINAPI
SetupInstallFileW( HINF hinf
, PINFCONTEXT inf_context
, PCWSTR source
, PCWSTR root
,
1111 PCWSTR dest
, DWORD style
, PSP_FILE_CALLBACK_W handler
, PVOID context
)
1113 static const WCHAR CopyFiles
[] = {'C','o','p','y','F','i','l','e','s',0};
1115 BOOL ret
, absolute
= (root
&& *root
&& !(style
& SP_COPY_SOURCE_ABSOLUTE
));
1116 WCHAR
*buffer
, *p
, *inf_source
= NULL
;
1119 TRACE("%p %p %s %s %s %x %p %p\n", hinf
, inf_context
, debugstr_w(source
), debugstr_w(root
),
1120 debugstr_w(dest
), style
, handler
, context
);
1129 if (!SetupFindFirstLineW( hinf
, CopyFiles
, NULL
, inf_context
)) return FALSE
;
1131 if (!SetupGetStringFieldW( inf_context
, 1, NULL
, 0, &len
)) return FALSE
;
1132 if (!(inf_source
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
1134 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1137 if (!SetupGetStringFieldW( inf_context
, 1, inf_source
, len
, NULL
)) return FALSE
;
1138 source
= inf_source
;
1142 SetLastError( ERROR_INVALID_PARAMETER
);
1146 len
= strlenW( source
) + 1;
1147 if (absolute
) len
+= strlenW( root
) + 1;
1149 if (!(p
= buffer
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
1151 HeapFree( GetProcessHeap(), 0, inf_source
);
1152 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1158 strcpyW( buffer
, root
);
1159 p
+= strlenW( buffer
);
1160 if (p
[-1] != '\\') *p
++ = '\\';
1162 while (*source
== '\\') source
++;
1163 strcpyW( p
, source
);
1165 ret
= do_file_copyW( buffer
, dest
, style
, handler
, context
);
1167 HeapFree( GetProcessHeap(), 0, inf_source
);
1168 HeapFree( GetProcessHeap(), 0, buffer
);
1172 /***********************************************************************
1173 * SetupCommitFileQueueW (SETUPAPI.@)
1175 BOOL WINAPI
SetupCommitFileQueueW( HWND owner
, HSPFILEQ handle
, PSP_FILE_CALLBACK_W handler
,
1178 struct file_queue
*queue
= handle
;
1180 BOOL result
= FALSE
;
1184 paths
.Source
= paths
.Target
= NULL
;
1186 if (!queue
->copy_queue
.count
&& !queue
->delete_queue
.count
&& !queue
->rename_queue
.count
)
1187 return TRUE
; /* nothing to do */
1189 if (!handler( context
, SPFILENOTIFY_STARTQUEUE
, (UINT_PTR
)owner
, 0 )) return FALSE
;
1191 /* perform deletes */
1193 if (queue
->delete_queue
.count
)
1195 if (!(handler( context
, SPFILENOTIFY_STARTSUBQUEUE
, FILEOP_DELETE
,
1196 queue
->delete_queue
.count
))) goto done
;
1197 for (op
= queue
->delete_queue
.head
; op
; op
= op
->next
)
1199 build_filepathsW( op
, &paths
);
1200 op_result
= handler( context
, SPFILENOTIFY_STARTDELETE
, (UINT_PTR
)&paths
, FILEOP_DELETE
);
1201 if (op_result
== FILEOP_ABORT
) goto done
;
1202 while (op_result
== FILEOP_DOIT
)
1204 TRACE( "deleting file %s\n", debugstr_w(paths
.Target
) );
1205 if (DeleteFileW( paths
.Target
)) break; /* success */
1206 paths
.Win32Error
= GetLastError();
1207 op_result
= handler( context
, SPFILENOTIFY_DELETEERROR
, (UINT_PTR
)&paths
, 0 );
1208 if (op_result
== FILEOP_ABORT
) goto done
;
1210 handler( context
, SPFILENOTIFY_ENDDELETE
, (UINT_PTR
)&paths
, 0 );
1212 handler( context
, SPFILENOTIFY_ENDSUBQUEUE
, FILEOP_DELETE
, 0 );
1215 /* perform renames */
1217 if (queue
->rename_queue
.count
)
1219 if (!(handler( context
, SPFILENOTIFY_STARTSUBQUEUE
, FILEOP_RENAME
,
1220 queue
->rename_queue
.count
))) goto done
;
1221 for (op
= queue
->rename_queue
.head
; op
; op
= op
->next
)
1223 build_filepathsW( op
, &paths
);
1224 op_result
= handler( context
, SPFILENOTIFY_STARTRENAME
, (UINT_PTR
)&paths
, FILEOP_RENAME
);
1225 if (op_result
== FILEOP_ABORT
) goto done
;
1226 while (op_result
== FILEOP_DOIT
)
1228 TRACE( "renaming file %s -> %s\n",
1229 debugstr_w(paths
.Source
), debugstr_w(paths
.Target
) );
1230 if (MoveFileW( paths
.Source
, paths
.Target
)) break; /* success */
1231 paths
.Win32Error
= GetLastError();
1232 op_result
= handler( context
, SPFILENOTIFY_RENAMEERROR
, (UINT_PTR
)&paths
, 0 );
1233 if (op_result
== FILEOP_ABORT
) goto done
;
1235 handler( context
, SPFILENOTIFY_ENDRENAME
, (UINT_PTR
)&paths
, 0 );
1237 handler( context
, SPFILENOTIFY_ENDSUBQUEUE
, FILEOP_RENAME
, 0 );
1240 /* perform copies */
1242 if (queue
->copy_queue
.count
)
1244 if (!(handler( context
, SPFILENOTIFY_STARTSUBQUEUE
, FILEOP_COPY
,
1245 queue
->copy_queue
.count
))) goto done
;
1246 for (op
= queue
->copy_queue
.head
; op
; op
= op
->next
)
1248 WCHAR newpath
[MAX_PATH
];
1250 build_filepathsW( op
, &paths
);
1251 op_result
= handler( context
, SPFILENOTIFY_STARTCOPY
, (UINT_PTR
)&paths
, FILEOP_COPY
);
1252 if (op_result
== FILEOP_ABORT
) goto done
;
1253 if (op_result
== FILEOP_NEWPATH
) op_result
= FILEOP_DOIT
;
1254 while (op_result
== FILEOP_DOIT
|| op_result
== FILEOP_NEWPATH
)
1256 TRACE( "copying file %s -> %s\n",
1257 debugstr_w( op_result
== FILEOP_NEWPATH
? newpath
: paths
.Source
),
1258 debugstr_w(paths
.Target
) );
1261 if (!create_full_pathW( op
->dst_path
))
1263 paths
.Win32Error
= GetLastError();
1264 op_result
= handler( context
, SPFILENOTIFY_COPYERROR
,
1265 (UINT_PTR
)&paths
, (UINT_PTR
)newpath
);
1266 if (op_result
== FILEOP_ABORT
) goto done
;
1269 if (do_file_copyW( op_result
== FILEOP_NEWPATH
? newpath
: paths
.Source
,
1270 paths
.Target
, op
->style
, handler
, context
)) break; /* success */
1271 /* try to extract it from the cabinet file */
1274 if (extract_cabinet_file( op
->src_tag
, op
->src_root
,
1275 paths
.Source
, paths
.Target
)) break;
1277 paths
.Win32Error
= GetLastError();
1278 op_result
= handler( context
, SPFILENOTIFY_COPYERROR
,
1279 (UINT_PTR
)&paths
, (UINT_PTR
)newpath
);
1280 if (op_result
== FILEOP_ABORT
) goto done
;
1282 handler( context
, SPFILENOTIFY_ENDCOPY
, (UINT_PTR
)&paths
, 0 );
1284 handler( context
, SPFILENOTIFY_ENDSUBQUEUE
, FILEOP_COPY
, 0 );
1291 handler( context
, SPFILENOTIFY_ENDQUEUE
, result
, 0 );
1292 HeapFree( GetProcessHeap(), 0, (void *)paths
.Source
);
1293 HeapFree( GetProcessHeap(), 0, (void *)paths
.Target
);
1298 /***********************************************************************
1299 * SetupScanFileQueueA (SETUPAPI.@)
1301 BOOL WINAPI
SetupScanFileQueueA( HSPFILEQ handle
, DWORD flags
, HWND window
,
1302 PSP_FILE_CALLBACK_A handler
, PVOID context
, PDWORD result
)
1304 struct callback_WtoA_context ctx
;
1306 TRACE("%p %x %p %p %p %p\n", handle
, flags
, window
, handler
, context
, result
);
1308 ctx
.orig_context
= context
;
1309 ctx
.orig_handler
= handler
;
1311 return SetupScanFileQueueW( handle
, flags
, window
, QUEUE_callback_WtoA
, &ctx
, result
);
1315 /***********************************************************************
1316 * SetupScanFileQueueW (SETUPAPI.@)
1318 BOOL WINAPI
SetupScanFileQueueW( HSPFILEQ handle
, DWORD flags
, HWND window
,
1319 PSP_FILE_CALLBACK_W handler
, PVOID context
, PDWORD result
)
1321 struct file_queue
*queue
= handle
;
1324 UINT notification
= 0;
1327 TRACE("%p %x %p %p %p %p\n", handle
, flags
, window
, handler
, context
, result
);
1329 if (!queue
->copy_queue
.count
) return TRUE
;
1331 if (flags
& SPQ_SCAN_USE_CALLBACK
) notification
= SPFILENOTIFY_QUEUESCAN
;
1332 else if (flags
& SPQ_SCAN_USE_CALLBACKEX
) notification
= SPFILENOTIFY_QUEUESCAN_EX
;
1334 if (flags
& ~(SPQ_SCAN_USE_CALLBACK
| SPQ_SCAN_USE_CALLBACKEX
))
1336 FIXME("flags %x not fully implemented\n", flags
);
1339 paths
.Source
= paths
.Target
= NULL
;
1341 for (op
= queue
->copy_queue
.head
; op
; op
= op
->next
)
1343 build_filepathsW( op
, &paths
);
1344 switch (notification
)
1346 case SPFILENOTIFY_QUEUESCAN
:
1347 /* FIXME: handle delay flag */
1348 if (handler( context
, notification
, (UINT_PTR
)paths
.Target
, 0 )) goto done
;
1350 case SPFILENOTIFY_QUEUESCAN_EX
:
1351 if (handler( context
, notification
, (UINT_PTR
)&paths
, 0 )) goto done
;
1354 ret
= TRUE
; goto done
;
1361 if (result
) *result
= 0;
1362 HeapFree( GetProcessHeap(), 0, (void *)paths
.Source
);
1363 HeapFree( GetProcessHeap(), 0, (void *)paths
.Target
);
1368 /***********************************************************************
1369 * SetupGetFileQueueCount (SETUPAPI.@)
1371 BOOL WINAPI
SetupGetFileQueueCount( HSPFILEQ handle
, UINT op
, PUINT result
)
1373 struct file_queue
*queue
= handle
;
1378 *result
= queue
->copy_queue
.count
;
1381 *result
= queue
->rename_queue
.count
;
1384 *result
= queue
->delete_queue
.count
;
1391 /***********************************************************************
1392 * SetupGetFileQueueFlags (SETUPAPI.@)
1394 BOOL WINAPI
SetupGetFileQueueFlags( HSPFILEQ handle
, PDWORD flags
)
1396 struct file_queue
*queue
= handle
;
1397 *flags
= queue
->flags
;
1402 /***********************************************************************
1403 * SetupSetFileQueueFlags (SETUPAPI.@)
1405 BOOL WINAPI
SetupSetFileQueueFlags( HSPFILEQ handle
, DWORD mask
, DWORD flags
)
1407 struct file_queue
*queue
= handle
;
1408 queue
->flags
= (queue
->flags
& ~mask
) | flags
;
1413 /***********************************************************************
1414 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1416 BOOL WINAPI
SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle
, PSP_ALTPLATFORM_INFO platform
, PCSTR catalogfile
)
1418 FIXME("(%p, %p, %s) stub!\n", handle
, platform
, debugstr_a(catalogfile
));
1423 /***********************************************************************
1424 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1426 BOOL WINAPI
SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle
, PSP_ALTPLATFORM_INFO platform
, PCWSTR catalogfile
)
1428 FIXME("(%p, %p, %s) stub!\n", handle
, platform
, debugstr_w(catalogfile
));
1433 /***********************************************************************
1434 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1436 PVOID WINAPI
SetupInitDefaultQueueCallback( HWND owner
)
1438 return SetupInitDefaultQueueCallbackEx( owner
, 0, 0, 0, NULL
);
1442 /***********************************************************************
1443 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1445 PVOID WINAPI
SetupInitDefaultQueueCallbackEx( HWND owner
, HWND progress
, UINT msg
,
1446 DWORD reserved1
, PVOID reserved2
)
1448 struct default_callback_context
*context
;
1450 if ((context
= HeapAlloc( GetProcessHeap(), 0, sizeof(*context
) )))
1452 context
->owner
= owner
;
1453 context
->progress
= progress
;
1454 context
->message
= msg
;
1460 /***********************************************************************
1461 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1463 void WINAPI
SetupTermDefaultQueueCallback( PVOID context
)
1465 HeapFree( GetProcessHeap(), 0, context
);
1469 /***********************************************************************
1470 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1472 UINT WINAPI
SetupDefaultQueueCallbackA( PVOID context
, UINT notification
,
1473 UINT_PTR param1
, UINT_PTR param2
)
1475 FILEPATHS_A
*paths
= (FILEPATHS_A
*)param1
;
1476 struct default_callback_context
*ctx
= (struct default_callback_context
*)context
;
1478 switch(notification
)
1480 case SPFILENOTIFY_STARTQUEUE
:
1481 TRACE( "start queue\n" );
1483 case SPFILENOTIFY_ENDQUEUE
:
1484 TRACE( "end queue\n" );
1486 case SPFILENOTIFY_STARTSUBQUEUE
:
1487 TRACE( "start subqueue %ld count %ld\n", param1
, param2
);
1489 case SPFILENOTIFY_ENDSUBQUEUE
:
1490 TRACE( "end subqueue %ld\n", param1
);
1492 case SPFILENOTIFY_STARTDELETE
:
1493 TRACE( "start delete %s\n", debugstr_a(paths
->Target
) );
1495 case SPFILENOTIFY_ENDDELETE
:
1496 TRACE( "end delete %s\n", debugstr_a(paths
->Target
) );
1498 case SPFILENOTIFY_DELETEERROR
:
1499 /*Windows Ignores attempts to delete files / folders which do not exist*/
1500 if ((paths
->Win32Error
!= ERROR_FILE_NOT_FOUND
) && (paths
->Win32Error
!= ERROR_PATH_NOT_FOUND
))
1501 SetupDeleteErrorA(ctx
->owner
, NULL
, paths
->Target
, paths
->Win32Error
, 0);
1503 case SPFILENOTIFY_STARTRENAME
:
1504 TRACE( "start rename %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1506 case SPFILENOTIFY_ENDRENAME
:
1507 TRACE( "end rename %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1509 case SPFILENOTIFY_RENAMEERROR
:
1510 SetupRenameErrorA(ctx
->owner
, NULL
, paths
->Source
, paths
->Target
, paths
->Win32Error
, 0);
1512 case SPFILENOTIFY_STARTCOPY
:
1513 TRACE( "start copy %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1515 case SPFILENOTIFY_ENDCOPY
:
1516 TRACE( "end copy %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1518 case SPFILENOTIFY_COPYERROR
:
1519 ERR( "copy error %d %s -> %s\n", paths
->Win32Error
,
1520 debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1522 case SPFILENOTIFY_NEEDMEDIA
:
1523 TRACE( "need media\n" );
1526 FIXME( "notification %d params %lx,%lx\n", notification
, param1
, param2
);
1533 /***********************************************************************
1534 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1536 UINT WINAPI
SetupDefaultQueueCallbackW( PVOID context
, UINT notification
,
1537 UINT_PTR param1
, UINT_PTR param2
)
1539 FILEPATHS_W
*paths
= (FILEPATHS_W
*)param1
;
1540 struct default_callback_context
*ctx
= (struct default_callback_context
*)context
;
1542 switch(notification
)
1544 case SPFILENOTIFY_STARTQUEUE
:
1545 TRACE( "start queue\n" );
1547 case SPFILENOTIFY_ENDQUEUE
:
1548 TRACE( "end queue\n" );
1550 case SPFILENOTIFY_STARTSUBQUEUE
:
1551 TRACE( "start subqueue %ld count %ld\n", param1
, param2
);
1553 case SPFILENOTIFY_ENDSUBQUEUE
:
1554 TRACE( "end subqueue %ld\n", param1
);
1556 case SPFILENOTIFY_STARTDELETE
:
1557 TRACE( "start delete %s\n", debugstr_w(paths
->Target
) );
1559 case SPFILENOTIFY_ENDDELETE
:
1560 TRACE( "end delete %s\n", debugstr_w(paths
->Target
) );
1562 case SPFILENOTIFY_DELETEERROR
:
1563 /*Windows Ignores attempts to delete files / folders which do not exist*/
1564 if ((paths
->Win32Error
!= ERROR_FILE_NOT_FOUND
) && (paths
->Win32Error
!= ERROR_PATH_NOT_FOUND
))
1565 SetupDeleteErrorW(ctx
->owner
, NULL
, paths
->Target
, paths
->Win32Error
, 0);
1567 case SPFILENOTIFY_STARTRENAME
:
1568 SetupRenameErrorW(ctx
->owner
, NULL
, paths
->Source
, paths
->Target
, paths
->Win32Error
, 0);
1570 case SPFILENOTIFY_ENDRENAME
:
1571 TRACE( "end rename %s -> %s\n", debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1573 case SPFILENOTIFY_RENAMEERROR
:
1574 ERR( "rename error %d %s -> %s\n", paths
->Win32Error
,
1575 debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1577 case SPFILENOTIFY_STARTCOPY
:
1578 TRACE( "start copy %s -> %s\n", debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1580 case SPFILENOTIFY_ENDCOPY
:
1581 TRACE( "end copy %s -> %s\n", debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1583 case SPFILENOTIFY_COPYERROR
:
1584 ERR( "copy error %d %s -> %s\n", paths
->Win32Error
,
1585 debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1587 case SPFILENOTIFY_NEEDMEDIA
:
1588 TRACE( "need media\n" );
1591 FIXME( "notification %d params %lx,%lx\n", notification
, param1
, param2
);
1597 /***********************************************************************
1598 * SetupDeleteErrorA (SETUPAPI.@)
1601 UINT WINAPI
SetupDeleteErrorA( HWND parent
, PCSTR dialogTitle
, PCSTR file
,
1602 UINT w32error
, DWORD style
)
1604 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1605 w32error
, debugstr_a(file
) );
1606 return DPROMPT_SKIPFILE
;
1609 /***********************************************************************
1610 * SetupDeleteErrorW (SETUPAPI.@)
1613 UINT WINAPI
SetupDeleteErrorW( HWND parent
, PCWSTR dialogTitle
, PCWSTR file
,
1614 UINT w32error
, DWORD style
)
1616 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1617 w32error
, debugstr_w(file
) );
1618 return DPROMPT_SKIPFILE
;
1621 /***********************************************************************
1622 * SetupRenameErrorA (SETUPAPI.@)
1625 UINT WINAPI
SetupRenameErrorA( HWND parent
, PCSTR dialogTitle
, PCSTR source
,
1626 PCSTR target
, UINT w32error
, DWORD style
)
1628 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1629 w32error
, debugstr_a(source
), debugstr_a(target
));
1630 return DPROMPT_SKIPFILE
;
1633 /***********************************************************************
1634 * SetupRenameErrorW (SETUPAPI.@)
1637 UINT WINAPI
SetupRenameErrorW( HWND parent
, PCWSTR dialogTitle
, PCWSTR source
,
1638 PCWSTR target
, UINT w32error
, DWORD style
)
1640 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1641 w32error
, debugstr_w(source
), debugstr_w(target
));
1642 return DPROMPT_SKIPFILE
;
1646 /***********************************************************************
1647 * SetupCopyErrorA (SETUPAPI.@)
1650 UINT WINAPI
SetupCopyErrorA( HWND parent
, PCSTR dialogTitle
, PCSTR diskname
,
1651 PCSTR sourcepath
, PCSTR sourcefile
, PCSTR targetpath
,
1652 UINT w32error
, DWORD style
, PSTR pathbuffer
,
1653 DWORD buffersize
, PDWORD requiredsize
)
1655 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1656 w32error
, debugstr_a(sourcefile
), debugstr_a(sourcepath
) ,debugstr_a(targetpath
));
1657 return DPROMPT_SKIPFILE
;
1660 /***********************************************************************
1661 * SetupCopyErrorW (SETUPAPI.@)
1664 UINT WINAPI
SetupCopyErrorW( HWND parent
, PCWSTR dialogTitle
, PCWSTR diskname
,
1665 PCWSTR sourcepath
, PCWSTR sourcefile
, PCWSTR targetpath
,
1666 UINT w32error
, DWORD style
, PWSTR pathbuffer
,
1667 DWORD buffersize
, PDWORD requiredsize
)
1669 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1670 w32error
, debugstr_w(sourcefile
), debugstr_w(sourcepath
) ,debugstr_w(targetpath
));
1671 return DPROMPT_SKIPFILE
;
1674 /***********************************************************************
1675 * pSetupGetQueueFlags (SETUPAPI.@)
1677 DWORD WINAPI
pSetupGetQueueFlags( HSPFILEQ handle
)
1679 struct file_queue
*queue
= handle
;
1680 return queue
->flags
;
1683 /***********************************************************************
1684 * pSetupSetQueueFlags (SETUPAPI.@)
1686 BOOL WINAPI
pSetupSetQueueFlags( HSPFILEQ handle
, DWORD flags
)
1688 struct file_queue
*queue
= handle
;
1689 queue
->flags
= flags
;