1 /* 2 * SetupAPI driver-related functions 3 * 4 * Copyright 2005-2006 Herv� Poussineau (hpoussin@reactos.org) 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 /* Unicode constants */ 24 static const WCHAR BackSlash[] = {'\\',0}; 25 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0}; 26 static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0}; 27 static const WCHAR InfDirectory[] = {'i','n','f','\\',0}; 28 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0}; 29 30 static const WCHAR INF_MANUFACTURER[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0}; 31 static const WCHAR INF_PROVIDER[] = {'P','r','o','v','i','d','e','r',0}; 32 static const WCHAR INF_DRIVER_VER[] = {'D','r','i','v','e','r','V','e','r',0}; 33 34 35 /*********************************************************************** 36 * struct InfFileDetails management 37 */ 38 static VOID 39 ReferenceInfFile(struct InfFileDetails* infFile) 40 { 41 InterlockedIncrement(&infFile->References); 42 } 43 44 VOID 45 DereferenceInfFile(struct InfFileDetails* infFile) 46 { 47 if (InterlockedDecrement(&infFile->References) == 0) 48 { 49 SetupCloseInfFile(infFile->hInf); 50 HeapFree(GetProcessHeap(), 0, infFile); 51 } 52 } 53 54 struct InfFileDetails * 55 CreateInfFileDetails( 56 IN LPCWSTR FullInfFileName) 57 { 58 struct InfFileDetails *details; 59 PWCHAR last; 60 DWORD Needed; 61 62 Needed = FIELD_OFFSET(struct InfFileDetails, szData) 63 + strlenW(FullInfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL); 64 65 details = HeapAlloc(GetProcessHeap(), 0, Needed); 66 if (!details) 67 { 68 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 69 return NULL; 70 } 71 72 memset(details, 0, Needed); 73 strcpyW(details->szData, FullInfFileName); 74 last = strrchrW(details->szData, '\\'); 75 if (last) 76 { 77 details->DirectoryName = details->szData; 78 details->FileName = last + 1; 79 *last = '\0'; 80 } 81 else 82 details->FileName = details->szData; 83 ReferenceInfFile(details); 84 details->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL); 85 if (details->hInf == INVALID_HANDLE_VALUE) 86 { 87 HeapFree(GetProcessHeap(), 0, details); 88 return NULL; 89 } 90 return details; 91 } 92 93 BOOL 94 DestroyDriverInfoElement(struct DriverInfoElement* driverInfo) 95 { 96 DereferenceInfFile(driverInfo->InfFileDetails); 97 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId); 98 HeapFree(GetProcessHeap(), 0, driverInfo); 99 return TRUE; 100 } 101 102 /*********************************************************************** 103 * Helper functions for SetupDiBuildDriverInfoList 104 */ 105 static BOOL 106 AddKnownDriverToList( 107 IN PLIST_ENTRY DriverListHead, 108 IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */ 109 IN LPGUID ClassGuid, 110 IN struct InfFileDetails *InfFileDetails, 111 IN LPCWSTR InfFile, 112 IN LPCWSTR SectionName, 113 IN LPCWSTR DriverDescription, 114 IN LPCWSTR ProviderName, 115 IN LPCWSTR ManufacturerName, 116 IN LPCWSTR MatchingId, 117 IN FILETIME DriverDate, 118 IN DWORDLONG DriverVersion, 119 IN DWORD Rank) 120 { 121 struct DriverInfoElement *driverInfo = NULL; 122 HANDLE hFile = INVALID_HANDLE_VALUE; 123 BOOL Result = FALSE; 124 PLIST_ENTRY PreviousEntry; 125 BOOL ret = FALSE; 126 127 driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement)); 128 if (!driverInfo) 129 { 130 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 131 goto cleanup; 132 } 133 memset(driverInfo, 0, sizeof(struct DriverInfoElement)); 134 135 driverInfo->Params.cbSize = sizeof(SP_DRVINSTALL_PARAMS); 136 driverInfo->Params.Reserved = (ULONG_PTR)driverInfo; 137 138 driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W); 139 driverInfo->Details.Reserved = (ULONG_PTR)driverInfo; 140 141 /* Copy InfFileName field */ 142 lstrcpynW(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1); 143 driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0'; 144 145 /* Fill InfDate field */ 146 hFile = CreateFileW( 147 InfFile, 148 GENERIC_READ, FILE_SHARE_READ, 149 NULL, OPEN_EXISTING, 0, NULL); 150 if (hFile == INVALID_HANDLE_VALUE) 151 goto cleanup; 152 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate); 153 if (!Result) 154 goto cleanup; 155 156 /* Fill SectionName field */ 157 lstrcpynW(driverInfo->Details.SectionName, SectionName, LINE_LEN); 158 159 /* Fill DrvDescription field */ 160 lstrcpynW(driverInfo->Details.DrvDescription, DriverDescription, LINE_LEN); 161 162 /* Copy MatchingId information */ 163 if (MatchingId) 164 { 165 driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId) + 1) * sizeof(WCHAR)); 166 if (!driverInfo->MatchingId) 167 { 168 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 169 goto cleanup; 170 } 171 RtlCopyMemory(driverInfo->MatchingId, MatchingId, (strlenW(MatchingId) + 1) * sizeof(WCHAR)); 172 } 173 else 174 driverInfo->MatchingId = NULL; 175 176 TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n", 177 debugstr_w(driverInfo->Details.DrvDescription), debugstr_w(InfFile), 178 debugstr_w(SectionName), Rank); 179 180 driverInfo->Params.Rank = Rank; 181 memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME)); 182 memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID)); 183 driverInfo->Info.DriverType = DriverType; 184 driverInfo->Info.Reserved = (ULONG_PTR)driverInfo; 185 lstrcpynW(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1); 186 driverInfo->Info.Description[LINE_LEN - 1] = '\0'; 187 lstrcpynW(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1); 188 driverInfo->Info.MfgName[LINE_LEN - 1] = '\0'; 189 if (ProviderName) 190 { 191 lstrcpynW(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1); 192 driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0'; 193 } 194 else 195 driverInfo->Info.ProviderName[0] = '\0'; 196 driverInfo->Info.DriverDate = DriverDate; 197 driverInfo->Info.DriverVersion = DriverVersion; 198 ReferenceInfFile(InfFileDetails); 199 driverInfo->InfFileDetails = InfFileDetails; 200 201 /* Insert current driver in driver list, according to its rank */ 202 PreviousEntry = DriverListHead->Flink; 203 while (PreviousEntry != DriverListHead) 204 { 205 struct DriverInfoElement *CurrentDriver; 206 CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry); 207 if (CurrentDriver->Params.Rank > Rank || 208 (CurrentDriver->Params.Rank == Rank && CurrentDriver->DriverDate.QuadPart < driverInfo->DriverDate.QuadPart)) 209 { 210 /* Insert before the current item */ 211 InsertHeadList(PreviousEntry->Blink, &driverInfo->ListEntry); 212 break; 213 } 214 PreviousEntry = PreviousEntry->Flink; 215 } 216 if (PreviousEntry == DriverListHead) 217 { 218 /* Insert at the end of the list */ 219 InsertTailList(DriverListHead, &driverInfo->ListEntry); 220 } 221 222 ret = TRUE; 223 224 cleanup: 225 if (!ret) 226 { 227 if (driverInfo) 228 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId); 229 HeapFree(GetProcessHeap(), 0, driverInfo); 230 } 231 if (hFile != INVALID_HANDLE_VALUE) 232 CloseHandle(hFile); 233 234 return ret; 235 } 236 237 static BOOL 238 AddDriverToList( 239 IN PLIST_ENTRY DriverListHead, 240 IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */ 241 IN LPGUID ClassGuid, 242 IN INFCONTEXT ContextDevice, 243 IN struct InfFileDetails *InfFileDetails, 244 IN LPCWSTR InfFile, 245 IN LPCWSTR ProviderName, 246 IN LPCWSTR ManufacturerName, 247 IN LPCWSTR MatchingId, 248 IN FILETIME DriverDate, 249 IN DWORDLONG DriverVersion, 250 IN DWORD Rank) 251 { 252 LPWSTR SectionName = NULL; 253 LPWSTR DriverDescription = NULL; 254 BOOL Result; 255 BOOL ret = FALSE; 256 257 /* Read SectionName */ 258 SectionName = MyMalloc(LINE_LEN); 259 if (!SectionName) 260 { 261 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 262 goto cleanup; 263 } 264 ZeroMemory(SectionName, LINE_LEN); 265 Result = SetupGetStringFieldW( 266 &ContextDevice, 267 1, 268 SectionName, 269 LINE_LEN, 270 NULL); 271 if (!Result) 272 goto cleanup; 273 274 /* Read DriverDescription */ 275 DriverDescription = MyMalloc(LINE_LEN); 276 if (!DriverDescription) 277 { 278 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 279 goto cleanup; 280 } 281 ZeroMemory(DriverDescription, LINE_LEN); 282 Result = SetupGetStringFieldW( 283 &ContextDevice, 284 0, /* Field index */ 285 DriverDescription, LINE_LEN, 286 NULL); 287 288 ret = AddKnownDriverToList( 289 DriverListHead, 290 DriverType, 291 ClassGuid, 292 InfFileDetails, 293 InfFile, 294 SectionName, 295 DriverDescription, 296 ProviderName, 297 ManufacturerName, 298 MatchingId, 299 DriverDate, 300 DriverVersion, 301 Rank); 302 303 cleanup: 304 MyFree(SectionName); 305 MyFree(DriverDescription); 306 307 return ret; 308 } 309 310 static BOOL 311 GetVersionInformationFromInfFile( 312 IN HINF hInf, 313 OUT LPGUID ClassGuid, 314 OUT LPWSTR* pProviderName, 315 OUT FILETIME* DriverDate, 316 OUT DWORDLONG* DriverVersion) 317 { 318 DWORD RequiredSize; 319 WCHAR guidW[MAX_GUID_STRING_LEN + 1]; 320 LPWSTR DriverVer = NULL; 321 LPWSTR ProviderName = NULL; 322 LPWSTR pComma; /* Points into DriverVer */ 323 LPWSTR pVersion = NULL; /* Points into DriverVer */ 324 SYSTEMTIME SystemTime; 325 BOOL Result; 326 BOOL ret = FALSE; /* Final result */ 327 328 /* Get class Guid */ 329 if (!SetupGetLineTextW( 330 NULL, /* Context */ 331 hInf, 332 Version, ClassGUID, 333 guidW, sizeof(guidW), 334 NULL /* Required size */)) 335 { 336 goto cleanup; 337 } 338 guidW[37] = '\0'; /* Replace the } by a NULL character */ 339 if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK) 340 { 341 SetLastError(ERROR_GEN_FAILURE); 342 goto cleanup; 343 } 344 345 /* Get provider name */ 346 Result = SetupGetLineTextW( 347 NULL, /* Context */ 348 hInf, Version, INF_PROVIDER, 349 NULL, 0, 350 &RequiredSize); 351 if (Result) 352 { 353 /* We know the needed buffer size */ 354 ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); 355 if (!ProviderName) 356 { 357 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 358 goto cleanup; 359 } 360 Result = SetupGetLineTextW( 361 NULL, /* Context */ 362 hInf, Version, INF_PROVIDER, 363 ProviderName, RequiredSize, 364 &RequiredSize); 365 } 366 if (!Result) 367 goto cleanup; 368 *pProviderName = ProviderName; 369 370 /* Read the "DriverVer" value */ 371 Result = SetupGetLineTextW( 372 NULL, /* Context */ 373 hInf, Version, INF_DRIVER_VER, 374 NULL, 0, 375 &RequiredSize); 376 if (Result) 377 { 378 /* We know know the needed buffer size */ 379 DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); 380 if (!DriverVer) 381 { 382 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 383 goto cleanup; 384 } 385 Result = SetupGetLineTextW( 386 NULL, /* Context */ 387 hInf, Version, INF_DRIVER_VER, 388 DriverVer, RequiredSize, 389 &RequiredSize); 390 } 391 else 392 { 393 /* windows sets default date of 00/00/0000 when this directive is missing*/ 394 memset(DriverDate, 0, sizeof(FILETIME)); 395 *DriverVersion = 0; 396 return TRUE; 397 } 398 399 /* Get driver date and driver version, by analyzing the "DriverVer" value */ 400 pComma = strchrW(DriverVer, ','); 401 if (pComma != NULL) 402 { 403 *pComma = UNICODE_NULL; 404 pVersion = pComma + 1; 405 } 406 /* Get driver date version. Invalid date = 00/00/00 */ 407 memset(DriverDate, 0, sizeof(FILETIME)); 408 if (strlenW(DriverVer) == 10 409 && (DriverVer[2] == '-' || DriverVer[2] == '/') 410 && (DriverVer[5] == '-' || DriverVer[5] == '/')) 411 { 412 memset(&SystemTime, 0, sizeof(SYSTEMTIME)); 413 DriverVer[2] = DriverVer[5] = UNICODE_NULL; 414 SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0'; 415 SystemTime.wDay = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0'; 416 SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0'; 417 SystemTimeToFileTime(&SystemTime, DriverDate); 418 } 419 /* Get driver version. Invalid version = 0.0.0.0 */ 420 *DriverVersion = 0; 421 if (pVersion) 422 { 423 WORD Major, Minor = 0, Revision = 0, Build = 0; 424 LPWSTR pMinor = NULL, pRevision = NULL, pBuild = NULL; 425 LARGE_INTEGER fullVersion; 426 427 pMinor = strchrW(pVersion, '.'); 428 if (pMinor) 429 { 430 *pMinor = 0; 431 pRevision = strchrW(++pMinor, '.'); 432 Minor = atoiW(pMinor); 433 } 434 if (pRevision) 435 { 436 *pRevision = 0; 437 pBuild = strchrW(++pRevision, '.'); 438 Revision = atoiW(pRevision); 439 } 440 if (pBuild) 441 { 442 *pBuild = 0; 443 pBuild++; 444 Build = atoiW(pBuild); 445 } 446 Major = atoiW(pVersion); 447 fullVersion.u.HighPart = Major << 16 | Minor; 448 fullVersion.u.LowPart = Revision << 16 | Build; 449 memcpy(DriverVersion, &fullVersion, sizeof(LARGE_INTEGER)); 450 } 451 452 ret = TRUE; 453 454 cleanup: 455 if (!ret) 456 { 457 HeapFree(GetProcessHeap(), 0, ProviderName); 458 *pProviderName = NULL; 459 } 460 HeapFree(GetProcessHeap(), 0, DriverVer); 461 462 return ret; 463 } 464 465 static BOOL 466 GetHardwareAndCompatibleIDsLists( 467 IN HDEVINFO DeviceInfoSet, 468 IN OUT PSP_DEVINFO_DATA DeviceInfoData, 469 OUT LPWSTR *pHardwareIDs OPTIONAL, 470 OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL, 471 OUT LPWSTR *pCompatibleIDs OPTIONAL, 472 OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL) 473 { 474 LPWSTR HardwareIDs = NULL; 475 LPWSTR CompatibleIDs = NULL; 476 DWORD RequiredSize; 477 BOOL Result; 478 479 /* Get hardware IDs list */ 480 Result = FALSE; 481 RequiredSize = 512; /* Initial buffer size */ 482 SetLastError(ERROR_INSUFFICIENT_BUFFER); 483 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 484 { 485 MyFree(HardwareIDs); 486 HardwareIDs = MyMalloc(RequiredSize); 487 if (!HardwareIDs) 488 { 489 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 490 goto done; 491 } 492 Result = SetupDiGetDeviceRegistryPropertyW( 493 DeviceInfoSet, 494 DeviceInfoData, 495 SPDRP_HARDWAREID, 496 NULL, 497 (PBYTE)HardwareIDs, 498 RequiredSize, 499 &RequiredSize); 500 } 501 if (!Result) 502 { 503 if (GetLastError() == ERROR_FILE_NOT_FOUND) 504 { 505 /* No hardware ID for this device */ 506 MyFree(HardwareIDs); 507 HardwareIDs = NULL; 508 RequiredSize = 0; 509 } 510 else 511 goto done; 512 } 513 if (pHardwareIDs) 514 *pHardwareIDs = HardwareIDs; 515 if (pHardwareIDsRequiredSize) 516 *pHardwareIDsRequiredSize = RequiredSize; 517 518 /* Get compatible IDs list */ 519 Result = FALSE; 520 RequiredSize = 512; /* Initial buffer size */ 521 SetLastError(ERROR_INSUFFICIENT_BUFFER); 522 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 523 { 524 MyFree(CompatibleIDs); 525 CompatibleIDs = MyMalloc(RequiredSize); 526 if (!CompatibleIDs) 527 { 528 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 529 goto done; 530 } 531 Result = SetupDiGetDeviceRegistryPropertyW( 532 DeviceInfoSet, 533 DeviceInfoData, 534 SPDRP_COMPATIBLEIDS, 535 NULL, 536 (PBYTE)CompatibleIDs, 537 RequiredSize, 538 &RequiredSize); 539 } 540 if (!Result) 541 { 542 if (GetLastError() == ERROR_FILE_NOT_FOUND) 543 { 544 /* No compatible ID for this device */ 545 MyFree(CompatibleIDs); 546 CompatibleIDs = NULL; 547 RequiredSize = 0; 548 } 549 else 550 goto done; 551 } 552 if (pCompatibleIDs) 553 *pCompatibleIDs = CompatibleIDs; 554 if (pCompatibleIDsRequiredSize) 555 *pCompatibleIDsRequiredSize = RequiredSize; 556 557 Result = TRUE; 558 559 done: 560 if (!Result) 561 { 562 MyFree(HardwareIDs); 563 MyFree(CompatibleIDs); 564 } 565 return Result; 566 } 567 568 #if _WIN32_WINNT < 0x0600 569 /* WARNING: 570 * This code has been copied from advapi32/reg/reg.c, 571 * so this dll can be tested as is on Windows XP 572 */ 573 574 #define RRF_RT_REG_NONE (1 << 0) 575 #define RRF_RT_REG_SZ (1 << 1) 576 #define RRF_RT_REG_EXPAND_SZ (1 << 2) 577 #define RRF_RT_REG_BINARY (1 << 3) 578 #define RRF_RT_REG_DWORD (1 << 4) 579 #define RRF_RT_REG_MULTI_SZ (1 << 5) 580 #define RRF_RT_REG_QWORD (1 << 6) 581 #define RRF_RT_DWORD (RRF_RT_REG_BINARY | RRF_RT_REG_DWORD) 582 #define RRF_RT_QWORD (RRF_RT_REG_BINARY | RRF_RT_REG_QWORD) 583 #define RRF_NOEXPAND (1 << 28) 584 #define RRF_ZEROONFAILURE (1 << 29) 585 586 static VOID 587 RegpApplyRestrictions( DWORD dwFlags, DWORD dwType, DWORD cbData, 588 PLONG ret ) 589 { 590 /* Check if the type is restricted by the passed flags */ 591 if (*ret == ERROR_SUCCESS || *ret == ERROR_MORE_DATA) 592 { 593 DWORD dwMask = 0; 594 595 switch (dwType) 596 { 597 case REG_NONE: dwMask = RRF_RT_REG_NONE; break; 598 case REG_SZ: dwMask = RRF_RT_REG_SZ; break; 599 case REG_EXPAND_SZ: dwMask = RRF_RT_REG_EXPAND_SZ; break; 600 case REG_MULTI_SZ: dwMask = RRF_RT_REG_MULTI_SZ; break; 601 case REG_BINARY: dwMask = RRF_RT_REG_BINARY; break; 602 case REG_DWORD: dwMask = RRF_RT_REG_DWORD; break; 603 case REG_QWORD: dwMask = RRF_RT_REG_QWORD; break; 604 } 605 606 if (dwFlags & dwMask) 607 { 608 /* Type is not restricted, check for size mismatch */ 609 if (dwType == REG_BINARY) 610 { 611 DWORD cbExpect = 0; 612 613 if ((dwFlags & RRF_RT_DWORD) == RRF_RT_DWORD) 614 cbExpect = 4; 615 else if ((dwFlags & RRF_RT_QWORD) == RRF_RT_QWORD) 616 cbExpect = 8; 617 618 if (cbExpect && cbData != cbExpect) 619 *ret = ERROR_DATATYPE_MISMATCH; 620 } 621 } 622 else *ret = ERROR_UNSUPPORTED_TYPE; 623 } 624 } 625 626 static LONG WINAPI 627 RegGetValueW( HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue, 628 DWORD dwFlags, LPDWORD pdwType, PVOID pvData, 629 LPDWORD pcbData ) 630 { 631 DWORD dwType, cbData = pcbData ? *pcbData : 0; 632 PVOID pvBuf = NULL; 633 LONG ret; 634 635 TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n", 636 hKey, debugstr_w(pszSubKey), debugstr_w(pszValue), dwFlags, pdwType, 637 pvData, pcbData, cbData); 638 639 if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND)) 640 return ERROR_INVALID_PARAMETER; 641 642 if (pszSubKey && pszSubKey[0]) 643 { 644 ret = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey); 645 if (ret != ERROR_SUCCESS) return ret; 646 } 647 648 ret = RegQueryValueExW(hKey, pszValue, NULL, &dwType, pvData, &cbData); 649 650 /* If we are going to expand we need to read in the whole the value even 651 * if the passed buffer was too small as the expanded string might be 652 * smaller than the unexpanded one and could fit into cbData bytes. */ 653 if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && 654 (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND))) 655 { 656 do { 657 if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf); 658 659 pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData); 660 if (!pvBuf) 661 { 662 ret = ERROR_NOT_ENOUGH_MEMORY; 663 break; 664 } 665 666 if (ret == ERROR_MORE_DATA) 667 ret = RegQueryValueExW(hKey, pszValue, NULL, 668 &dwType, pvBuf, &cbData); 669 else 670 { 671 /* Even if cbData was large enough we have to copy the 672 * string since ExpandEnvironmentStrings can't handle 673 * overlapping buffers. */ 674 CopyMemory(pvBuf, pvData, cbData); 675 } 676 677 /* Both the type or the value itself could have been modified in 678 * between so we have to keep retrying until the buffer is large 679 * enough or we no longer have to expand the value. */ 680 } while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA); 681 682 if (ret == ERROR_SUCCESS) 683 { 684 if (dwType == REG_EXPAND_SZ) 685 { 686 cbData = ExpandEnvironmentStringsW(pvBuf, pvData, 687 pcbData ? (*pcbData)/sizeof(WCHAR) : 0); 688 dwType = REG_SZ; 689 if(pcbData && cbData > ((*pcbData)/sizeof(WCHAR))) 690 ret = ERROR_MORE_DATA; 691 } 692 else if (pcbData) 693 CopyMemory(pvData, pvBuf, *pcbData); 694 } 695 696 if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf); 697 } 698 699 if (pszSubKey && pszSubKey[0]) 700 RegCloseKey(hKey); 701 702 RegpApplyRestrictions(dwFlags, dwType, cbData, &ret); 703 704 if (pcbData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE)) 705 ZeroMemory(pvData, *pcbData); 706 707 if (pdwType) *pdwType = dwType; 708 if (pcbData) *pcbData = cbData; 709 710 return ret; 711 } 712 #endif /* End of code copied from advapi32/reg/reg.c */ 713 714 /*********************************************************************** 715 * SetupDiBuildDriverInfoList (SETUPAPI.@) 716 */ 717 BOOL WINAPI 718 SetupDiBuildDriverInfoList( 719 IN HDEVINFO DeviceInfoSet, 720 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 721 IN DWORD DriverType) 722 { 723 struct DeviceInfoSet *list; 724 SP_DEVINSTALL_PARAMS_W InstallParams; 725 PVOID Buffer = NULL; 726 struct InfFileDetails *currentInfFileDetails = NULL; 727 LPWSTR ProviderName = NULL; 728 LPWSTR ManufacturerName = NULL; 729 WCHAR ManufacturerSection[LINE_LEN + 1]; 730 LPWSTR HardwareIDs = NULL; 731 LPWSTR CompatibleIDs = NULL; 732 LPWSTR FullInfFileName = NULL; 733 LPWSTR ExcludeFromSelect = NULL; 734 FILETIME DriverDate; 735 DWORDLONG DriverVersion = 0; 736 DWORD RequiredSize; 737 BOOL ret = FALSE; 738 739 TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType); 740 741 if (!DeviceInfoSet) 742 SetLastError(ERROR_INVALID_HANDLE); 743 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 744 SetLastError(ERROR_INVALID_HANDLE); 745 else if (list->HKLM != HKEY_LOCAL_MACHINE) 746 SetLastError(ERROR_INVALID_HANDLE); 747 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER) 748 SetLastError(ERROR_INVALID_PARAMETER); 749 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData) 750 SetLastError(ERROR_INVALID_PARAMETER); 751 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 752 SetLastError(ERROR_INVALID_USER_BUFFER); 753 else 754 { 755 PLIST_ENTRY pDriverListHead = &list->DriverListHead; 756 BOOL Result; 757 758 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 759 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 760 if (!Result) 761 goto done; 762 763 if (DeviceInfoData) 764 { 765 struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 766 if (!(devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)) 767 pDriverListHead = &devInfo->DriverListHead; 768 } 769 770 if (DriverType == SPDIT_COMPATDRIVER) 771 { 772 /* Get hardware and compatible IDs lists */ 773 Result = GetHardwareAndCompatibleIDsLists( 774 DeviceInfoSet, 775 DeviceInfoData, 776 &HardwareIDs, 777 NULL, 778 &CompatibleIDs, 779 NULL); 780 if (!Result) 781 goto done; 782 if (!HardwareIDs && !CompatibleIDs) 783 { 784 SetLastError(ERROR_FILE_NOT_FOUND); 785 goto done; 786 } 787 } 788 789 if (InstallParams.FlagsEx & DI_FLAGSEX_INSTALLEDDRIVER) 790 { 791 HKEY hDriverKey; 792 WCHAR InfFileName[MAX_PATH]; 793 WCHAR InfFileSection[MAX_PATH]; 794 ULONG RequiredSize; 795 struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 796 struct InfFileDetails *infFileDetails = NULL; 797 FILETIME DriverDate; 798 LONG rc; 799 DWORD len; 800 801 /* Prepend inf directory name to file name */ 802 len = sizeof(InfFileName) / sizeof(InfFileName[0]); 803 RequiredSize = GetSystemWindowsDirectoryW(InfFileName, len); 804 if (RequiredSize == 0 || RequiredSize >= len) 805 goto done; 806 if (*InfFileName && InfFileName[strlenW(InfFileName) - 1] != '\\') 807 strcatW(InfFileName, BackSlash); 808 strcatW(InfFileName, InfDirectory); 809 810 /* Read some information from registry, before creating the driver structure */ 811 hDriverKey = SETUPDI_OpenDrvKey(((struct DeviceInfoSet *)DeviceInfoSet)->HKLM, devInfo, KEY_QUERY_VALUE); 812 if (hDriverKey == INVALID_HANDLE_VALUE) 813 goto done; 814 RequiredSize = (len - strlenW(InfFileName)) * sizeof(WCHAR); 815 rc = RegGetValueW( 816 hDriverKey, 817 NULL, 818 REGSTR_VAL_INFPATH, 819 RRF_RT_REG_SZ, 820 NULL, 821 &InfFileName[strlenW(InfFileName)], 822 &RequiredSize); 823 if (rc != ERROR_SUCCESS) 824 { 825 SetLastError(rc); 826 CloseHandle(hDriverKey); 827 goto done; 828 } 829 RequiredSize = sizeof(InfFileSection); 830 rc = RegGetValueW( 831 hDriverKey, 832 NULL, 833 REGSTR_VAL_INFSECTION, 834 RRF_RT_REG_SZ, 835 NULL, 836 InfFileSection, 837 &RequiredSize); 838 if (rc != ERROR_SUCCESS) 839 { 840 SetLastError(rc); 841 CloseHandle(hDriverKey); 842 goto done; 843 } 844 TRACE("Current driver in %s/%s\n", debugstr_w(InfFileName), debugstr_w(InfFileSection)); 845 infFileDetails = CreateInfFileDetails(InfFileName); 846 if (!infFileDetails) 847 { 848 CloseHandle(hDriverKey); 849 goto done; 850 } 851 DriverDate.dwLowDateTime = DriverDate.dwHighDateTime = 0; /* FIXME */ 852 CloseHandle(hDriverKey); 853 ret = AddKnownDriverToList( 854 pDriverListHead, 855 SPDIT_COMPATDRIVER, 856 &devInfo->ClassGuid, 857 infFileDetails, 858 InfFileName, 859 InfFileSection, /* Yes, we don't care of section extension */ 860 L"DriverDescription", /* FIXME */ 861 L"ProviderName", /* FIXME */ 862 L"ManufacturerName", /* FIXME */ 863 L"MatchingId", /* FIXME */ 864 DriverDate, 865 0, /* FIXME: DriverVersion */ 866 0); 867 if (!ret) 868 DereferenceInfFile(infFileDetails); 869 Result = FALSE; 870 } 871 else if (InstallParams.Flags & DI_ENUMSINGLEINF) 872 { 873 /* InstallParams.DriverPath contains the name of a .inf file */ 874 RequiredSize = strlenW(InstallParams.DriverPath) + 2; 875 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); 876 if (!Buffer) 877 { 878 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 879 goto done; 880 } 881 strcpyW(Buffer, InstallParams.DriverPath); 882 ((LPWSTR)Buffer)[RequiredSize - 1] = 0; 883 Result = TRUE; 884 } 885 else 886 { 887 /* Enumerate .inf files */ 888 Result = FALSE; 889 RequiredSize = 32768; /* Initial buffer size */ 890 SetLastError(ERROR_INSUFFICIENT_BUFFER); 891 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 892 { 893 HeapFree(GetProcessHeap(), 0, Buffer); 894 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); 895 if (!Buffer) 896 { 897 Result = FALSE; 898 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 899 break; 900 } 901 Result = SetupGetInfFileListW( 902 *InstallParams.DriverPath ? InstallParams.DriverPath : NULL, 903 INF_STYLE_WIN4, 904 Buffer, RequiredSize, 905 &RequiredSize); 906 } 907 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND) 908 { 909 /* No .inf file in specified directory. So, we should 910 * success as we created an empty driver info list. 911 */ 912 ret = TRUE; 913 goto done; 914 } 915 } 916 if (Result) 917 { 918 LPCWSTR filename; 919 LPWSTR pFullFilename; 920 921 if (InstallParams.Flags & DI_ENUMSINGLEINF) 922 { 923 /* Only a filename */ 924 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); 925 if (!FullInfFileName) 926 goto done; 927 pFullFilename = &FullInfFileName[0]; 928 } 929 else if (*InstallParams.DriverPath) 930 { 931 /* Directory name specified */ 932 DWORD len; 933 len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL); 934 if (len == 0) 935 goto done; 936 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, (len + 1 + MAX_PATH) * sizeof(WCHAR)); 937 if (!FullInfFileName) 938 goto done; 939 len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL); 940 if (len == 0) 941 goto done; 942 if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\') 943 strcatW(FullInfFileName, BackSlash); 944 pFullFilename = &FullInfFileName[strlenW(FullInfFileName)]; 945 } 946 else 947 { 948 /* Nothing specified ; need to get the %SYSTEMROOT%\ directory */ 949 DWORD len; 950 len = GetSystemWindowsDirectoryW(NULL, 0); 951 if (len == 0) 952 goto done; 953 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, (len + 1 + strlenW(InfDirectory) + MAX_PATH) * sizeof(WCHAR)); 954 if (!FullInfFileName) 955 goto done; 956 len = GetSystemWindowsDirectoryW(FullInfFileName, len); 957 if (len == 0) 958 goto done; 959 if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\') 960 strcatW(FullInfFileName, BackSlash); 961 strcatW(FullInfFileName, InfDirectory); 962 pFullFilename = &FullInfFileName[strlenW(FullInfFileName)]; 963 } 964 965 for (filename = (LPCWSTR)Buffer; *filename; filename += strlenW(filename) + 1) 966 { 967 INFCONTEXT ContextManufacturer, ContextDevice; 968 GUID ClassGuid; 969 970 strcpyW(pFullFilename, filename); 971 TRACE("Opening file %s\n", debugstr_w(FullInfFileName)); 972 973 currentInfFileDetails = CreateInfFileDetails(FullInfFileName); 974 if (!currentInfFileDetails) 975 continue; 976 977 if (!GetVersionInformationFromInfFile( 978 currentInfFileDetails->hInf, 979 &ClassGuid, 980 &ProviderName, 981 &DriverDate, 982 &DriverVersion)) 983 { 984 DereferenceInfFile(currentInfFileDetails); 985 currentInfFileDetails = NULL; 986 continue; 987 } 988 989 if (DriverType == SPDIT_CLASSDRIVER) 990 { 991 /* Check if the ClassGuid in this .inf file is corresponding with our needs */ 992 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid)) 993 { 994 goto next; 995 } 996 } 997 998 if (InstallParams.FlagsEx & DI_FLAGSEX_ALLOWEXCLUDEDDRVS) 999 { 1000 /* Read ExcludeFromSelect control flags */ 1001 /* FIXME */ 1002 } 1003 else 1004 FIXME("ExcludeFromSelect list ignored\n"); 1005 1006 /* Get the manufacturers list */ 1007 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, INF_MANUFACTURER, NULL, &ContextManufacturer); 1008 while (Result) 1009 { 1010 Result = SetupGetStringFieldW( 1011 &ContextManufacturer, 1012 0, /* Field index */ 1013 NULL, 0, 1014 &RequiredSize); 1015 if (Result) 1016 { 1017 /* We got the needed size for the buffer */ 1018 ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); 1019 if (!ManufacturerName) 1020 { 1021 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1022 goto done; 1023 } 1024 Result = SetupGetStringFieldW( 1025 &ContextManufacturer, 1026 0, /* Field index */ 1027 ManufacturerName, RequiredSize, 1028 &RequiredSize); 1029 } 1030 /* Get manufacturer section name */ 1031 Result = SetupGetStringFieldW( 1032 &ContextManufacturer, 1033 1, /* Field index */ 1034 ManufacturerSection, LINE_LEN, 1035 &RequiredSize); 1036 if (Result) 1037 { 1038 ManufacturerSection[RequiredSize] = 0; /* Final NULL char */ 1039 /* Add (possible) extension to manufacturer section name */ 1040 Result = SetupDiGetActualSectionToInstallW( 1041 currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL); 1042 if (Result) 1043 { 1044 TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection)); 1045 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice); 1046 } 1047 } 1048 while (Result) 1049 { 1050 if (DriverType == SPDIT_CLASSDRIVER) 1051 { 1052 /* FIXME: Check ExcludeFromSelect list */ 1053 if (!AddDriverToList( 1054 pDriverListHead, 1055 DriverType, 1056 &ClassGuid, 1057 ContextDevice, 1058 currentInfFileDetails, 1059 FullInfFileName, 1060 ProviderName, 1061 ManufacturerName, 1062 NULL, 1063 DriverDate, DriverVersion, 1064 0)) 1065 { 1066 break; 1067 } 1068 } 1069 else /* DriverType = SPDIT_COMPATDRIVER */ 1070 { 1071 /* 1. Get all fields */ 1072 DWORD FieldCount = SetupGetFieldCount(&ContextDevice); 1073 DWORD DriverRank; 1074 DWORD i; 1075 LPCWSTR currentId; 1076 BOOL DriverAlreadyAdded; 1077 1078 for (i = 2; i <= FieldCount; i++) 1079 { 1080 LPWSTR DeviceId = NULL; 1081 Result = FALSE; 1082 RequiredSize = 128; /* Initial buffer size */ 1083 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1084 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 1085 { 1086 HeapFree(GetProcessHeap(), 0, DeviceId); 1087 DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); 1088 if (!DeviceId) 1089 { 1090 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1091 goto done; 1092 } 1093 Result = SetupGetStringFieldW( 1094 &ContextDevice, 1095 i, 1096 DeviceId, RequiredSize, 1097 &RequiredSize); 1098 } 1099 if (!Result) 1100 { 1101 HeapFree(GetProcessHeap(), 0, DeviceId); 1102 goto done; 1103 } 1104 /* FIXME: Check ExcludeFromSelect list */ 1105 DriverAlreadyAdded = FALSE; 1106 if (HardwareIDs) 1107 { 1108 for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++) 1109 { 1110 if (strcmpiW(DeviceId, currentId) == 0) 1111 { 1112 AddDriverToList( 1113 pDriverListHead, 1114 DriverType, 1115 &ClassGuid, 1116 ContextDevice, 1117 currentInfFileDetails, 1118 FullInfFileName, 1119 ProviderName, 1120 ManufacturerName, 1121 currentId, 1122 DriverDate, DriverVersion, 1123 DriverRank + (i == 2 ? 0 : 0x1000 + i - 3)); 1124 DriverAlreadyAdded = TRUE; 1125 } 1126 } 1127 } 1128 if (CompatibleIDs) 1129 { 1130 for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++) 1131 { 1132 if (strcmpiW(DeviceId, currentId) == 0) 1133 { 1134 AddDriverToList( 1135 pDriverListHead, 1136 DriverType, 1137 &ClassGuid, 1138 ContextDevice, 1139 currentInfFileDetails, 1140 FullInfFileName, 1141 ProviderName, 1142 ManufacturerName, 1143 currentId, 1144 DriverDate, DriverVersion, 1145 DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3)); 1146 DriverAlreadyAdded = TRUE; 1147 } 1148 } 1149 } 1150 HeapFree(GetProcessHeap(), 0, DeviceId); 1151 } 1152 } 1153 Result = SetupFindNextLine(&ContextDevice, &ContextDevice); 1154 } 1155 1156 HeapFree(GetProcessHeap(), 0, ManufacturerName); 1157 ManufacturerName = NULL; 1158 Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer); 1159 } 1160 1161 ret = TRUE; 1162 next: 1163 HeapFree(GetProcessHeap(), 0, ProviderName); 1164 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect); 1165 ProviderName = ExcludeFromSelect = NULL; 1166 1167 DereferenceInfFile(currentInfFileDetails); 1168 currentInfFileDetails = NULL; 1169 } 1170 ret = TRUE; 1171 } 1172 } 1173 1174 done: 1175 if (ret) 1176 { 1177 if (DeviceInfoData) 1178 { 1179 InstallParams.Flags |= DI_DIDCOMPAT; 1180 InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO; 1181 } 1182 else 1183 { 1184 InstallParams.Flags |= DI_DIDCLASS; 1185 InstallParams.FlagsEx |= DI_FLAGSEX_DIDINFOLIST; 1186 } 1187 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 1188 } 1189 1190 HeapFree(GetProcessHeap(), 0, ProviderName); 1191 HeapFree(GetProcessHeap(), 0, ManufacturerName); 1192 MyFree(HardwareIDs); 1193 MyFree(CompatibleIDs); 1194 HeapFree(GetProcessHeap(), 0, FullInfFileName); 1195 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect); 1196 if (currentInfFileDetails) 1197 DereferenceInfFile(currentInfFileDetails); 1198 HeapFree(GetProcessHeap(), 0, Buffer); 1199 1200 TRACE("Returning %d\n", ret); 1201 return ret; 1202 } 1203 1204 /*********************************************************************** 1205 * SetupDiDestroyDriverInfoList (SETUPAPI.@) 1206 */ 1207 BOOL WINAPI 1208 SetupDiDestroyDriverInfoList( 1209 IN HDEVINFO DeviceInfoSet, 1210 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 1211 IN DWORD DriverType) 1212 { 1213 struct DeviceInfoSet *list; 1214 BOOL ret = FALSE; 1215 1216 TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType); 1217 1218 if (!DeviceInfoSet) 1219 SetLastError(ERROR_INVALID_HANDLE); 1220 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1221 SetLastError(ERROR_INVALID_HANDLE); 1222 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER) 1223 SetLastError(ERROR_INVALID_PARAMETER); 1224 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData) 1225 SetLastError(ERROR_INVALID_PARAMETER); 1226 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 1227 SetLastError(ERROR_INVALID_USER_BUFFER); 1228 else 1229 { 1230 PLIST_ENTRY ListEntry; 1231 struct DriverInfoElement *driverInfo; 1232 SP_DEVINSTALL_PARAMS_W InstallParams; 1233 1234 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 1235 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams)) 1236 goto done; 1237 1238 if (!DeviceInfoData) 1239 /* Fall back to destroying class driver list */ 1240 DriverType = SPDIT_CLASSDRIVER; 1241 1242 if (DriverType == SPDIT_CLASSDRIVER) 1243 { 1244 while (!IsListEmpty(&list->DriverListHead)) 1245 { 1246 ListEntry = RemoveHeadList(&list->DriverListHead); 1247 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry); 1248 DestroyDriverInfoElement(driverInfo); 1249 } 1250 InstallParams.ClassInstallReserved = 0; 1251 InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS); 1252 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDINFOLIST; 1253 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParams); 1254 } 1255 else 1256 { 1257 SP_DEVINSTALL_PARAMS_W InstallParamsSet; 1258 struct DeviceInfo *deviceInfo; 1259 1260 InstallParamsSet.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 1261 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet)) 1262 goto done; 1263 deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 1264 while (!IsListEmpty(&deviceInfo->DriverListHead)) 1265 { 1266 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead); 1267 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry); 1268 if ((PVOID)InstallParamsSet.ClassInstallReserved == driverInfo) 1269 { 1270 InstallParamsSet.ClassInstallReserved = 0; 1271 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet); 1272 } 1273 DestroyDriverInfoElement(driverInfo); 1274 } 1275 InstallParams.ClassInstallReserved = 0; 1276 InstallParams.Flags &= ~DI_DIDCOMPAT; 1277 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDCOMPATINFO; 1278 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 1279 } 1280 } 1281 1282 done: 1283 TRACE("Returning %d\n", ret); 1284 return ret; 1285 } 1286 1287 /*********************************************************************** 1288 * SetupDiEnumDriverInfoA (SETUPAPI.@) 1289 */ 1290 BOOL WINAPI 1291 SetupDiEnumDriverInfoA( 1292 IN HDEVINFO DeviceInfoSet, 1293 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 1294 IN DWORD DriverType, 1295 IN DWORD MemberIndex, 1296 OUT PSP_DRVINFO_DATA_A DriverInfoData) 1297 { 1298 SP_DRVINFO_DATA_V2_W driverInfoData2W; 1299 BOOL ret = FALSE; 1300 1301 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData, 1302 DriverType, MemberIndex, DriverInfoData); 1303 1304 if (DriverInfoData == NULL) 1305 SetLastError(ERROR_INVALID_PARAMETER); 1306 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A)) 1307 SetLastError(ERROR_INVALID_USER_BUFFER); 1308 else 1309 { 1310 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W); 1311 ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData, 1312 DriverType, MemberIndex, &driverInfoData2W); 1313 1314 if (ret) 1315 { 1316 /* Do W->A conversion */ 1317 DriverInfoData->DriverType = driverInfoData2W.DriverType; 1318 DriverInfoData->Reserved = driverInfoData2W.Reserved; 1319 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1, 1320 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0) 1321 { 1322 DriverInfoData->Description[0] = '\0'; 1323 ret = FALSE; 1324 } 1325 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1, 1326 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0) 1327 { 1328 DriverInfoData->MfgName[0] = '\0'; 1329 ret = FALSE; 1330 } 1331 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1, 1332 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0) 1333 { 1334 DriverInfoData->ProviderName[0] = '\0'; 1335 ret = FALSE; 1336 } 1337 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A)) 1338 { 1339 /* Copy more fields */ 1340 DriverInfoData->DriverDate = driverInfoData2W.DriverDate; 1341 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion; 1342 } 1343 } 1344 } 1345 1346 TRACE("Returning %d\n", ret); 1347 return ret; 1348 } 1349 1350 1351 /*********************************************************************** 1352 * SetupDiEnumDriverInfoW (SETUPAPI.@) 1353 */ 1354 BOOL WINAPI 1355 SetupDiEnumDriverInfoW( 1356 IN HDEVINFO DeviceInfoSet, 1357 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 1358 IN DWORD DriverType, 1359 IN DWORD MemberIndex, 1360 OUT PSP_DRVINFO_DATA_W DriverInfoData) 1361 { 1362 PLIST_ENTRY ListHead; 1363 BOOL ret = FALSE; 1364 1365 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData, 1366 DriverType, MemberIndex, DriverInfoData); 1367 1368 if (!DeviceInfoSet || !DriverInfoData) 1369 SetLastError(ERROR_INVALID_PARAMETER); 1370 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 1371 SetLastError(ERROR_INVALID_HANDLE); 1372 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1373 SetLastError(ERROR_INVALID_HANDLE); 1374 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER) 1375 SetLastError(ERROR_INVALID_PARAMETER); 1376 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData) 1377 SetLastError(ERROR_INVALID_PARAMETER); 1378 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W)) 1379 SetLastError(ERROR_INVALID_USER_BUFFER); 1380 else 1381 { 1382 struct DeviceInfo *devInfo = NULL; 1383 PLIST_ENTRY ItemList; 1384 if (DeviceInfoData) 1385 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 1386 if (!devInfo || (devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)) 1387 { 1388 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead; 1389 } 1390 else 1391 { 1392 ListHead = &devInfo->DriverListHead; 1393 } 1394 1395 ItemList = ListHead->Flink; 1396 while (ItemList != ListHead && MemberIndex-- > 0) 1397 ItemList = ItemList->Flink; 1398 if (ItemList == ListHead) 1399 SetLastError(ERROR_NO_MORE_ITEMS); 1400 else 1401 { 1402 struct DriverInfoElement *DrvInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry); 1403 1404 memcpy( 1405 &DriverInfoData->DriverType, 1406 &DrvInfo->Info.DriverType, 1407 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType)); 1408 ret = TRUE; 1409 } 1410 } 1411 1412 TRACE("Returning %d\n", ret); 1413 return ret; 1414 } 1415 1416 /*********************************************************************** 1417 * SetupDiGetSelectedDriverA (SETUPAPI.@) 1418 */ 1419 BOOL WINAPI 1420 SetupDiGetSelectedDriverA( 1421 IN HDEVINFO DeviceInfoSet, 1422 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 1423 OUT PSP_DRVINFO_DATA_A DriverInfoData) 1424 { 1425 SP_DRVINFO_DATA_V2_W driverInfoData2W; 1426 BOOL ret = FALSE; 1427 1428 if (DriverInfoData == NULL) 1429 SetLastError(ERROR_INVALID_PARAMETER); 1430 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A)) 1431 SetLastError(ERROR_INVALID_USER_BUFFER); 1432 else 1433 { 1434 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W); 1435 1436 ret = SetupDiGetSelectedDriverW(DeviceInfoSet, 1437 DeviceInfoData, 1438 &driverInfoData2W); 1439 1440 if (ret) 1441 { 1442 /* Do W->A conversion */ 1443 DriverInfoData->DriverType = driverInfoData2W.DriverType; 1444 DriverInfoData->Reserved = driverInfoData2W.Reserved; 1445 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1, 1446 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0) 1447 { 1448 DriverInfoData->Description[0] = '\0'; 1449 ret = FALSE; 1450 } 1451 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1, 1452 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0) 1453 { 1454 DriverInfoData->MfgName[0] = '\0'; 1455 ret = FALSE; 1456 } 1457 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1, 1458 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0) 1459 { 1460 DriverInfoData->ProviderName[0] = '\0'; 1461 ret = FALSE; 1462 } 1463 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A)) 1464 { 1465 /* Copy more fields */ 1466 DriverInfoData->DriverDate = driverInfoData2W.DriverDate; 1467 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion; 1468 } 1469 } 1470 } 1471 1472 return ret; 1473 } 1474 1475 /*********************************************************************** 1476 * SetupDiGetSelectedDriverW (SETUPAPI.@) 1477 */ 1478 BOOL WINAPI 1479 SetupDiGetSelectedDriverW( 1480 IN HDEVINFO DeviceInfoSet, 1481 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 1482 OUT PSP_DRVINFO_DATA_W DriverInfoData) 1483 { 1484 BOOL ret = FALSE; 1485 1486 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData); 1487 1488 if (!DeviceInfoSet || !DriverInfoData) 1489 SetLastError(ERROR_INVALID_PARAMETER); 1490 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 1491 SetLastError(ERROR_INVALID_HANDLE); 1492 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1493 SetLastError(ERROR_INVALID_HANDLE); 1494 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 1495 SetLastError(ERROR_INVALID_USER_BUFFER); 1496 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W)) 1497 SetLastError(ERROR_INVALID_USER_BUFFER); 1498 else 1499 { 1500 SP_DEVINSTALL_PARAMS InstallParams; 1501 1502 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 1503 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams)) 1504 { 1505 struct DriverInfoElement *driverInfo; 1506 driverInfo = (struct DriverInfoElement *)InstallParams.ClassInstallReserved; 1507 if (driverInfo == NULL) 1508 SetLastError(ERROR_NO_DRIVER_SELECTED); 1509 else 1510 { 1511 memcpy( 1512 &DriverInfoData->DriverType, 1513 &driverInfo->Info.DriverType, 1514 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType)); 1515 ret = TRUE; 1516 } 1517 } 1518 } 1519 1520 TRACE("Returning %d\n", ret); 1521 return ret; 1522 } 1523 1524 /*********************************************************************** 1525 * SetupDiSetSelectedDriverA (SETUPAPI.@) 1526 */ 1527 BOOL WINAPI 1528 SetupDiSetSelectedDriverA( 1529 IN HDEVINFO DeviceInfoSet, 1530 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 1531 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL) 1532 { 1533 SP_DRVINFO_DATA_V1_W DriverInfoDataW; 1534 PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL; 1535 BOOL ret = FALSE; 1536 1537 if (DriverInfoData != NULL) 1538 { 1539 if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) && 1540 DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A)) 1541 { 1542 SetLastError(ERROR_INVALID_PARAMETER); 1543 return FALSE; 1544 } 1545 1546 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W); 1547 DriverInfoDataW.Reserved = DriverInfoData->Reserved; 1548 1549 if (DriverInfoDataW.Reserved == 0) 1550 { 1551 DriverInfoDataW.DriverType = DriverInfoData->DriverType; 1552 1553 /* convert the strings to unicode */ 1554 if (!MultiByteToWideChar(CP_ACP, 1555 0, 1556 DriverInfoData->Description, 1557 LINE_LEN, 1558 DriverInfoDataW.Description, 1559 LINE_LEN) || 1560 !MultiByteToWideChar(CP_ACP, 1561 0, 1562 DriverInfoData->ProviderName, 1563 LINE_LEN, 1564 DriverInfoDataW.ProviderName, 1565 LINE_LEN)) 1566 { 1567 return FALSE; 1568 } 1569 } 1570 1571 pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW; 1572 } 1573 1574 ret = SetupDiSetSelectedDriverW(DeviceInfoSet, 1575 DeviceInfoData, 1576 pDriverInfoDataW); 1577 1578 if (ret && pDriverInfoDataW != NULL) 1579 { 1580 DriverInfoData->Reserved = DriverInfoDataW.Reserved; 1581 } 1582 1583 return ret; 1584 } 1585 1586 /*********************************************************************** 1587 * SetupDiSetSelectedDriverW (SETUPAPI.@) 1588 */ 1589 BOOL WINAPI 1590 SetupDiSetSelectedDriverW( 1591 IN HDEVINFO DeviceInfoSet, 1592 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 1593 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL) 1594 { 1595 BOOL ret = FALSE; 1596 1597 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData); 1598 1599 if (!DeviceInfoSet) 1600 SetLastError(ERROR_INVALID_PARAMETER); 1601 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 1602 SetLastError(ERROR_INVALID_HANDLE); 1603 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1604 SetLastError(ERROR_INVALID_HANDLE); 1605 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 1606 SetLastError(ERROR_INVALID_USER_BUFFER); 1607 else if (DriverInfoData && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W)) 1608 SetLastError(ERROR_INVALID_USER_BUFFER); 1609 else 1610 { 1611 struct DriverInfoElement **pDriverInfo; 1612 PLIST_ENTRY ListHead, ItemList; 1613 1614 if (DeviceInfoData) 1615 { 1616 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams.ClassInstallReserved; 1617 ListHead = &((struct DeviceInfo *)DeviceInfoData->Reserved)->DriverListHead; 1618 } 1619 else 1620 { 1621 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.ClassInstallReserved; 1622 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead; 1623 } 1624 1625 if (!DriverInfoData) 1626 { 1627 *pDriverInfo = NULL; 1628 ret = TRUE; 1629 } 1630 else 1631 { 1632 /* Search selected driver in list */ 1633 ItemList = ListHead->Flink; 1634 while (ItemList != ListHead) 1635 { 1636 if (DriverInfoData->Reserved != 0) 1637 { 1638 if (DriverInfoData->Reserved == (ULONG_PTR)ItemList) 1639 break; 1640 } 1641 else 1642 { 1643 /* The caller wants to compare only DriverType, Description and ProviderName fields */ 1644 struct DriverInfoElement *driverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry); 1645 if (driverInfo->Info.DriverType == DriverInfoData->DriverType 1646 && strcmpW(driverInfo->Info.Description, DriverInfoData->Description) == 0 1647 && strcmpW(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0) 1648 { 1649 break; 1650 } 1651 } 1652 ItemList = ItemList->Flink; 1653 } 1654 if (ItemList == ListHead) 1655 SetLastError(ERROR_INVALID_PARAMETER); 1656 else 1657 { 1658 *pDriverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry); 1659 DriverInfoData->Reserved = (ULONG_PTR)ItemList; 1660 ret = TRUE; 1661 TRACE("Choosing driver whose rank is 0x%lx\n", 1662 (*pDriverInfo)->Params.Rank); 1663 if (DeviceInfoData) 1664 memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID)); 1665 } 1666 } 1667 } 1668 1669 TRACE("Returning %d\n", ret); 1670 return ret; 1671 } 1672 1673 /*********************************************************************** 1674 * SetupDiGetDriverInfoDetailA (SETUPAPI.@) 1675 */ 1676 BOOL WINAPI 1677 SetupDiGetDriverInfoDetailA( 1678 IN HDEVINFO DeviceInfoSet, 1679 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 1680 IN PSP_DRVINFO_DATA_A DriverInfoData, 1681 IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL, 1682 IN DWORD DriverInfoDetailDataSize, 1683 OUT PDWORD RequiredSize OPTIONAL) 1684 { 1685 SP_DRVINFO_DATA_V2_W DriverInfoDataW; 1686 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW = NULL; 1687 DWORD BufSize = 0; 1688 DWORD HardwareIDLen = 0; 1689 BOOL ret = FALSE; 1690 1691 /* do some sanity checks, the unicode version might do more thorough checks */ 1692 if (DriverInfoData == NULL || 1693 (DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) || 1694 (DriverInfoDetailData != NULL && 1695 (DriverInfoDetailDataSize < FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + sizeof(CHAR) || 1696 DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_A)))) 1697 { 1698 SetLastError(ERROR_INVALID_PARAMETER); 1699 goto Cleanup; 1700 } 1701 1702 /* make sure we support both versions of the SP_DRVINFO_DATA structure */ 1703 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V1_A)) 1704 { 1705 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W); 1706 } 1707 else if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A)) 1708 { 1709 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V2_W); 1710 } 1711 else 1712 { 1713 SetLastError(ERROR_INVALID_PARAMETER); 1714 goto Cleanup; 1715 } 1716 DriverInfoDataW.DriverType = DriverInfoData->DriverType; 1717 DriverInfoDataW.Reserved = DriverInfoData->Reserved; 1718 1719 /* convert the strings to unicode */ 1720 if (MultiByteToWideChar(CP_ACP, 1721 0, 1722 DriverInfoData->Description, 1723 LINE_LEN, 1724 DriverInfoDataW.Description, 1725 LINE_LEN) && 1726 MultiByteToWideChar(CP_ACP, 1727 0, 1728 DriverInfoData->MfgName, 1729 LINE_LEN, 1730 DriverInfoDataW.MfgName, 1731 LINE_LEN) && 1732 MultiByteToWideChar(CP_ACP, 1733 0, 1734 DriverInfoData->ProviderName, 1735 LINE_LEN, 1736 DriverInfoDataW.ProviderName, 1737 LINE_LEN)) 1738 { 1739 if (DriverInfoDataW.cbSize == sizeof(SP_DRVINFO_DATA_V2_W)) 1740 { 1741 DriverInfoDataW.DriverDate = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverDate; 1742 DriverInfoDataW.DriverVersion = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverVersion; 1743 } 1744 1745 if (DriverInfoDetailData != NULL) 1746 { 1747 /* calculate the unicode buffer size from the ansi buffer size */ 1748 HardwareIDLen = DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID); 1749 BufSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) + 1750 (HardwareIDLen * sizeof(WCHAR)); 1751 1752 DriverInfoDetailDataW = MyMalloc(BufSize); 1753 if (DriverInfoDetailDataW == NULL) 1754 { 1755 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1756 goto Cleanup; 1757 } 1758 1759 /* initialize the buffer */ 1760 ZeroMemory(DriverInfoDetailDataW, 1761 BufSize); 1762 DriverInfoDetailDataW->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W); 1763 } 1764 1765 /* call the unicode version */ 1766 ret = SetupDiGetDriverInfoDetailW(DeviceInfoSet, 1767 DeviceInfoData, 1768 &DriverInfoDataW, 1769 DriverInfoDetailDataW, 1770 BufSize, 1771 RequiredSize); 1772 1773 if (ret) 1774 { 1775 if (DriverInfoDetailDataW != NULL) 1776 { 1777 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */ 1778 DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A); 1779 DriverInfoDetailData->InfDate = DriverInfoDetailDataW->InfDate; 1780 DriverInfoDetailData->Reserved = DriverInfoDetailDataW->Reserved; 1781 if (WideCharToMultiByte(CP_ACP, 1782 0, 1783 DriverInfoDetailDataW->SectionName, 1784 LINE_LEN, 1785 DriverInfoDetailData->SectionName, 1786 LINE_LEN, 1787 NULL, 1788 NULL) && 1789 WideCharToMultiByte(CP_ACP, 1790 0, 1791 DriverInfoDetailDataW->InfFileName, 1792 MAX_PATH, 1793 DriverInfoDetailData->InfFileName, 1794 MAX_PATH, 1795 NULL, 1796 NULL) && 1797 WideCharToMultiByte(CP_ACP, 1798 0, 1799 DriverInfoDetailDataW->DrvDescription, 1800 LINE_LEN, 1801 DriverInfoDetailData->DrvDescription, 1802 LINE_LEN, 1803 NULL, 1804 NULL) && 1805 WideCharToMultiByte(CP_ACP, 1806 0, 1807 DriverInfoDetailDataW->HardwareID, 1808 HardwareIDLen, 1809 DriverInfoDetailData->HardwareID, 1810 HardwareIDLen, 1811 NULL, 1812 NULL)) 1813 { 1814 DWORD len, cnt = 0; 1815 DWORD hwidlen = HardwareIDLen; 1816 CHAR *s = DriverInfoDetailData->HardwareID; 1817 1818 /* count the strings in the list */ 1819 while (*s != '\0') 1820 { 1821 len = lstrlenA(s) + 1; 1822 if (hwidlen > len) 1823 { 1824 cnt++; 1825 s += len; 1826 hwidlen -= len; 1827 } 1828 else 1829 { 1830 /* looks like the string list wasn't terminated... */ 1831 SetLastError(ERROR_INVALID_USER_BUFFER); 1832 ret = FALSE; 1833 break; 1834 } 1835 } 1836 1837 /* make sure CompatIDsOffset points to the second string in the 1838 list, if present */ 1839 if (cnt > 1) 1840 { 1841 DriverInfoDetailData->CompatIDsOffset = lstrlenA(DriverInfoDetailData->HardwareID) + 1; 1842 DriverInfoDetailData->CompatIDsLength = (DWORD)(s - DriverInfoDetailData->HardwareID) - 1843 DriverInfoDetailData->CompatIDsOffset + 1; 1844 } 1845 else 1846 { 1847 DriverInfoDetailData->CompatIDsOffset = 0; 1848 DriverInfoDetailData->CompatIDsLength = 0; 1849 } 1850 } 1851 else 1852 { 1853 ret = FALSE; 1854 } 1855 } 1856 1857 if (RequiredSize != NULL) 1858 { 1859 *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + 1860 (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR)); 1861 } 1862 } 1863 } 1864 1865 Cleanup: 1866 if (DriverInfoDetailDataW != NULL) 1867 { 1868 MyFree(DriverInfoDetailDataW); 1869 } 1870 1871 return ret; 1872 } 1873 1874 /*********************************************************************** 1875 * SetupDiGetDriverInfoDetailW (SETUPAPI.@) 1876 */ 1877 BOOL WINAPI 1878 SetupDiGetDriverInfoDetailW( 1879 IN HDEVINFO DeviceInfoSet, 1880 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 1881 IN PSP_DRVINFO_DATA_W DriverInfoData, 1882 IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL, 1883 IN DWORD DriverInfoDetailDataSize, 1884 OUT PDWORD RequiredSize OPTIONAL) 1885 { 1886 BOOL ret = FALSE; 1887 1888 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData, 1889 DriverInfoData, DriverInfoDetailData, 1890 DriverInfoDetailDataSize, RequiredSize); 1891 1892 if (!DeviceInfoSet) 1893 SetLastError(ERROR_INVALID_PARAMETER); 1894 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 1895 SetLastError(ERROR_INVALID_HANDLE); 1896 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1897 SetLastError(ERROR_INVALID_HANDLE); 1898 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 1899 SetLastError(ERROR_INVALID_USER_BUFFER); 1900 else if (!DriverInfoData) 1901 SetLastError(ERROR_INVALID_PARAMETER); 1902 else if (!DriverInfoDetailData && DriverInfoDetailDataSize != 0) 1903 SetLastError(ERROR_INVALID_PARAMETER); 1904 else if (DriverInfoDetailData && DriverInfoDetailDataSize < sizeof(SP_DRVINFO_DETAIL_DATA_W)) 1905 SetLastError(ERROR_INVALID_PARAMETER); 1906 else if (DriverInfoDetailData && DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_W)) 1907 SetLastError(ERROR_INVALID_USER_BUFFER); 1908 else if (DriverInfoData->Reserved == 0) 1909 SetLastError(ERROR_NO_DRIVER_SELECTED); 1910 else 1911 { 1912 struct DriverInfoElement *driverInfoElement; 1913 LPWSTR HardwareIDs = NULL; 1914 LPWSTR CompatibleIDs = NULL; 1915 LPWSTR pBuffer = NULL; 1916 LPCWSTR DeviceID = NULL; 1917 ULONG HardwareIDsSize, CompatibleIDsSize; 1918 ULONG sizeNeeded, sizeLeft, size; 1919 BOOL Result; 1920 1921 driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved; 1922 1923 /* Get hardware and compatible IDs lists */ 1924 Result = GetHardwareAndCompatibleIDsLists( 1925 DeviceInfoSet, 1926 DeviceInfoData, 1927 &HardwareIDs, &HardwareIDsSize, 1928 &CompatibleIDs, &CompatibleIDsSize); 1929 if (!Result) 1930 goto done; 1931 1932 sizeNeeded = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) 1933 + HardwareIDsSize + CompatibleIDsSize; 1934 if (RequiredSize) 1935 *RequiredSize = sizeNeeded; 1936 1937 if (!DriverInfoDetailData) 1938 { 1939 ret = TRUE; 1940 goto done; 1941 } 1942 1943 memcpy( 1944 DriverInfoDetailData, 1945 &driverInfoElement->Details, 1946 driverInfoElement->Details.cbSize); 1947 DriverInfoDetailData->CompatIDsOffset = 0; 1948 DriverInfoDetailData->CompatIDsLength = 0; 1949 1950 sizeLeft = (DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR); 1951 pBuffer = DriverInfoDetailData->HardwareID; 1952 /* Add as many as possible HardwareIDs in the list */ 1953 DeviceID = HardwareIDs; 1954 while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft) 1955 { 1956 TRACE("Adding %s to list\n", debugstr_w(DeviceID)); 1957 wcscpy(pBuffer, DeviceID); 1958 DeviceID += size + 1; 1959 pBuffer += size + 1; 1960 sizeLeft -= size + 1; 1961 DriverInfoDetailData->CompatIDsOffset += size + 1; 1962 } 1963 if (sizeLeft > 0) 1964 { 1965 *pBuffer = UNICODE_NULL; 1966 sizeLeft--; 1967 DriverInfoDetailData->CompatIDsOffset++; 1968 } 1969 /* Add as many as possible CompatibleIDs in the list */ 1970 DeviceID = CompatibleIDs; 1971 while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft) 1972 { 1973 TRACE("Adding %s to list\n", debugstr_w(DeviceID)); 1974 wcscpy(pBuffer, DeviceID); 1975 DeviceID += size + 1; 1976 pBuffer += size + 1; 1977 sizeLeft -= size + 1; 1978 DriverInfoDetailData->CompatIDsLength += size + 1; 1979 } 1980 if (sizeLeft > 0) 1981 { 1982 *pBuffer = UNICODE_NULL; 1983 sizeLeft--; 1984 DriverInfoDetailData->CompatIDsLength++; 1985 } 1986 1987 if (sizeNeeded > DriverInfoDetailDataSize) 1988 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1989 else 1990 ret = TRUE; 1991 1992 done: 1993 MyFree(HardwareIDs); 1994 MyFree(CompatibleIDs); 1995 } 1996 1997 TRACE("Returning %d\n", ret); 1998 return ret; 1999 } 2000 2001 /*********************************************************************** 2002 * SetupDiGetDriverInstallParamsW (SETUPAPI.@) 2003 */ 2004 BOOL WINAPI 2005 SetupDiGetDriverInstallParamsW( 2006 IN HDEVINFO DeviceInfoSet, 2007 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 2008 IN PSP_DRVINFO_DATA_W DriverInfoData, 2009 OUT PSP_DRVINSTALL_PARAMS DriverInstallParams) 2010 { 2011 BOOL ret = FALSE; 2012 2013 TRACE("%p %p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData, DriverInstallParams); 2014 2015 if (!DeviceInfoSet || !DriverInfoData || !DriverInstallParams) 2016 SetLastError(ERROR_INVALID_PARAMETER); 2017 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 2018 SetLastError(ERROR_INVALID_HANDLE); 2019 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2020 SetLastError(ERROR_INVALID_HANDLE); 2021 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 2022 SetLastError(ERROR_INVALID_USER_BUFFER); 2023 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W)) 2024 SetLastError(ERROR_INVALID_USER_BUFFER); 2025 else if (DriverInstallParams->cbSize != sizeof(SP_DRVINSTALL_PARAMS)) 2026 SetLastError(ERROR_INVALID_USER_BUFFER); 2027 else 2028 { 2029 SP_DEVINSTALL_PARAMS InstallParams; 2030 2031 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 2032 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams)) 2033 { 2034 struct DriverInfoElement *driverInfo; 2035 driverInfo = (struct DriverInfoElement *)InstallParams.ClassInstallReserved; 2036 if (driverInfo == NULL) 2037 SetLastError(ERROR_NO_DRIVER_SELECTED); 2038 else 2039 { 2040 memcpy( 2041 DriverInstallParams, 2042 &driverInfo->Params, 2043 DriverInstallParams->cbSize); 2044 ret = TRUE; 2045 } 2046 } 2047 } 2048 2049 TRACE("Returning %d\n", ret); 2050 return ret; 2051 } 2052 2053 /*********************************************************************** 2054 * SetupDiSelectBestCompatDrv (SETUPAPI.@) 2055 */ 2056 BOOL WINAPI 2057 SetupDiSelectBestCompatDrv( 2058 IN HDEVINFO DeviceInfoSet, 2059 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 2060 { 2061 SP_DRVINFO_DATA_W drvInfoData; 2062 BOOL ret; 2063 2064 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 2065 2066 /* Drivers are sorted by rank in the driver list, so 2067 * the first driver in the list is the best one. 2068 */ 2069 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W); 2070 ret = SetupDiEnumDriverInfoW( 2071 DeviceInfoSet, 2072 DeviceInfoData, 2073 SPDIT_COMPATDRIVER, 2074 0, /* Member index */ 2075 &drvInfoData); 2076 2077 if (ret) 2078 { 2079 ret = SetupDiSetSelectedDriverW( 2080 DeviceInfoSet, 2081 DeviceInfoData, 2082 &drvInfoData); 2083 } 2084 2085 TRACE("Returning %d\n", ret); 2086 return ret; 2087 } 2088 2089 /*********************************************************************** 2090 * SetupDiInstallDriverFiles (SETUPAPI.@) 2091 */ 2092 BOOL WINAPI 2093 SetupDiInstallDriverFiles( 2094 IN HDEVINFO DeviceInfoSet, 2095 IN PSP_DEVINFO_DATA DeviceInfoData) 2096 { 2097 BOOL ret = FALSE; 2098 2099 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 2100 2101 if (!DeviceInfoSet) 2102 SetLastError(ERROR_INVALID_PARAMETER); 2103 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 2104 SetLastError(ERROR_INVALID_HANDLE); 2105 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2106 SetLastError(ERROR_INVALID_HANDLE); 2107 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 2108 SetLastError(ERROR_INVALID_USER_BUFFER); 2109 else if (DeviceInfoData && ((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams.ClassInstallReserved == 0) 2110 SetLastError(ERROR_NO_DRIVER_SELECTED); 2111 else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.ClassInstallReserved == 0) 2112 SetLastError(ERROR_NO_DRIVER_SELECTED); 2113 else 2114 { 2115 SP_DEVINSTALL_PARAMS_W InstallParams; 2116 struct DriverInfoElement *SelectedDriver; 2117 WCHAR SectionName[MAX_PATH]; 2118 DWORD SectionNameLength = 0; 2119 PVOID InstallMsgHandler; 2120 PVOID InstallMsgHandlerContext; 2121 PVOID Context = NULL; 2122 2123 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 2124 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 2125 if (!ret) 2126 goto done; 2127 2128 SelectedDriver = (struct DriverInfoElement *)InstallParams.ClassInstallReserved; 2129 if (!SelectedDriver) 2130 { 2131 SetLastError(ERROR_NO_DRIVER_SELECTED); 2132 goto done; 2133 } 2134 2135 ret = SetupDiGetActualSectionToInstallW( 2136 SelectedDriver->InfFileDetails->hInf, 2137 SelectedDriver->Details.SectionName, 2138 SectionName, MAX_PATH - strlenW(DotCoInstallers), &SectionNameLength, NULL); 2139 if (!ret) 2140 goto done; 2141 2142 if (InstallParams.InstallMsgHandler) 2143 { 2144 InstallMsgHandler = InstallParams.InstallMsgHandler; 2145 InstallMsgHandlerContext = InstallParams.InstallMsgHandlerContext; 2146 } 2147 else 2148 { 2149 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent); 2150 if (!Context) 2151 goto cleanup; 2152 InstallMsgHandler = SetupDefaultQueueCallbackW; 2153 InstallMsgHandlerContext = Context; 2154 } 2155 ret = SetupInstallFromInfSectionW(InstallParams.hwndParent, 2156 SelectedDriver->InfFileDetails->hInf, SectionName, 2157 SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, 2158 InstallMsgHandler, InstallMsgHandlerContext, 2159 DeviceInfoSet, DeviceInfoData); 2160 if (!ret) 2161 goto done; 2162 2163 /* Install files from .CoInstallers section */ 2164 lstrcatW(SectionName, DotCoInstallers); 2165 ret = SetupInstallFromInfSectionW(InstallParams.hwndParent, 2166 SelectedDriver->InfFileDetails->hInf, SectionName, 2167 SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, 2168 InstallMsgHandler, InstallMsgHandlerContext, 2169 DeviceInfoSet, DeviceInfoData); 2170 if (!ret) 2171 goto done; 2172 2173 /* Set the DI_NOFILECOPY flag to prevent another 2174 * installation during SetupDiInstallDevice */ 2175 InstallParams.Flags |= DI_NOFILECOPY; 2176 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 2177 2178 cleanup: 2179 if (Context) 2180 SetupTermDefaultQueueCallback(Context); 2181 } 2182 2183 done: 2184 TRACE("Returning %d\n", ret); 2185 return ret; 2186 } 2187