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
73 struct file_op_queue copy_queue
;
74 struct file_op_queue delete_queue
;
75 struct file_op_queue rename_queue
;
80 /* append a file operation to a queue */
81 static inline void queue_file_op( struct file_op_queue
*queue
, struct file_op
*op
)
84 if (queue
->tail
) queue
->tail
->next
= op
;
85 else queue
->head
= op
;
90 /* free all the file operations on a given queue */
91 static void free_file_op_queue( struct file_op_queue
*queue
)
93 struct file_op
*t
, *op
= queue
->head
;
97 HeapFree( GetProcessHeap(), 0, op
->src_root
);
98 HeapFree( GetProcessHeap(), 0, op
->src_path
);
99 HeapFree( GetProcessHeap(), 0, op
->src_file
);
100 HeapFree( GetProcessHeap(), 0, op
->src_descr
);
101 HeapFree( GetProcessHeap(), 0, op
->src_tag
);
102 HeapFree( GetProcessHeap(), 0, op
->dst_path
);
103 if (op
->dst_file
!= op
->src_file
) HeapFree( GetProcessHeap(), 0, op
->dst_file
);
106 HeapFree( GetProcessHeap(), 0, t
);
110 /* concat 3 strings to make a path, handling separators correctly */
111 static void concat_W( WCHAR
*buffer
, const WCHAR
*src1
, const WCHAR
*src2
, const WCHAR
*src3
)
116 strcpyW( buffer
, src1
);
117 buffer
+= strlenW(buffer
);
118 if (buffer
[-1] != '\\') *buffer
++ = '\\';
119 if (src2
) while (*src2
== '\\') src2
++;
124 strcpyW( buffer
, src2
);
125 buffer
+= strlenW(buffer
);
126 if (buffer
[-1] != '\\') *buffer
++ = '\\';
127 if (src3
) while (*src3
== '\\') src3
++;
131 strcpyW( buffer
, src3
);
132 buffer
+= strlenW(buffer
);
137 /***********************************************************************
140 * Build a FILEPATHS_W structure for a given file operation.
142 static BOOL
build_filepathsW( const struct file_op
*op
, FILEPATHS_W
*paths
)
144 unsigned int src_len
= 1, dst_len
= 1;
145 WCHAR
*source
= (PWSTR
)paths
->Source
, *target
= (PWSTR
)paths
->Target
;
147 if (op
->src_root
) src_len
+= strlenW(op
->src_root
) + 1;
148 if (op
->src_path
) src_len
+= strlenW(op
->src_path
) + 1;
149 if (op
->src_file
) src_len
+= strlenW(op
->src_file
) + 1;
150 if (op
->dst_path
) dst_len
+= strlenW(op
->dst_path
) + 1;
151 if (op
->dst_file
) dst_len
+= strlenW(op
->dst_file
) + 1;
152 src_len
*= sizeof(WCHAR
);
153 dst_len
*= sizeof(WCHAR
);
155 if (!source
|| HeapSize( GetProcessHeap(), 0, source
) < src_len
)
157 HeapFree( GetProcessHeap(), 0, source
);
158 paths
->Source
= source
= HeapAlloc( GetProcessHeap(), 0, src_len
);
160 if (!target
|| HeapSize( GetProcessHeap(), 0, target
) < dst_len
)
162 HeapFree( GetProcessHeap(), 0, target
);
163 paths
->Target
= target
= HeapAlloc( GetProcessHeap(), 0, dst_len
);
165 if (!source
|| !target
) return FALSE
;
166 concat_W( source
, op
->src_root
, op
->src_path
, op
->src_file
);
167 concat_W( target
, NULL
, op
->dst_path
, op
->dst_file
);
168 paths
->Win32Error
= 0;
174 /***********************************************************************
175 * QUEUE_callback_WtoA
177 * Map a file callback parameters from W to A and call the A callback.
179 UINT CALLBACK
QUEUE_callback_WtoA( void *context
, UINT notification
,
180 UINT_PTR param1
, UINT_PTR param2
)
182 struct callback_WtoA_context
*callback_ctx
= context
;
183 char buffer
[MAX_PATH
];
185 UINT_PTR old_param2
= param2
;
189 case SPFILENOTIFY_COPYERROR
:
190 param2
= (UINT_PTR
)buffer
;
192 case SPFILENOTIFY_STARTDELETE
:
193 case SPFILENOTIFY_ENDDELETE
:
194 case SPFILENOTIFY_DELETEERROR
:
195 case SPFILENOTIFY_STARTRENAME
:
196 case SPFILENOTIFY_ENDRENAME
:
197 case SPFILENOTIFY_RENAMEERROR
:
198 case SPFILENOTIFY_STARTCOPY
:
199 case SPFILENOTIFY_ENDCOPY
:
200 case SPFILENOTIFY_QUEUESCAN_EX
:
202 FILEPATHS_W
*pathsW
= (FILEPATHS_W
*)param1
;
205 pathsA
.Source
= strdupWtoA( pathsW
->Source
);
206 pathsA
.Target
= strdupWtoA( pathsW
->Target
);
207 pathsA
.Win32Error
= pathsW
->Win32Error
;
208 pathsA
.Flags
= pathsW
->Flags
;
209 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
,
210 (UINT_PTR
)&pathsA
, param2
);
211 HeapFree( GetProcessHeap(), 0, (void *)pathsA
.Source
);
212 HeapFree( GetProcessHeap(), 0, (void *)pathsA
.Target
);
214 if (notification
== SPFILENOTIFY_COPYERROR
)
215 MultiByteToWideChar( CP_ACP
, 0, buffer
, -1, (WCHAR
*)old_param2
, MAX_PATH
);
218 case SPFILENOTIFY_STARTREGISTRATION
:
219 case SPFILENOTIFY_ENDREGISTRATION
:
221 SP_REGISTER_CONTROL_STATUSW
*statusW
= (SP_REGISTER_CONTROL_STATUSW
*)param1
;
222 SP_REGISTER_CONTROL_STATUSA statusA
;
224 statusA
.cbSize
= sizeof(statusA
);
225 statusA
.FileName
= strdupWtoA( statusW
->FileName
);
226 statusA
.Win32Error
= statusW
->Win32Error
;
227 statusA
.FailureCode
= statusW
->FailureCode
;
228 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
,
229 (UINT_PTR
)&statusA
, param2
);
230 HeapFree( GetProcessHeap(), 0, (LPSTR
)statusA
.FileName
);
234 case SPFILENOTIFY_QUEUESCAN
:
236 LPWSTR targetW
= (LPWSTR
)param1
;
237 LPSTR target
= strdupWtoA( targetW
);
239 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
,
240 (UINT_PTR
)target
, param2
);
241 HeapFree( GetProcessHeap(), 0, target
);
245 case SPFILENOTIFY_NEEDMEDIA
:
246 FIXME("mapping for %d not implemented\n",notification
);
247 case SPFILENOTIFY_STARTQUEUE
:
248 case SPFILENOTIFY_ENDQUEUE
:
249 case SPFILENOTIFY_STARTSUBQUEUE
:
250 case SPFILENOTIFY_ENDSUBQUEUE
:
252 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
, param1
, param2
);
259 /***********************************************************************
262 * Retrieve the source file information for a given file.
264 static void get_src_file_info( HINF hinf
, struct file_op
*op
)
266 static const WCHAR SourceDisksNames
[] =
267 {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0};
268 static const WCHAR SourceDisksFiles
[] =
269 {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
271 INFCONTEXT file_ctx
, disk_ctx
;
275 /* find the SourceDisksFiles entry */
276 if (!SetupFindFirstLineW( hinf
, SourceDisksFiles
, op
->src_file
, &file_ctx
))
278 if ((op
->style
& (SP_COPY_SOURCE_ABSOLUTE
|SP_COPY_SOURCEPATH_ABSOLUTE
))) return;
279 /* no specific info, use .inf file source directory */
280 if (!op
->src_root
) op
->src_root
= PARSER_get_src_root( hinf
);
283 if (!SetupGetIntField( &file_ctx
, 1, &diskid
)) return;
285 /* now find the diskid in the SourceDisksNames section */
286 if (!SetupFindFirstLineW( hinf
, SourceDisksNames
, NULL
, &disk_ctx
)) return;
289 if (SetupGetIntField( &disk_ctx
, 0, &id
) && (id
== diskid
)) break;
290 if (!SetupFindNextLine( &disk_ctx
, &disk_ctx
)) return;
293 /* and fill in the missing info */
297 if (SetupGetStringFieldW( &disk_ctx
, 1, NULL
, 0, &len
) &&
298 (op
->src_descr
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) )))
299 SetupGetStringFieldW( &disk_ctx
, 1, op
->src_descr
, len
, NULL
);
303 if (SetupGetStringFieldW( &disk_ctx
, 2, NULL
, 0, &len
) &&
304 (op
->src_tag
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) )))
305 SetupGetStringFieldW( &disk_ctx
, 2, op
->src_tag
, len
, NULL
);
307 if (!op
->src_path
&& !(op
->style
& SP_COPY_SOURCE_ABSOLUTE
))
310 if (!(op
->style
& SP_COPY_SOURCEPATH_ABSOLUTE
))
312 /* retrieve relative path for this disk */
313 if (!SetupGetStringFieldW( &disk_ctx
, 4, NULL
, 0, &len
)) len
= 0;
315 /* retrieve relative path for this file */
316 if (!SetupGetStringFieldW( &file_ctx
, 2, NULL
, 0, &len2
)) len2
= 0;
319 (op
->src_path
= HeapAlloc( GetProcessHeap(), 0, (len
+len2
)*sizeof(WCHAR
) )))
321 WCHAR
*ptr
= op
->src_path
;
324 SetupGetStringFieldW( &disk_ctx
, 4, op
->src_path
, len
, NULL
);
325 ptr
= op
->src_path
+ strlenW(op
->src_path
);
326 if (len2
&& ptr
> op
->src_path
&& ptr
[-1] != '\\') *ptr
++ = '\\';
328 if (!SetupGetStringFieldW( &file_ctx
, 2, ptr
, len2
, NULL
)) *ptr
= 0;
331 if (!op
->src_root
) op
->src_root
= PARSER_get_src_root(hinf
);
335 /***********************************************************************
336 * get_destination_dir
338 * Retrieve the destination dir for a given section.
340 static WCHAR
*get_destination_dir( HINF hinf
, const WCHAR
*section
)
342 static const WCHAR Dest
[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
343 static const WCHAR Def
[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
345 WCHAR systemdir
[MAX_PATH
], *dir
;
348 if (!(ret
= SetupFindFirstLineW( hinf
, Dest
, section
, &context
)))
349 ret
= SetupFindFirstLineW( hinf
, Dest
, Def
, &context
);
351 if (ret
&& (dir
= PARSER_get_dest_dir( &context
)))
354 GetSystemDirectoryW( systemdir
, MAX_PATH
);
355 return strdupW( systemdir
);
359 static void (WINAPI
*pExtractFiles
)( LPSTR
, LPSTR
, DWORD
, DWORD
, DWORD
, DWORD
);
361 /***********************************************************************
362 * extract_cabinet_file
364 * Extract a file from a .cab file.
366 static BOOL
extract_cabinet_file( const WCHAR
*cabinet
, const WCHAR
*root
,
367 const WCHAR
*src
, const WCHAR
*dst
)
369 static const WCHAR extW
[] = {'.','c','a','b',0};
370 static HMODULE advpack
;
372 char *cab_path
, *cab_file
;
373 int len
= strlenW( cabinet
);
375 /* make sure the cabinet file has a .cab extension */
376 if (len
<= 4 || strcmpiW( cabinet
+ len
- 4, extW
)) return FALSE
;
379 if (!advpack
&& !(advpack
= LoadLibraryA( "advpack.dll" )))
381 ERR( "could not load advpack.dll\n" );
384 if (!(pExtractFiles
= (void *)GetProcAddress( advpack
, "ExtractFiles" )))
386 ERR( "could not find ExtractFiles in advpack.dll\n" );
391 if (!(cab_path
= strdupWtoA( root
))) return FALSE
;
392 len
= WideCharToMultiByte( CP_ACP
, 0, cabinet
, -1, NULL
, 0, NULL
, NULL
);
393 if (!(cab_file
= HeapAlloc( GetProcessHeap(), 0, strlen(cab_path
) + len
+ 1 )))
395 HeapFree( GetProcessHeap(), 0, cab_path
);
398 strcpy( cab_file
, cab_path
);
399 if (cab_file
[0] && cab_file
[strlen(cab_file
)-1] != '\\') strcat( cab_file
, "\\" );
400 WideCharToMultiByte( CP_ACP
, 0, cabinet
, -1, cab_file
+ strlen(cab_file
), len
, NULL
, NULL
);
401 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file
) );
402 pExtractFiles( cab_file
, cab_path
, 0, 0, 0, 0 );
403 HeapFree( GetProcessHeap(), 0, cab_file
);
404 HeapFree( GetProcessHeap(), 0, cab_path
);
405 return CopyFileW( src
, dst
, FALSE
/*FIXME*/ );
409 /***********************************************************************
410 * SetupOpenFileQueue (SETUPAPI.@)
412 HSPFILEQ WINAPI
SetupOpenFileQueue(void)
414 struct file_queue
*queue
;
416 if (!(queue
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*queue
))))
417 return INVALID_HANDLE_VALUE
;
422 /***********************************************************************
423 * SetupCloseFileQueue (SETUPAPI.@)
425 BOOL WINAPI
SetupCloseFileQueue( HSPFILEQ handle
)
427 struct file_queue
*queue
= handle
;
429 free_file_op_queue( &queue
->copy_queue
);
430 free_file_op_queue( &queue
->rename_queue
);
431 free_file_op_queue( &queue
->delete_queue
);
432 HeapFree( GetProcessHeap(), 0, queue
);
437 /***********************************************************************
438 * SetupQueueCopyIndirectA (SETUPAPI.@)
440 BOOL WINAPI
SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params
)
442 struct file_queue
*queue
= params
->QueueHandle
;
445 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
446 op
->style
= params
->CopyStyle
;
447 op
->src_root
= strdupAtoW( params
->SourceRootPath
);
448 op
->src_path
= strdupAtoW( params
->SourcePath
);
449 op
->src_file
= strdupAtoW( params
->SourceFilename
);
450 op
->src_descr
= strdupAtoW( params
->SourceDescription
);
451 op
->src_tag
= strdupAtoW( params
->SourceTagfile
);
452 op
->dst_path
= strdupAtoW( params
->TargetDirectory
);
453 op
->dst_file
= strdupAtoW( params
->TargetFilename
);
456 if (!op
->src_file
) op
->src_file
= op
->dst_file
;
457 if (params
->LayoutInf
)
459 get_src_file_info( params
->LayoutInf
, op
);
460 if (!op
->dst_path
) op
->dst_path
= get_destination_dir( params
->LayoutInf
, op
->dst_file
);
463 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
464 debugstr_w(op
->src_root
), debugstr_w(op
->src_path
), debugstr_w(op
->src_file
),
465 debugstr_w(op
->dst_path
), debugstr_w(op
->dst_file
),
466 debugstr_w(op
->src_descr
), debugstr_w(op
->src_tag
) );
468 queue_file_op( &queue
->copy_queue
, op
);
473 /***********************************************************************
474 * SetupQueueCopyIndirectW (SETUPAPI.@)
476 BOOL WINAPI
SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params
)
478 struct file_queue
*queue
= params
->QueueHandle
;
481 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
482 op
->style
= params
->CopyStyle
;
483 op
->src_root
= strdupW( params
->SourceRootPath
);
484 op
->src_path
= strdupW( params
->SourcePath
);
485 op
->src_file
= strdupW( params
->SourceFilename
);
486 op
->src_descr
= strdupW( params
->SourceDescription
);
487 op
->src_tag
= strdupW( params
->SourceTagfile
);
488 op
->dst_path
= strdupW( params
->TargetDirectory
);
489 op
->dst_file
= strdupW( params
->TargetFilename
);
492 if (!op
->src_file
) op
->src_file
= op
->dst_file
;
493 if (params
->LayoutInf
)
495 get_src_file_info( params
->LayoutInf
, op
);
496 if (!op
->dst_path
) op
->dst_path
= get_destination_dir( params
->LayoutInf
, op
->dst_file
);
499 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
500 debugstr_w(op
->src_root
), debugstr_w(op
->src_path
), debugstr_w(op
->src_file
),
501 debugstr_w(op
->dst_path
), debugstr_w(op
->dst_file
),
502 debugstr_w(op
->src_descr
), debugstr_w(op
->src_tag
) );
504 queue_file_op( &queue
->copy_queue
, op
);
509 /***********************************************************************
510 * SetupQueueCopyA (SETUPAPI.@)
512 BOOL WINAPI
SetupQueueCopyA( HSPFILEQ queue
, PCSTR src_root
, PCSTR src_path
, PCSTR src_file
,
513 PCSTR src_descr
, PCSTR src_tag
, PCSTR dst_dir
, PCSTR dst_file
,
516 SP_FILE_COPY_PARAMS_A params
;
518 params
.cbSize
= sizeof(params
);
519 params
.QueueHandle
= queue
;
520 params
.SourceRootPath
= src_root
;
521 params
.SourcePath
= src_path
;
522 params
.SourceFilename
= src_file
;
523 params
.SourceDescription
= src_descr
;
524 params
.SourceTagfile
= src_tag
;
525 params
.TargetDirectory
= dst_dir
;
526 params
.TargetFilename
= dst_file
;
527 params
.CopyStyle
= style
;
528 params
.LayoutInf
= 0;
529 params
.SecurityDescriptor
= NULL
;
530 return SetupQueueCopyIndirectA( ¶ms
);
534 /***********************************************************************
535 * SetupQueueCopyW (SETUPAPI.@)
537 BOOL WINAPI
SetupQueueCopyW( HSPFILEQ queue
, PCWSTR src_root
, PCWSTR src_path
, PCWSTR src_file
,
538 PCWSTR src_descr
, PCWSTR src_tag
, PCWSTR dst_dir
, PCWSTR dst_file
,
541 SP_FILE_COPY_PARAMS_W params
;
543 params
.cbSize
= sizeof(params
);
544 params
.QueueHandle
= queue
;
545 params
.SourceRootPath
= src_root
;
546 params
.SourcePath
= src_path
;
547 params
.SourceFilename
= src_file
;
548 params
.SourceDescription
= src_descr
;
549 params
.SourceTagfile
= src_tag
;
550 params
.TargetDirectory
= dst_dir
;
551 params
.TargetFilename
= dst_file
;
552 params
.CopyStyle
= style
;
553 params
.LayoutInf
= 0;
554 params
.SecurityDescriptor
= NULL
;
555 return SetupQueueCopyIndirectW( ¶ms
);
559 /***********************************************************************
560 * SetupQueueDefaultCopyA (SETUPAPI.@)
562 BOOL WINAPI
SetupQueueDefaultCopyA( HSPFILEQ queue
, HINF hinf
, PCSTR src_root
, PCSTR src_file
,
563 PCSTR dst_file
, DWORD style
)
565 SP_FILE_COPY_PARAMS_A params
;
567 params
.cbSize
= sizeof(params
);
568 params
.QueueHandle
= queue
;
569 params
.SourceRootPath
= src_root
;
570 params
.SourcePath
= NULL
;
571 params
.SourceFilename
= src_file
;
572 params
.SourceDescription
= NULL
;
573 params
.SourceTagfile
= NULL
;
574 params
.TargetDirectory
= NULL
;
575 params
.TargetFilename
= dst_file
;
576 params
.CopyStyle
= style
;
577 params
.LayoutInf
= hinf
;
578 params
.SecurityDescriptor
= NULL
;
579 return SetupQueueCopyIndirectA( ¶ms
);
583 /***********************************************************************
584 * SetupQueueDefaultCopyW (SETUPAPI.@)
586 BOOL WINAPI
SetupQueueDefaultCopyW( HSPFILEQ queue
, HINF hinf
, PCWSTR src_root
, PCWSTR src_file
,
587 PCWSTR dst_file
, DWORD style
)
589 SP_FILE_COPY_PARAMS_W params
;
591 params
.cbSize
= sizeof(params
);
592 params
.QueueHandle
= queue
;
593 params
.SourceRootPath
= src_root
;
594 params
.SourcePath
= NULL
;
595 params
.SourceFilename
= src_file
;
596 params
.SourceDescription
= NULL
;
597 params
.SourceTagfile
= NULL
;
598 params
.TargetDirectory
= NULL
;
599 params
.TargetFilename
= dst_file
;
600 params
.CopyStyle
= style
;
601 params
.LayoutInf
= hinf
;
602 params
.SecurityDescriptor
= NULL
;
603 return SetupQueueCopyIndirectW( ¶ms
);
607 /***********************************************************************
608 * SetupQueueDeleteA (SETUPAPI.@)
610 BOOL WINAPI
SetupQueueDeleteA( HSPFILEQ handle
, PCSTR part1
, PCSTR part2
)
612 struct file_queue
*queue
= handle
;
615 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
620 op
->src_descr
= NULL
;
622 op
->dst_path
= strdupAtoW( part1
);
623 op
->dst_file
= strdupAtoW( part2
);
624 queue_file_op( &queue
->delete_queue
, op
);
629 /***********************************************************************
630 * SetupQueueDeleteW (SETUPAPI.@)
632 BOOL WINAPI
SetupQueueDeleteW( HSPFILEQ handle
, PCWSTR part1
, PCWSTR part2
)
634 struct file_queue
*queue
= handle
;
637 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
642 op
->src_descr
= NULL
;
644 op
->dst_path
= strdupW( part1
);
645 op
->dst_file
= strdupW( part2
);
646 queue_file_op( &queue
->delete_queue
, op
);
651 /***********************************************************************
652 * SetupQueueRenameA (SETUPAPI.@)
654 BOOL WINAPI
SetupQueueRenameA( HSPFILEQ handle
, PCSTR SourcePath
, PCSTR SourceFilename
,
655 PCSTR TargetPath
, PCSTR TargetFilename
)
657 struct file_queue
*queue
= handle
;
660 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
663 op
->src_path
= strdupAtoW( SourcePath
);
664 op
->src_file
= strdupAtoW( SourceFilename
);
665 op
->src_descr
= NULL
;
667 op
->dst_path
= strdupAtoW( TargetPath
);
668 op
->dst_file
= strdupAtoW( TargetFilename
);
669 queue_file_op( &queue
->rename_queue
, op
);
674 /***********************************************************************
675 * SetupQueueRenameW (SETUPAPI.@)
677 BOOL WINAPI
SetupQueueRenameW( HSPFILEQ handle
, PCWSTR SourcePath
, PCWSTR SourceFilename
,
678 PCWSTR TargetPath
, PCWSTR TargetFilename
)
680 struct file_queue
*queue
= handle
;
683 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
686 op
->src_path
= strdupW( SourcePath
);
687 op
->src_file
= strdupW( SourceFilename
);
688 op
->src_descr
= NULL
;
690 op
->dst_path
= strdupW( TargetPath
);
691 op
->dst_file
= strdupW( TargetFilename
);
692 queue_file_op( &queue
->rename_queue
, op
);
697 /***********************************************************************
698 * SetupQueueCopySectionA (SETUPAPI.@)
700 BOOL WINAPI
SetupQueueCopySectionA( HSPFILEQ queue
, PCSTR src_root
, HINF hinf
, HINF hlist
,
701 PCSTR section
, DWORD style
)
703 UNICODE_STRING sectionW
;
706 if (!RtlCreateUnicodeStringFromAsciiz( §ionW
, section
))
708 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
712 ret
= SetupQueueCopySectionW( queue
, NULL
, hinf
, hlist
, sectionW
.Buffer
, style
);
716 if (RtlCreateUnicodeStringFromAsciiz( &srcW
, src_root
))
718 ret
= SetupQueueCopySectionW( queue
, srcW
.Buffer
, hinf
, hlist
, sectionW
.Buffer
, style
);
719 RtlFreeUnicodeString( &srcW
);
721 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
723 RtlFreeUnicodeString( §ionW
);
728 /***********************************************************************
729 * SetupQueueCopySectionW (SETUPAPI.@)
731 BOOL WINAPI
SetupQueueCopySectionW( HSPFILEQ queue
, PCWSTR src_root
, HINF hinf
, HINF hlist
,
732 PCWSTR section
, DWORD style
)
734 SP_FILE_COPY_PARAMS_W params
;
736 WCHAR dest
[MAX_PATH
], src
[MAX_PATH
], *dest_dir
;
740 TRACE( "hinf=%p/%p section=%s root=%s\n",
741 hinf
, hlist
, debugstr_w(section
), debugstr_w(src_root
) );
743 params
.cbSize
= sizeof(params
);
744 params
.QueueHandle
= queue
;
745 params
.SourceRootPath
= src_root
;
746 params
.SourcePath
= NULL
;
747 params
.SourceDescription
= NULL
;
748 params
.SourceTagfile
= NULL
;
749 params
.TargetFilename
= dest
;
750 params
.CopyStyle
= style
;
751 params
.LayoutInf
= hinf
;
752 params
.SecurityDescriptor
= NULL
;
754 if (!hlist
) hlist
= hinf
;
755 if (!hinf
) hinf
= hlist
;
756 if (!SetupFindFirstLineW( hlist
, section
, NULL
, &context
)) return FALSE
;
757 if (!(params
.TargetDirectory
= dest_dir
= get_destination_dir( hinf
, section
))) return FALSE
;
760 if (!SetupGetStringFieldW( &context
, 1, dest
, sizeof(dest
)/sizeof(WCHAR
), NULL
))
762 if (!SetupGetStringFieldW( &context
, 2, src
, sizeof(src
)/sizeof(WCHAR
), NULL
)) *src
= 0;
763 if (!SetupGetIntField( &context
, 4, &flags
)) flags
= 0; /* FIXME */
765 params
.SourceFilename
= *src
? src
: NULL
;
766 if (!SetupQueueCopyIndirectW( ¶ms
)) goto end
;
767 } while (SetupFindNextLine( &context
, &context
));
770 HeapFree(GetProcessHeap(), 0, dest_dir
);
775 /***********************************************************************
776 * SetupQueueDeleteSectionA (SETUPAPI.@)
778 BOOL WINAPI
SetupQueueDeleteSectionA( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCSTR section
)
780 UNICODE_STRING sectionW
;
783 if (RtlCreateUnicodeStringFromAsciiz( §ionW
, section
))
785 ret
= SetupQueueDeleteSectionW( queue
, hinf
, hlist
, sectionW
.Buffer
);
786 RtlFreeUnicodeString( §ionW
);
788 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
793 /***********************************************************************
794 * SetupQueueDeleteSectionW (SETUPAPI.@)
796 BOOL WINAPI
SetupQueueDeleteSectionW( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCWSTR section
)
800 WCHAR buffer
[MAX_PATH
];
804 TRACE( "hinf=%p/%p section=%s\n", hinf
, hlist
, debugstr_w(section
) );
806 if (!hlist
) hlist
= hinf
;
807 if (!SetupFindFirstLineW( hlist
, section
, NULL
, &context
)) return FALSE
;
808 if (!(dest_dir
= get_destination_dir( hinf
, section
))) return FALSE
;
811 if (!SetupGetStringFieldW( &context
, 1, buffer
, sizeof(buffer
)/sizeof(WCHAR
), NULL
))
813 if (!SetupGetIntField( &context
, 4, &flags
)) flags
= 0;
814 if (!SetupQueueDeleteW( queue
, dest_dir
, buffer
)) goto done
;
815 } while (SetupFindNextLine( &context
, &context
));
819 HeapFree( GetProcessHeap(), 0, dest_dir
);
824 /***********************************************************************
825 * SetupQueueRenameSectionA (SETUPAPI.@)
827 BOOL WINAPI
SetupQueueRenameSectionA( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCSTR section
)
829 UNICODE_STRING sectionW
;
832 if (RtlCreateUnicodeStringFromAsciiz( §ionW
, section
))
834 ret
= SetupQueueRenameSectionW( queue
, hinf
, hlist
, sectionW
.Buffer
);
835 RtlFreeUnicodeString( §ionW
);
837 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
842 /***********************************************************************
843 * SetupQueueRenameSectionW (SETUPAPI.@)
845 BOOL WINAPI
SetupQueueRenameSectionW( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCWSTR section
)
849 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
852 TRACE( "hinf=%p/%p section=%s\n", hinf
, hlist
, debugstr_w(section
) );
854 if (!hlist
) hlist
= hinf
;
855 if (!SetupFindFirstLineW( hlist
, section
, NULL
, &context
)) return FALSE
;
856 if (!(dest_dir
= get_destination_dir( hinf
, section
))) return FALSE
;
859 if (!SetupGetStringFieldW( &context
, 1, dst
, sizeof(dst
)/sizeof(WCHAR
), NULL
))
861 if (!SetupGetStringFieldW( &context
, 2, src
, sizeof(src
)/sizeof(WCHAR
), NULL
))
863 if (!SetupQueueRenameW( queue
, dest_dir
, src
, NULL
, dst
)) goto done
;
864 } while (SetupFindNextLine( &context
, &context
));
868 HeapFree( GetProcessHeap(), 0, dest_dir
);
873 /***********************************************************************
874 * SetupCommitFileQueueA (SETUPAPI.@)
876 BOOL WINAPI
SetupCommitFileQueueA( HWND owner
, HSPFILEQ queue
, PSP_FILE_CALLBACK_A handler
,
879 struct callback_WtoA_context ctx
;
881 ctx
.orig_context
= context
;
882 ctx
.orig_handler
= handler
;
883 return SetupCommitFileQueueW( owner
, queue
, QUEUE_callback_WtoA
, &ctx
);
887 /***********************************************************************
890 * Recursively create all directories in the path.
892 static BOOL
create_full_pathW(const WCHAR
*path
)
898 new_path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(path
) + 1) * sizeof(WCHAR
));
899 strcpyW(new_path
, path
);
901 while((len
= strlenW(new_path
)) && new_path
[len
- 1] == '\\')
902 new_path
[len
- 1] = 0;
904 while(!CreateDirectoryW(new_path
, NULL
))
907 DWORD last_error
= GetLastError();
909 if(last_error
== ERROR_ALREADY_EXISTS
)
912 if(last_error
!= ERROR_PATH_NOT_FOUND
)
918 if(!(slash
= strrchrW(new_path
, '\\')))
924 len
= slash
- new_path
;
926 if(!create_full_pathW(new_path
))
931 new_path
[len
] = '\\';
934 HeapFree(GetProcessHeap(), 0, new_path
);
938 static BOOL
do_file_copyW( LPCWSTR source
, LPCWSTR target
, DWORD style
,
939 PSP_FILE_CALLBACK_W handler
, PVOID context
)
944 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source
),debugstr_w(target
),style
);
946 /* before copy processing */
947 if (style
& SP_COPY_REPLACEONLY
)
949 if (GetFileAttributesW(target
) == INVALID_FILE_ATTRIBUTES
)
952 if (style
& (SP_COPY_NEWER_OR_SAME
| SP_COPY_NEWER_ONLY
| SP_COPY_FORCE_NEWER
))
954 DWORD VersionSizeSource
=0;
955 DWORD VersionSizeTarget
=0;
959 * This is sort of an interesting workaround. You see, calling
960 * GetVersionInfoSize on a builtin dll loads that dll into memory
961 * and we do not properly unload builtin dlls.. so we effectively
962 * lock into memory all the targets we are replacing. This leads
963 * to problems when we try to register the replaced dlls.
965 * So I will test for the existence of the files first so that
966 * we just basically unconditionally replace the builtin versions.
968 if ((GetFileAttributesW(target
) != INVALID_FILE_ATTRIBUTES
) &&
969 (GetFileAttributesW(source
) != INVALID_FILE_ATTRIBUTES
))
971 VersionSizeSource
= GetFileVersionInfoSizeW(source
,&zero
);
972 VersionSizeTarget
= GetFileVersionInfoSizeW(target
,&zero
);
975 TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget
,
978 if (VersionSizeSource
&& VersionSizeTarget
)
980 LPVOID VersionSource
;
981 LPVOID VersionTarget
;
982 VS_FIXEDFILEINFO
*TargetInfo
;
983 VS_FIXEDFILEINFO
*SourceInfo
;
985 static const WCHAR SubBlock
[]={'\\',0};
988 VersionSource
= HeapAlloc(GetProcessHeap(),0,VersionSizeSource
);
989 VersionTarget
= HeapAlloc(GetProcessHeap(),0,VersionSizeTarget
);
991 ret
= GetFileVersionInfoW(source
,0,VersionSizeSource
,VersionSource
);
993 ret
= GetFileVersionInfoW(target
, 0, VersionSizeTarget
,
998 ret
= VerQueryValueW(VersionSource
, SubBlock
,
999 (LPVOID
*)&SourceInfo
, &length
);
1001 ret
= VerQueryValueW(VersionTarget
, SubBlock
,
1002 (LPVOID
*)&TargetInfo
, &length
);
1006 FILEPATHS_W filepaths
;
1008 TRACE("Versions: Source %i.%i target %i.%i\n",
1009 SourceInfo
->dwFileVersionMS
, SourceInfo
->dwFileVersionLS
,
1010 TargetInfo
->dwFileVersionMS
, TargetInfo
->dwFileVersionLS
);
1012 /* used in case of notification */
1013 filepaths
.Target
= target
;
1014 filepaths
.Source
= source
;
1015 filepaths
.Win32Error
= 0;
1016 filepaths
.Flags
= 0;
1018 if (TargetInfo
->dwFileVersionMS
> SourceInfo
->dwFileVersionMS
)
1021 docopy
= handler (context
, SPFILENOTIFY_TARGETNEWER
, (UINT_PTR
)&filepaths
, 0);
1025 else if ((TargetInfo
->dwFileVersionMS
== SourceInfo
->dwFileVersionMS
)
1026 && (TargetInfo
->dwFileVersionLS
> SourceInfo
->dwFileVersionLS
))
1029 docopy
= handler (context
, SPFILENOTIFY_TARGETNEWER
, (UINT_PTR
)&filepaths
, 0);
1033 else if ((style
& SP_COPY_NEWER_ONLY
) &&
1034 (TargetInfo
->dwFileVersionMS
==
1035 SourceInfo
->dwFileVersionMS
)
1036 &&(TargetInfo
->dwFileVersionLS
==
1037 SourceInfo
->dwFileVersionLS
))
1040 docopy
= handler (context
, SPFILENOTIFY_TARGETNEWER
, (UINT_PTR
)&filepaths
, 0);
1046 HeapFree(GetProcessHeap(),0,VersionSource
);
1047 HeapFree(GetProcessHeap(),0,VersionTarget
);
1050 if (style
& (SP_COPY_NOOVERWRITE
| SP_COPY_FORCE_NOOVERWRITE
))
1052 if (GetFileAttributesW(target
) != INVALID_FILE_ATTRIBUTES
)
1054 FIXME("Notify user target file exists\n");
1058 if (style
& (SP_COPY_NODECOMP
| SP_COPY_LANGUAGEAWARE
| SP_COPY_FORCE_IN_USE
|
1059 SP_COPY_IN_USE_NEEDS_REBOOT
| SP_COPY_NOSKIP
| SP_COPY_WARNIFSKIP
))
1061 ERR("Unsupported style(s) 0x%x\n",style
);
1066 rc
= CopyFileW(source
,target
,FALSE
);
1067 TRACE("Did copy... rc was %i\n",rc
);
1070 /* after copy processing */
1071 if (style
& SP_COPY_DELETESOURCE
)
1074 DeleteFileW(source
);
1080 /***********************************************************************
1081 * SetupInstallFileExA (SETUPAPI.@)
1083 BOOL WINAPI
SetupInstallFileExA( HINF hinf
, PINFCONTEXT inf_context
, PCSTR source
, PCSTR root
,
1084 PCSTR dest
, DWORD style
, PSP_FILE_CALLBACK_A handler
, PVOID context
, PBOOL in_use
)
1087 struct callback_WtoA_context ctx
;
1088 UNICODE_STRING sourceW
, rootW
, destW
;
1090 TRACE("%p %p %s %s %s %x %p %p %p\n", hinf
, inf_context
, debugstr_a(source
), debugstr_a(root
),
1091 debugstr_a(dest
), style
, handler
, context
, in_use
);
1093 sourceW
.Buffer
= rootW
.Buffer
= destW
.Buffer
= NULL
;
1094 if (source
&& !RtlCreateUnicodeStringFromAsciiz( &sourceW
, source
))
1096 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1099 if (root
&& !RtlCreateUnicodeStringFromAsciiz( &rootW
, root
))
1101 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1104 if (dest
&& !RtlCreateUnicodeStringFromAsciiz( &destW
, dest
))
1106 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1110 ctx
.orig_context
= context
;
1111 ctx
.orig_handler
= handler
;
1113 ret
= SetupInstallFileExW( hinf
, inf_context
, sourceW
.Buffer
, rootW
.Buffer
, destW
.Buffer
, style
, QUEUE_callback_WtoA
, &ctx
, in_use
);
1116 RtlFreeUnicodeString( &sourceW
);
1117 RtlFreeUnicodeString( &rootW
);
1118 RtlFreeUnicodeString( &destW
);
1122 /***********************************************************************
1123 * SetupInstallFileA (SETUPAPI.@)
1125 BOOL WINAPI
SetupInstallFileA( HINF hinf
, PINFCONTEXT inf_context
, PCSTR source
, PCSTR root
,
1126 PCSTR dest
, DWORD style
, PSP_FILE_CALLBACK_A handler
, PVOID context
)
1128 return SetupInstallFileExA( hinf
, inf_context
, source
, root
, dest
, style
, handler
, context
, NULL
);
1131 /***********************************************************************
1132 * SetupInstallFileExW (SETUPAPI.@)
1134 BOOL WINAPI
SetupInstallFileExW( HINF hinf
, PINFCONTEXT inf_context
, PCWSTR source
, PCWSTR root
,
1135 PCWSTR dest
, DWORD style
, PSP_FILE_CALLBACK_W handler
, PVOID context
, PBOOL in_use
)
1137 static const WCHAR CopyFiles
[] = {'C','o','p','y','F','i','l','e','s',0};
1139 BOOL ret
, absolute
= (root
&& *root
&& !(style
& SP_COPY_SOURCE_ABSOLUTE
));
1140 WCHAR
*buffer
, *p
, *inf_source
= NULL
;
1143 TRACE("%p %p %s %s %s %x %p %p %p\n", hinf
, inf_context
, debugstr_w(source
), debugstr_w(root
),
1144 debugstr_w(dest
), style
, handler
, context
, in_use
);
1146 if (in_use
) FIXME("no file in use support\n");
1155 if (!SetupFindFirstLineW( hinf
, CopyFiles
, NULL
, inf_context
)) return FALSE
;
1157 if (!SetupGetStringFieldW( inf_context
, 1, NULL
, 0, &len
)) return FALSE
;
1158 if (!(inf_source
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
1160 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1163 if (!SetupGetStringFieldW( inf_context
, 1, inf_source
, len
, NULL
))
1165 HeapFree( GetProcessHeap(), 0, inf_source
);
1168 source
= inf_source
;
1172 SetLastError( ERROR_INVALID_PARAMETER
);
1176 len
= strlenW( source
) + 1;
1177 if (absolute
) len
+= strlenW( root
) + 1;
1179 if (!(p
= buffer
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
1181 HeapFree( GetProcessHeap(), 0, inf_source
);
1182 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1188 strcpyW( buffer
, root
);
1189 p
+= strlenW( buffer
);
1190 if (p
[-1] != '\\') *p
++ = '\\';
1192 while (*source
== '\\') source
++;
1193 strcpyW( p
, source
);
1195 ret
= do_file_copyW( buffer
, dest
, style
, handler
, context
);
1197 HeapFree( GetProcessHeap(), 0, inf_source
);
1198 HeapFree( GetProcessHeap(), 0, buffer
);
1202 /***********************************************************************
1203 * SetupInstallFileW (SETUPAPI.@)
1205 BOOL WINAPI
SetupInstallFileW( HINF hinf
, PINFCONTEXT inf_context
, PCWSTR source
, PCWSTR root
,
1206 PCWSTR dest
, DWORD style
, PSP_FILE_CALLBACK_W handler
, PVOID context
)
1208 return SetupInstallFileExW( hinf
, inf_context
, source
, root
, dest
, style
, handler
, context
, NULL
);
1211 /***********************************************************************
1212 * SetupCommitFileQueueW (SETUPAPI.@)
1214 BOOL WINAPI
SetupCommitFileQueueW( HWND owner
, HSPFILEQ handle
, PSP_FILE_CALLBACK_W handler
,
1217 struct file_queue
*queue
= handle
;
1219 BOOL result
= FALSE
;
1223 paths
.Source
= paths
.Target
= NULL
;
1225 if (!queue
->copy_queue
.count
&& !queue
->delete_queue
.count
&& !queue
->rename_queue
.count
)
1226 return TRUE
; /* nothing to do */
1228 if (!handler( context
, SPFILENOTIFY_STARTQUEUE
, (UINT_PTR
)owner
, 0 )) return FALSE
;
1230 /* perform deletes */
1232 if (queue
->delete_queue
.count
)
1234 if (!(handler( context
, SPFILENOTIFY_STARTSUBQUEUE
, FILEOP_DELETE
,
1235 queue
->delete_queue
.count
))) goto done
;
1236 for (op
= queue
->delete_queue
.head
; op
; op
= op
->next
)
1238 build_filepathsW( op
, &paths
);
1239 op_result
= handler( context
, SPFILENOTIFY_STARTDELETE
, (UINT_PTR
)&paths
, FILEOP_DELETE
);
1240 if (op_result
== FILEOP_ABORT
) goto done
;
1241 while (op_result
== FILEOP_DOIT
)
1243 TRACE( "deleting file %s\n", debugstr_w(paths
.Target
) );
1244 if (DeleteFileW( paths
.Target
)) break; /* success */
1245 paths
.Win32Error
= GetLastError();
1246 op_result
= handler( context
, SPFILENOTIFY_DELETEERROR
, (UINT_PTR
)&paths
, 0 );
1247 if (op_result
== FILEOP_ABORT
) goto done
;
1249 handler( context
, SPFILENOTIFY_ENDDELETE
, (UINT_PTR
)&paths
, 0 );
1251 handler( context
, SPFILENOTIFY_ENDSUBQUEUE
, FILEOP_DELETE
, 0 );
1254 /* perform renames */
1256 if (queue
->rename_queue
.count
)
1258 if (!(handler( context
, SPFILENOTIFY_STARTSUBQUEUE
, FILEOP_RENAME
,
1259 queue
->rename_queue
.count
))) goto done
;
1260 for (op
= queue
->rename_queue
.head
; op
; op
= op
->next
)
1262 build_filepathsW( op
, &paths
);
1263 op_result
= handler( context
, SPFILENOTIFY_STARTRENAME
, (UINT_PTR
)&paths
, FILEOP_RENAME
);
1264 if (op_result
== FILEOP_ABORT
) goto done
;
1265 while (op_result
== FILEOP_DOIT
)
1267 TRACE( "renaming file %s -> %s\n",
1268 debugstr_w(paths
.Source
), debugstr_w(paths
.Target
) );
1269 if (MoveFileW( paths
.Source
, paths
.Target
)) break; /* success */
1270 paths
.Win32Error
= GetLastError();
1271 op_result
= handler( context
, SPFILENOTIFY_RENAMEERROR
, (UINT_PTR
)&paths
, 0 );
1272 if (op_result
== FILEOP_ABORT
) goto done
;
1274 handler( context
, SPFILENOTIFY_ENDRENAME
, (UINT_PTR
)&paths
, 0 );
1276 handler( context
, SPFILENOTIFY_ENDSUBQUEUE
, FILEOP_RENAME
, 0 );
1279 /* perform copies */
1281 if (queue
->copy_queue
.count
)
1283 if (!(handler( context
, SPFILENOTIFY_STARTSUBQUEUE
, FILEOP_COPY
,
1284 queue
->copy_queue
.count
))) goto done
;
1285 for (op
= queue
->copy_queue
.head
; op
; op
= op
->next
)
1287 WCHAR newpath
[MAX_PATH
];
1289 build_filepathsW( op
, &paths
);
1290 op_result
= handler( context
, SPFILENOTIFY_STARTCOPY
, (UINT_PTR
)&paths
, FILEOP_COPY
);
1291 if (op_result
== FILEOP_ABORT
) goto done
;
1292 if (op_result
== FILEOP_NEWPATH
) op_result
= FILEOP_DOIT
;
1293 while (op_result
== FILEOP_DOIT
|| op_result
== FILEOP_NEWPATH
)
1295 TRACE( "copying file %s -> %s\n",
1296 debugstr_w( op_result
== FILEOP_NEWPATH
? newpath
: paths
.Source
),
1297 debugstr_w(paths
.Target
) );
1300 if (!create_full_pathW( op
->dst_path
))
1302 paths
.Win32Error
= GetLastError();
1303 op_result
= handler( context
, SPFILENOTIFY_COPYERROR
,
1304 (UINT_PTR
)&paths
, (UINT_PTR
)newpath
);
1305 if (op_result
== FILEOP_ABORT
) goto done
;
1308 if (do_file_copyW( op_result
== FILEOP_NEWPATH
? newpath
: paths
.Source
,
1309 paths
.Target
, op
->style
, handler
, context
)) break; /* success */
1310 /* try to extract it from the cabinet file */
1313 if (extract_cabinet_file( op
->src_tag
, op
->src_root
,
1314 paths
.Source
, paths
.Target
)) break;
1316 paths
.Win32Error
= GetLastError();
1317 op_result
= handler( context
, SPFILENOTIFY_COPYERROR
,
1318 (UINT_PTR
)&paths
, (UINT_PTR
)newpath
);
1319 if (op_result
== FILEOP_ABORT
) goto done
;
1321 handler( context
, SPFILENOTIFY_ENDCOPY
, (UINT_PTR
)&paths
, 0 );
1323 handler( context
, SPFILENOTIFY_ENDSUBQUEUE
, FILEOP_COPY
, 0 );
1330 handler( context
, SPFILENOTIFY_ENDQUEUE
, result
, 0 );
1331 HeapFree( GetProcessHeap(), 0, (void *)paths
.Source
);
1332 HeapFree( GetProcessHeap(), 0, (void *)paths
.Target
);
1337 /***********************************************************************
1338 * SetupScanFileQueueA (SETUPAPI.@)
1340 BOOL WINAPI
SetupScanFileQueueA( HSPFILEQ handle
, DWORD flags
, HWND window
,
1341 PSP_FILE_CALLBACK_A handler
, PVOID context
, PDWORD result
)
1343 struct callback_WtoA_context ctx
;
1345 TRACE("%p %x %p %p %p %p\n", handle
, flags
, window
, handler
, context
, result
);
1347 ctx
.orig_context
= context
;
1348 ctx
.orig_handler
= handler
;
1350 return SetupScanFileQueueW( handle
, flags
, window
, QUEUE_callback_WtoA
, &ctx
, result
);
1354 /***********************************************************************
1355 * SetupScanFileQueueW (SETUPAPI.@)
1357 BOOL WINAPI
SetupScanFileQueueW( HSPFILEQ handle
, DWORD flags
, HWND window
,
1358 PSP_FILE_CALLBACK_W handler
, PVOID context
, PDWORD result
)
1360 struct file_queue
*queue
= handle
;
1363 UINT notification
= 0;
1366 TRACE("%p %x %p %p %p %p\n", handle
, flags
, window
, handler
, context
, result
);
1368 if (!queue
->copy_queue
.count
) return TRUE
;
1370 if (flags
& SPQ_SCAN_USE_CALLBACK
) notification
= SPFILENOTIFY_QUEUESCAN
;
1371 else if (flags
& SPQ_SCAN_USE_CALLBACKEX
) notification
= SPFILENOTIFY_QUEUESCAN_EX
;
1373 if (flags
& ~(SPQ_SCAN_USE_CALLBACK
| SPQ_SCAN_USE_CALLBACKEX
))
1375 FIXME("flags %x not fully implemented\n", flags
);
1378 paths
.Source
= paths
.Target
= NULL
;
1380 for (op
= queue
->copy_queue
.head
; op
; op
= op
->next
)
1382 build_filepathsW( op
, &paths
);
1383 switch (notification
)
1385 case SPFILENOTIFY_QUEUESCAN
:
1386 /* FIXME: handle delay flag */
1387 if (handler( context
, notification
, (UINT_PTR
)paths
.Target
, 0 )) goto done
;
1389 case SPFILENOTIFY_QUEUESCAN_EX
:
1390 if (handler( context
, notification
, (UINT_PTR
)&paths
, 0 )) goto done
;
1393 ret
= TRUE
; goto done
;
1400 if (result
) *result
= 0;
1401 HeapFree( GetProcessHeap(), 0, (void *)paths
.Source
);
1402 HeapFree( GetProcessHeap(), 0, (void *)paths
.Target
);
1407 /***********************************************************************
1408 * SetupGetFileQueueCount (SETUPAPI.@)
1410 BOOL WINAPI
SetupGetFileQueueCount( HSPFILEQ handle
, UINT op
, PUINT result
)
1412 struct file_queue
*queue
= handle
;
1417 *result
= queue
->copy_queue
.count
;
1420 *result
= queue
->rename_queue
.count
;
1423 *result
= queue
->delete_queue
.count
;
1430 /***********************************************************************
1431 * SetupGetFileQueueFlags (SETUPAPI.@)
1433 BOOL WINAPI
SetupGetFileQueueFlags( HSPFILEQ handle
, PDWORD flags
)
1435 struct file_queue
*queue
= handle
;
1436 *flags
= queue
->flags
;
1441 /***********************************************************************
1442 * SetupSetFileQueueFlags (SETUPAPI.@)
1444 BOOL WINAPI
SetupSetFileQueueFlags( HSPFILEQ handle
, DWORD mask
, DWORD flags
)
1446 struct file_queue
*queue
= handle
;
1447 queue
->flags
= (queue
->flags
& ~mask
) | flags
;
1452 /***********************************************************************
1453 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1455 BOOL WINAPI
SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle
, PSP_ALTPLATFORM_INFO platform
, PCSTR catalogfile
)
1457 FIXME("(%p, %p, %s) stub!\n", handle
, platform
, debugstr_a(catalogfile
));
1462 /***********************************************************************
1463 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1465 BOOL WINAPI
SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle
, PSP_ALTPLATFORM_INFO platform
, PCWSTR catalogfile
)
1467 FIXME("(%p, %p, %s) stub!\n", handle
, platform
, debugstr_w(catalogfile
));
1472 /***********************************************************************
1473 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1475 PVOID WINAPI
SetupInitDefaultQueueCallback( HWND owner
)
1477 return SetupInitDefaultQueueCallbackEx( owner
, 0, 0, 0, NULL
);
1481 /***********************************************************************
1482 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1484 PVOID WINAPI
SetupInitDefaultQueueCallbackEx( HWND owner
, HWND progress
, UINT msg
,
1485 DWORD reserved1
, PVOID reserved2
)
1487 struct default_callback_context
*context
;
1489 if ((context
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*context
) )))
1491 context
->magic
= 0x43515053; /* "SPQC" */
1492 context
->owner
= owner
;
1493 context
->progress
= progress
;
1494 context
->message
= msg
;
1500 /***********************************************************************
1501 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1503 void WINAPI
SetupTermDefaultQueueCallback( PVOID context
)
1505 HeapFree( GetProcessHeap(), 0, context
);
1509 /***********************************************************************
1510 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1512 UINT WINAPI
SetupDefaultQueueCallbackA( PVOID context
, UINT notification
,
1513 UINT_PTR param1
, UINT_PTR param2
)
1515 FILEPATHS_A
*paths
= (FILEPATHS_A
*)param1
;
1516 struct default_callback_context
*ctx
= context
;
1518 switch(notification
)
1520 case SPFILENOTIFY_STARTQUEUE
:
1521 TRACE( "start queue\n" );
1523 case SPFILENOTIFY_ENDQUEUE
:
1524 TRACE( "end queue\n" );
1526 case SPFILENOTIFY_STARTSUBQUEUE
:
1527 TRACE( "start subqueue %ld count %ld\n", param1
, param2
);
1529 case SPFILENOTIFY_ENDSUBQUEUE
:
1530 TRACE( "end subqueue %ld\n", param1
);
1532 case SPFILENOTIFY_STARTDELETE
:
1533 TRACE( "start delete %s\n", debugstr_a(paths
->Target
) );
1535 case SPFILENOTIFY_ENDDELETE
:
1536 TRACE( "end delete %s\n", debugstr_a(paths
->Target
) );
1538 case SPFILENOTIFY_DELETEERROR
:
1539 /*Windows Ignores attempts to delete files / folders which do not exist*/
1540 if ((paths
->Win32Error
!= ERROR_FILE_NOT_FOUND
) && (paths
->Win32Error
!= ERROR_PATH_NOT_FOUND
))
1541 SetupDeleteErrorA(ctx
->owner
, NULL
, paths
->Target
, paths
->Win32Error
, 0);
1543 case SPFILENOTIFY_STARTRENAME
:
1544 TRACE( "start rename %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1546 case SPFILENOTIFY_ENDRENAME
:
1547 TRACE( "end rename %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1549 case SPFILENOTIFY_RENAMEERROR
:
1550 SetupRenameErrorA(ctx
->owner
, NULL
, paths
->Source
, paths
->Target
, paths
->Win32Error
, 0);
1552 case SPFILENOTIFY_STARTCOPY
:
1553 TRACE( "start copy %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1555 case SPFILENOTIFY_ENDCOPY
:
1556 TRACE( "end copy %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1558 case SPFILENOTIFY_COPYERROR
:
1559 ERR( "copy error %d %s -> %s\n", paths
->Win32Error
,
1560 debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1562 case SPFILENOTIFY_NEEDMEDIA
:
1563 TRACE( "need media\n" );
1566 FIXME( "notification %d params %lx,%lx\n", notification
, param1
, param2
);
1573 /***********************************************************************
1574 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1576 UINT WINAPI
SetupDefaultQueueCallbackW( PVOID context
, UINT notification
,
1577 UINT_PTR param1
, UINT_PTR param2
)
1579 FILEPATHS_W
*paths
= (FILEPATHS_W
*)param1
;
1580 struct default_callback_context
*ctx
= context
;
1582 switch(notification
)
1584 case SPFILENOTIFY_STARTQUEUE
:
1585 TRACE( "start queue\n" );
1587 case SPFILENOTIFY_ENDQUEUE
:
1588 TRACE( "end queue\n" );
1590 case SPFILENOTIFY_STARTSUBQUEUE
:
1591 TRACE( "start subqueue %ld count %ld\n", param1
, param2
);
1593 case SPFILENOTIFY_ENDSUBQUEUE
:
1594 TRACE( "end subqueue %ld\n", param1
);
1596 case SPFILENOTIFY_STARTDELETE
:
1597 TRACE( "start delete %s\n", debugstr_w(paths
->Target
) );
1599 case SPFILENOTIFY_ENDDELETE
:
1600 TRACE( "end delete %s\n", debugstr_w(paths
->Target
) );
1602 case SPFILENOTIFY_DELETEERROR
:
1603 /*Windows Ignores attempts to delete files / folders which do not exist*/
1604 if ((paths
->Win32Error
!= ERROR_FILE_NOT_FOUND
) && (paths
->Win32Error
!= ERROR_PATH_NOT_FOUND
))
1605 SetupDeleteErrorW(ctx
->owner
, NULL
, paths
->Target
, paths
->Win32Error
, 0);
1607 case SPFILENOTIFY_STARTRENAME
:
1608 SetupRenameErrorW(ctx
->owner
, NULL
, paths
->Source
, paths
->Target
, paths
->Win32Error
, 0);
1610 case SPFILENOTIFY_ENDRENAME
:
1611 TRACE( "end rename %s -> %s\n", debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1613 case SPFILENOTIFY_RENAMEERROR
:
1614 ERR( "rename error %d %s -> %s\n", paths
->Win32Error
,
1615 debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1617 case SPFILENOTIFY_STARTCOPY
:
1618 TRACE( "start copy %s -> %s\n", debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1620 case SPFILENOTIFY_ENDCOPY
:
1621 TRACE( "end copy %s -> %s\n", debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1623 case SPFILENOTIFY_COPYERROR
:
1624 ERR( "copy error %d %s -> %s\n", paths
->Win32Error
,
1625 debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1627 case SPFILENOTIFY_NEEDMEDIA
:
1628 TRACE( "need media\n" );
1631 FIXME( "notification %d params %lx,%lx\n", notification
, param1
, param2
);
1637 /***********************************************************************
1638 * SetupDeleteErrorA (SETUPAPI.@)
1641 UINT WINAPI
SetupDeleteErrorA( HWND parent
, PCSTR dialogTitle
, PCSTR file
,
1642 UINT w32error
, DWORD style
)
1644 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1645 w32error
, debugstr_a(file
) );
1646 return DPROMPT_SKIPFILE
;
1649 /***********************************************************************
1650 * SetupDeleteErrorW (SETUPAPI.@)
1653 UINT WINAPI
SetupDeleteErrorW( HWND parent
, PCWSTR dialogTitle
, PCWSTR file
,
1654 UINT w32error
, DWORD style
)
1656 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1657 w32error
, debugstr_w(file
) );
1658 return DPROMPT_SKIPFILE
;
1661 /***********************************************************************
1662 * SetupRenameErrorA (SETUPAPI.@)
1665 UINT WINAPI
SetupRenameErrorA( HWND parent
, PCSTR dialogTitle
, PCSTR source
,
1666 PCSTR target
, UINT w32error
, DWORD style
)
1668 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1669 w32error
, debugstr_a(source
), debugstr_a(target
));
1670 return DPROMPT_SKIPFILE
;
1673 /***********************************************************************
1674 * SetupRenameErrorW (SETUPAPI.@)
1677 UINT WINAPI
SetupRenameErrorW( HWND parent
, PCWSTR dialogTitle
, PCWSTR source
,
1678 PCWSTR target
, UINT w32error
, DWORD style
)
1680 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1681 w32error
, debugstr_w(source
), debugstr_w(target
));
1682 return DPROMPT_SKIPFILE
;
1686 /***********************************************************************
1687 * SetupCopyErrorA (SETUPAPI.@)
1690 UINT WINAPI
SetupCopyErrorA( HWND parent
, PCSTR dialogTitle
, PCSTR diskname
,
1691 PCSTR sourcepath
, PCSTR sourcefile
, PCSTR targetpath
,
1692 UINT w32error
, DWORD style
, PSTR pathbuffer
,
1693 DWORD buffersize
, PDWORD requiredsize
)
1695 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1696 w32error
, debugstr_a(sourcefile
), debugstr_a(sourcepath
) ,debugstr_a(targetpath
));
1697 return DPROMPT_SKIPFILE
;
1700 /***********************************************************************
1701 * SetupCopyErrorW (SETUPAPI.@)
1704 UINT WINAPI
SetupCopyErrorW( HWND parent
, PCWSTR dialogTitle
, PCWSTR diskname
,
1705 PCWSTR sourcepath
, PCWSTR sourcefile
, PCWSTR targetpath
,
1706 UINT w32error
, DWORD style
, PWSTR pathbuffer
,
1707 DWORD buffersize
, PDWORD requiredsize
)
1709 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1710 w32error
, debugstr_w(sourcefile
), debugstr_w(sourcepath
) ,debugstr_w(targetpath
));
1711 return DPROMPT_SKIPFILE
;
1714 /***********************************************************************
1715 * pSetupGetQueueFlags (SETUPAPI.@)
1717 DWORD WINAPI
pSetupGetQueueFlags( HSPFILEQ handle
)
1719 struct file_queue
*queue
= handle
;
1720 return queue
->flags
;
1723 /***********************************************************************
1724 * pSetupSetQueueFlags (SETUPAPI.@)
1726 BOOL WINAPI
pSetupSetQueueFlags( HSPFILEQ handle
, DWORD flags
)
1728 struct file_queue
*queue
= handle
;
1729 queue
->flags
= flags
;