1 /* 2 * Setupapi file queue routines 3 * 4 * Copyright 2002 Alexandre Julliard for CodeWeavers 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "setupapi_private.h" 22 23 #include <aclapi.h> 24 25 /* Unicode constants */ 26 static const WCHAR DotSecurity[] = {'.','S','e','c','u','r','i','t','y',0}; 27 28 /* context structure for the default queue callback */ 29 struct default_callback_context 30 { 31 HWND owner; 32 HWND progress; 33 UINT message; 34 }; 35 36 struct file_op 37 { 38 struct file_op *next; 39 UINT style; 40 WCHAR *src_root; 41 WCHAR *src_path; 42 WCHAR *src_file; 43 WCHAR *src_descr; 44 WCHAR *src_tag; 45 WCHAR *dst_path; 46 WCHAR *dst_file; 47 PSECURITY_DESCRIPTOR dst_sd; 48 }; 49 50 struct file_op_queue 51 { 52 struct file_op *head; 53 struct file_op *tail; 54 unsigned int count; 55 }; 56 57 struct file_queue 58 { 59 struct file_op_queue copy_queue; 60 struct file_op_queue delete_queue; 61 struct file_op_queue rename_queue; 62 DWORD flags; 63 }; 64 65 66 static inline WCHAR *strdupW( const WCHAR *str ) 67 { 68 WCHAR *ret = NULL; 69 if (str) 70 { 71 int len = (strlenW(str) + 1) * sizeof(WCHAR); 72 if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( ret, str, len ); 73 } 74 return ret; 75 } 76 77 static inline char *strdupWtoA( const WCHAR *str ) 78 { 79 char *ret = NULL; 80 if (str) 81 { 82 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL ); 83 if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) 84 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL ); 85 } 86 return ret; 87 } 88 89 /* append a file operation to a queue */ 90 static inline void queue_file_op( struct file_op_queue *queue, struct file_op *op ) 91 { 92 op->next = NULL; 93 if (queue->tail) queue->tail->next = op; 94 else queue->head = op; 95 queue->tail = op; 96 queue->count++; 97 } 98 99 /* free all the file operations on a given queue */ 100 static void free_file_op_queue( struct file_op_queue *queue ) 101 { 102 struct file_op *t, *op = queue->head; 103 104 while( op ) 105 { 106 HeapFree( GetProcessHeap(), 0, op->src_root ); 107 HeapFree( GetProcessHeap(), 0, op->src_path ); 108 HeapFree( GetProcessHeap(), 0, op->src_file ); 109 HeapFree( GetProcessHeap(), 0, op->src_descr ); 110 HeapFree( GetProcessHeap(), 0, op->src_tag ); 111 HeapFree( GetProcessHeap(), 0, op->dst_path ); 112 if (op->dst_sd) LocalFree( op->dst_sd); 113 if (op->dst_file != op->src_file) HeapFree( GetProcessHeap(), 0, op->dst_file ); 114 t = op; 115 op = op->next; 116 HeapFree( GetProcessHeap(), 0, t ); 117 } 118 } 119 120 /* concat 3 strings to make a path, handling separators correctly */ 121 static void concat_W( WCHAR *buffer, const WCHAR *src1, const WCHAR *src2, const WCHAR *src3 ) 122 { 123 *buffer = 0; 124 if (src1 && *src1) 125 { 126 strcpyW( buffer, src1 ); 127 buffer += strlenW(buffer ); 128 if (buffer[-1] != '\\') *buffer++ = '\\'; 129 if (src2) while (*src2 == '\\') src2++; 130 } 131 132 if (src2) 133 { 134 strcpyW( buffer, src2 ); 135 buffer += strlenW(buffer ); 136 if (buffer[-1] != '\\') *buffer++ = '\\'; 137 if (src3) while (*src3 == '\\') src3++; 138 } 139 140 if (src3) 141 strcpyW( buffer, src3 ); 142 } 143 144 145 /*********************************************************************** 146 * build_filepathsW 147 * 148 * Build a FILEPATHS_W structure for a given file operation. 149 */ 150 static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths ) 151 { 152 unsigned int src_len = 1, dst_len = 1; 153 WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target; 154 155 if (op->src_root) src_len += strlenW(op->src_root) + 1; 156 if (op->src_path) src_len += strlenW(op->src_path) + 1; 157 if (op->src_file) src_len += strlenW(op->src_file) + 1; 158 if (op->dst_path) dst_len += strlenW(op->dst_path) + 1; 159 if (op->dst_file) dst_len += strlenW(op->dst_file) + 1; 160 src_len *= sizeof(WCHAR); 161 dst_len *= sizeof(WCHAR); 162 163 if (!source || HeapSize( GetProcessHeap(), 0, source ) < src_len ) 164 { 165 HeapFree( GetProcessHeap(), 0, source ); 166 paths->Source = source = HeapAlloc( GetProcessHeap(), 0, src_len ); 167 } 168 if (!target || HeapSize( GetProcessHeap(), 0, target ) < dst_len ) 169 { 170 HeapFree( GetProcessHeap(), 0, target ); 171 paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len ); 172 } 173 if (!source || !target) return FALSE; 174 concat_W( source, op->src_root, op->src_path, op->src_file ); 175 concat_W( target, NULL, op->dst_path, op->dst_file ); 176 paths->Win32Error = 0; 177 paths->Flags = 0; 178 return TRUE; 179 } 180 181 182 /*********************************************************************** 183 * QUEUE_callback_WtoA 184 * 185 * Map a file callback parameters from W to A and call the A callback. 186 */ 187 UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification, 188 UINT_PTR param1, UINT_PTR param2 ) 189 { 190 struct callback_WtoA_context *callback_ctx = context; 191 char buffer[MAX_PATH]; 192 UINT ret; 193 UINT_PTR old_param2 = param2; 194 195 switch(notification) 196 { 197 case SPFILENOTIFY_COPYERROR: 198 param2 = (UINT_PTR)&buffer; 199 /* fall through */ 200 case SPFILENOTIFY_STARTDELETE: 201 case SPFILENOTIFY_ENDDELETE: 202 case SPFILENOTIFY_DELETEERROR: 203 case SPFILENOTIFY_STARTRENAME: 204 case SPFILENOTIFY_ENDRENAME: 205 case SPFILENOTIFY_RENAMEERROR: 206 case SPFILENOTIFY_STARTCOPY: 207 case SPFILENOTIFY_ENDCOPY: 208 case SPFILENOTIFY_QUEUESCAN_EX: 209 { 210 FILEPATHS_W *pathsW = (FILEPATHS_W *)param1; 211 FILEPATHS_A pathsA; 212 213 pathsA.Source = strdupWtoA( pathsW->Source ); 214 pathsA.Target = strdupWtoA( pathsW->Target ); 215 pathsA.Win32Error = pathsW->Win32Error; 216 pathsA.Flags = pathsW->Flags; 217 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, 218 (UINT_PTR)&pathsA, param2 ); 219 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Source ); 220 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Target ); 221 } 222 if (notification == SPFILENOTIFY_COPYERROR) 223 MultiByteToWideChar( CP_ACP, 0, buffer, -1, (WCHAR *)old_param2, MAX_PATH ); 224 break; 225 226 case SPFILENOTIFY_STARTREGISTRATION: 227 case SPFILENOTIFY_ENDREGISTRATION: 228 { 229 SP_REGISTER_CONTROL_STATUSW *statusW = (SP_REGISTER_CONTROL_STATUSW *)param1; 230 SP_REGISTER_CONTROL_STATUSA statusA; 231 232 statusA.cbSize = sizeof(statusA); 233 statusA.FileName = strdupWtoA( statusW->FileName ); 234 statusA.Win32Error = statusW->Win32Error; 235 statusA.FailureCode = statusW->FailureCode; 236 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, 237 (UINT_PTR)&statusA, param2 ); 238 HeapFree( GetProcessHeap(), 0, (LPSTR)statusA.FileName ); 239 } 240 break; 241 242 case SPFILENOTIFY_QUEUESCAN: 243 { 244 LPWSTR targetW = (LPWSTR)param1; 245 LPSTR target = strdupWtoA( targetW ); 246 247 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, 248 (UINT_PTR)target, param2 ); 249 HeapFree( GetProcessHeap(), 0, target ); 250 } 251 break; 252 253 case SPFILENOTIFY_NEEDMEDIA: 254 FIXME("mapping for %d not implemented\n",notification); 255 case SPFILENOTIFY_STARTQUEUE: 256 case SPFILENOTIFY_ENDQUEUE: 257 case SPFILENOTIFY_STARTSUBQUEUE: 258 case SPFILENOTIFY_ENDSUBQUEUE: 259 default: 260 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, param1, param2 ); 261 break; 262 } 263 return ret; 264 } 265 266 267 /*********************************************************************** 268 * get_src_file_info 269 * 270 * Retrieve the source file information for a given file. 271 */ 272 static void get_src_file_info( HINF hinf, struct file_op *op ) 273 { 274 static const WCHAR SourceDisksNames[] = 275 {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0}; 276 static const WCHAR SourceDisksFiles[] = 277 {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0}; 278 279 INFCONTEXT file_ctx, disk_ctx; 280 INT id, diskid; 281 DWORD len, len2; 282 WCHAR SectionName[MAX_PATH]; 283 284 /* find the SourceDisksFiles entry */ 285 if(!SetupDiGetActualSectionToInstallW(hinf, SourceDisksFiles, SectionName, MAX_PATH, NULL, NULL)) 286 return; 287 if (!SetupFindFirstLineW( hinf, SectionName, op->src_file, &file_ctx )) 288 { 289 if ((op->style & (SP_COPY_SOURCE_ABSOLUTE|SP_COPY_SOURCEPATH_ABSOLUTE))) return; 290 /* no specific info, use .inf file source directory */ 291 if (!op->src_root) op->src_root = PARSER_get_src_root( hinf ); 292 return; 293 } 294 if (!SetupGetIntField( &file_ctx, 1, &diskid )) return; 295 296 /* now find the diskid in the SourceDisksNames section */ 297 if(!SetupDiGetActualSectionToInstallW(hinf, SourceDisksNames, SectionName, MAX_PATH, NULL, NULL)) 298 return; 299 if (!SetupFindFirstLineW( hinf, SectionName, NULL, &disk_ctx )) return; 300 for (;;) 301 { 302 if (SetupGetIntField( &disk_ctx, 0, &id ) && (id == diskid)) break; 303 if (!SetupFindNextLine( &disk_ctx, &disk_ctx )) return; 304 } 305 306 /* and fill in the missing info */ 307 308 if (!op->src_descr) 309 { 310 if (SetupGetStringFieldW( &disk_ctx, 1, NULL, 0, &len ) && 311 (op->src_descr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ))) 312 SetupGetStringFieldW( &disk_ctx, 1, op->src_descr, len, NULL ); 313 } 314 if (!op->src_tag) 315 { 316 if (SetupGetStringFieldW( &disk_ctx, 2, NULL, 0, &len ) && 317 (op->src_tag = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ))) 318 SetupGetStringFieldW( &disk_ctx, 2, op->src_tag, len, NULL ); 319 } 320 if (!op->src_path && !(op->style & SP_COPY_SOURCE_ABSOLUTE)) 321 { 322 len = len2 = 0; 323 if (!(op->style & SP_COPY_SOURCEPATH_ABSOLUTE)) 324 { 325 /* retrieve relative path for this disk */ 326 if (!SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len )) len = 0; 327 } 328 /* retrieve relative path for this file */ 329 if (!SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len2 )) len2 = 0; 330 331 if ((len || len2) && 332 (op->src_path = HeapAlloc( GetProcessHeap(), 0, (len+len2)*sizeof(WCHAR) ))) 333 { 334 WCHAR *ptr = op->src_path; 335 if (len) 336 { 337 SetupGetStringFieldW( &disk_ctx, 4, op->src_path, len, NULL ); 338 ptr = op->src_path + strlenW(op->src_path); 339 if (len2 && ptr > op->src_path && ptr[-1] != '\\') *ptr++ = '\\'; 340 } 341 if (!SetupGetStringFieldW( &file_ctx, 2, ptr, len2, NULL )) *ptr = 0; 342 } 343 } 344 if (!op->src_root) op->src_root = PARSER_get_src_root(hinf); 345 } 346 347 348 /*********************************************************************** 349 * get_destination_dir 350 * 351 * Retrieve the destination dir for a given section. 352 */ 353 static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section ) 354 { 355 static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0}; 356 static const WCHAR Def[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0}; 357 INFCONTEXT context; 358 359 if (!SetupFindFirstLineW( hinf, Dest, section, &context ) && 360 !SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL; 361 return PARSER_get_dest_dir( &context ); 362 } 363 364 365 static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD ); 366 367 /*********************************************************************** 368 * extract_cabinet_file 369 * 370 * Extract a file from a .cab file. 371 */ 372 static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root, 373 const WCHAR *src, const WCHAR *dst ) 374 { 375 static const WCHAR extW[] = {'.','c','a','b',0}; 376 static HMODULE advpack; 377 378 char *cab_path, *cab_file; 379 int len = strlenW( cabinet ); 380 381 /* make sure the cabinet file has a .cab extension */ 382 if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE; 383 if (!pExtractFiles) 384 { 385 if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" ))) 386 { 387 ERR( "could not load advpack.dll\n" ); 388 return FALSE; 389 } 390 if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" ))) 391 { 392 ERR( "could not find ExtractFiles in advpack.dll\n" ); 393 return FALSE; 394 } 395 } 396 397 if (!(cab_path = strdupWtoA( root ))) return FALSE; 398 len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL ); 399 if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 ))) 400 { 401 HeapFree( GetProcessHeap(), 0, cab_path ); 402 return FALSE; 403 } 404 strcpy( cab_file, cab_path ); 405 if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" ); 406 WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL ); 407 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) ); 408 pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 ); 409 HeapFree( GetProcessHeap(), 0, cab_file ); 410 HeapFree( GetProcessHeap(), 0, cab_path ); 411 return CopyFileW( src, dst, FALSE /*FIXME*/ ); 412 } 413 414 415 /*********************************************************************** 416 * SetupOpenFileQueue (SETUPAPI.@) 417 */ 418 HSPFILEQ WINAPI SetupOpenFileQueue(void) 419 { 420 struct file_queue *queue; 421 422 if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue)))) 423 return INVALID_HANDLE_VALUE; 424 return queue; 425 } 426 427 428 /*********************************************************************** 429 * SetupCloseFileQueue (SETUPAPI.@) 430 */ 431 BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle ) 432 { 433 struct file_queue *queue = handle; 434 435 free_file_op_queue( &queue->copy_queue ); 436 free_file_op_queue( &queue->rename_queue ); 437 free_file_op_queue( &queue->delete_queue ); 438 HeapFree( GetProcessHeap(), 0, queue ); 439 return TRUE; 440 } 441 442 443 /*********************************************************************** 444 * SetupQueueCopyIndirectA (SETUPAPI.@) 445 */ 446 BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params ) 447 { 448 struct file_queue *queue = params->QueueHandle; 449 struct file_op *op; 450 451 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; 452 op->style = params->CopyStyle; 453 op->src_root = strdupAtoW( params->SourceRootPath ); 454 op->src_path = strdupAtoW( params->SourcePath ); 455 op->src_file = strdupAtoW( params->SourceFilename ); 456 op->src_descr = strdupAtoW( params->SourceDescription ); 457 op->src_tag = strdupAtoW( params->SourceTagfile ); 458 op->dst_path = strdupAtoW( params->TargetDirectory ); 459 op->dst_file = strdupAtoW( params->TargetFilename ); 460 op->dst_sd = NULL; 461 462 /* some defaults */ 463 if (!op->src_file) op->src_file = op->dst_file; 464 if (params->LayoutInf) 465 { 466 get_src_file_info( params->LayoutInf, op ); 467 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file ); 468 } 469 470 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n", 471 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file), 472 debugstr_w(op->dst_path), debugstr_w(op->dst_file), 473 debugstr_w(op->src_descr), debugstr_w(op->src_tag) ); 474 475 queue_file_op( &queue->copy_queue, op ); 476 return TRUE; 477 } 478 479 480 /*********************************************************************** 481 * SetupQueueCopyIndirectW (SETUPAPI.@) 482 */ 483 BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params ) 484 { 485 struct file_queue *queue = params->QueueHandle; 486 struct file_op *op; 487 488 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; 489 op->style = params->CopyStyle; 490 op->src_root = strdupW( params->SourceRootPath ); 491 op->src_path = strdupW( params->SourcePath ); 492 op->src_file = strdupW( params->SourceFilename ); 493 op->src_descr = strdupW( params->SourceDescription ); 494 op->src_tag = strdupW( params->SourceTagfile ); 495 op->dst_path = strdupW( params->TargetDirectory ); 496 op->dst_file = strdupW( params->TargetFilename ); 497 op->dst_sd = NULL; 498 if (params->SecurityDescriptor) 499 ConvertStringSecurityDescriptorToSecurityDescriptorW( params->SecurityDescriptor, SDDL_REVISION_1, &op->dst_sd, NULL ); 500 501 /* some defaults */ 502 if (!op->src_file) op->src_file = op->dst_file; 503 if (params->LayoutInf) 504 { 505 get_src_file_info( params->LayoutInf, op ); 506 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file ); 507 } 508 509 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n", 510 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file), 511 debugstr_w(op->dst_path), debugstr_w(op->dst_file), 512 debugstr_w(op->src_descr), debugstr_w(op->src_tag) ); 513 514 queue_file_op( &queue->copy_queue, op ); 515 return TRUE; 516 } 517 518 519 /*********************************************************************** 520 * SetupQueueCopyA (SETUPAPI.@) 521 */ 522 BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file, 523 PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file, 524 DWORD style ) 525 { 526 SP_FILE_COPY_PARAMS_A params; 527 528 params.cbSize = sizeof(params); 529 params.QueueHandle = queue; 530 params.SourceRootPath = src_root; 531 params.SourcePath = src_path; 532 params.SourceFilename = src_file; 533 params.SourceDescription = src_descr; 534 params.SourceTagfile = src_tag; 535 params.TargetDirectory = dst_dir; 536 params.TargetFilename = dst_file; 537 params.CopyStyle = style; 538 params.LayoutInf = 0; 539 params.SecurityDescriptor = NULL; 540 return SetupQueueCopyIndirectA( ¶ms ); 541 } 542 543 544 /*********************************************************************** 545 * SetupQueueCopyW (SETUPAPI.@) 546 */ 547 BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file, 548 PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file, 549 DWORD style ) 550 { 551 SP_FILE_COPY_PARAMS_W params; 552 553 params.cbSize = sizeof(params); 554 params.QueueHandle = queue; 555 params.SourceRootPath = src_root; 556 params.SourcePath = src_path; 557 params.SourceFilename = src_file; 558 params.SourceDescription = src_descr; 559 params.SourceTagfile = src_tag; 560 params.TargetDirectory = dst_dir; 561 params.TargetFilename = dst_file; 562 params.CopyStyle = style; 563 params.LayoutInf = 0; 564 params.SecurityDescriptor = NULL; 565 return SetupQueueCopyIndirectW( ¶ms ); 566 } 567 568 569 /*********************************************************************** 570 * SetupQueueDefaultCopyA (SETUPAPI.@) 571 */ 572 BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file, 573 PCSTR dst_file, DWORD style ) 574 { 575 SP_FILE_COPY_PARAMS_A params; 576 577 params.cbSize = sizeof(params); 578 params.QueueHandle = queue; 579 params.SourceRootPath = src_root; 580 params.SourcePath = NULL; 581 params.SourceFilename = src_file; 582 params.SourceDescription = NULL; 583 params.SourceTagfile = NULL; 584 params.TargetDirectory = NULL; 585 params.TargetFilename = dst_file; 586 params.CopyStyle = style; 587 params.LayoutInf = hinf; 588 params.SecurityDescriptor = NULL; 589 return SetupQueueCopyIndirectA( ¶ms ); 590 } 591 592 593 /*********************************************************************** 594 * SetupQueueDefaultCopyW (SETUPAPI.@) 595 */ 596 BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file, 597 PCWSTR dst_file, DWORD style ) 598 { 599 SP_FILE_COPY_PARAMS_W params; 600 601 params.cbSize = sizeof(params); 602 params.QueueHandle = queue; 603 params.SourceRootPath = src_root; 604 params.SourcePath = NULL; 605 params.SourceFilename = src_file; 606 params.SourceDescription = NULL; 607 params.SourceTagfile = NULL; 608 params.TargetDirectory = NULL; 609 params.TargetFilename = dst_file; 610 params.CopyStyle = style; 611 params.LayoutInf = hinf; 612 params.SecurityDescriptor = NULL; 613 return SetupQueueCopyIndirectW( ¶ms ); 614 } 615 616 617 /*********************************************************************** 618 * SetupQueueDeleteA (SETUPAPI.@) 619 */ 620 BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 ) 621 { 622 struct file_queue *queue = handle; 623 struct file_op *op; 624 625 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; 626 op->style = 0; 627 op->src_root = NULL; 628 op->src_path = NULL; 629 op->src_file = NULL; 630 op->src_descr = NULL; 631 op->src_tag = NULL; 632 op->dst_path = strdupAtoW( part1 ); 633 op->dst_file = strdupAtoW( part2 ); 634 op->dst_sd = NULL; 635 queue_file_op( &queue->delete_queue, op ); 636 return TRUE; 637 } 638 639 640 /*********************************************************************** 641 * SetupQueueDeleteW (SETUPAPI.@) 642 */ 643 BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 ) 644 { 645 struct file_queue *queue = handle; 646 struct file_op *op; 647 648 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; 649 op->style = 0; 650 op->src_root = NULL; 651 op->src_path = NULL; 652 op->src_file = NULL; 653 op->src_descr = NULL; 654 op->src_tag = NULL; 655 op->dst_path = strdupW( part1 ); 656 op->dst_file = strdupW( part2 ); 657 op->dst_sd = NULL; 658 queue_file_op( &queue->delete_queue, op ); 659 return TRUE; 660 } 661 662 663 /*********************************************************************** 664 * SetupQueueRenameA (SETUPAPI.@) 665 */ 666 BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename, 667 PCSTR TargetPath, PCSTR TargetFilename ) 668 { 669 struct file_queue *queue = handle; 670 struct file_op *op; 671 672 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; 673 op->style = 0; 674 op->src_root = NULL; 675 op->src_path = strdupAtoW( SourcePath ); 676 op->src_file = strdupAtoW( SourceFilename ); 677 op->src_descr = NULL; 678 op->src_tag = NULL; 679 op->dst_path = strdupAtoW( TargetPath ); 680 op->dst_file = strdupAtoW( TargetFilename ); 681 op->dst_sd = NULL; 682 queue_file_op( &queue->rename_queue, op ); 683 return TRUE; 684 } 685 686 687 /*********************************************************************** 688 * SetupQueueRenameW (SETUPAPI.@) 689 */ 690 BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename, 691 PCWSTR TargetPath, PCWSTR TargetFilename ) 692 { 693 struct file_queue *queue = handle; 694 struct file_op *op; 695 696 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; 697 op->style = 0; 698 op->src_root = NULL; 699 op->src_path = strdupW( SourcePath ); 700 op->src_file = strdupW( SourceFilename ); 701 op->src_descr = NULL; 702 op->src_tag = NULL; 703 op->dst_path = strdupW( TargetPath ); 704 op->dst_file = strdupW( TargetFilename ); 705 op->dst_sd = NULL; 706 queue_file_op( &queue->rename_queue, op ); 707 return TRUE; 708 } 709 710 711 /*********************************************************************** 712 * SetupQueueCopySectionA (SETUPAPI.@) 713 */ 714 BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist, 715 PCSTR section, DWORD style ) 716 { 717 UNICODE_STRING sectionW; 718 BOOL ret = FALSE; 719 720 if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section )) 721 { 722 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 723 return FALSE; 724 } 725 if (!src_root) 726 ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style ); 727 else 728 { 729 UNICODE_STRING srcW; 730 if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root )) 731 { 732 ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style ); 733 RtlFreeUnicodeString( &srcW ); 734 } 735 else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 736 } 737 RtlFreeUnicodeString( §ionW ); 738 return ret; 739 } 740 741 742 /*********************************************************************** 743 * SetupQueueCopySectionW (SETUPAPI.@) 744 */ 745 BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist, 746 PCWSTR section, DWORD style ) 747 { 748 SP_FILE_COPY_PARAMS_W params; 749 LPWSTR security_key, security_descriptor = NULL; 750 INFCONTEXT context, security_context; 751 WCHAR dest[MAX_PATH], src[MAX_PATH]; 752 INT flags; 753 DWORD required; 754 BOOL ret; 755 756 TRACE( "hinf=%p/%p section=%s root=%s\n", 757 hinf, hlist, debugstr_w(section), debugstr_w(src_root) ); 758 759 /* Check for .Security section */ 760 security_key = MyMalloc( (strlenW( section ) + strlenW( DotSecurity )) * sizeof(WCHAR) + sizeof(UNICODE_NULL) ); 761 if (!security_key) 762 { 763 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 764 return FALSE; 765 } 766 strcpyW( security_key, section ); 767 strcatW( security_key, DotSecurity ); 768 ret = SetupFindFirstLineW( hinf, security_key, NULL, &security_context ); 769 MyFree(security_key); 770 if (ret) 771 { 772 if (!SetupGetLineTextW( &security_context, NULL, NULL, NULL, NULL, 0, &required )) 773 return FALSE; 774 security_descriptor = MyMalloc( required * sizeof(WCHAR) ); 775 if (!security_descriptor) 776 { 777 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 778 return FALSE; 779 } 780 if (!SetupGetLineTextW( &security_context, NULL, NULL, NULL, security_descriptor, required, NULL )) 781 { 782 MyFree( security_descriptor ); 783 return FALSE; 784 } 785 } 786 787 params.cbSize = sizeof(params); 788 params.QueueHandle = queue; 789 params.SourceRootPath = src_root; 790 params.SourcePath = NULL; 791 params.SourceDescription = NULL; 792 params.SourceTagfile = NULL; 793 params.TargetFilename = dest; 794 params.CopyStyle = style; 795 params.LayoutInf = hinf; 796 params.SecurityDescriptor = security_descriptor; 797 798 ret = FALSE; 799 if (!hlist) hlist = hinf; 800 if (!hinf) hinf = hlist; 801 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) goto done; 802 if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) goto done; 803 do 804 { 805 if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL )) 806 goto done; 807 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0; 808 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */ 809 810 params.SourceFilename = *src ? src : NULL; 811 if (!SetupQueueCopyIndirectW( ¶ms )) goto done; 812 } while (SetupFindNextLine( &context, &context )); 813 ret = TRUE; 814 815 done: 816 if (security_descriptor) 817 MyFree( security_descriptor ); 818 return ret; 819 } 820 821 822 /*********************************************************************** 823 * SetupQueueDeleteSectionA (SETUPAPI.@) 824 */ 825 BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section ) 826 { 827 UNICODE_STRING sectionW; 828 BOOL ret = FALSE; 829 830 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section )) 831 { 832 ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer ); 833 RtlFreeUnicodeString( §ionW ); 834 } 835 else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 836 return ret; 837 } 838 839 840 /*********************************************************************** 841 * SetupQueueDeleteSectionW (SETUPAPI.@) 842 */ 843 BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section ) 844 { 845 INFCONTEXT context; 846 WCHAR *dest_dir; 847 WCHAR buffer[MAX_PATH]; 848 BOOL ret = FALSE; 849 INT flags; 850 851 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) ); 852 853 if (!hlist) hlist = hinf; 854 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE; 855 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE; 856 do 857 { 858 if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) 859 goto done; 860 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; 861 if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done; 862 } while (SetupFindNextLine( &context, &context )); 863 864 ret = TRUE; 865 done: 866 HeapFree( GetProcessHeap(), 0, dest_dir ); 867 return ret; 868 } 869 870 871 /*********************************************************************** 872 * SetupQueueRenameSectionA (SETUPAPI.@) 873 */ 874 BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section ) 875 { 876 UNICODE_STRING sectionW; 877 BOOL ret = FALSE; 878 879 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section )) 880 { 881 ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer ); 882 RtlFreeUnicodeString( §ionW ); 883 } 884 else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 885 return ret; 886 } 887 888 889 /*********************************************************************** 890 * SetupQueueRenameSectionW (SETUPAPI.@) 891 */ 892 BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section ) 893 { 894 INFCONTEXT context; 895 WCHAR *dest_dir; 896 WCHAR src[MAX_PATH], dst[MAX_PATH]; 897 BOOL ret = FALSE; 898 899 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) ); 900 901 if (!hlist) hlist = hinf; 902 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE; 903 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE; 904 do 905 { 906 if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL )) 907 goto done; 908 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) 909 goto done; 910 if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done; 911 } while (SetupFindNextLine( &context, &context )); 912 913 ret = TRUE; 914 done: 915 HeapFree( GetProcessHeap(), 0, dest_dir ); 916 return ret; 917 } 918 919 920 /*********************************************************************** 921 * SetupCommitFileQueueA (SETUPAPI.@) 922 */ 923 BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler, 924 PVOID context ) 925 { 926 struct callback_WtoA_context ctx; 927 928 ctx.orig_context = context; 929 ctx.orig_handler = handler; 930 return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx ); 931 } 932 933 934 /*********************************************************************** 935 * create_full_pathW 936 * 937 * Recursively create all directories in the path. 938 */ 939 static BOOL create_full_pathW(const WCHAR *path) 940 { 941 BOOL ret = TRUE; 942 int len; 943 WCHAR *new_path; 944 945 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR)); 946 strcpyW(new_path, path); 947 948 while((len = strlenW(new_path)) && new_path[len - 1] == '\\') 949 new_path[len - 1] = 0; 950 951 while(!CreateDirectoryW(new_path, NULL)) 952 { 953 WCHAR *slash; 954 DWORD last_error = GetLastError(); 955 956 if(last_error == ERROR_ALREADY_EXISTS) 957 break; 958 959 if(last_error != ERROR_PATH_NOT_FOUND) 960 { 961 ret = FALSE; 962 break; 963 } 964 965 if(!(slash = strrchrW(new_path, '\\'))) 966 { 967 ret = FALSE; 968 break; 969 } 970 971 len = slash - new_path; 972 new_path[len] = 0; 973 if(!create_full_pathW(new_path)) 974 { 975 ret = FALSE; 976 break; 977 } 978 new_path[len] = '\\'; 979 } 980 981 HeapFree(GetProcessHeap(), 0, new_path); 982 return ret; 983 } 984 985 static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style, 986 PSP_FILE_CALLBACK_W handler, PVOID context ) 987 { 988 BOOL rc = FALSE; 989 BOOL docopy = TRUE; 990 WCHAR TempFile[MAX_PATH]; 991 INT hSource, hTemp; 992 OFSTRUCT OfStruct; 993 WCHAR TempPath[MAX_PATH]; 994 995 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source),debugstr_w(target),style); 996 997 /* Get a temp file name */ 998 if (!GetTempPathW(sizeof(TempPath) / sizeof(WCHAR), TempPath)) 999 { 1000 ERR("GetTempPathW error\n"); 1001 return FALSE; 1002 } 1003 if (!GetTempFileNameW(TempPath, L"", 0, TempFile)) 1004 { 1005 ERR("GetTempFileNameW(%s) error\n", debugstr_w(TempPath)); 1006 return FALSE; 1007 } 1008 1009 /* Try to open the source file */ 1010 hSource = LZOpenFileW((LPWSTR)source, &OfStruct, OF_READ); 1011 if (hSource < 0) 1012 { 1013 ERR("LZOpenFileW(1) error %d %s\n", (int)hSource, debugstr_w(source)); 1014 return FALSE; 1015 } 1016 1017 /* Extract the compressed file to a temp location */ 1018 hTemp = LZOpenFileW(TempFile, &OfStruct, OF_CREATE); 1019 if (hTemp < 0) 1020 { 1021 DWORD dwLastError = GetLastError(); 1022 1023 ERR("LZOpenFileW(2) error %d %s\n", (int)hTemp, debugstr_w(TempFile)); 1024 1025 /* Close the source handle */ 1026 LZClose(hSource); 1027 1028 /* Restore error condition triggered by LZOpenFileW */ 1029 SetLastError(dwLastError); 1030 return FALSE; 1031 } 1032 1033 LZCopy(hSource, hTemp); 1034 LZClose(hSource); 1035 LZClose(hTemp); 1036 1037 /* before copy processing */ 1038 if (style & SP_COPY_REPLACEONLY) 1039 { 1040 if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES) 1041 docopy = FALSE; 1042 } 1043 if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER)) 1044 { 1045 DWORD VersionSizeSource=0; 1046 DWORD VersionSizeTarget=0; 1047 DWORD zero=0; 1048 1049 /* 1050 * This is sort of an interesting workaround. You see, calling 1051 * GetVersionInfoSize on a builtin dll loads that dll into memory 1052 * and we do not properly unload builtin dlls.. so we effectively 1053 * lock into memory all the targets we are replacing. This leads 1054 * to problems when we try to register the replaced dlls. 1055 * 1056 * So I will test for the existence of the files first so that 1057 * we just basically unconditionally replace the builtin versions. 1058 */ 1059 if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) && 1060 (GetFileAttributesW(TempFile) != INVALID_FILE_ATTRIBUTES)) 1061 { 1062 VersionSizeSource = GetFileVersionInfoSizeW(TempFile,&zero); 1063 VersionSizeTarget = GetFileVersionInfoSizeW((LPWSTR)target,&zero); 1064 } 1065 1066 TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget, 1067 VersionSizeSource); 1068 1069 if (VersionSizeSource && VersionSizeTarget) 1070 { 1071 LPVOID VersionSource; 1072 LPVOID VersionTarget; 1073 VS_FIXEDFILEINFO *TargetInfo; 1074 VS_FIXEDFILEINFO *SourceInfo; 1075 UINT length; 1076 WCHAR SubBlock[2]={'\\',0}; 1077 DWORD ret; 1078 1079 VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource); 1080 VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget); 1081 1082 ret = GetFileVersionInfoW(TempFile,0,VersionSizeSource,VersionSource); 1083 if (ret) 1084 ret = GetFileVersionInfoW((LPWSTR)target, 0, VersionSizeTarget, 1085 VersionTarget); 1086 1087 if (ret) 1088 { 1089 ret = VerQueryValueW(VersionSource, SubBlock, 1090 (LPVOID*)&SourceInfo, &length); 1091 if (ret) 1092 ret = VerQueryValueW(VersionTarget, SubBlock, 1093 (LPVOID*)&TargetInfo, &length); 1094 1095 if (ret) 1096 { 1097 FILEPATHS_W filepaths; 1098 1099 TRACE("Versions: Source %i.%i target %i.%i\n", 1100 SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS, 1101 TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS); 1102 1103 /* used in case of notification */ 1104 filepaths.Target = target; 1105 filepaths.Source = source; 1106 filepaths.Win32Error = 0; 1107 filepaths.Flags = 0; 1108 1109 if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS) 1110 { 1111 if (handler) 1112 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0); 1113 else 1114 docopy = FALSE; 1115 } 1116 else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS) 1117 && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS)) 1118 { 1119 if (handler) 1120 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0); 1121 else 1122 docopy = FALSE; 1123 } 1124 else if ((style & SP_COPY_NEWER_ONLY) && 1125 (TargetInfo->dwFileVersionMS == 1126 SourceInfo->dwFileVersionMS) 1127 &&(TargetInfo->dwFileVersionLS == 1128 SourceInfo->dwFileVersionLS)) 1129 { 1130 if (handler) 1131 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0); 1132 else 1133 docopy = FALSE; 1134 } 1135 } 1136 } 1137 HeapFree(GetProcessHeap(),0,VersionSource); 1138 HeapFree(GetProcessHeap(),0,VersionTarget); 1139 } 1140 } 1141 if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE)) 1142 { 1143 if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) 1144 { 1145 FIXME("Notify user target file exists\n"); 1146 docopy = FALSE; 1147 } 1148 } 1149 if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE | 1150 SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP)) 1151 { 1152 ERR("Unsupported style(s) 0x%x\n",style); 1153 } 1154 1155 if (docopy) 1156 { 1157 rc = MoveFileExW(TempFile,target,MOVEFILE_REPLACE_EXISTING); 1158 TRACE("Did copy... rc was %i\n",rc); 1159 } 1160 1161 /* after copy processing */ 1162 if (style & SP_COPY_DELETESOURCE) 1163 { 1164 if (rc) 1165 DeleteFileW(source); 1166 } 1167 1168 return rc; 1169 } 1170 1171 /*********************************************************************** 1172 * SetupInstallFileA (SETUPAPI.@) 1173 */ 1174 BOOL WINAPI SetupInstallFileA( HINF hinf, PINFCONTEXT inf_context, PCSTR source, PCSTR root, 1175 PCSTR dest, DWORD style, PSP_FILE_CALLBACK_A handler, PVOID context ) 1176 { 1177 BOOL ret = FALSE; 1178 struct callback_WtoA_context ctx; 1179 UNICODE_STRING sourceW, rootW, destW; 1180 1181 TRACE("%p %p %s %s %s %x %p %p\n", hinf, inf_context, debugstr_a(source), debugstr_a(root), 1182 debugstr_a(dest), style, handler, context); 1183 1184 sourceW.Buffer = rootW.Buffer = destW.Buffer = NULL; 1185 if (source && !RtlCreateUnicodeStringFromAsciiz( &sourceW, source )) 1186 { 1187 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 1188 return FALSE; 1189 } 1190 if (root && !RtlCreateUnicodeStringFromAsciiz( &rootW, root )) 1191 { 1192 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 1193 goto exit; 1194 } 1195 if (dest && !RtlCreateUnicodeStringFromAsciiz( &destW, dest )) 1196 { 1197 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 1198 goto exit; 1199 } 1200 1201 ctx.orig_context = context; 1202 ctx.orig_handler = handler; 1203 1204 ret = SetupInstallFileW( hinf, inf_context, sourceW.Buffer, rootW.Buffer, destW.Buffer, style, QUEUE_callback_WtoA, &ctx ); 1205 1206 exit: 1207 RtlFreeUnicodeString( &sourceW ); 1208 RtlFreeUnicodeString( &rootW ); 1209 RtlFreeUnicodeString( &destW ); 1210 return ret; 1211 } 1212 1213 /*********************************************************************** 1214 * SetupInstallFileW (SETUPAPI.@) 1215 */ 1216 BOOL WINAPI SetupInstallFileW( HINF hinf, PINFCONTEXT inf_context, PCWSTR source, PCWSTR root, 1217 PCWSTR dest, DWORD style, PSP_FILE_CALLBACK_W handler, PVOID context ) 1218 { 1219 static const WCHAR CopyFiles[] = {'C','o','p','y','F','i','l','e','s',0}; 1220 1221 BOOL ret, absolute = (root && *root && !(style & SP_COPY_SOURCE_ABSOLUTE)); 1222 WCHAR *buffer, *p, *inf_source = NULL; 1223 unsigned int len; 1224 1225 TRACE("%p %p %s %s %s %x %p %p\n", hinf, inf_context, debugstr_w(source), debugstr_w(root), 1226 debugstr_w(dest), style, handler, context); 1227 1228 if (hinf) 1229 { 1230 INFCONTEXT ctx; 1231 1232 if (!inf_context) 1233 { 1234 inf_context = &ctx; 1235 if (!SetupFindFirstLineW( hinf, CopyFiles, NULL, inf_context )) return FALSE; 1236 } 1237 if (!SetupGetStringFieldW( inf_context, 1, NULL, 0, (PDWORD) &len )) return FALSE; 1238 if (!(inf_source = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) 1239 { 1240 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 1241 return FALSE; 1242 } 1243 if (!SetupGetStringFieldW( inf_context, 1, inf_source, len, NULL )) 1244 { 1245 HeapFree( GetProcessHeap(), 0, inf_source ); 1246 return FALSE; 1247 } 1248 source = inf_source; 1249 } 1250 else if (!source) 1251 { 1252 SetLastError( ERROR_INVALID_PARAMETER ); 1253 return FALSE; 1254 } 1255 1256 len = strlenW( source ) + 1; 1257 if (absolute) len += strlenW( root ) + 1; 1258 1259 if (!(p = buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) 1260 { 1261 HeapFree( GetProcessHeap(), 0, inf_source ); 1262 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 1263 return FALSE; 1264 } 1265 1266 if (absolute) 1267 { 1268 strcpyW( buffer, root ); 1269 p += strlenW( buffer ); 1270 if (p[-1] != '\\') *p++ = '\\'; 1271 } 1272 while (*source == '\\') source++; 1273 strcpyW( p, source ); 1274 1275 ret = do_file_copyW( buffer, dest, style, handler, context ); 1276 1277 HeapFree( GetProcessHeap(), 0, inf_source ); 1278 HeapFree( GetProcessHeap(), 0, buffer ); 1279 return ret; 1280 } 1281 1282 /*********************************************************************** 1283 * SetupCommitFileQueueW (SETUPAPI.@) 1284 */ 1285 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler, 1286 PVOID context ) 1287 { 1288 struct file_queue *queue = handle; 1289 struct file_op *op; 1290 BOOL result = FALSE; 1291 FILEPATHS_W paths; 1292 UINT op_result; 1293 1294 paths.Source = paths.Target = NULL; 1295 1296 if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count) 1297 return TRUE; /* nothing to do */ 1298 1299 if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE; 1300 1301 /* perform deletes */ 1302 1303 if (queue->delete_queue.count) 1304 { 1305 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE, 1306 queue->delete_queue.count ))) goto done; 1307 for (op = queue->delete_queue.head; op; op = op->next) 1308 { 1309 build_filepathsW( op, &paths ); 1310 op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE); 1311 if (op_result == FILEOP_ABORT) goto done; 1312 while (op_result == FILEOP_DOIT) 1313 { 1314 TRACE( "deleting file %s\n", debugstr_w(paths.Target) ); 1315 if (DeleteFileW( paths.Target )) break; /* success */ 1316 paths.Win32Error = GetLastError(); 1317 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 ); 1318 if (op_result == FILEOP_ABORT) goto done; 1319 } 1320 handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 ); 1321 } 1322 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 ); 1323 } 1324 1325 /* perform renames */ 1326 1327 if (queue->rename_queue.count) 1328 { 1329 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME, 1330 queue->rename_queue.count ))) goto done; 1331 for (op = queue->rename_queue.head; op; op = op->next) 1332 { 1333 build_filepathsW( op, &paths ); 1334 op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME); 1335 if (op_result == FILEOP_ABORT) goto done; 1336 while (op_result == FILEOP_DOIT) 1337 { 1338 TRACE( "renaming file %s -> %s\n", 1339 debugstr_w(paths.Source), debugstr_w(paths.Target) ); 1340 if (MoveFileW( paths.Source, paths.Target )) break; /* success */ 1341 paths.Win32Error = GetLastError(); 1342 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 ); 1343 if (op_result == FILEOP_ABORT) goto done; 1344 } 1345 handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 ); 1346 } 1347 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 ); 1348 } 1349 1350 /* perform copies */ 1351 1352 if (queue->copy_queue.count) 1353 { 1354 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY, 1355 queue->copy_queue.count ))) goto done; 1356 for (op = queue->copy_queue.head; op; op = op->next) 1357 { 1358 WCHAR newpath[MAX_PATH]; 1359 1360 build_filepathsW( op, &paths ); 1361 op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY ); 1362 if (op_result == FILEOP_ABORT) goto done; 1363 if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT; 1364 while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH) 1365 { 1366 TRACE( "copying file %s -> %s\n", 1367 debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ), 1368 debugstr_w(paths.Target) ); 1369 if (op->dst_path) 1370 { 1371 if (!create_full_pathW( op->dst_path )) 1372 { 1373 paths.Win32Error = GetLastError(); 1374 op_result = handler( context, SPFILENOTIFY_COPYERROR, 1375 (UINT_PTR)&paths, (UINT_PTR)newpath ); 1376 if (op_result == FILEOP_ABORT) goto done; 1377 } 1378 } 1379 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source, 1380 paths.Target, op->style, handler, context )) break; /* success */ 1381 /* try to extract it from the cabinet file */ 1382 if (op->src_tag) 1383 { 1384 if (extract_cabinet_file( op->src_tag, op->src_root, 1385 paths.Source, paths.Target )) break; 1386 } 1387 paths.Win32Error = GetLastError(); 1388 op_result = handler( context, SPFILENOTIFY_COPYERROR, 1389 (UINT_PTR)&paths, (UINT_PTR)newpath ); 1390 if (op_result == FILEOP_ABORT) goto done; 1391 } 1392 if (op->dst_sd) 1393 { 1394 PSID psidOwner = NULL, psidGroup = NULL; 1395 PACL pDacl = NULL, pSacl = NULL; 1396 SECURITY_INFORMATION security_info = 0; 1397 BOOL present, dummy; 1398 1399 if (GetSecurityDescriptorOwner( op->dst_sd, &psidOwner, &dummy ) && psidOwner) 1400 security_info |= OWNER_SECURITY_INFORMATION; 1401 if (GetSecurityDescriptorGroup( op->dst_sd, &psidGroup, &dummy ) && psidGroup) 1402 security_info |= GROUP_SECURITY_INFORMATION; 1403 if (GetSecurityDescriptorDacl( op->dst_sd, &present, &pDacl, &dummy )) 1404 security_info |= DACL_SECURITY_INFORMATION; 1405 if (GetSecurityDescriptorSacl( op->dst_sd, &present, &pSacl, &dummy )) 1406 security_info |= DACL_SECURITY_INFORMATION; 1407 SetNamedSecurityInfoW( (LPWSTR)paths.Target, SE_FILE_OBJECT, security_info, 1408 psidOwner, psidGroup, pDacl, pSacl ); 1409 /* Yes, ignore the return code... */ 1410 } 1411 handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 ); 1412 } 1413 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 ); 1414 } 1415 1416 1417 result = TRUE; 1418 1419 done: 1420 handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 ); 1421 HeapFree( GetProcessHeap(), 0, (void *)paths.Source ); 1422 HeapFree( GetProcessHeap(), 0, (void *)paths.Target ); 1423 return result; 1424 } 1425 1426 1427 /*********************************************************************** 1428 * SetupScanFileQueueA (SETUPAPI.@) 1429 */ 1430 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ handle, DWORD flags, HWND window, 1431 PSP_FILE_CALLBACK_A handler, PVOID context, PDWORD result ) 1432 { 1433 struct callback_WtoA_context ctx; 1434 1435 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result); 1436 1437 ctx.orig_context = context; 1438 ctx.orig_handler = handler; 1439 1440 return SetupScanFileQueueW( handle, flags, window, QUEUE_callback_WtoA, &ctx, result ); 1441 } 1442 1443 1444 /*********************************************************************** 1445 * SetupScanFileQueueW (SETUPAPI.@) 1446 */ 1447 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ handle, DWORD flags, HWND window, 1448 PSP_FILE_CALLBACK_W handler, PVOID context, PDWORD result ) 1449 { 1450 struct file_queue *queue = handle; 1451 struct file_op *op; 1452 FILEPATHS_W paths; 1453 UINT notification = 0; 1454 BOOL ret = FALSE; 1455 1456 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result); 1457 1458 *result = FALSE; 1459 1460 if (!queue->copy_queue.count) return TRUE; 1461 1462 if (flags & SPQ_SCAN_USE_CALLBACK) notification = SPFILENOTIFY_QUEUESCAN; 1463 else if (flags & SPQ_SCAN_USE_CALLBACKEX) notification = SPFILENOTIFY_QUEUESCAN_EX; 1464 1465 if (flags & ~(SPQ_SCAN_USE_CALLBACK | SPQ_SCAN_USE_CALLBACKEX)) 1466 { 1467 FIXME("flags %x not fully implemented\n", flags); 1468 } 1469 1470 paths.Source = paths.Target = NULL; 1471 1472 for (op = queue->copy_queue.head; op; op = op->next) 1473 { 1474 build_filepathsW( op, &paths ); 1475 switch (notification) 1476 { 1477 case SPFILENOTIFY_QUEUESCAN: 1478 /* FIXME: handle delay flag */ 1479 if (handler( context, notification, (UINT_PTR)paths.Target, 0 )) goto done; 1480 break; 1481 case SPFILENOTIFY_QUEUESCAN_EX: 1482 if (handler( context, notification, (UINT_PTR)&paths, 0 )) goto done; 1483 break; 1484 default: 1485 ret = TRUE; goto done; 1486 } 1487 } 1488 1489 *result = TRUE; 1490 1491 done: 1492 HeapFree( GetProcessHeap(), 0, (void *)paths.Source ); 1493 HeapFree( GetProcessHeap(), 0, (void *)paths.Target ); 1494 return ret; 1495 } 1496 1497 1498 /*********************************************************************** 1499 * SetupGetFileQueueCount (SETUPAPI.@) 1500 */ 1501 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result ) 1502 { 1503 struct file_queue *queue = handle; 1504 1505 switch(op) 1506 { 1507 case FILEOP_COPY: 1508 *result = queue->copy_queue.count; 1509 return TRUE; 1510 case FILEOP_RENAME: 1511 *result = queue->rename_queue.count; 1512 return TRUE; 1513 case FILEOP_DELETE: 1514 *result = queue->delete_queue.count; 1515 return TRUE; 1516 } 1517 return FALSE; 1518 } 1519 1520 1521 /*********************************************************************** 1522 * SetupGetFileQueueFlags (SETUPAPI.@) 1523 */ 1524 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags ) 1525 { 1526 struct file_queue *queue = handle; 1527 *flags = queue->flags; 1528 return TRUE; 1529 } 1530 1531 1532 /*********************************************************************** 1533 * SetupSetFileQueueFlags (SETUPAPI.@) 1534 */ 1535 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags ) 1536 { 1537 struct file_queue *queue = handle; 1538 queue->flags = (queue->flags & ~mask) | flags; 1539 return TRUE; 1540 } 1541 1542 1543 /*********************************************************************** 1544 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@) 1545 */ 1546 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile) 1547 { 1548 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile)); 1549 return FALSE; 1550 } 1551 1552 1553 /*********************************************************************** 1554 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@) 1555 */ 1556 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile) 1557 { 1558 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile)); 1559 return FALSE; 1560 } 1561 1562 1563 /*********************************************************************** 1564 * SetupInitDefaultQueueCallback (SETUPAPI.@) 1565 */ 1566 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner ) 1567 { 1568 return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL ); 1569 } 1570 1571 1572 /*********************************************************************** 1573 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@) 1574 */ 1575 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg, 1576 DWORD reserved1, PVOID reserved2 ) 1577 { 1578 struct default_callback_context *context; 1579 1580 if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) ))) 1581 { 1582 context->owner = owner; 1583 context->progress = progress; 1584 context->message = msg; 1585 } 1586 return context; 1587 } 1588 1589 1590 /*********************************************************************** 1591 * SetupTermDefaultQueueCallback (SETUPAPI.@) 1592 */ 1593 void WINAPI SetupTermDefaultQueueCallback( PVOID context ) 1594 { 1595 HeapFree( GetProcessHeap(), 0, context ); 1596 } 1597 1598 1599 /*********************************************************************** 1600 * SetupDefaultQueueCallbackA (SETUPAPI.@) 1601 */ 1602 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification, 1603 UINT_PTR param1, UINT_PTR param2 ) 1604 { 1605 FILEPATHS_A *paths = (FILEPATHS_A *)param1; 1606 struct default_callback_context *ctx = (struct default_callback_context *)context; 1607 1608 switch(notification) 1609 { 1610 case SPFILENOTIFY_STARTQUEUE: 1611 TRACE( "start queue\n" ); 1612 return TRUE; 1613 case SPFILENOTIFY_ENDQUEUE: 1614 TRACE( "end queue\n" ); 1615 return 0; 1616 case SPFILENOTIFY_STARTSUBQUEUE: 1617 TRACE( "start subqueue %ld count %ld\n", param1, param2 ); 1618 return TRUE; 1619 case SPFILENOTIFY_ENDSUBQUEUE: 1620 TRACE( "end subqueue %ld\n", param1 ); 1621 return 0; 1622 case SPFILENOTIFY_STARTDELETE: 1623 TRACE( "start delete %s\n", debugstr_a(paths->Target) ); 1624 return FILEOP_DOIT; 1625 case SPFILENOTIFY_ENDDELETE: 1626 TRACE( "end delete %s\n", debugstr_a(paths->Target) ); 1627 return 0; 1628 case SPFILENOTIFY_DELETEERROR: 1629 /*Windows Ignores attempts to delete files / folders which do not exist*/ 1630 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND)) 1631 SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0); 1632 return FILEOP_SKIP; 1633 case SPFILENOTIFY_STARTRENAME: 1634 TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); 1635 return FILEOP_DOIT; 1636 case SPFILENOTIFY_ENDRENAME: 1637 TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); 1638 return 0; 1639 case SPFILENOTIFY_RENAMEERROR: 1640 SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0); 1641 return FILEOP_SKIP; 1642 case SPFILENOTIFY_STARTCOPY: 1643 TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); 1644 return FILEOP_DOIT; 1645 case SPFILENOTIFY_ENDCOPY: 1646 TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); 1647 return 0; 1648 case SPFILENOTIFY_COPYERROR: 1649 ERR( "copy error %d %s -> %s\n", paths->Win32Error, 1650 debugstr_a(paths->Source), debugstr_a(paths->Target) ); 1651 return FILEOP_SKIP; 1652 case SPFILENOTIFY_NEEDMEDIA: 1653 TRACE( "need media\n" ); 1654 return FILEOP_SKIP; 1655 default: 1656 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 ); 1657 break; 1658 } 1659 return 0; 1660 } 1661 1662 1663 /*********************************************************************** 1664 * SetupDefaultQueueCallbackW (SETUPAPI.@) 1665 */ 1666 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification, 1667 UINT_PTR param1, UINT_PTR param2 ) 1668 { 1669 FILEPATHS_W *paths = (FILEPATHS_W *)param1; 1670 struct default_callback_context *ctx = (struct default_callback_context *)context; 1671 1672 switch(notification) 1673 { 1674 case SPFILENOTIFY_STARTQUEUE: 1675 TRACE( "start queue\n" ); 1676 return TRUE; 1677 case SPFILENOTIFY_ENDQUEUE: 1678 TRACE( "end queue\n" ); 1679 return 0; 1680 case SPFILENOTIFY_STARTSUBQUEUE: 1681 TRACE( "start subqueue %ld count %ld\n", param1, param2 ); 1682 return TRUE; 1683 case SPFILENOTIFY_ENDSUBQUEUE: 1684 TRACE( "end subqueue %ld\n", param1 ); 1685 return 0; 1686 case SPFILENOTIFY_STARTDELETE: 1687 TRACE( "start delete %s\n", debugstr_w(paths->Target) ); 1688 return FILEOP_DOIT; 1689 case SPFILENOTIFY_ENDDELETE: 1690 TRACE( "end delete %s\n", debugstr_w(paths->Target) ); 1691 return 0; 1692 case SPFILENOTIFY_DELETEERROR: 1693 /*Windows Ignores attempts to delete files / folders which do not exist*/ 1694 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND)) 1695 SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0); 1696 return FILEOP_SKIP; 1697 case SPFILENOTIFY_STARTRENAME: 1698 SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0); 1699 return FILEOP_DOIT; 1700 case SPFILENOTIFY_ENDRENAME: 1701 TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); 1702 return 0; 1703 case SPFILENOTIFY_RENAMEERROR: 1704 ERR( "rename error %d %s -> %s\n", paths->Win32Error, 1705 debugstr_w(paths->Source), debugstr_w(paths->Target) ); 1706 return FILEOP_SKIP; 1707 case SPFILENOTIFY_STARTCOPY: 1708 TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); 1709 return FILEOP_DOIT; 1710 case SPFILENOTIFY_ENDCOPY: 1711 TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); 1712 return 0; 1713 case SPFILENOTIFY_COPYERROR: 1714 ERR( "copy error %d %s -> %s\n", paths->Win32Error, 1715 debugstr_w(paths->Source), debugstr_w(paths->Target) ); 1716 return FILEOP_SKIP; 1717 case SPFILENOTIFY_NEEDMEDIA: 1718 TRACE( "need media\n" ); 1719 return FILEOP_SKIP; 1720 default: 1721 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 ); 1722 break; 1723 } 1724 return 0; 1725 } 1726 1727 /*********************************************************************** 1728 * SetupDeleteErrorA (SETUPAPI.@) 1729 */ 1730 1731 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file, 1732 UINT w32error, DWORD style) 1733 { 1734 FIXME( "stub: (Error Number %d when attempting to delete %s)\n", 1735 w32error, debugstr_a(file) ); 1736 return DPROMPT_SKIPFILE; 1737 } 1738 1739 /*********************************************************************** 1740 * SetupDeleteErrorW (SETUPAPI.@) 1741 */ 1742 1743 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file, 1744 UINT w32error, DWORD style) 1745 { 1746 FIXME( "stub: (Error Number %d when attempting to delete %s)\n", 1747 w32error, debugstr_w(file) ); 1748 return DPROMPT_SKIPFILE; 1749 } 1750 1751 /*********************************************************************** 1752 * SetupRenameErrorA (SETUPAPI.@) 1753 */ 1754 1755 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source, 1756 PCSTR target, UINT w32error, DWORD style) 1757 { 1758 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n", 1759 w32error, debugstr_a(source), debugstr_a(target)); 1760 return DPROMPT_SKIPFILE; 1761 } 1762 1763 /*********************************************************************** 1764 * SetupRenameErrorW (SETUPAPI.@) 1765 */ 1766 1767 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source, 1768 PCWSTR target, UINT w32error, DWORD style) 1769 { 1770 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n", 1771 w32error, debugstr_w(source), debugstr_w(target)); 1772 return DPROMPT_SKIPFILE; 1773 } 1774 1775 1776 /*********************************************************************** 1777 * SetupCopyErrorA (SETUPAPI.@) 1778 */ 1779 1780 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname, 1781 PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath, 1782 UINT w32error, DWORD style, PSTR pathbuffer, 1783 DWORD buffersize, PDWORD requiredsize) 1784 { 1785 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n", 1786 w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath)); 1787 return DPROMPT_SKIPFILE; 1788 } 1789 1790 /*********************************************************************** 1791 * SetupCopyErrorW (SETUPAPI.@) 1792 */ 1793 1794 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname, 1795 PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath, 1796 UINT w32error, DWORD style, PWSTR pathbuffer, 1797 DWORD buffersize, PDWORD requiredsize) 1798 { 1799 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n", 1800 w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath)); 1801 return DPROMPT_SKIPFILE; 1802 } 1803 1804 /*********************************************************************** 1805 * pSetupGetQueueFlags (SETUPAPI.@) 1806 */ 1807 DWORD WINAPI pSetupGetQueueFlags( HSPFILEQ handle ) 1808 { 1809 struct file_queue *queue = handle; 1810 return queue->flags; 1811 } 1812 1813 /*********************************************************************** 1814 * pSetupSetQueueFlags (SETUPAPI.@) 1815 */ 1816 BOOL WINAPI pSetupSetQueueFlags( HSPFILEQ handle, DWORD flags ) 1817 { 1818 struct file_queue *queue = handle; 1819 queue->flags = flags; 1820 return TRUE; 1821 } 1822