1 /* 2 * setupapi query functions 3 * 4 * Copyright 2006 James Hawkins 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 static const WCHAR source_disks_names[] = 24 {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0}; 25 static const WCHAR source_disks_files[] = 26 {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0}; 27 28 /* fills the PSP_INF_INFORMATION struct fill_info is TRUE 29 * always returns the required size of the information 30 */ 31 static BOOL fill_inf_info(HINF inf, PSP_INF_INFORMATION buffer, DWORD size, DWORD *required) 32 { 33 LPCWSTR filename = PARSER_get_inf_filename(inf); 34 DWORD total_size = FIELD_OFFSET(SP_INF_INFORMATION, VersionData) 35 + (lstrlenW(filename) + 1) * sizeof(WCHAR); 36 37 if (required) *required = total_size; 38 39 /* FIXME: we need to parse the INF file to find the correct version info */ 40 if (buffer) 41 { 42 if (size < total_size) 43 { 44 SetLastError(ERROR_INSUFFICIENT_BUFFER); 45 return FALSE; 46 } 47 buffer->InfStyle = INF_STYLE_WIN4; 48 buffer->InfCount = 1; 49 /* put the filename in buffer->VersionData */ 50 lstrcpyW((LPWSTR)&buffer->VersionData[0], filename); 51 } 52 return TRUE; 53 } 54 55 static HINF search_for_inf(LPCVOID InfSpec, DWORD SearchControl) 56 { 57 HINF hInf = INVALID_HANDLE_VALUE; 58 WCHAR inf_path[MAX_PATH]; 59 60 static const WCHAR infW[] = {'\\','i','n','f','\\',0}; 61 static const WCHAR system32W[] = {'\\','s','y','s','t','e','m','3','2','\\',0}; 62 63 if (SearchControl == INFINFO_REVERSE_DEFAULT_SEARCH) 64 { 65 GetWindowsDirectoryW(inf_path, MAX_PATH); 66 lstrcatW(inf_path, system32W); 67 lstrcatW(inf_path, InfSpec); 68 69 hInf = SetupOpenInfFileW(inf_path, NULL, 70 INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); 71 if (hInf != INVALID_HANDLE_VALUE) 72 return hInf; 73 74 GetWindowsDirectoryW(inf_path, MAX_PATH); 75 lstrcpyW(inf_path, infW); 76 lstrcatW(inf_path, InfSpec); 77 78 return SetupOpenInfFileW(inf_path, NULL, 79 INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); 80 } 81 82 return INVALID_HANDLE_VALUE; 83 } 84 85 /*********************************************************************** 86 * SetupGetInfInformationA (SETUPAPI.@) 87 * 88 */ 89 BOOL WINAPI SetupGetInfInformationA(LPCVOID InfSpec, DWORD SearchControl, 90 PSP_INF_INFORMATION ReturnBuffer, 91 DWORD ReturnBufferSize, PDWORD RequiredSize) 92 { 93 LPWSTR inf = (LPWSTR)InfSpec; 94 DWORD len; 95 BOOL ret; 96 97 if (InfSpec && SearchControl >= INFINFO_INF_NAME_IS_ABSOLUTE) 98 { 99 len = MultiByteToWideChar(CP_ACP, 0, InfSpec, -1, NULL, 0); 100 inf = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 101 if (!inf) 102 { 103 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 104 return FALSE; 105 } 106 MultiByteToWideChar(CP_ACP, 0, InfSpec, -1, inf, len); 107 } 108 109 ret = SetupGetInfInformationW(inf, SearchControl, ReturnBuffer, 110 ReturnBufferSize, RequiredSize); 111 112 if (SearchControl >= INFINFO_INF_NAME_IS_ABSOLUTE) 113 HeapFree(GetProcessHeap(), 0, inf); 114 115 return ret; 116 } 117 118 /*********************************************************************** 119 * SetupGetInfInformationW (SETUPAPI.@) 120 * 121 * BUGS 122 * Only handles the case when InfSpec is an INF handle. 123 */ 124 BOOL WINAPI SetupGetInfInformationW(LPCVOID InfSpec, DWORD SearchControl, 125 PSP_INF_INFORMATION ReturnBuffer, 126 DWORD ReturnBufferSize, PDWORD RequiredSize) 127 { 128 HINF inf; 129 BOOL ret; 130 DWORD infSize; 131 132 TRACE("(%p, %d, %p, %d, %p)\n", InfSpec, SearchControl, ReturnBuffer, 133 ReturnBufferSize, RequiredSize); 134 135 if (!InfSpec) 136 { 137 if (SearchControl == INFINFO_INF_SPEC_IS_HINF) 138 SetLastError(ERROR_INVALID_HANDLE); 139 else 140 SetLastError(ERROR_INVALID_PARAMETER); 141 142 return FALSE; 143 } 144 145 switch (SearchControl) 146 { 147 case INFINFO_INF_SPEC_IS_HINF: 148 inf = (HINF)InfSpec; 149 break; 150 case INFINFO_INF_NAME_IS_ABSOLUTE: 151 case INFINFO_DEFAULT_SEARCH: 152 inf = SetupOpenInfFileW(InfSpec, NULL, 153 INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); 154 break; 155 case INFINFO_REVERSE_DEFAULT_SEARCH: 156 inf = search_for_inf(InfSpec, SearchControl); 157 break; 158 case INFINFO_INF_PATH_LIST_SEARCH: 159 FIXME("Unhandled search control: %d\n", SearchControl); 160 161 if (RequiredSize) 162 *RequiredSize = 0; 163 164 return FALSE; 165 default: 166 SetLastError(ERROR_INVALID_PARAMETER); 167 return FALSE; 168 } 169 170 if (inf == INVALID_HANDLE_VALUE) 171 { 172 SetLastError(ERROR_FILE_NOT_FOUND); 173 return FALSE; 174 } 175 176 ret = fill_inf_info(inf, ReturnBuffer, ReturnBufferSize, &infSize); 177 if (!ReturnBuffer && (ReturnBufferSize >= infSize)) 178 { 179 SetLastError(ERROR_INVALID_PARAMETER); 180 ret = FALSE; 181 } 182 if (RequiredSize) *RequiredSize = infSize; 183 184 if (SearchControl >= INFINFO_INF_NAME_IS_ABSOLUTE) 185 SetupCloseInfFile(inf); 186 187 return ret; 188 } 189 190 /*********************************************************************** 191 * SetupQueryInfFileInformationA (SETUPAPI.@) 192 */ 193 BOOL WINAPI SetupQueryInfFileInformationA(PSP_INF_INFORMATION InfInformation, 194 UINT InfIndex, PSTR ReturnBuffer, 195 DWORD ReturnBufferSize, PDWORD RequiredSize) 196 { 197 LPWSTR filenameW; 198 DWORD size; 199 BOOL ret; 200 201 ret = SetupQueryInfFileInformationW(InfInformation, InfIndex, NULL, 0, &size); 202 if (!ret) 203 return FALSE; 204 205 filenameW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); 206 207 ret = SetupQueryInfFileInformationW(InfInformation, InfIndex, 208 filenameW, size, &size); 209 if (!ret) 210 { 211 HeapFree(GetProcessHeap(), 0, filenameW); 212 return FALSE; 213 } 214 215 if (RequiredSize) 216 *RequiredSize = size; 217 218 if (!ReturnBuffer) 219 { 220 HeapFree(GetProcessHeap(), 0, filenameW); 221 if (ReturnBufferSize) 222 { 223 SetLastError(ERROR_INVALID_PARAMETER); 224 return FALSE; 225 } 226 227 return TRUE; 228 } 229 230 if (size > ReturnBufferSize) 231 { 232 HeapFree(GetProcessHeap(), 0, filenameW); 233 SetLastError(ERROR_INSUFFICIENT_BUFFER); 234 return FALSE; 235 } 236 237 WideCharToMultiByte(CP_ACP, 0, filenameW, -1, ReturnBuffer, size, NULL, NULL); 238 HeapFree(GetProcessHeap(), 0, filenameW); 239 240 return ret; 241 } 242 243 /*********************************************************************** 244 * SetupQueryInfFileInformationW (SETUPAPI.@) 245 */ 246 BOOL WINAPI SetupQueryInfFileInformationW(PSP_INF_INFORMATION InfInformation, 247 UINT InfIndex, PWSTR ReturnBuffer, 248 DWORD ReturnBufferSize, PDWORD RequiredSize) 249 { 250 DWORD len; 251 LPWSTR ptr; 252 253 TRACE("(%p, %u, %p, %d, %p) Stub!\n", InfInformation, InfIndex, 254 ReturnBuffer, ReturnBufferSize, RequiredSize); 255 256 if (!InfInformation) 257 { 258 SetLastError(ERROR_INVALID_PARAMETER); 259 return FALSE; 260 } 261 262 if (InfIndex != 0) 263 FIXME("Appended INF files are not handled\n"); 264 265 ptr = (LPWSTR)InfInformation->VersionData; 266 len = lstrlenW(ptr); 267 268 if (RequiredSize) 269 *RequiredSize = len + 1; 270 271 if (!ReturnBuffer) 272 return TRUE; 273 274 if (ReturnBufferSize < len) 275 { 276 SetLastError(ERROR_INSUFFICIENT_BUFFER); 277 return FALSE; 278 } 279 280 lstrcpyW(ReturnBuffer, ptr); 281 return TRUE; 282 } 283 284 /*********************************************************************** 285 * SetupGetSourceFileLocationA (SETUPAPI.@) 286 */ 287 288 BOOL WINAPI SetupGetSourceFileLocationA( HINF hinf, PINFCONTEXT context, PCSTR filename, 289 PUINT source_id, PSTR buffer, DWORD buffer_size, 290 PDWORD required_size ) 291 { 292 BOOL ret = FALSE; 293 WCHAR *filenameW = NULL, *bufferW = NULL; 294 DWORD required; 295 INT size; 296 297 TRACE("%p, %p, %s, %p, %p, 0x%08x, %p\n", hinf, context, debugstr_a(filename), source_id, 298 buffer, buffer_size, required_size); 299 300 if (filename && *filename && !(filenameW = strdupAtoW( filename ))) 301 return FALSE; 302 303 if (!SetupGetSourceFileLocationW( hinf, context, filenameW, source_id, NULL, 0, &required )) 304 goto done; 305 306 if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, required * sizeof(WCHAR) ))) 307 goto done; 308 309 if (!SetupGetSourceFileLocationW( hinf, context, filenameW, source_id, bufferW, required, NULL )) 310 goto done; 311 312 size = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL ); 313 if (required_size) *required_size = size; 314 315 if (buffer) 316 { 317 if (buffer_size >= size) 318 WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, buffer_size, NULL, NULL ); 319 else 320 { 321 SetLastError( ERROR_INSUFFICIENT_BUFFER ); 322 goto done; 323 } 324 } 325 ret = TRUE; 326 327 done: 328 HeapFree( GetProcessHeap(), 0, filenameW ); 329 HeapFree( GetProcessHeap(), 0, bufferW ); 330 return ret; 331 } 332 333 static LPWSTR get_source_id( HINF hinf, PINFCONTEXT context, PCWSTR filename ) 334 { 335 WCHAR Section[MAX_PATH]; 336 DWORD size; 337 LPWSTR source_id; 338 339 if (!SetupDiGetActualSectionToInstallW(hinf, source_disks_files, Section, MAX_PATH, NULL, NULL)) 340 return NULL; 341 342 if (!SetupFindFirstLineW( hinf, Section, filename, context ) && 343 !SetupFindFirstLineW( hinf, source_disks_files, filename, context )) 344 return NULL; 345 346 if (!SetupGetStringFieldW( context, 1, NULL, 0, &size )) 347 return NULL; 348 349 if (!(source_id = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) 350 return NULL; 351 352 if (!SetupGetStringFieldW( context, 1, source_id, size, NULL )) 353 { 354 HeapFree( GetProcessHeap(), 0, source_id ); 355 return NULL; 356 } 357 358 if (!SetupDiGetActualSectionToInstallW(hinf, source_disks_names, Section, MAX_PATH, NULL, NULL)) 359 { 360 HeapFree( GetProcessHeap(), 0, source_id ); 361 return NULL; 362 } 363 364 if (!SetupFindFirstLineW( hinf, Section, source_id, context ) && 365 !SetupFindFirstLineW( hinf, source_disks_names, source_id, context )) 366 { 367 HeapFree( GetProcessHeap(), 0, source_id ); 368 return NULL; 369 } 370 return source_id; 371 } 372 373 /*********************************************************************** 374 * SetupGetSourceFileLocationW (SETUPAPI.@) 375 */ 376 377 BOOL WINAPI SetupGetSourceFileLocationW( HINF hinf, PINFCONTEXT context, PCWSTR filename, 378 PUINT source_id, PWSTR buffer, DWORD buffer_size, 379 PDWORD required_size ) 380 { 381 INFCONTEXT ctx; 382 WCHAR *end, *source_id_str; 383 384 TRACE("%p, %p, %s, %p, %p, 0x%08x, %p\n", hinf, context, debugstr_w(filename), source_id, 385 buffer, buffer_size, required_size); 386 387 if (!context) context = &ctx; 388 389 if (!(source_id_str = get_source_id( hinf, context, filename ))) 390 return FALSE; 391 392 *source_id = strtolW( source_id_str, &end, 10 ); 393 if (end == source_id_str || *end) 394 { 395 HeapFree( GetProcessHeap(), 0, source_id_str ); 396 return FALSE; 397 } 398 HeapFree( GetProcessHeap(), 0, source_id_str ); 399 400 if (SetupGetStringFieldW( context, 4, buffer, buffer_size, required_size )) 401 return TRUE; 402 403 if (required_size) *required_size = 1; 404 if (buffer) 405 { 406 if (buffer_size >= 1) buffer[0] = 0; 407 else 408 { 409 SetLastError( ERROR_INSUFFICIENT_BUFFER ); 410 return FALSE; 411 } 412 } 413 return TRUE; 414 } 415 416 /*********************************************************************** 417 * SetupGetSourceInfoA (SETUPAPI.@) 418 */ 419 420 BOOL WINAPI SetupGetSourceInfoA( HINF hinf, UINT source_id, UINT info, 421 PSTR buffer, DWORD buffer_size, LPDWORD required_size ) 422 { 423 BOOL ret = FALSE; 424 WCHAR *bufferW = NULL; 425 DWORD required; 426 INT size; 427 428 TRACE("%p, %d, %d, %p, %d, %p\n", hinf, source_id, info, buffer, buffer_size, 429 required_size); 430 431 if (!SetupGetSourceInfoW( hinf, source_id, info, NULL, 0, &required )) 432 return FALSE; 433 434 if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, required * sizeof(WCHAR) ))) 435 return FALSE; 436 437 if (!SetupGetSourceInfoW( hinf, source_id, info, bufferW, required, NULL )) 438 goto done; 439 440 size = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL ); 441 if (required_size) *required_size = size; 442 443 if (buffer) 444 { 445 if (buffer_size >= size) 446 WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, buffer_size, NULL, NULL ); 447 else 448 { 449 SetLastError( ERROR_INSUFFICIENT_BUFFER ); 450 goto done; 451 } 452 } 453 ret = TRUE; 454 455 done: 456 HeapFree( GetProcessHeap(), 0, bufferW ); 457 return ret; 458 } 459 460 /*********************************************************************** 461 * SetupGetSourceInfoW (SETUPAPI.@) 462 */ 463 464 BOOL WINAPI SetupGetSourceInfoW( HINF hinf, UINT source_id, UINT info, 465 PWSTR buffer, DWORD buffer_size, LPDWORD required_size ) 466 { 467 WCHAR Section[MAX_PATH]; 468 INFCONTEXT ctx; 469 WCHAR source_id_str[11]; 470 static const WCHAR fmt[] = {'%','d',0}; 471 DWORD index; 472 473 TRACE("%p, %d, %d, %p, %d, %p\n", hinf, source_id, info, buffer, buffer_size, 474 required_size); 475 476 sprintfW( source_id_str, fmt, source_id ); 477 478 if (!SetupDiGetActualSectionToInstallW(hinf, source_disks_names, Section, MAX_PATH, NULL, NULL)) 479 return FALSE; 480 481 if (!SetupFindFirstLineW( hinf, Section, source_id_str, &ctx ) && 482 !SetupFindFirstLineW( hinf, source_disks_names, source_id_str, &ctx )) 483 return FALSE; 484 485 switch (info) 486 { 487 case SRCINFO_PATH: index = 4; break; 488 case SRCINFO_TAGFILE: index = 2; break; 489 case SRCINFO_DESCRIPTION: index = 1; break; 490 default: 491 WARN("unknown info level: %d\n", info); 492 return FALSE; 493 } 494 495 if (SetupGetStringFieldW( &ctx, index, buffer, buffer_size, required_size )) 496 return TRUE; 497 498 if (required_size) *required_size = 1; 499 if (buffer) 500 { 501 if (buffer_size >= 1) buffer[0] = 0; 502 else 503 { 504 SetLastError( ERROR_INSUFFICIENT_BUFFER ); 505 return FALSE; 506 } 507 } 508 return TRUE; 509 } 510 511 /*********************************************************************** 512 * SetupGetTargetPathA (SETUPAPI.@) 513 */ 514 515 BOOL WINAPI SetupGetTargetPathA( HINF hinf, PINFCONTEXT context, PCSTR section, PSTR buffer, 516 DWORD buffer_size, PDWORD required_size ) 517 { 518 BOOL ret = FALSE; 519 WCHAR *sectionW = NULL, *bufferW = NULL; 520 DWORD required; 521 INT size; 522 523 TRACE("%p, %p, %s, %p, 0x%08x, %p\n", hinf, context, debugstr_a(section), buffer, 524 buffer_size, required_size); 525 526 if (section && !(sectionW = strdupAtoW( section ))) 527 return FALSE; 528 529 if (!SetupGetTargetPathW( hinf, context, sectionW, NULL, 0, &required )) 530 goto done; 531 532 if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, required * sizeof(WCHAR) ))) 533 goto done; 534 535 if (!SetupGetTargetPathW( hinf, context, sectionW, bufferW, required, NULL )) 536 goto done; 537 538 size = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL ); 539 if (required_size) *required_size = size; 540 541 if (buffer) 542 { 543 if (buffer_size >= size) 544 WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, buffer_size, NULL, NULL ); 545 else 546 { 547 SetLastError( ERROR_INSUFFICIENT_BUFFER ); 548 goto done; 549 } 550 } 551 ret = TRUE; 552 553 done: 554 HeapFree( GetProcessHeap(), 0, sectionW ); 555 HeapFree( GetProcessHeap(), 0, bufferW ); 556 return ret; 557 } 558 559 /*********************************************************************** 560 * SetupGetTargetPathW (SETUPAPI.@) 561 */ 562 563 BOOL WINAPI SetupGetTargetPathW( HINF hinf, PINFCONTEXT context, PCWSTR section, PWSTR buffer, 564 DWORD buffer_size, PDWORD required_size ) 565 { 566 static const WCHAR destination_dirs[] = 567 {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0}; 568 static const WCHAR default_dest_dir[] = 569 {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0}; 570 571 INFCONTEXT ctx; 572 WCHAR *dir, systemdir[MAX_PATH]; 573 unsigned int size; 574 BOOL ret = FALSE; 575 576 TRACE("%p, %p, %s, %p, 0x%08x, %p\n", hinf, context, debugstr_w(section), buffer, 577 buffer_size, required_size); 578 579 if (context) ret = SetupFindFirstLineW( hinf, destination_dirs, NULL, context ); 580 else if (section) 581 { 582 if (!(ret = SetupFindFirstLineW( hinf, destination_dirs, section, &ctx ))) 583 ret = SetupFindFirstLineW( hinf, destination_dirs, default_dest_dir, &ctx ); 584 } 585 if (!ret || !(dir = PARSER_get_dest_dir( context ? context : &ctx ))) 586 { 587 GetSystemDirectoryW( systemdir, MAX_PATH ); 588 dir = systemdir; 589 } 590 size = strlenW( dir ) + 1; 591 if (required_size) *required_size = size; 592 593 if (buffer) 594 { 595 if (buffer_size >= size) 596 lstrcpyW( buffer, dir ); 597 else 598 { 599 SetLastError( ERROR_INSUFFICIENT_BUFFER ); 600 if (dir != systemdir) HeapFree( GetProcessHeap(), 0, dir ); 601 return FALSE; 602 } 603 } 604 if (dir != systemdir) HeapFree( GetProcessHeap(), 0, dir ); 605 return TRUE; 606 } 607 608 /*********************************************************************** 609 * SetupQueryInfOriginalFileInformationA (SETUPAPI.@) 610 */ 611 BOOL WINAPI SetupQueryInfOriginalFileInformationA( 612 PSP_INF_INFORMATION InfInformation, UINT InfIndex, 613 PSP_ALTPLATFORM_INFO AlternativePlatformInfo, 614 PSP_ORIGINAL_FILE_INFO_A OriginalFileInfo) 615 { 616 BOOL ret; 617 SP_ORIGINAL_FILE_INFO_W OriginalFileInfoW; 618 619 TRACE("(%p, %d, %p, %p)\n", InfInformation, InfIndex, 620 AlternativePlatformInfo, OriginalFileInfo); 621 622 if (OriginalFileInfo->cbSize != sizeof(*OriginalFileInfo)) 623 { 624 WARN("incorrect OriginalFileInfo->cbSize of %d\n", OriginalFileInfo->cbSize); 625 SetLastError( ERROR_INVALID_USER_BUFFER ); 626 return FALSE; 627 } 628 629 OriginalFileInfoW.cbSize = sizeof(OriginalFileInfoW); 630 ret = SetupQueryInfOriginalFileInformationW(InfInformation, InfIndex, 631 AlternativePlatformInfo, &OriginalFileInfoW); 632 if (ret) 633 { 634 WideCharToMultiByte(CP_ACP, 0, OriginalFileInfoW.OriginalInfName, -1, 635 OriginalFileInfo->OriginalInfName, MAX_PATH, NULL, NULL); 636 WideCharToMultiByte(CP_ACP, 0, OriginalFileInfoW.OriginalCatalogName, -1, 637 OriginalFileInfo->OriginalCatalogName, MAX_PATH, NULL, NULL); 638 } 639 640 return ret; 641 } 642 643 /*********************************************************************** 644 * SetupQueryInfOriginalFileInformationW (SETUPAPI.@) 645 */ 646 BOOL WINAPI SetupQueryInfOriginalFileInformationW( 647 PSP_INF_INFORMATION InfInformation, UINT InfIndex, 648 PSP_ALTPLATFORM_INFO AlternativePlatformInfo, 649 PSP_ORIGINAL_FILE_INFO_W OriginalFileInfo) 650 { 651 LPCWSTR inf_name; 652 LPCWSTR inf_path; 653 HINF hinf; 654 static const WCHAR wszVersion[] = { 'V','e','r','s','i','o','n',0 }; 655 static const WCHAR wszCatalogFile[] = { 'C','a','t','a','l','o','g','F','i','l','e',0 }; 656 657 FIXME("(%p, %d, %p, %p): semi-stub\n", InfInformation, InfIndex, 658 AlternativePlatformInfo, OriginalFileInfo); 659 660 if (OriginalFileInfo->cbSize != sizeof(*OriginalFileInfo)) 661 { 662 WARN("incorrect OriginalFileInfo->cbSize of %d\n", OriginalFileInfo->cbSize); 663 SetLastError(ERROR_INVALID_USER_BUFFER); 664 return FALSE; 665 } 666 667 inf_path = (LPWSTR)InfInformation->VersionData; 668 669 /* FIXME: we should get OriginalCatalogName from CatalogFile line in 670 * the original inf file and cache it, but that would require building a 671 * .pnf file. */ 672 hinf = SetupOpenInfFileW(inf_path, NULL, INF_STYLE_WIN4, NULL); 673 if (hinf == INVALID_HANDLE_VALUE) return FALSE; 674 675 if (!SetupGetLineTextW(NULL, hinf, wszVersion, wszCatalogFile, 676 OriginalFileInfo->OriginalCatalogName, 677 sizeof(OriginalFileInfo->OriginalCatalogName)/sizeof(OriginalFileInfo->OriginalCatalogName[0]), 678 NULL)) 679 { 680 OriginalFileInfo->OriginalCatalogName[0] = '\0'; 681 } 682 SetupCloseInfFile(hinf); 683 684 /* FIXME: not quite correct as we just return the same file name as 685 * destination (copied) inf file, not the source (original) inf file. 686 * to fix it properly would require building a .pnf file */ 687 /* file name is stored in VersionData field of InfInformation */ 688 inf_name = strrchrW(inf_path, '\\'); 689 if (inf_name) inf_name++; 690 else inf_name = inf_path; 691 692 strcpyW(OriginalFileInfo->OriginalInfName, inf_name); 693 694 return TRUE; 695 } 696