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
33 #include "setupapi_private.h"
35 #include "wine/debug.h"
36 #include "wine/heap.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
40 /* context structure for the default queue callback */
41 struct default_callback_context
68 struct source_media
*media
;
81 struct file_op_queue copy_queue
;
82 struct file_op_queue delete_queue
;
83 struct file_op_queue rename_queue
;
85 struct source_media
**sources
;
86 unsigned int source_count
;
89 #define FILE_QUEUE_MAGIC 0x21514653
91 /* append a file operation to a queue */
92 static inline void queue_file_op( struct file_op_queue
*queue
, struct file_op
*op
)
95 if (queue
->tail
) queue
->tail
->next
= op
;
96 else queue
->head
= op
;
101 /* free all the file operations on a given queue */
102 static void free_file_op_queue( struct file_op_queue
*queue
)
104 struct file_op
*t
, *op
= queue
->head
;
108 HeapFree( GetProcessHeap(), 0, op
->src_path
);
109 HeapFree( GetProcessHeap(), 0, op
->src_file
);
110 HeapFree( GetProcessHeap(), 0, op
->dst_path
);
111 if (op
->dst_file
!= op
->src_file
) HeapFree( GetProcessHeap(), 0, op
->dst_file
);
114 HeapFree( GetProcessHeap(), 0, t
);
118 /* concat 3 strings to make a path, handling separators correctly */
119 static void concat_W( WCHAR
*buffer
, const WCHAR
*src1
, const WCHAR
*src2
, const WCHAR
*src3
)
124 lstrcpyW( buffer
, src1
);
125 buffer
+= lstrlenW(buffer
);
126 if (buffer
[-1] != '\\') *buffer
++ = '\\';
128 if (src2
) while (*src2
== '\\') src2
++;
133 lstrcpyW( buffer
, src2
);
134 buffer
+= lstrlenW(buffer
);
135 if (buffer
[-1] != '\\') *buffer
++ = '\\';
137 if (src3
) while (*src3
== '\\') src3
++;
141 lstrcpyW( buffer
, src3
);
145 /***********************************************************************
148 * Build a FILEPATHS_W structure for a given file operation.
150 static BOOL
build_filepathsW( const struct file_op
*op
, FILEPATHS_W
*paths
)
152 unsigned int src_len
= 1, dst_len
= 1;
153 WCHAR
*source
= (PWSTR
)paths
->Source
, *target
= (PWSTR
)paths
->Target
;
155 if (!op
->src_file
|| op
->src_file
[0] != '@')
157 if (op
->media
) src_len
+= lstrlenW(op
->media
->root
) + 1;
158 if (op
->src_path
) src_len
+= lstrlenW(op
->src_path
) + 1;
160 if (op
->src_file
) src_len
+= lstrlenW(op
->src_file
) + 1;
161 if (op
->dst_path
) dst_len
+= lstrlenW(op
->dst_path
) + 1;
162 if (op
->dst_file
) dst_len
+= lstrlenW(op
->dst_file
) + 1;
163 src_len
*= sizeof(WCHAR
);
164 dst_len
*= sizeof(WCHAR
);
166 if (!source
|| HeapSize( GetProcessHeap(), 0, source
) < src_len
)
168 HeapFree( GetProcessHeap(), 0, source
);
169 paths
->Source
= source
= HeapAlloc( GetProcessHeap(), 0, src_len
);
171 if (!target
|| HeapSize( GetProcessHeap(), 0, target
) < dst_len
)
173 HeapFree( GetProcessHeap(), 0, target
);
174 paths
->Target
= target
= HeapAlloc( GetProcessHeap(), 0, dst_len
);
176 if (!source
|| !target
) return FALSE
;
177 if (!op
->src_file
|| op
->src_file
[0] != '@')
178 concat_W( source
, op
->media
? op
->media
->root
: NULL
, op
->src_path
, op
->src_file
);
180 lstrcpyW( source
, op
->src_file
);
181 concat_W( target
, NULL
, op
->dst_path
, op
->dst_file
);
182 paths
->Win32Error
= 0;
188 /***********************************************************************
189 * QUEUE_callback_WtoA
191 * Map a file callback parameters from W to A and call the A callback.
193 UINT CALLBACK
QUEUE_callback_WtoA( void *context
, UINT notification
,
194 UINT_PTR param1
, UINT_PTR param2
)
196 struct callback_WtoA_context
*callback_ctx
= context
;
197 char buffer
[MAX_PATH
];
199 UINT_PTR old_param2
= param2
;
203 case SPFILENOTIFY_COPYERROR
:
205 param2
= (UINT_PTR
)buffer
;
207 case SPFILENOTIFY_STARTDELETE
:
208 case SPFILENOTIFY_ENDDELETE
:
209 case SPFILENOTIFY_DELETEERROR
:
210 case SPFILENOTIFY_STARTRENAME
:
211 case SPFILENOTIFY_ENDRENAME
:
212 case SPFILENOTIFY_RENAMEERROR
:
213 case SPFILENOTIFY_STARTCOPY
:
214 case SPFILENOTIFY_ENDCOPY
:
215 case SPFILENOTIFY_QUEUESCAN_EX
:
217 FILEPATHS_W
*pathsW
= (FILEPATHS_W
*)param1
;
220 pathsA
.Source
= strdupWtoA( pathsW
->Source
);
221 pathsA
.Target
= strdupWtoA( pathsW
->Target
);
222 pathsA
.Win32Error
= pathsW
->Win32Error
;
223 pathsA
.Flags
= pathsW
->Flags
;
224 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
,
225 (UINT_PTR
)&pathsA
, param2
);
226 HeapFree( GetProcessHeap(), 0, (void *)pathsA
.Source
);
227 HeapFree( GetProcessHeap(), 0, (void *)pathsA
.Target
);
229 if (notification
== SPFILENOTIFY_COPYERROR
)
230 MultiByteToWideChar( CP_ACP
, 0, buffer
, -1, (WCHAR
*)old_param2
, MAX_PATH
);
233 case SPFILENOTIFY_STARTREGISTRATION
:
234 case SPFILENOTIFY_ENDREGISTRATION
:
236 SP_REGISTER_CONTROL_STATUSW
*statusW
= (SP_REGISTER_CONTROL_STATUSW
*)param1
;
237 SP_REGISTER_CONTROL_STATUSA statusA
;
239 statusA
.cbSize
= sizeof(statusA
);
240 statusA
.FileName
= strdupWtoA( statusW
->FileName
);
241 statusA
.Win32Error
= statusW
->Win32Error
;
242 statusA
.FailureCode
= statusW
->FailureCode
;
243 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
,
244 (UINT_PTR
)&statusA
, param2
);
245 HeapFree( GetProcessHeap(), 0, (LPSTR
)statusA
.FileName
);
249 case SPFILENOTIFY_QUEUESCAN
:
251 LPWSTR targetW
= (LPWSTR
)param1
;
252 LPSTR target
= strdupWtoA( targetW
);
254 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
,
255 (UINT_PTR
)target
, param2
);
256 HeapFree( GetProcessHeap(), 0, target
);
260 case SPFILENOTIFY_NEEDMEDIA
:
262 const SOURCE_MEDIA_W
*mediaW
= (const SOURCE_MEDIA_W
*)param1
;
264 SOURCE_MEDIA_A mediaA
;
266 mediaA
.Tagfile
= strdupWtoA(mediaW
->Tagfile
);
267 mediaA
.Description
= strdupWtoA(mediaW
->Description
);
268 mediaA
.SourcePath
= strdupWtoA(mediaW
->SourcePath
);
269 mediaA
.SourceFile
= strdupWtoA(mediaW
->SourceFile
);
270 mediaA
.Flags
= mediaW
->Flags
;
273 ret
= callback_ctx
->orig_handler(callback_ctx
->orig_context
, notification
,
274 (UINT_PTR
)&mediaA
, (UINT_PTR
)&path
);
275 MultiByteToWideChar(CP_ACP
, 0, path
, -1, (WCHAR
*)param2
, MAX_PATH
);
277 heap_free((char *)mediaA
.Tagfile
);
278 heap_free((char *)mediaA
.Description
);
279 heap_free((char *)mediaA
.SourcePath
);
280 heap_free((char *)mediaA
.SourceFile
);
283 case SPFILENOTIFY_STARTQUEUE
:
284 case SPFILENOTIFY_ENDQUEUE
:
285 case SPFILENOTIFY_STARTSUBQUEUE
:
286 case SPFILENOTIFY_ENDSUBQUEUE
:
288 ret
= callback_ctx
->orig_handler( callback_ctx
->orig_context
, notification
, param1
, param2
);
294 static void get_source_info( HINF hinf
, const WCHAR
*src_file
, SP_FILE_COPY_PARAMS_W
*params
,
295 WCHAR
*src_root
, WCHAR
*src_path
)
297 INFCONTEXT file_ctx
, disk_ctx
;
301 /* find the SourceDisksFiles entry */
302 if (!SetupFindFirstLineW( hinf
, L
"SourceDisksFiles", src_file
, &file_ctx
)) return;
303 if (!SetupGetIntField( &file_ctx
, 1, &diskid
)) return;
305 /* now find the diskid in the SourceDisksNames section */
306 if (!SetupFindFirstLineW( hinf
, L
"SourceDisksNames", NULL
, &disk_ctx
)) return;
309 if (SetupGetIntField( &disk_ctx
, 0, &id
) && (id
== diskid
)) break;
310 if (!SetupFindNextLine( &disk_ctx
, &disk_ctx
)) return;
313 if (SetupGetStringFieldW( &disk_ctx
, 1, NULL
, 0, &len
) && len
> sizeof(WCHAR
)
314 && (params
->SourceDescription
= heap_alloc( len
* sizeof(WCHAR
) )))
315 SetupGetStringFieldW( &disk_ctx
, 1, (WCHAR
*)params
->SourceDescription
, len
, NULL
);
317 if (SetupGetStringFieldW( &disk_ctx
, 2, NULL
, 0, &len
) && len
> sizeof(WCHAR
)
318 && (params
->SourceTagfile
= heap_alloc( len
* sizeof(WCHAR
) )))
319 SetupGetStringFieldW( &disk_ctx
, 2, (WCHAR
*)params
->SourceTagfile
, len
, NULL
);
321 if (SetupGetStringFieldW( &disk_ctx
, 4, NULL
, 0, &len
) && len
> sizeof(WCHAR
)
322 && len
< MAX_PATH
- lstrlenW( src_root
) - 1)
324 lstrcatW( src_root
, L
"\\" );
325 SetupGetStringFieldW( &disk_ctx
, 4, src_root
+ lstrlenW( src_root
),
326 MAX_PATH
- lstrlenW( src_root
), NULL
);
329 if (SetupGetStringFieldW( &file_ctx
, 2, NULL
, 0, &len
) && len
> sizeof(WCHAR
) && len
< MAX_PATH
)
331 SetupGetStringFieldW( &file_ctx
, 2, src_path
, MAX_PATH
, NULL
);
332 params
->SourcePath
= src_path
;
336 /***********************************************************************
337 * get_destination_dir
339 * Retrieve the destination dir for a given section.
341 static WCHAR
*get_destination_dir( HINF hinf
, const WCHAR
*section
)
344 WCHAR systemdir
[MAX_PATH
], *dir
;
347 if (!section
|| !(ret
= SetupFindFirstLineW( hinf
, L
"DestinationDirs", section
, &context
)))
348 ret
= SetupFindFirstLineW( hinf
, L
"DestinationDirs", L
"DefaultDestDir", &context
);
350 if (ret
&& (dir
= PARSER_get_dest_dir( &context
)))
353 GetSystemDirectoryW( systemdir
, MAX_PATH
);
354 return strdupW( systemdir
);
357 struct extract_cab_ctx
363 static UINT WINAPI
extract_cab_cb( void *arg
, UINT message
, UINT_PTR param1
, UINT_PTR param2
)
365 struct extract_cab_ctx
*ctx
= arg
;
369 case SPFILENOTIFY_FILEINCABINET
:
371 FILE_IN_CABINET_INFO_W
*info
= (FILE_IN_CABINET_INFO_W
*)param1
;
372 const WCHAR
*filename
;
374 if ((filename
= wcsrchr( info
->NameInCabinet
, '\\' )))
377 filename
= info
->NameInCabinet
;
379 if (lstrcmpiW( filename
, ctx
->src
))
382 lstrcpyW( info
->FullTargetName
, ctx
->dst
);
385 case SPFILENOTIFY_FILEEXTRACTED
:
387 const FILEPATHS_W
*paths
= (const FILEPATHS_W
*)param1
;
388 return paths
->Win32Error
;
390 case SPFILENOTIFY_NEEDNEWCABINET
:
392 const CABINET_INFO_W
*info
= (const CABINET_INFO_W
*)param1
;
393 lstrcpyW( (WCHAR
*)param2
, info
->CabinetPath
);
394 return ERROR_SUCCESS
;
396 case SPFILENOTIFY_CABINETINFO
:
399 FIXME("Unexpected message %#x.\n", message
);
404 /***********************************************************************
405 * extract_cabinet_file
407 * Extract a file from a .cab file.
409 static BOOL
extract_cabinet_file( const WCHAR
*cabinet
, const WCHAR
*root
,
410 const WCHAR
*src
, const WCHAR
*dst
)
412 struct extract_cab_ctx ctx
= {src
, dst
};
413 int len
= lstrlenW( cabinet
);
414 WCHAR path
[MAX_PATH
];
416 /* make sure the cabinet file has a .cab extension */
417 if (len
<= 4 || wcsicmp( cabinet
+ len
- 4, L
".cab" )) return FALSE
;
419 lstrcpyW(path
, root
);
420 lstrcatW(path
, L
"\\" );
421 lstrcatW(path
, cabinet
);
423 return SetupIterateCabinetW( path
, 0, extract_cab_cb
, &ctx
);
426 /***********************************************************************
427 * SetupOpenFileQueue (SETUPAPI.@)
429 HSPFILEQ WINAPI
SetupOpenFileQueue(void)
431 struct file_queue
*queue
;
433 if (!(queue
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*queue
))))
434 return INVALID_HANDLE_VALUE
;
435 queue
->magic
= FILE_QUEUE_MAGIC
;
440 /***********************************************************************
441 * SetupCloseFileQueue (SETUPAPI.@)
443 BOOL WINAPI
SetupCloseFileQueue( HSPFILEQ handle
)
445 struct file_queue
*queue
= handle
;
448 /* Windows XP DDK installer passes the handle returned from
449 * SetupInitDefaultQueueCallback() to this function. */
450 if (queue
->magic
!= FILE_QUEUE_MAGIC
)
452 SetLastError(ERROR_INVALID_HANDLE
);
456 free_file_op_queue( &queue
->copy_queue
);
457 free_file_op_queue( &queue
->rename_queue
);
458 free_file_op_queue( &queue
->delete_queue
);
459 for (i
= 0; i
< queue
->source_count
; ++i
)
461 heap_free( queue
->sources
[i
]->desc
);
462 heap_free( queue
->sources
[i
]->tag
);
463 heap_free( queue
->sources
[i
] );
465 heap_free( queue
->sources
);
466 HeapFree( GetProcessHeap(), 0, queue
);
471 /***********************************************************************
472 * SetupQueueCopyIndirectA (SETUPAPI.@)
474 BOOL WINAPI
SetupQueueCopyIndirectA( SP_FILE_COPY_PARAMS_A
*paramsA
)
476 SP_FILE_COPY_PARAMS_W paramsW
;
479 paramsW
.cbSize
= sizeof(paramsW
);
480 paramsW
.QueueHandle
= paramsA
->QueueHandle
;
481 paramsW
.SourceRootPath
= strdupAtoW( paramsA
->SourceRootPath
);
482 paramsW
.SourcePath
= strdupAtoW( paramsA
->SourcePath
);
483 paramsW
.SourceFilename
= strdupAtoW( paramsA
->SourceFilename
);
484 paramsW
.SourceDescription
= strdupAtoW( paramsA
->SourceDescription
);
485 paramsW
.SourceTagfile
= strdupAtoW( paramsA
->SourceTagfile
);
486 paramsW
.TargetDirectory
= strdupAtoW( paramsA
->TargetDirectory
);
487 paramsW
.TargetFilename
= strdupAtoW( paramsA
->TargetFilename
);
488 paramsW
.CopyStyle
= paramsA
->CopyStyle
;
489 paramsW
.LayoutInf
= paramsA
->LayoutInf
;
490 paramsW
.SecurityDescriptor
= strdupAtoW( paramsA
->SecurityDescriptor
);
492 ret
= SetupQueueCopyIndirectW( ¶msW
);
494 heap_free( (WCHAR
*)paramsW
.SourceRootPath
);
495 heap_free( (WCHAR
*)paramsW
.SourcePath
);
496 heap_free( (WCHAR
*)paramsW
.SourceFilename
);
497 heap_free( (WCHAR
*)paramsW
.SourceDescription
);
498 heap_free( (WCHAR
*)paramsW
.SourceTagfile
);
499 heap_free( (WCHAR
*)paramsW
.TargetDirectory
);
500 heap_free( (WCHAR
*)paramsW
.TargetFilename
);
501 heap_free( (WCHAR
*)paramsW
.SecurityDescriptor
);
505 static BOOL
equal_str(const WCHAR
*a
, const WCHAR
*b
)
507 return (!a
&& !b
) || (a
&& b
&& !wcscmp(a
, b
));
510 static struct source_media
*get_source_media(struct file_queue
*queue
,
511 const WCHAR
*root
, const WCHAR
*desc
, const WCHAR
*tag
)
515 for (i
= 0; i
< queue
->source_count
; ++i
)
517 if (!wcscmp(root
, queue
->sources
[i
]->root
)
518 && equal_str(desc
, queue
->sources
[i
]->desc
)
519 && equal_str(tag
, queue
->sources
[i
]->tag
))
521 return queue
->sources
[i
];
525 queue
->sources
= heap_realloc( queue
->sources
, ++queue
->source_count
* sizeof(*queue
->sources
) );
526 queue
->sources
[i
] = heap_alloc( sizeof(*queue
->sources
[i
]) );
527 lstrcpyW(queue
->sources
[i
]->root
, root
);
528 queue
->sources
[i
]->desc
= strdupW(desc
);
529 queue
->sources
[i
]->tag
= strdupW(tag
);
530 queue
->sources
[i
]->resolved
= FALSE
;
531 queue
->sources
[i
]->cabinet
= FALSE
;
533 return queue
->sources
[i
];
536 /***********************************************************************
537 * SetupQueueCopyIndirectW (SETUPAPI.@)
539 BOOL WINAPI
SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params
)
541 struct file_queue
*queue
= params
->QueueHandle
;
544 if (!(op
= HeapAlloc( GetProcessHeap(), 0, sizeof(*op
) ))) return FALSE
;
545 op
->style
= params
->CopyStyle
;
546 op
->src_path
= strdupW( params
->SourcePath
);
547 op
->src_file
= strdupW( params
->SourceFilename
);
548 op
->dst_path
= strdupW( params
->TargetDirectory
);
549 op
->dst_file
= strdupW( params
->TargetFilename
);
552 if (!op
->dst_file
) op
->dst_file
= op
->src_file
;
553 if (params
->LayoutInf
)
554 FIXME("Unhandled LayoutInf %p.\n", params
->LayoutInf
);
556 op
->media
= get_source_media( queue
, params
->SourceRootPath
? params
->SourceRootPath
: L
"",
557 params
->SourceDescription
, params
->SourceTagfile
);
559 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n",
560 debugstr_w(op
->media
->root
), debugstr_w(op
->src_path
), debugstr_w(op
->src_file
),
561 debugstr_w(op
->dst_path
), debugstr_w(op
->dst_file
),
562 debugstr_w(op
->media
->desc
), debugstr_w(op
->media
->tag
) );
564 queue_file_op( &queue
->copy_queue
, op
);
569 /***********************************************************************
570 * SetupQueueCopyA (SETUPAPI.@)
572 BOOL WINAPI
SetupQueueCopyA( HSPFILEQ queue
, PCSTR src_root
, PCSTR src_path
, PCSTR src_file
,
573 PCSTR src_descr
, PCSTR src_tag
, PCSTR dst_dir
, PCSTR dst_file
,
576 SP_FILE_COPY_PARAMS_A params
;
578 params
.cbSize
= sizeof(params
);
579 params
.QueueHandle
= queue
;
580 params
.SourceRootPath
= src_root
;
581 params
.SourcePath
= src_path
;
582 params
.SourceFilename
= src_file
;
583 params
.SourceDescription
= src_descr
;
584 params
.SourceTagfile
= src_tag
;
585 params
.TargetDirectory
= dst_dir
;
586 params
.TargetFilename
= dst_file
;
587 params
.CopyStyle
= style
;
588 params
.LayoutInf
= 0;
589 params
.SecurityDescriptor
= NULL
;
590 return SetupQueueCopyIndirectA( ¶ms
);
594 /***********************************************************************
595 * SetupQueueCopyW (SETUPAPI.@)
597 BOOL WINAPI
SetupQueueCopyW( HSPFILEQ queue
, PCWSTR src_root
, PCWSTR src_path
, PCWSTR src_file
,
598 PCWSTR src_descr
, PCWSTR src_tag
, PCWSTR dst_dir
, PCWSTR dst_file
,
601 SP_FILE_COPY_PARAMS_W params
;
603 params
.cbSize
= sizeof(params
);
604 params
.QueueHandle
= queue
;
605 params
.SourceRootPath
= src_root
;
606 params
.SourcePath
= src_path
;
607 params
.SourceFilename
= src_file
;
608 params
.SourceDescription
= src_descr
;
609 params
.SourceTagfile
= src_tag
;
610 params
.TargetDirectory
= dst_dir
;
611 params
.TargetFilename
= dst_file
;
612 params
.CopyStyle
= style
;
613 params
.LayoutInf
= 0;
614 params
.SecurityDescriptor
= NULL
;
615 return SetupQueueCopyIndirectW( ¶ms
);
619 /***********************************************************************
620 * SetupQueueDefaultCopyA (SETUPAPI.@)
622 BOOL WINAPI
SetupQueueDefaultCopyA( HSPFILEQ queue
, HINF hinf
, const char *src_rootA
,
623 const char *src_fileA
, const char *dst_fileA
, DWORD style
)
625 WCHAR src_rootW
[MAX_PATH
], src_fileW
[MAX_PATH
], dst_fileW
[MAX_PATH
];
627 if (!src_rootA
|| !src_fileA
|| !dst_fileA
)
629 SetLastError(ERROR_INVALID_PARAMETER
);
633 MultiByteToWideChar( CP_ACP
, 0, src_rootA
, -1, src_rootW
, ARRAY_SIZE(src_rootW
) );
634 MultiByteToWideChar( CP_ACP
, 0, src_fileA
, -1, src_fileW
, ARRAY_SIZE(src_fileW
) );
635 MultiByteToWideChar( CP_ACP
, 0, dst_fileA
, -1, dst_fileW
, ARRAY_SIZE(dst_fileW
) );
636 return SetupQueueDefaultCopyW( queue
, hinf
, src_rootW
, src_fileW
, dst_fileW
, style
);
640 /***********************************************************************
641 * SetupQueueDefaultCopyW (SETUPAPI.@)
643 BOOL WINAPI
SetupQueueDefaultCopyW( HSPFILEQ queue
, HINF hinf
, PCWSTR src_root
, PCWSTR src_file
,
644 PCWSTR dst_file
, DWORD style
)
646 WCHAR src_root_buffer
[MAX_PATH
], src_path
[MAX_PATH
];
647 SP_FILE_COPY_PARAMS_W params
;
650 if (!src_root
|| !src_file
|| !dst_file
)
652 SetLastError(ERROR_INVALID_PARAMETER
);
656 params
.cbSize
= sizeof(params
);
657 params
.QueueHandle
= queue
;
658 params
.SourceRootPath
= src_root_buffer
;
659 params
.SourcePath
= NULL
;
660 params
.SourceFilename
= src_file
;
661 params
.SourceDescription
= NULL
;
662 params
.SourceTagfile
= NULL
;
663 params
.TargetFilename
= dst_file
;
664 params
.CopyStyle
= style
;
665 params
.LayoutInf
= NULL
;
666 params
.SecurityDescriptor
= NULL
;
668 lstrcpyW( src_root_buffer
, src_root
);
670 if (!(params
.TargetDirectory
= get_destination_dir( hinf
, NULL
))) return FALSE
;
671 get_source_info( hinf
, src_file
, ¶ms
, src_root_buffer
, src_path
);
673 ret
= SetupQueueCopyIndirectW( ¶ms
);
675 heap_free( (WCHAR
*)params
.TargetDirectory
);
676 heap_free( (WCHAR
*)params
.SourceDescription
);
677 heap_free( (WCHAR
*)params
.SourceTagfile
);
682 /***********************************************************************
683 * SetupQueueDeleteA (SETUPAPI.@)
685 BOOL WINAPI
SetupQueueDeleteA( HSPFILEQ handle
, PCSTR part1
, PCSTR part2
)
687 struct file_queue
*queue
= handle
;
690 if (!(op
= heap_alloc_zero( sizeof(*op
) ))) return FALSE
;
691 op
->dst_path
= strdupAtoW( part1
);
692 op
->dst_file
= strdupAtoW( part2
);
693 queue_file_op( &queue
->delete_queue
, op
);
698 /***********************************************************************
699 * SetupQueueDeleteW (SETUPAPI.@)
701 BOOL WINAPI
SetupQueueDeleteW( HSPFILEQ handle
, PCWSTR part1
, PCWSTR part2
)
703 struct file_queue
*queue
= handle
;
706 if (!(op
= heap_alloc_zero( sizeof(*op
) ))) return FALSE
;
707 op
->dst_path
= strdupW( part1
);
708 op
->dst_file
= strdupW( part2
);
709 queue_file_op( &queue
->delete_queue
, op
);
714 /***********************************************************************
715 * SetupQueueRenameA (SETUPAPI.@)
717 BOOL WINAPI
SetupQueueRenameA( HSPFILEQ handle
, PCSTR SourcePath
, PCSTR SourceFilename
,
718 PCSTR TargetPath
, PCSTR TargetFilename
)
720 struct file_queue
*queue
= handle
;
723 if (!(op
= heap_alloc_zero( sizeof(*op
) ))) return FALSE
;
724 op
->src_path
= strdupAtoW( SourcePath
);
725 op
->src_file
= strdupAtoW( SourceFilename
);
726 op
->dst_path
= strdupAtoW( TargetPath
);
727 op
->dst_file
= strdupAtoW( TargetFilename
);
728 queue_file_op( &queue
->rename_queue
, op
);
733 /***********************************************************************
734 * SetupQueueRenameW (SETUPAPI.@)
736 BOOL WINAPI
SetupQueueRenameW( HSPFILEQ handle
, PCWSTR SourcePath
, PCWSTR SourceFilename
,
737 PCWSTR TargetPath
, PCWSTR TargetFilename
)
739 struct file_queue
*queue
= handle
;
742 if (!(op
= heap_alloc_zero( sizeof(*op
) ))) return FALSE
;
743 op
->src_path
= strdupW( SourcePath
);
744 op
->src_file
= strdupW( SourceFilename
);
745 op
->dst_path
= strdupW( TargetPath
);
746 op
->dst_file
= strdupW( TargetFilename
);
747 queue_file_op( &queue
->rename_queue
, op
);
752 /***********************************************************************
753 * SetupQueueCopySectionA (SETUPAPI.@)
755 BOOL WINAPI
SetupQueueCopySectionA( HSPFILEQ queue
, PCSTR src_root
, HINF hinf
, HINF hlist
,
756 PCSTR section
, DWORD style
)
758 UNICODE_STRING sectionW
;
761 if (!RtlCreateUnicodeStringFromAsciiz( §ionW
, section
))
763 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
767 ret
= SetupQueueCopySectionW( queue
, NULL
, hinf
, hlist
, sectionW
.Buffer
, style
);
771 if (RtlCreateUnicodeStringFromAsciiz( &srcW
, src_root
))
773 ret
= SetupQueueCopySectionW( queue
, srcW
.Buffer
, hinf
, hlist
, sectionW
.Buffer
, style
);
774 RtlFreeUnicodeString( &srcW
);
776 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
778 RtlFreeUnicodeString( §ionW
);
782 /***********************************************************************
783 * SetupQueueCopySectionW (SETUPAPI.@)
785 BOOL WINAPI
SetupQueueCopySectionW( HSPFILEQ queue
, PCWSTR src_root
, HINF hinf
, HINF hlist
,
786 PCWSTR section
, DWORD style
)
788 WCHAR src_root_buffer
[MAX_PATH
], src_path
[MAX_PATH
], src_file
[MAX_PATH
], dst_file
[MAX_PATH
], *dest_dir
;
790 SP_FILE_COPY_PARAMS_W params
;
795 TRACE("queue %p, src_root %s, hinf %p, hlist %p, section %s, style %#x.\n",
796 queue
, debugstr_w(src_root
), hinf
, hlist
, debugstr_w(section
), style
);
800 SetLastError(ERROR_INVALID_PARAMETER
);
804 params
.cbSize
= sizeof(params
);
805 params
.QueueHandle
= queue
;
806 params
.SourceRootPath
= src_root_buffer
;
807 params
.SourceFilename
= src_file
;
808 params
.TargetFilename
= dst_file
;
809 params
.CopyStyle
= style
;
810 params
.LayoutInf
= NULL
;
811 params
.SecurityDescriptor
= NULL
;
813 lstrcpyW( src_root_buffer
, src_root
);
815 if (!hlist
) hlist
= hinf
;
816 if (!hinf
) hinf
= hlist
;
817 if (!SetupFindFirstLineW( hlist
, section
, NULL
, &context
)) return FALSE
;
818 if (!(params
.TargetDirectory
= dest_dir
= get_destination_dir( hinf
, section
))) return FALSE
;
821 params
.SourcePath
= NULL
;
822 params
.SourceDescription
= NULL
;
823 params
.SourceTagfile
= NULL
;
824 lstrcpyW( src_root_buffer
, src_root
);
827 if (!SetupGetStringFieldW( &context
, 1, dst_file
, ARRAY_SIZE( dst_file
), NULL
))
829 if (!SetupGetStringFieldW( &context
, 2, src_file
, ARRAY_SIZE( src_file
), &len
) || len
<= sizeof(WCHAR
))
830 lstrcpyW( src_file
, dst_file
);
832 if (!SetupGetIntField( &context
, 4, &flags
)) flags
= 0; /* FIXME */
834 get_source_info( hinf
, src_file
, ¶ms
, src_root_buffer
, src_path
);
836 if (!SetupQueueCopyIndirectW( ¶ms
)) goto end
;
838 heap_free( (WCHAR
*)params
.SourceDescription
);
839 heap_free( (WCHAR
*)params
.SourceTagfile
);
840 } while (SetupFindNextLine( &context
, &context
));
844 HeapFree(GetProcessHeap(), 0, dest_dir
);
849 /***********************************************************************
850 * SetupQueueDeleteSectionA (SETUPAPI.@)
852 BOOL WINAPI
SetupQueueDeleteSectionA( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCSTR section
)
854 UNICODE_STRING sectionW
;
857 if (RtlCreateUnicodeStringFromAsciiz( §ionW
, section
))
859 ret
= SetupQueueDeleteSectionW( queue
, hinf
, hlist
, sectionW
.Buffer
);
860 RtlFreeUnicodeString( §ionW
);
862 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
867 /***********************************************************************
868 * SetupQueueDeleteSectionW (SETUPAPI.@)
870 BOOL WINAPI
SetupQueueDeleteSectionW( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCWSTR section
)
874 WCHAR buffer
[MAX_PATH
];
878 TRACE( "hinf=%p/%p section=%s\n", hinf
, hlist
, debugstr_w(section
) );
880 if (!hlist
) hlist
= hinf
;
881 if (!SetupFindFirstLineW( hlist
, section
, NULL
, &context
)) return FALSE
;
882 if (!(dest_dir
= get_destination_dir( hinf
, section
))) return FALSE
;
885 if (!SetupGetStringFieldW( &context
, 1, buffer
, ARRAY_SIZE( buffer
), NULL
))
887 if (!SetupGetIntField( &context
, 4, &flags
)) flags
= 0;
888 if (!SetupQueueDeleteW( queue
, dest_dir
, buffer
)) goto done
;
889 } while (SetupFindNextLine( &context
, &context
));
893 HeapFree( GetProcessHeap(), 0, dest_dir
);
898 /***********************************************************************
899 * SetupQueueRenameSectionA (SETUPAPI.@)
901 BOOL WINAPI
SetupQueueRenameSectionA( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCSTR section
)
903 UNICODE_STRING sectionW
;
906 if (RtlCreateUnicodeStringFromAsciiz( §ionW
, section
))
908 ret
= SetupQueueRenameSectionW( queue
, hinf
, hlist
, sectionW
.Buffer
);
909 RtlFreeUnicodeString( §ionW
);
911 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
916 /***********************************************************************
917 * SetupQueueRenameSectionW (SETUPAPI.@)
919 BOOL WINAPI
SetupQueueRenameSectionW( HSPFILEQ queue
, HINF hinf
, HINF hlist
, PCWSTR section
)
923 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
926 TRACE( "hinf=%p/%p section=%s\n", hinf
, hlist
, debugstr_w(section
) );
928 if (!hlist
) hlist
= hinf
;
929 if (!SetupFindFirstLineW( hlist
, section
, NULL
, &context
)) return FALSE
;
930 if (!(dest_dir
= get_destination_dir( hinf
, section
))) return FALSE
;
933 if (!SetupGetStringFieldW( &context
, 1, dst
, ARRAY_SIZE( dst
), NULL
))
935 if (!SetupGetStringFieldW( &context
, 2, src
, ARRAY_SIZE( src
), NULL
))
937 if (!SetupQueueRenameW( queue
, dest_dir
, src
, NULL
, dst
)) goto done
;
938 } while (SetupFindNextLine( &context
, &context
));
942 HeapFree( GetProcessHeap(), 0, dest_dir
);
947 /***********************************************************************
948 * SetupCommitFileQueueA (SETUPAPI.@)
950 BOOL WINAPI
SetupCommitFileQueueA( HWND owner
, HSPFILEQ queue
, PSP_FILE_CALLBACK_A handler
,
953 struct callback_WtoA_context ctx
;
955 ctx
.orig_context
= context
;
956 ctx
.orig_handler
= handler
;
957 return SetupCommitFileQueueW( owner
, queue
, QUEUE_callback_WtoA
, &ctx
);
961 /***********************************************************************
964 * Recursively create all directories in the path.
966 static BOOL
create_full_pathW(const WCHAR
*path
)
972 new_path
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(path
) + 1) * sizeof(WCHAR
));
973 lstrcpyW(new_path
, path
);
975 while((len
= lstrlenW(new_path
)) && new_path
[len
- 1] == '\\')
976 new_path
[len
- 1] = 0;
978 while(!CreateDirectoryW(new_path
, NULL
))
981 DWORD last_error
= GetLastError();
983 if(last_error
== ERROR_ALREADY_EXISTS
)
986 if(last_error
!= ERROR_PATH_NOT_FOUND
)
992 if(!(slash
= wcsrchr(new_path
, '\\')))
998 len
= slash
- new_path
;
1000 if(!create_full_pathW(new_path
))
1005 new_path
[len
] = '\\';
1008 HeapFree(GetProcessHeap(), 0, new_path
);
1012 static BOOL
copy_file( LPCWSTR source
, LPCWSTR target
)
1014 WCHAR module
[MAX_PATH
];
1019 DWORD size
, written
;
1024 TRACE( "%s -> %s\n", debugstr_w(source
), debugstr_w(target
) );
1026 if (source
[0] != '@') return CopyFileW( source
, target
, FALSE
);
1028 /* Wine extension: when the source of a file copy is in the format "@file.dll,-123"
1029 * the source data is extracted from the corresponding file.dll resource */
1031 source
++; /* skip '@' */
1032 p
= wcschr( source
, ',' );
1033 if (!p
|| p
- source
>= MAX_PATH
)
1035 SetLastError( ERROR_RESOURCE_DATA_NOT_FOUND
);
1038 memcpy( module
, source
, (p
- source
) * sizeof(WCHAR
) );
1039 module
[p
- source
] = 0;
1040 id
= -wcstol( p
+ 1, NULL
, 10 );
1041 if (id
<= 0 || id
> 0xffff ||
1042 !(mod
= LoadLibraryExW( module
, 0, LOAD_LIBRARY_AS_DATAFILE
)) ||
1043 !(res
= FindResourceW( mod
, MAKEINTRESOURCEW(id
), L
"WINE_DATA_FILE" )) ||
1044 !(data
= LoadResource( mod
, res
)))
1046 WARN( "failed to save %s #%d to %s\n", debugstr_w(module
), -id
, debugstr_w(target
) );
1047 if (mod
) FreeLibrary( mod
);
1048 SetLastError( ERROR_RESOURCE_DATA_NOT_FOUND
);
1051 size
= SizeofResource( mod
, res
);
1052 if ((handle
= CreateFileW( target
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
1053 CREATE_ALWAYS
, 0, 0 )) == INVALID_HANDLE_VALUE
)
1055 WARN( "failed to save %s #%d to %s\n", debugstr_w(module
), -id
, debugstr_w(target
) );
1056 if (mod
) FreeLibrary( mod
);
1059 ret
= WriteFile( handle
, LockResource(data
), size
, &written
, NULL
) && written
== size
;
1060 CloseHandle( handle
);
1061 if (!ret
) DeleteFileW( target
);
1065 static BOOL
do_file_copyW( LPCWSTR source
, LPCWSTR target
, DWORD style
,
1066 PSP_FILE_CALLBACK_W handler
, PVOID context
)
1071 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source
),debugstr_w(target
),style
);
1073 /* before copy processing */
1074 if (style
& SP_COPY_REPLACEONLY
)
1076 if (GetFileAttributesW(target
) == INVALID_FILE_ATTRIBUTES
)
1079 if (style
& (SP_COPY_NEWER_OR_SAME
| SP_COPY_NEWER_ONLY
| SP_COPY_FORCE_NEWER
))
1081 DWORD VersionSizeSource
=0;
1082 DWORD VersionSizeTarget
=0;
1086 * This is sort of an interesting workaround. You see, calling
1087 * GetVersionInfoSize on a builtin dll loads that dll into memory
1088 * and we do not properly unload builtin dlls.. so we effectively
1089 * lock into memory all the targets we are replacing. This leads
1090 * to problems when we try to register the replaced dlls.
1092 * So I will test for the existence of the files first so that
1093 * we just basically unconditionally replace the builtin versions.
1095 if ((GetFileAttributesW(target
) != INVALID_FILE_ATTRIBUTES
) &&
1096 (GetFileAttributesW(source
) != INVALID_FILE_ATTRIBUTES
))
1098 VersionSizeSource
= GetFileVersionInfoSizeW(source
,&zero
);
1099 VersionSizeTarget
= GetFileVersionInfoSizeW(target
,&zero
);
1102 if (VersionSizeSource
&& VersionSizeTarget
)
1104 LPVOID VersionSource
;
1105 LPVOID VersionTarget
;
1106 VS_FIXEDFILEINFO
*TargetInfo
;
1107 VS_FIXEDFILEINFO
*SourceInfo
;
1111 VersionSource
= HeapAlloc(GetProcessHeap(),0,VersionSizeSource
);
1112 VersionTarget
= HeapAlloc(GetProcessHeap(),0,VersionSizeTarget
);
1114 ret
= GetFileVersionInfoW(source
,0,VersionSizeSource
,VersionSource
);
1116 ret
= GetFileVersionInfoW(target
, 0, VersionSizeTarget
,
1121 ret
= VerQueryValueW(VersionSource
, L
"\\", (LPVOID
*)&SourceInfo
, &length
);
1123 ret
= VerQueryValueW(VersionTarget
, L
"\\", (LPVOID
*)&TargetInfo
, &length
);
1127 FILEPATHS_W filepaths
;
1129 TRACE("Versions: Source %i.%i target %i.%i\n",
1130 SourceInfo
->dwFileVersionMS
, SourceInfo
->dwFileVersionLS
,
1131 TargetInfo
->dwFileVersionMS
, TargetInfo
->dwFileVersionLS
);
1133 /* used in case of notification */
1134 filepaths
.Target
= target
;
1135 filepaths
.Source
= source
;
1136 filepaths
.Win32Error
= 0;
1137 filepaths
.Flags
= 0;
1139 if (TargetInfo
->dwFileVersionMS
> SourceInfo
->dwFileVersionMS
)
1142 docopy
= handler (context
, SPFILENOTIFY_TARGETNEWER
, (UINT_PTR
)&filepaths
, 0);
1146 else if ((TargetInfo
->dwFileVersionMS
== SourceInfo
->dwFileVersionMS
)
1147 && (TargetInfo
->dwFileVersionLS
> SourceInfo
->dwFileVersionLS
))
1150 docopy
= handler (context
, SPFILENOTIFY_TARGETNEWER
, (UINT_PTR
)&filepaths
, 0);
1154 else if ((style
& SP_COPY_NEWER_ONLY
) &&
1155 (TargetInfo
->dwFileVersionMS
==
1156 SourceInfo
->dwFileVersionMS
)
1157 &&(TargetInfo
->dwFileVersionLS
==
1158 SourceInfo
->dwFileVersionLS
))
1161 docopy
= handler (context
, SPFILENOTIFY_TARGETNEWER
, (UINT_PTR
)&filepaths
, 0);
1167 HeapFree(GetProcessHeap(),0,VersionSource
);
1168 HeapFree(GetProcessHeap(),0,VersionTarget
);
1171 if (style
& (SP_COPY_NOOVERWRITE
| SP_COPY_FORCE_NOOVERWRITE
))
1173 if (GetFileAttributesW(target
) != INVALID_FILE_ATTRIBUTES
)
1175 FIXME("Notify user target file exists\n");
1179 if (style
& (SP_COPY_NODECOMP
| SP_COPY_LANGUAGEAWARE
| SP_COPY_FORCE_IN_USE
|
1180 SP_COPY_NOSKIP
| SP_COPY_WARNIFSKIP
))
1182 ERR("Unsupported style(s) 0x%x\n",style
);
1187 rc
= copy_file( source
, target
);
1188 if (!rc
&& GetLastError() == ERROR_SHARING_VIOLATION
&&
1189 (style
& SP_COPY_IN_USE_NEEDS_REBOOT
))
1191 WCHAR temp_file
[MAX_PATH
];
1192 WCHAR temp
[MAX_PATH
];
1194 if (GetTempPathW(MAX_PATH
, temp
) &&
1195 GetTempFileNameW(temp
, L
"SET", 0, temp_file
))
1197 rc
= copy_file( source
, temp_file
);
1199 rc
= MoveFileExW(temp_file
, target
, MOVEFILE_DELAY_UNTIL_REBOOT
);
1201 DeleteFileW(temp_file
);
1204 if (!rc
) WARN( "failed to copy, err %u\n", GetLastError() );
1207 SetLastError(ERROR_SUCCESS
);
1209 /* after copy processing */
1210 if (style
& SP_COPY_DELETESOURCE
)
1213 DeleteFileW(source
);
1219 /***********************************************************************
1220 * SetupInstallFileExA (SETUPAPI.@)
1222 BOOL WINAPI
SetupInstallFileExA( HINF hinf
, PINFCONTEXT inf_context
, PCSTR source
, PCSTR root
,
1223 PCSTR dest
, DWORD style
, PSP_FILE_CALLBACK_A handler
, PVOID context
, PBOOL in_use
)
1226 struct callback_WtoA_context ctx
;
1227 UNICODE_STRING sourceW
, rootW
, destW
;
1229 TRACE("%p %p %s %s %s %x %p %p %p\n", hinf
, inf_context
, debugstr_a(source
), debugstr_a(root
),
1230 debugstr_a(dest
), style
, handler
, context
, in_use
);
1232 sourceW
.Buffer
= rootW
.Buffer
= destW
.Buffer
= NULL
;
1233 if (source
&& !RtlCreateUnicodeStringFromAsciiz( &sourceW
, source
))
1235 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1238 if (root
&& !RtlCreateUnicodeStringFromAsciiz( &rootW
, root
))
1240 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1243 if (dest
&& !RtlCreateUnicodeStringFromAsciiz( &destW
, dest
))
1245 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1249 ctx
.orig_context
= context
;
1250 ctx
.orig_handler
= handler
;
1252 ret
= SetupInstallFileExW( hinf
, inf_context
, sourceW
.Buffer
, rootW
.Buffer
, destW
.Buffer
, style
, QUEUE_callback_WtoA
, &ctx
, in_use
);
1255 RtlFreeUnicodeString( &sourceW
);
1256 RtlFreeUnicodeString( &rootW
);
1257 RtlFreeUnicodeString( &destW
);
1261 /***********************************************************************
1262 * SetupInstallFileA (SETUPAPI.@)
1264 BOOL WINAPI
SetupInstallFileA( HINF hinf
, PINFCONTEXT inf_context
, PCSTR source
, PCSTR root
,
1265 PCSTR dest
, DWORD style
, PSP_FILE_CALLBACK_A handler
, PVOID context
)
1267 return SetupInstallFileExA( hinf
, inf_context
, source
, root
, dest
, style
, handler
, context
, NULL
);
1270 /***********************************************************************
1271 * SetupInstallFileExW (SETUPAPI.@)
1273 BOOL WINAPI
SetupInstallFileExW( HINF hinf
, PINFCONTEXT inf_context
, PCWSTR source
, PCWSTR root
,
1274 PCWSTR dest
, DWORD style
, PSP_FILE_CALLBACK_W handler
, PVOID context
, PBOOL in_use
)
1276 BOOL ret
, absolute
= (root
&& *root
&& !(style
& SP_COPY_SOURCE_ABSOLUTE
));
1277 WCHAR
*buffer
, *p
, *inf_source
= NULL
, dest_path
[MAX_PATH
];
1280 TRACE("%p %p %s %s %s %x %p %p %p\n", hinf
, inf_context
, debugstr_w(source
), debugstr_w(root
),
1281 debugstr_w(dest
), style
, handler
, context
, in_use
);
1283 if (in_use
) FIXME("no file in use support\n");
1295 if (!SetupFindFirstLineW( hinf
, L
"CopyFiles", NULL
, inf_context
)) return FALSE
;
1297 if (!SetupGetStringFieldW( inf_context
, 1, NULL
, 0, &len
)) return FALSE
;
1298 if (!(inf_source
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
1300 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1303 if (!SetupGetStringFieldW( inf_context
, 1, inf_source
, len
, NULL
))
1305 HeapFree( GetProcessHeap(), 0, inf_source
);
1308 source
= inf_source
;
1310 if ((dest_dir
= get_destination_dir( hinf
, NULL
)))
1312 lstrcpyW( dest_path
, dest_dir
);
1313 lstrcatW( dest_path
, L
"\\" );
1314 heap_free( dest_dir
);
1319 SetLastError( ERROR_INVALID_PARAMETER
);
1323 len
= lstrlenW( source
) + 1;
1324 if (absolute
) len
+= lstrlenW( root
) + 1;
1326 if (!(p
= buffer
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
1328 HeapFree( GetProcessHeap(), 0, inf_source
);
1329 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1335 lstrcpyW( buffer
, root
);
1336 p
+= lstrlenW( buffer
);
1337 if (p
[-1] != '\\') *p
++ = '\\';
1339 while (*source
== '\\') source
++;
1340 lstrcpyW( p
, source
);
1342 lstrcatW( dest_path
, dest
);
1344 ret
= do_file_copyW( buffer
, dest_path
, style
, handler
, context
);
1346 HeapFree( GetProcessHeap(), 0, inf_source
);
1347 HeapFree( GetProcessHeap(), 0, buffer
);
1351 /***********************************************************************
1352 * SetupInstallFileW (SETUPAPI.@)
1354 BOOL WINAPI
SetupInstallFileW( HINF hinf
, PINFCONTEXT inf_context
, PCWSTR source
, PCWSTR root
,
1355 PCWSTR dest
, DWORD style
, PSP_FILE_CALLBACK_W handler
, PVOID context
)
1357 return SetupInstallFileExW( hinf
, inf_context
, source
, root
, dest
, style
, handler
, context
, NULL
);
1360 static BOOL
queue_copy_file( const WCHAR
*source
, const WCHAR
*dest
,
1361 const struct file_op
*op
, PSP_FILE_CALLBACK_W handler
, void *context
)
1363 TRACE("copying file %s -> %s\n", debugstr_w(source
), debugstr_w(dest
));
1365 if (op
->dst_path
&& !create_full_pathW(op
->dst_path
))
1368 if (do_file_copyW(source
, dest
, op
->style
, handler
, context
) || GetLastError() == ERROR_SUCCESS
)
1371 /* try to extract it from the cabinet file */
1372 if (op
->media
->tag
&& extract_cabinet_file(op
->media
->tag
, op
->media
->root
, op
->src_file
, dest
))
1374 op
->media
->cabinet
= TRUE
;
1381 /***********************************************************************
1382 * SetupCommitFileQueueW (SETUPAPI.@)
1384 BOOL WINAPI
SetupCommitFileQueueW( HWND owner
, HSPFILEQ handle
, PSP_FILE_CALLBACK_W handler
,
1387 struct file_queue
*queue
= handle
;
1389 BOOL result
= FALSE
;
1393 paths
.Source
= paths
.Target
= NULL
;
1395 if (!queue
->copy_queue
.count
&& !queue
->delete_queue
.count
&& !queue
->rename_queue
.count
)
1396 return TRUE
; /* nothing to do */
1398 if (!handler( context
, SPFILENOTIFY_STARTQUEUE
, (UINT_PTR
)owner
, 0 )) return FALSE
;
1400 /* perform deletes */
1402 if (queue
->delete_queue
.count
)
1404 if (!(handler( context
, SPFILENOTIFY_STARTSUBQUEUE
, FILEOP_DELETE
,
1405 queue
->delete_queue
.count
))) goto done
;
1406 for (op
= queue
->delete_queue
.head
; op
; op
= op
->next
)
1408 build_filepathsW( op
, &paths
);
1409 op_result
= handler( context
, SPFILENOTIFY_STARTDELETE
, (UINT_PTR
)&paths
, FILEOP_DELETE
);
1410 if (op_result
== FILEOP_ABORT
) goto done
;
1411 while (op_result
== FILEOP_DOIT
)
1413 TRACE( "deleting file %s\n", debugstr_w(paths
.Target
) );
1414 if (DeleteFileW( paths
.Target
)) break; /* success */
1415 paths
.Win32Error
= GetLastError();
1416 op_result
= handler( context
, SPFILENOTIFY_DELETEERROR
, (UINT_PTR
)&paths
, 0 );
1417 if (op_result
== FILEOP_ABORT
) goto done
;
1419 handler( context
, SPFILENOTIFY_ENDDELETE
, (UINT_PTR
)&paths
, 0 );
1421 handler( context
, SPFILENOTIFY_ENDSUBQUEUE
, FILEOP_DELETE
, 0 );
1424 /* perform renames */
1426 if (queue
->rename_queue
.count
)
1428 if (!(handler( context
, SPFILENOTIFY_STARTSUBQUEUE
, FILEOP_RENAME
,
1429 queue
->rename_queue
.count
))) goto done
;
1430 for (op
= queue
->rename_queue
.head
; op
; op
= op
->next
)
1432 build_filepathsW( op
, &paths
);
1433 op_result
= handler( context
, SPFILENOTIFY_STARTRENAME
, (UINT_PTR
)&paths
, FILEOP_RENAME
);
1434 if (op_result
== FILEOP_ABORT
) goto done
;
1435 while (op_result
== FILEOP_DOIT
)
1437 TRACE( "renaming file %s -> %s\n",
1438 debugstr_w(paths
.Source
), debugstr_w(paths
.Target
) );
1439 if (MoveFileW( paths
.Source
, paths
.Target
)) break; /* success */
1440 paths
.Win32Error
= GetLastError();
1441 op_result
= handler( context
, SPFILENOTIFY_RENAMEERROR
, (UINT_PTR
)&paths
, 0 );
1442 if (op_result
== FILEOP_ABORT
) goto done
;
1444 handler( context
, SPFILENOTIFY_ENDRENAME
, (UINT_PTR
)&paths
, 0 );
1446 handler( context
, SPFILENOTIFY_ENDSUBQUEUE
, FILEOP_RENAME
, 0 );
1449 /* perform copies */
1451 if (queue
->copy_queue
.count
)
1453 if (!(handler( context
, SPFILENOTIFY_STARTSUBQUEUE
, FILEOP_COPY
,
1454 queue
->copy_queue
.count
))) goto done
;
1455 for (op
= queue
->copy_queue
.head
; op
; op
= op
->next
)
1457 WCHAR newpath
[MAX_PATH
];
1459 if (!op
->media
->resolved
)
1461 /* The NEEDMEDIA callback asks for the folder containing the
1462 * first file, but that might be in a subdir of the source
1463 * disk's root directory. We have to do some contortions to
1464 * correct for this. Pretend that the file we're using
1465 * actually isn't in a subdirectory, but keep track of what it
1466 * was, and then later strip it from the root path that we
1467 * ultimately resolve the source disk to. */
1468 WCHAR src_path
[MAX_PATH
];
1469 size_t path_len
= 0;
1474 lstrcpyW(src_path
, op
->src_path
);
1475 path_len
= lstrlenW(src_path
);
1477 lstrcatW(op
->media
->root
, L
"\\");
1478 lstrcatW(op
->media
->root
, op
->src_path
);
1480 heap_free(op
->src_path
);
1481 op
->src_path
= NULL
;
1486 SOURCE_MEDIA_W media
;
1487 media
.Reserved
= NULL
;
1488 media
.Tagfile
= op
->media
->tag
;
1489 media
.Description
= op
->media
->desc
;
1490 media
.SourcePath
= op
->media
->root
;
1491 media
.SourceFile
= op
->src_file
;
1492 media
.Flags
= op
->style
& (SP_COPY_WARNIFSKIP
| SP_COPY_NOSKIP
| SP_FLAG_CABINETCONTINUATION
| SP_COPY_NOBROWSE
);
1495 op_result
= handler( context
, SPFILENOTIFY_NEEDMEDIA
, (UINT_PTR
)&media
, (UINT_PTR
)newpath
);
1497 if (op_result
== FILEOP_ABORT
)
1499 else if (op_result
== FILEOP_SKIP
)
1501 else if (op_result
== FILEOP_NEWPATH
)
1502 lstrcpyW(op
->media
->root
, newpath
);
1503 else if (op_result
!= FILEOP_DOIT
)
1504 FIXME("Unhandled return value %#x.\n", op_result
);
1506 build_filepathsW( op
, &paths
);
1507 op_result
= handler( context
, SPFILENOTIFY_STARTCOPY
, (UINT_PTR
)&paths
, FILEOP_COPY
);
1508 if (op_result
== FILEOP_ABORT
)
1510 else if (op_result
== FILEOP_SKIP
)
1512 else if (op_result
!= FILEOP_DOIT
)
1513 FIXME("Unhandled return value %#x.\n", op_result
);
1515 if (queue_copy_file( paths
.Source
, paths
.Target
, op
, handler
, context
))
1517 if (path_len
> 0 && !op
->media
->cabinet
)
1519 size_t root_len
= lstrlenW(op
->media
->root
);
1520 if (path_len
<= root_len
&& !wcsnicmp(op
->media
->root
+ root_len
- path_len
, src_path
, path_len
))
1521 op
->media
->root
[root_len
- path_len
- 1] = 0;
1523 op
->media
->resolved
= TRUE
;
1524 handler( context
, SPFILENOTIFY_ENDCOPY
, (UINT_PTR
)&paths
, 0 );
1527 paths
.Win32Error
= GetLastError();
1528 if (paths
.Win32Error
== ERROR_PATH_NOT_FOUND
||
1529 paths
.Win32Error
== ERROR_FILE_NOT_FOUND
)
1533 op_result
= handler( context
, SPFILENOTIFY_COPYERROR
, (UINT_PTR
)&paths
, (UINT_PTR
)newpath
);
1534 if (op_result
== FILEOP_ABORT
)
1536 else if (op_result
== FILEOP_SKIP
)
1538 else if (op_result
== FILEOP_NEWPATH
)
1540 lstrcpyW(op
->media
->root
, newpath
);
1541 build_filepathsW(op
, &paths
);
1543 else if (op_result
!= FILEOP_DOIT
)
1544 FIXME("Unhandled return value %#x.\n", op_result
);
1549 build_filepathsW( op
, &paths
);
1550 op_result
= handler( context
, SPFILENOTIFY_STARTCOPY
, (UINT_PTR
)&paths
, FILEOP_COPY
);
1551 if (op_result
== FILEOP_ABORT
)
1553 else if (op_result
== FILEOP_SKIP
)
1555 else if (op_result
!= FILEOP_DOIT
)
1556 FIXME("Unhandled return value %#x.\n", op_result
);
1558 while (op_result
== FILEOP_DOIT
|| op_result
== FILEOP_NEWPATH
)
1560 if (queue_copy_file( paths
.Source
, paths
.Target
, op
, handler
, context
))
1563 paths
.Win32Error
= GetLastError();
1565 op_result
= handler( context
, SPFILENOTIFY_COPYERROR
, (UINT_PTR
)&paths
, (UINT_PTR
)newpath
);
1566 if (op_result
== FILEOP_ABORT
)
1568 else if (op_result
== FILEOP_NEWPATH
)
1570 lstrcpyW(op
->media
->root
, newpath
);
1571 build_filepathsW(op
, &paths
);
1573 else if (op_result
!= FILEOP_SKIP
&& op_result
!= FILEOP_DOIT
)
1574 FIXME("Unhandled return value %#x.\n", op_result
);
1576 handler( context
, SPFILENOTIFY_ENDCOPY
, (UINT_PTR
)&paths
, 0 );
1579 handler( context
, SPFILENOTIFY_ENDSUBQUEUE
, FILEOP_COPY
, 0 );
1586 handler( context
, SPFILENOTIFY_ENDQUEUE
, result
, 0 );
1587 HeapFree( GetProcessHeap(), 0, (void *)paths
.Source
);
1588 HeapFree( GetProcessHeap(), 0, (void *)paths
.Target
);
1593 /***********************************************************************
1594 * SetupScanFileQueueA (SETUPAPI.@)
1596 BOOL WINAPI
SetupScanFileQueueA( HSPFILEQ handle
, DWORD flags
, HWND window
,
1597 PSP_FILE_CALLBACK_A handler
, PVOID context
, PDWORD result
)
1599 struct callback_WtoA_context ctx
;
1601 TRACE("%p %x %p %p %p %p\n", handle
, flags
, window
, handler
, context
, result
);
1603 ctx
.orig_context
= context
;
1604 ctx
.orig_handler
= handler
;
1606 return SetupScanFileQueueW( handle
, flags
, window
, QUEUE_callback_WtoA
, &ctx
, result
);
1610 /***********************************************************************
1611 * SetupScanFileQueueW (SETUPAPI.@)
1613 BOOL WINAPI
SetupScanFileQueueW( HSPFILEQ handle
, DWORD flags
, HWND window
,
1614 PSP_FILE_CALLBACK_W handler
, PVOID context
, PDWORD result
)
1616 struct file_queue
*queue
= handle
;
1619 UINT notification
= 0;
1622 TRACE("%p %x %p %p %p %p\n", handle
, flags
, window
, handler
, context
, result
);
1624 if (!queue
->copy_queue
.count
) return TRUE
;
1626 if (flags
& SPQ_SCAN_USE_CALLBACK
) notification
= SPFILENOTIFY_QUEUESCAN
;
1627 else if (flags
& SPQ_SCAN_USE_CALLBACKEX
) notification
= SPFILENOTIFY_QUEUESCAN_EX
;
1629 if (flags
& ~(SPQ_SCAN_USE_CALLBACK
| SPQ_SCAN_USE_CALLBACKEX
))
1631 FIXME("flags %x not fully implemented\n", flags
);
1634 paths
.Source
= paths
.Target
= NULL
;
1636 for (op
= queue
->copy_queue
.head
; op
; op
= op
->next
)
1638 build_filepathsW( op
, &paths
);
1639 switch (notification
)
1641 case SPFILENOTIFY_QUEUESCAN
:
1642 /* FIXME: handle delay flag */
1643 if (handler( context
, notification
, (UINT_PTR
)paths
.Target
, 0 )) goto done
;
1645 case SPFILENOTIFY_QUEUESCAN_EX
:
1646 if (handler( context
, notification
, (UINT_PTR
)&paths
, 0 )) goto done
;
1649 ret
= TRUE
; goto done
;
1656 if (result
) *result
= 0;
1657 HeapFree( GetProcessHeap(), 0, (void *)paths
.Source
);
1658 HeapFree( GetProcessHeap(), 0, (void *)paths
.Target
);
1663 /***********************************************************************
1664 * SetupGetFileQueueCount (SETUPAPI.@)
1666 BOOL WINAPI
SetupGetFileQueueCount( HSPFILEQ handle
, UINT op
, PUINT result
)
1668 struct file_queue
*queue
= handle
;
1673 *result
= queue
->copy_queue
.count
;
1676 *result
= queue
->rename_queue
.count
;
1679 *result
= queue
->delete_queue
.count
;
1686 /***********************************************************************
1687 * SetupGetFileQueueFlags (SETUPAPI.@)
1689 BOOL WINAPI
SetupGetFileQueueFlags( HSPFILEQ handle
, PDWORD flags
)
1691 struct file_queue
*queue
= handle
;
1692 *flags
= queue
->flags
;
1697 /***********************************************************************
1698 * SetupSetFileQueueFlags (SETUPAPI.@)
1700 BOOL WINAPI
SetupSetFileQueueFlags( HSPFILEQ handle
, DWORD mask
, DWORD flags
)
1702 struct file_queue
*queue
= handle
;
1703 queue
->flags
= (queue
->flags
& ~mask
) | flags
;
1708 /***********************************************************************
1709 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@)
1711 BOOL WINAPI
SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle
, PSP_ALTPLATFORM_INFO platform
, PCSTR catalogfile
)
1713 FIXME("(%p, %p, %s) stub!\n", handle
, platform
, debugstr_a(catalogfile
));
1718 /***********************************************************************
1719 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@)
1721 BOOL WINAPI
SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle
, PSP_ALTPLATFORM_INFO platform
, PCWSTR catalogfile
)
1723 FIXME("(%p, %p, %s) stub!\n", handle
, platform
, debugstr_w(catalogfile
));
1728 /***********************************************************************
1729 * SetupInitDefaultQueueCallback (SETUPAPI.@)
1731 PVOID WINAPI
SetupInitDefaultQueueCallback( HWND owner
)
1733 return SetupInitDefaultQueueCallbackEx( owner
, 0, 0, 0, NULL
);
1737 /***********************************************************************
1738 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@)
1740 PVOID WINAPI
SetupInitDefaultQueueCallbackEx( HWND owner
, HWND progress
, UINT msg
,
1741 DWORD reserved1
, PVOID reserved2
)
1743 struct default_callback_context
*context
;
1745 if ((context
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*context
) )))
1747 context
->magic
= 0x43515053; /* "SPQC" */
1748 context
->owner
= owner
;
1749 context
->progress
= progress
;
1750 context
->message
= msg
;
1756 /***********************************************************************
1757 * SetupTermDefaultQueueCallback (SETUPAPI.@)
1759 void WINAPI
SetupTermDefaultQueueCallback( PVOID context
)
1761 HeapFree( GetProcessHeap(), 0, context
);
1765 /***********************************************************************
1766 * SetupDefaultQueueCallbackA (SETUPAPI.@)
1768 UINT WINAPI
SetupDefaultQueueCallbackA( PVOID context
, UINT notification
,
1769 UINT_PTR param1
, UINT_PTR param2
)
1771 FILEPATHS_A
*paths
= (FILEPATHS_A
*)param1
;
1772 struct default_callback_context
*ctx
= context
;
1774 switch(notification
)
1776 case SPFILENOTIFY_STARTQUEUE
:
1777 TRACE( "start queue\n" );
1779 case SPFILENOTIFY_ENDQUEUE
:
1780 TRACE( "end queue\n" );
1782 case SPFILENOTIFY_STARTSUBQUEUE
:
1783 TRACE( "start subqueue %ld count %ld\n", param1
, param2
);
1785 case SPFILENOTIFY_ENDSUBQUEUE
:
1786 TRACE( "end subqueue %ld\n", param1
);
1788 case SPFILENOTIFY_STARTDELETE
:
1789 TRACE( "start delete %s\n", debugstr_a(paths
->Target
) );
1791 case SPFILENOTIFY_ENDDELETE
:
1792 TRACE( "end delete %s\n", debugstr_a(paths
->Target
) );
1794 case SPFILENOTIFY_DELETEERROR
:
1795 /*Windows Ignores attempts to delete files / folders which do not exist*/
1796 if ((paths
->Win32Error
!= ERROR_FILE_NOT_FOUND
) && (paths
->Win32Error
!= ERROR_PATH_NOT_FOUND
))
1797 SetupDeleteErrorA(ctx
->owner
, NULL
, paths
->Target
, paths
->Win32Error
, 0);
1799 case SPFILENOTIFY_STARTRENAME
:
1800 TRACE( "start rename %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1802 case SPFILENOTIFY_ENDRENAME
:
1803 TRACE( "end rename %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1805 case SPFILENOTIFY_RENAMEERROR
:
1806 SetupRenameErrorA(ctx
->owner
, NULL
, paths
->Source
, paths
->Target
, paths
->Win32Error
, 0);
1808 case SPFILENOTIFY_STARTCOPY
:
1809 TRACE( "start copy %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1811 case SPFILENOTIFY_ENDCOPY
:
1812 TRACE( "end copy %s -> %s\n", debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1814 case SPFILENOTIFY_COPYERROR
:
1815 ERR( "copy error %d %s -> %s\n", paths
->Win32Error
,
1816 debugstr_a(paths
->Source
), debugstr_a(paths
->Target
) );
1818 case SPFILENOTIFY_NEEDMEDIA
:
1820 const SOURCE_MEDIA_A
*media
= (const SOURCE_MEDIA_A
*)param1
;
1821 TRACE( "need media %s %s\n", debugstr_a(media
->SourcePath
), debugstr_a(media
->SourceFile
) );
1822 strcpy( (char *)param2
, media
->SourcePath
);
1826 FIXME( "notification %d params %lx,%lx\n", notification
, param1
, param2
);
1833 /***********************************************************************
1834 * SetupDefaultQueueCallbackW (SETUPAPI.@)
1836 UINT WINAPI
SetupDefaultQueueCallbackW( PVOID context
, UINT notification
,
1837 UINT_PTR param1
, UINT_PTR param2
)
1839 FILEPATHS_W
*paths
= (FILEPATHS_W
*)param1
;
1840 struct default_callback_context
*ctx
= context
;
1842 switch(notification
)
1844 case SPFILENOTIFY_STARTQUEUE
:
1845 TRACE( "start queue\n" );
1847 case SPFILENOTIFY_ENDQUEUE
:
1848 TRACE( "end queue\n" );
1850 case SPFILENOTIFY_STARTSUBQUEUE
:
1851 TRACE( "start subqueue %ld count %ld\n", param1
, param2
);
1853 case SPFILENOTIFY_ENDSUBQUEUE
:
1854 TRACE( "end subqueue %ld\n", param1
);
1856 case SPFILENOTIFY_STARTDELETE
:
1857 TRACE( "start delete %s\n", debugstr_w(paths
->Target
) );
1859 case SPFILENOTIFY_ENDDELETE
:
1860 TRACE( "end delete %s\n", debugstr_w(paths
->Target
) );
1862 case SPFILENOTIFY_DELETEERROR
:
1863 /*Windows Ignores attempts to delete files / folders which do not exist*/
1864 if ((paths
->Win32Error
!= ERROR_FILE_NOT_FOUND
) && (paths
->Win32Error
!= ERROR_PATH_NOT_FOUND
))
1865 SetupDeleteErrorW(ctx
->owner
, NULL
, paths
->Target
, paths
->Win32Error
, 0);
1867 case SPFILENOTIFY_STARTRENAME
:
1868 SetupRenameErrorW(ctx
->owner
, NULL
, paths
->Source
, paths
->Target
, paths
->Win32Error
, 0);
1870 case SPFILENOTIFY_ENDRENAME
:
1871 TRACE( "end rename %s -> %s\n", debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1873 case SPFILENOTIFY_RENAMEERROR
:
1874 ERR( "rename error %d %s -> %s\n", paths
->Win32Error
,
1875 debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1877 case SPFILENOTIFY_STARTCOPY
:
1878 TRACE( "start copy %s -> %s\n", debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1880 case SPFILENOTIFY_ENDCOPY
:
1881 TRACE( "end copy %s -> %s\n", debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1883 case SPFILENOTIFY_COPYERROR
:
1884 ERR( "copy error %d %s -> %s\n", paths
->Win32Error
,
1885 debugstr_w(paths
->Source
), debugstr_w(paths
->Target
) );
1887 case SPFILENOTIFY_NEEDMEDIA
:
1889 const SOURCE_MEDIA_W
*media
= (const SOURCE_MEDIA_W
*)param1
;
1890 TRACE( "need media %s %s\n", debugstr_w(media
->SourcePath
), debugstr_w(media
->SourceFile
) );
1891 lstrcpyW( (WCHAR
*)param2
, media
->SourcePath
);
1895 FIXME( "notification %d params %lx,%lx\n", notification
, param1
, param2
);
1901 /***********************************************************************
1902 * SetupDeleteErrorA (SETUPAPI.@)
1905 UINT WINAPI
SetupDeleteErrorA( HWND parent
, PCSTR dialogTitle
, PCSTR file
,
1906 UINT w32error
, DWORD style
)
1908 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1909 w32error
, debugstr_a(file
) );
1910 return DPROMPT_SKIPFILE
;
1913 /***********************************************************************
1914 * SetupDeleteErrorW (SETUPAPI.@)
1917 UINT WINAPI
SetupDeleteErrorW( HWND parent
, PCWSTR dialogTitle
, PCWSTR file
,
1918 UINT w32error
, DWORD style
)
1920 FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
1921 w32error
, debugstr_w(file
) );
1922 return DPROMPT_SKIPFILE
;
1925 /***********************************************************************
1926 * SetupRenameErrorA (SETUPAPI.@)
1929 UINT WINAPI
SetupRenameErrorA( HWND parent
, PCSTR dialogTitle
, PCSTR source
,
1930 PCSTR target
, UINT w32error
, DWORD style
)
1932 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1933 w32error
, debugstr_a(source
), debugstr_a(target
));
1934 return DPROMPT_SKIPFILE
;
1937 /***********************************************************************
1938 * SetupRenameErrorW (SETUPAPI.@)
1941 UINT WINAPI
SetupRenameErrorW( HWND parent
, PCWSTR dialogTitle
, PCWSTR source
,
1942 PCWSTR target
, UINT w32error
, DWORD style
)
1944 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
1945 w32error
, debugstr_w(source
), debugstr_w(target
));
1946 return DPROMPT_SKIPFILE
;
1950 /***********************************************************************
1951 * SetupCopyErrorA (SETUPAPI.@)
1954 UINT WINAPI
SetupCopyErrorA( HWND parent
, PCSTR dialogTitle
, PCSTR diskname
,
1955 PCSTR sourcepath
, PCSTR sourcefile
, PCSTR targetpath
,
1956 UINT w32error
, DWORD style
, PSTR pathbuffer
,
1957 DWORD buffersize
, PDWORD requiredsize
)
1959 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1960 w32error
, debugstr_a(sourcefile
), debugstr_a(sourcepath
) ,debugstr_a(targetpath
));
1961 return DPROMPT_SKIPFILE
;
1964 /***********************************************************************
1965 * SetupCopyErrorW (SETUPAPI.@)
1968 UINT WINAPI
SetupCopyErrorW( HWND parent
, PCWSTR dialogTitle
, PCWSTR diskname
,
1969 PCWSTR sourcepath
, PCWSTR sourcefile
, PCWSTR targetpath
,
1970 UINT w32error
, DWORD style
, PWSTR pathbuffer
,
1971 DWORD buffersize
, PDWORD requiredsize
)
1973 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
1974 w32error
, debugstr_w(sourcefile
), debugstr_w(sourcepath
) ,debugstr_w(targetpath
));
1975 return DPROMPT_SKIPFILE
;
1978 /***********************************************************************
1979 * pSetupGetQueueFlags (SETUPAPI.@)
1981 DWORD WINAPI
pSetupGetQueueFlags( HSPFILEQ handle
)
1983 struct file_queue
*queue
= handle
;
1984 return queue
->flags
;
1987 /***********************************************************************
1988 * pSetupSetQueueFlags (SETUPAPI.@)
1990 BOOL WINAPI
pSetupSetQueueFlags( HSPFILEQ handle
, DWORD flags
)
1992 struct file_queue
*queue
= handle
;
1993 queue
->flags
= flags
;