1 /* 2 * SetupAPI device installer 3 * 4 * Copyright 2000 Andreas Mohr for CodeWeavers 5 * 2005-2006 Herv� Poussineau (hpoussin@reactos.org) 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include "setupapi_private.h" 23 24 /* Unicode constants */ 25 static const WCHAR BackSlash[] = {'\\',0}; 26 static const WCHAR DateFormat[] = {'%','u','-','%','u','-','%','u',0}; 27 static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0}; 28 static const WCHAR DotHW[] = {'.','H','W',0}; 29 static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0}; 30 static const WCHAR InfDirectory[] = {'i','n','f','\\',0}; 31 static const WCHAR InstanceKeyFormat[] = {'%','0','4','l','u',0}; 32 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0}; 33 static const WCHAR VersionFormat[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; 34 35 static const WCHAR REGSTR_DRIVER_DATE[] = {'D','r','i','v','e','r','D','a','t','e',0}; 36 static const WCHAR REGSTR_DRIVER_DATE_DATA[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0}; 37 static const WCHAR REGSTR_DRIVER_VERSION[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0}; 38 static const WCHAR REGSTR_SECURITY[] = {'S','e','c','u','r','i','t','y',0}; 39 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0}; 40 41 typedef DWORD 42 (CALLBACK* CLASS_INSTALL_PROC) ( 43 IN DI_FUNCTION InstallFunction, 44 IN HDEVINFO DeviceInfoSet, 45 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL); 46 typedef BOOL 47 (WINAPI* DEFAULT_CLASS_INSTALL_PROC) ( 48 IN HDEVINFO DeviceInfoSet, 49 IN OUT PSP_DEVINFO_DATA DeviceInfoData); 50 typedef DWORD 51 (CALLBACK* COINSTALLER_PROC) ( 52 IN DI_FUNCTION InstallFunction, 53 IN HDEVINFO DeviceInfoSet, 54 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 55 IN OUT PCOINSTALLER_CONTEXT_DATA Context); 56 57 struct CoInstallerElement 58 { 59 LIST_ENTRY ListEntry; 60 61 HMODULE Module; 62 COINSTALLER_PROC Function; 63 BOOL DoPostProcessing; 64 PVOID PrivateData; 65 }; 66 67 struct GetSectionCallbackInfo 68 { 69 PSP_ALTPLATFORM_INFO PlatformInfo; 70 BYTE ProductType; 71 WORD SuiteMask; 72 DWORD PrefixLength; 73 WCHAR BestSection[LINE_LEN + 1]; 74 DWORD BestScore1, BestScore2, BestScore3, BestScore4, BestScore5; 75 }; 76 77 78 79 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr) 80 { 81 static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-', 82 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2', 83 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%', 84 '0','2','X','}',0}; 85 86 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3, 87 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], 88 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); 89 } 90 91 static DWORD 92 GetErrorCodeFromCrCode(const IN CONFIGRET cr) 93 { 94 switch (cr) 95 { 96 case CR_ACCESS_DENIED: return ERROR_ACCESS_DENIED; 97 case CR_BUFFER_SMALL: return ERROR_INSUFFICIENT_BUFFER; 98 case CR_CALL_NOT_IMPLEMENTED: return ERROR_CALL_NOT_IMPLEMENTED; 99 case CR_FAILURE: return ERROR_GEN_FAILURE; 100 case CR_INVALID_DATA: return ERROR_INVALID_USER_BUFFER; 101 case CR_INVALID_DEVICE_ID: return ERROR_INVALID_PARAMETER; 102 case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME; 103 case CR_INVALID_DEVNODE: return ERROR_INVALID_PARAMETER; 104 case CR_INVALID_FLAG: return ERROR_INVALID_FLAGS; 105 case CR_INVALID_POINTER: return ERROR_INVALID_PARAMETER; 106 case CR_INVALID_PROPERTY: return ERROR_INVALID_PARAMETER; 107 case CR_NO_SUCH_DEVNODE: return ERROR_FILE_NOT_FOUND; 108 case CR_NO_SUCH_REGISTRY_KEY: return ERROR_FILE_NOT_FOUND; 109 case CR_NO_SUCH_VALUE: return ERROR_FILE_NOT_FOUND; 110 case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY; 111 case CR_REGISTRY_ERROR: return ERROR_GEN_FAILURE; 112 case CR_ALREADY_SUCH_DEVINST: return ERROR_DEVINST_ALREADY_EXISTS; 113 case CR_SUCCESS: return ERROR_SUCCESS; 114 default: return ERROR_GEN_FAILURE; 115 } 116 117 /* Does not happen */ 118 } 119 120 /* Lower scores are best ones */ 121 static BOOL 122 CheckSectionValid( 123 IN LPCWSTR SectionName, 124 IN PSP_ALTPLATFORM_INFO PlatformInfo, 125 IN BYTE ProductType, 126 IN WORD SuiteMask, 127 OUT PDWORD ScorePlatform, 128 OUT PDWORD ScoreMajorVersion, 129 OUT PDWORD ScoreMinorVersion, 130 OUT PDWORD ScoreProductType, 131 OUT PDWORD ScoreSuiteMask) 132 { 133 LPWSTR Section = NULL; 134 //LPCWSTR pExtensionPlatform; 135 LPCWSTR pExtensionArchitecture; 136 LPWSTR Fields[6]; 137 DWORD i; 138 BOOL ret = FALSE; 139 140 //static const WCHAR ExtensionPlatformNone[] = {'.',0}; 141 static const WCHAR ExtensionPlatformNT[] = {'.','N','T',0}; 142 static const WCHAR ExtensionPlatformWindows[] = {'.','W','i','n',0}; 143 144 static const WCHAR ExtensionArchitectureNone[] = {0}; 145 static const WCHAR ExtensionArchitecturealpha[] = {'a','l','p','h','a',0}; 146 static const WCHAR ExtensionArchitectureamd64[] = {'A','M','D','6','4',0}; 147 static const WCHAR ExtensionArchitectureia64[] = {'I','A','6','4',0}; 148 static const WCHAR ExtensionArchitecturemips[] = {'m','i','p','s',0}; 149 static const WCHAR ExtensionArchitectureppc[] = {'p','p','c',0}; 150 static const WCHAR ExtensionArchitecturex86[] = {'x','8','6',0}; 151 152 TRACE("%s %p 0x%x 0x%x\n", 153 debugstr_w(SectionName), PlatformInfo, ProductType, SuiteMask); 154 155 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = 0; 156 157 Section = pSetupDuplicateString(SectionName); 158 if (!Section) 159 { 160 TRACE("pSetupDuplicateString() failed\n"); 161 goto cleanup; 162 } 163 164 /* Set various extensions values */ 165 switch (PlatformInfo->Platform) 166 { 167 case VER_PLATFORM_WIN32_WINDOWS: 168 //pExtensionPlatform = ExtensionPlatformWindows; 169 break; 170 case VER_PLATFORM_WIN32_NT: 171 //pExtensionPlatform = ExtensionPlatformNT; 172 break; 173 default: 174 ERR("Unknown platform 0x%lx\n", PlatformInfo->Platform); 175 //pExtensionPlatform = ExtensionPlatformNone; 176 break; 177 } 178 switch (PlatformInfo->ProcessorArchitecture) 179 { 180 case PROCESSOR_ARCHITECTURE_ALPHA: 181 pExtensionArchitecture = ExtensionArchitecturealpha; 182 break; 183 case PROCESSOR_ARCHITECTURE_AMD64: 184 pExtensionArchitecture = ExtensionArchitectureamd64; 185 break; 186 case PROCESSOR_ARCHITECTURE_IA64: 187 pExtensionArchitecture = ExtensionArchitectureia64; 188 break; 189 case PROCESSOR_ARCHITECTURE_INTEL: 190 pExtensionArchitecture = ExtensionArchitecturex86; 191 break; 192 case PROCESSOR_ARCHITECTURE_MIPS: 193 pExtensionArchitecture = ExtensionArchitecturemips; 194 break; 195 case PROCESSOR_ARCHITECTURE_PPC: 196 pExtensionArchitecture = ExtensionArchitectureppc; 197 break; 198 default: 199 ERR("Unknown processor architecture 0x%x\n", PlatformInfo->ProcessorArchitecture); 200 case PROCESSOR_ARCHITECTURE_UNKNOWN: 201 pExtensionArchitecture = ExtensionArchitectureNone; 202 break; 203 } 204 205 /* 206 * Field[0] Platform 207 * Field[1] Architecture 208 * Field[2] Major version 209 * Field[3] Minor version 210 * Field[4] Product type 211 * Field[5] Suite mask 212 * Remark: these fields may be NULL if the information is not provided 213 */ 214 Fields[0] = Section; 215 if (Fields[0] == NULL) 216 { 217 TRACE("No extension found\n"); 218 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = ULONG_MAX; 219 ret = TRUE; 220 goto cleanup; 221 } 222 Fields[1] = Fields[0] + 1; 223 Fields[2] = Fields[3] = Fields[4] = Fields[5] = NULL; 224 for (i = 2; Fields[i - 1] != NULL && i < 6; i++) 225 { 226 Fields[i] = wcschr(Fields[i - 1], '.'); 227 if (Fields[i]) 228 { 229 Fields[i]++; 230 *(Fields[i] - 1) = UNICODE_NULL; 231 } 232 } 233 /* Take care of first 2 fields */ 234 if (strncmpiW(Fields[0], ExtensionPlatformWindows, strlenW(ExtensionPlatformWindows)) == 0) 235 { 236 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_WINDOWS) 237 { 238 TRACE("Mismatch on platform field\n"); 239 goto cleanup; 240 } 241 Fields[1] += wcslen(ExtensionPlatformWindows) - 1; 242 } 243 else if (strncmpiW(Fields[0], ExtensionPlatformNT, strlenW(ExtensionPlatformNT)) == 0) 244 { 245 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_NT) 246 { 247 TRACE("Mismatch on platform field\n"); 248 goto cleanup; 249 } 250 Fields[1] += wcslen(ExtensionPlatformNT) - 1; 251 } 252 else 253 { 254 /* No platform specified */ 255 *ScorePlatform |= 0x02; 256 } 257 if (strcmpiW(Fields[1], ExtensionArchitectureNone) == 0) 258 { 259 /* No architecture specified */ 260 *ScorePlatform |= 0x01; 261 } 262 else if (strcmpiW(Fields[1], pExtensionArchitecture) != 0) 263 { 264 TRACE("Mismatch on architecture field ('%s' and '%s')\n", 265 debugstr_w(Fields[1]), debugstr_w(pExtensionArchitecture)); 266 goto cleanup; 267 } 268 269 /* Check if informations are matching */ 270 if (Fields[2] && *Fields[2]) 271 { 272 DWORD MajorVersion, MinorVersion = 0; 273 MajorVersion = strtoulW(Fields[2], NULL, 0); 274 if ((MajorVersion == 0 || MajorVersion == ULONG_MAX) && 275 (errno == ERANGE || errno == EINVAL)) 276 { 277 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields[2])); 278 goto cleanup; 279 } 280 if (Fields[3] && *Fields[3]) 281 { 282 MinorVersion = strtoulW(Fields[3], NULL, 0); 283 if ((MinorVersion == 0 || MinorVersion == ULONG_MAX) && 284 (errno == ERANGE || errno == EINVAL)) 285 { 286 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields[3])); 287 goto cleanup; 288 } 289 } 290 if (PlatformInfo->MajorVersion < MajorVersion || 291 (PlatformInfo->MajorVersion == MajorVersion && PlatformInfo->MinorVersion < MinorVersion)) 292 { 293 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n", 294 MajorVersion, MinorVersion, PlatformInfo->MajorVersion, PlatformInfo->MinorVersion); 295 goto cleanup; 296 } 297 *ScoreMajorVersion = MajorVersion - PlatformInfo->MajorVersion; 298 if (MajorVersion == PlatformInfo->MajorVersion) 299 *ScoreMinorVersion = MinorVersion - PlatformInfo->MinorVersion; 300 else 301 *ScoreMinorVersion = MinorVersion; 302 } 303 else if (Fields[3] && *Fields[3]) 304 { 305 TRACE("Minor version found without major version\n"); 306 goto cleanup; 307 } 308 else 309 { 310 *ScoreMajorVersion = PlatformInfo->MajorVersion; 311 *ScoreMinorVersion = PlatformInfo->MinorVersion; 312 } 313 314 if (Fields[4] && *Fields[4]) 315 { 316 DWORD CurrentProductType; 317 CurrentProductType = strtoulW(Fields[4], NULL, 0); 318 if ((CurrentProductType == 0 || CurrentProductType == ULONG_MAX) && 319 (errno == ERANGE || errno == EINVAL)) 320 { 321 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields[4])); 322 goto cleanup; 323 } 324 if (CurrentProductType != ProductType) 325 { 326 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n", 327 CurrentProductType, ProductType); 328 goto cleanup; 329 } 330 } 331 else 332 *ScoreProductType = 1; 333 334 if (Fields[5] && *Fields[5]) 335 { 336 DWORD CurrentSuiteMask; 337 CurrentSuiteMask = strtoulW(Fields[5], NULL, 0); 338 if ((CurrentSuiteMask == 0 || CurrentSuiteMask == ULONG_MAX) && 339 (errno == ERANGE || errno == EINVAL)) 340 { 341 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields[5])); 342 goto cleanup; 343 } 344 if ((CurrentSuiteMask & ~SuiteMask) != 0) 345 { 346 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n", 347 CurrentSuiteMask, SuiteMask); 348 goto cleanup; 349 } 350 *ScoreSuiteMask = SuiteMask & ~CurrentSuiteMask; 351 } 352 else 353 *ScoreSuiteMask = SuiteMask; 354 355 ret = TRUE; 356 357 cleanup: 358 MyFree(Section); 359 return ret; 360 } 361 362 static BOOL 363 GetSectionCallback( 364 IN LPCWSTR SectionName, 365 IN PVOID Context) 366 { 367 struct GetSectionCallbackInfo *info = Context; 368 DWORD Score1, Score2, Score3, Score4, Score5; 369 BOOL ret; 370 371 if (SectionName[info->PrefixLength] != '.') 372 return TRUE; 373 374 ret = CheckSectionValid( 375 &SectionName[info->PrefixLength], 376 info->PlatformInfo, 377 info->ProductType, 378 info->SuiteMask, 379 &Score1, &Score2, &Score3, &Score4, &Score5); 380 if (!ret) 381 { 382 TRACE("Section %s not compatible\n", debugstr_w(SectionName)); 383 return TRUE; 384 } 385 if (Score1 > info->BestScore1) goto done; 386 if (Score1 < info->BestScore1) goto bettersection; 387 if (Score2 > info->BestScore2) goto done; 388 if (Score2 < info->BestScore2) goto bettersection; 389 if (Score3 > info->BestScore3) goto done; 390 if (Score3 < info->BestScore3) goto bettersection; 391 if (Score4 > info->BestScore4) goto done; 392 if (Score4 < info->BestScore4) goto bettersection; 393 if (Score5 > info->BestScore5) goto done; 394 if (Score5 < info->BestScore5) goto bettersection; 395 goto done; 396 397 bettersection: 398 strcpyW(info->BestSection, SectionName); 399 info->BestScore1 = Score1; 400 info->BestScore2 = Score2; 401 info->BestScore3 = Score3; 402 info->BestScore4 = Score4; 403 info->BestScore5 = Score5; 404 405 done: 406 return TRUE; 407 } 408 409 /*********************************************************************** 410 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@) 411 */ 412 BOOL WINAPI 413 SetupDiGetActualSectionToInstallExW( 414 IN HINF InfHandle, 415 IN PCWSTR InfSectionName, 416 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL, 417 OUT PWSTR InfSectionWithExt OPTIONAL, 418 IN DWORD InfSectionWithExtSize, 419 OUT PDWORD RequiredSize OPTIONAL, 420 OUT PWSTR* Extension OPTIONAL, 421 IN PVOID Reserved) 422 { 423 BOOL ret = FALSE; 424 425 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle, debugstr_w(InfSectionName), 426 AlternatePlatformInfo, InfSectionWithExt, InfSectionWithExtSize, 427 RequiredSize, Extension, Reserved); 428 429 if (!InfHandle || InfHandle == (HINF)INVALID_HANDLE_VALUE) 430 SetLastError(ERROR_INVALID_HANDLE); 431 else if (!InfSectionName) 432 SetLastError(ERROR_INVALID_PARAMETER); 433 else if (AlternatePlatformInfo && AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO)) 434 SetLastError(ERROR_INVALID_USER_BUFFER); 435 else if (Reserved != NULL) 436 SetLastError(ERROR_INVALID_PARAMETER); 437 else 438 { 439 static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, }; 440 static BYTE CurrentProductType = 0; 441 static WORD CurrentSuiteMask = 0; 442 PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform; 443 struct GetSectionCallbackInfo CallbackInfo; 444 DWORD dwFullLength; 445 BYTE ProductType; 446 WORD SuiteMask; 447 448 /* Fill platform info if needed */ 449 if (AlternatePlatformInfo) 450 { 451 pPlatformInfo = AlternatePlatformInfo; 452 ProductType = 0; 453 SuiteMask = 0; 454 } 455 else 456 { 457 if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO)) 458 { 459 /* That's the first time we go here. We need to fill in the structure */ 460 SYSTEM_INFO SystemInfo; 461 GetSystemInfo(&SystemInfo); 462 CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO); 463 CurrentPlatform.Platform = OsVersionInfo.dwPlatformId; 464 CurrentPlatform.MajorVersion = OsVersionInfo.dwMajorVersion; 465 CurrentPlatform.MinorVersion = OsVersionInfo.dwMinorVersion; 466 CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture; 467 CurrentPlatform.Reserved = 0; 468 CurrentProductType = OsVersionInfo.wProductType; 469 CurrentSuiteMask = OsVersionInfo.wSuiteMask; 470 } 471 ProductType = CurrentProductType; 472 SuiteMask = CurrentSuiteMask; 473 } 474 475 CallbackInfo.PlatformInfo = pPlatformInfo; 476 CallbackInfo.ProductType = ProductType; 477 CallbackInfo.SuiteMask = SuiteMask; 478 CallbackInfo.PrefixLength = strlenW(InfSectionName); 479 CallbackInfo.BestScore1 = ULONG_MAX; 480 CallbackInfo.BestScore2 = ULONG_MAX; 481 CallbackInfo.BestScore3 = ULONG_MAX; 482 CallbackInfo.BestScore4 = ULONG_MAX; 483 CallbackInfo.BestScore5 = ULONG_MAX; 484 strcpyW(CallbackInfo.BestSection, InfSectionName); 485 TRACE("EnumerateSectionsStartingWith(InfSectionName = %S)\n", InfSectionName); 486 if (!EnumerateSectionsStartingWith( 487 InfHandle, 488 InfSectionName, 489 GetSectionCallback, 490 &CallbackInfo)) 491 { 492 SetLastError(ERROR_GEN_FAILURE); 493 goto done; 494 } 495 TRACE("CallbackInfo.BestSection = %S\n", CallbackInfo.BestSection); 496 497 dwFullLength = lstrlenW(CallbackInfo.BestSection); 498 if (RequiredSize != NULL) 499 *RequiredSize = dwFullLength + 1; 500 501 if (InfSectionWithExtSize > 0) 502 { 503 if (InfSectionWithExtSize < dwFullLength + 1) 504 { 505 SetLastError(ERROR_INSUFFICIENT_BUFFER); 506 goto done; 507 } 508 strcpyW(InfSectionWithExt, CallbackInfo.BestSection); 509 if (Extension) 510 { 511 DWORD dwLength = lstrlenW(InfSectionName); 512 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength]; 513 } 514 } 515 516 ret = TRUE; 517 } 518 519 done: 520 TRACE("Returning %d\n", ret); 521 return ret; 522 } 523 524 525 BOOL 526 CreateDeviceInfo( 527 IN struct DeviceInfoSet *list, 528 IN LPCWSTR InstancePath, 529 IN LPCGUID pClassGuid, 530 OUT struct DeviceInfo **pDeviceInfo) 531 { 532 DWORD size; 533 CONFIGRET cr; 534 struct DeviceInfo *deviceInfo; 535 536 *pDeviceInfo = NULL; 537 538 size = FIELD_OFFSET(struct DeviceInfo, Data) + (strlenW(InstancePath) + 1) * sizeof(WCHAR); 539 deviceInfo = HeapAlloc(GetProcessHeap(), 0, size); 540 if (!deviceInfo) 541 { 542 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 543 return FALSE; 544 } 545 ZeroMemory(deviceInfo, size); 546 547 cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine); 548 if (cr != CR_SUCCESS) 549 { 550 SetLastError(GetErrorCodeFromCrCode(cr)); 551 return FALSE; 552 } 553 554 deviceInfo->set = list; 555 deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 556 strcpyW(deviceInfo->Data, InstancePath); 557 deviceInfo->instanceId = deviceInfo->Data; 558 deviceInfo->UniqueId = strrchrW(deviceInfo->Data, '\\'); 559 deviceInfo->DeviceDescription = NULL; 560 memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID)); 561 deviceInfo->CreationFlags = 0; 562 InitializeListHead(&deviceInfo->DriverListHead); 563 InitializeListHead(&deviceInfo->InterfaceListHead); 564 565 *pDeviceInfo = deviceInfo; 566 return TRUE; 567 } 568 569 570 static BOOL 571 DestroyClassInstallParams(struct ClassInstallParams* installParams) 572 { 573 HeapFree(GetProcessHeap(), 0, installParams->PropChangeParams); 574 HeapFree(GetProcessHeap(), 0, installParams->AddPropertyPageData); 575 return TRUE; 576 } 577 578 static BOOL 579 DestroyDeviceInfo(struct DeviceInfo *deviceInfo) 580 { 581 PLIST_ENTRY ListEntry; 582 struct DriverInfoElement *driverInfo; 583 struct DeviceInterface *deviceInterface; 584 585 while (!IsListEmpty(&deviceInfo->DriverListHead)) 586 { 587 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead); 588 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry); 589 if (!DestroyDriverInfoElement(driverInfo)) 590 return FALSE; 591 } 592 while (!IsListEmpty(&deviceInfo->InterfaceListHead)) 593 { 594 ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead); 595 deviceInterface = CONTAINING_RECORD(ListEntry, struct DeviceInterface, ListEntry); 596 if (!DestroyDeviceInterface(deviceInterface)) 597 return FALSE; 598 } 599 DestroyClassInstallParams(&deviceInfo->ClassInstallParams); 600 if (deviceInfo->hmodDevicePropPageProvider) 601 FreeLibrary(deviceInfo->hmodDevicePropPageProvider); 602 return HeapFree(GetProcessHeap(), 0, deviceInfo); 603 } 604 605 static BOOL 606 DestroyDeviceInfoSet(struct DeviceInfoSet* list) 607 { 608 PLIST_ENTRY ListEntry; 609 struct DeviceInfo *deviceInfo; 610 611 while (!IsListEmpty(&list->ListHead)) 612 { 613 ListEntry = RemoveHeadList(&list->ListHead); 614 deviceInfo = CONTAINING_RECORD(ListEntry, struct DeviceInfo, ListEntry); 615 if (!DestroyDeviceInfo(deviceInfo)) 616 return FALSE; 617 } 618 if (list->HKLM != HKEY_LOCAL_MACHINE) 619 RegCloseKey(list->HKLM); 620 CM_Disconnect_Machine(list->hMachine); 621 DestroyClassInstallParams(&list->ClassInstallParams); 622 if (list->hmodClassPropPageProvider) 623 FreeLibrary(list->hmodClassPropPageProvider); 624 return HeapFree(GetProcessHeap(), 0, list); 625 } 626 627 /*********************************************************************** 628 * SetupDiBuildClassInfoList (SETUPAPI.@) 629 * 630 * Returns a list of setup class GUIDs that identify the classes 631 * that are installed on a local machine. 632 * 633 * PARAMS 634 * Flags [I] control exclusion of classes from the list. 635 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs. 636 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList). 637 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned. 638 * 639 * RETURNS 640 * Success: TRUE. 641 * Failure: FALSE. 642 */ 643 BOOL WINAPI SetupDiBuildClassInfoList( 644 DWORD Flags, 645 LPGUID ClassGuidList, 646 DWORD ClassGuidListSize, 647 PDWORD RequiredSize) 648 { 649 TRACE("\n"); 650 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList, 651 ClassGuidListSize, RequiredSize, 652 NULL, NULL); 653 } 654 655 /*********************************************************************** 656 * SetupDiBuildClassInfoListExA (SETUPAPI.@) 657 * 658 * Returns a list of setup class GUIDs that identify the classes 659 * that are installed on a local or remote machine. 660 * 661 * PARAMS 662 * Flags [I] control exclusion of classes from the list. 663 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs. 664 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList). 665 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned. 666 * MachineName [I] name of a remote machine. 667 * Reserved [I] must be NULL. 668 * 669 * RETURNS 670 * Success: TRUE. 671 * Failure: FALSE. 672 */ 673 BOOL WINAPI SetupDiBuildClassInfoListExA( 674 DWORD Flags, 675 LPGUID ClassGuidList, 676 DWORD ClassGuidListSize, 677 PDWORD RequiredSize, 678 LPCSTR MachineName, 679 PVOID Reserved) 680 { 681 LPWSTR MachineNameW = NULL; 682 BOOL bResult; 683 684 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList, 685 ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved); 686 687 if (MachineName) 688 { 689 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 690 if (MachineNameW == NULL) return FALSE; 691 } 692 693 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList, 694 ClassGuidListSize, RequiredSize, 695 MachineNameW, Reserved); 696 697 MyFree(MachineNameW); 698 699 return bResult; 700 } 701 702 /*********************************************************************** 703 * SetupDiBuildClassInfoListExW (SETUPAPI.@) 704 * 705 * Returns a list of setup class GUIDs that identify the classes 706 * that are installed on a local or remote machine. 707 * 708 * PARAMS 709 * Flags [I] control exclusion of classes from the list. 710 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs. 711 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList). 712 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned. 713 * MachineName [I] name of a remote machine. 714 * Reserved [I] must be NULL. 715 * 716 * RETURNS 717 * Success: TRUE. 718 * Failure: FALSE. 719 */ 720 BOOL WINAPI SetupDiBuildClassInfoListExW( 721 DWORD Flags, 722 LPGUID ClassGuidList, 723 DWORD ClassGuidListSize, 724 PDWORD RequiredSize, 725 LPCWSTR MachineName, 726 PVOID Reserved) 727 { 728 WCHAR szKeyName[40]; 729 HKEY hClassesKey = INVALID_HANDLE_VALUE; 730 HKEY hClassKey; 731 DWORD dwLength; 732 DWORD dwIndex; 733 LONG lError; 734 DWORD dwGuidListIndex = 0; 735 736 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList, 737 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved); 738 739 if (!RequiredSize) 740 { 741 SetLastError(ERROR_INVALID_PARAMETER); 742 return FALSE; 743 } 744 else if (!ClassGuidList && ClassGuidListSize > 0) 745 { 746 SetLastError(ERROR_INVALID_PARAMETER); 747 return FALSE; 748 } 749 750 hClassesKey = SetupDiOpenClassRegKeyExW(NULL, 751 KEY_ENUMERATE_SUB_KEYS, 752 DIOCR_INSTALLER, 753 MachineName, 754 Reserved); 755 if (hClassesKey == INVALID_HANDLE_VALUE) 756 { 757 return FALSE; 758 } 759 760 for (dwIndex = 0; ; dwIndex++) 761 { 762 dwLength = 40; 763 lError = RegEnumKeyExW(hClassesKey, 764 dwIndex, 765 szKeyName, 766 &dwLength, 767 NULL, 768 NULL, 769 NULL, 770 NULL); 771 TRACE("RegEnumKeyExW() returns %d\n", lError); 772 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) 773 { 774 TRACE("Key name: %s\n", debugstr_w(szKeyName)); 775 776 if (RegOpenKeyExW(hClassesKey, 777 szKeyName, 778 0, 779 KEY_QUERY_VALUE, 780 &hClassKey)) 781 { 782 RegCloseKey(hClassesKey); 783 return FALSE; 784 } 785 786 if (!RegQueryValueExW(hClassKey, 787 REGSTR_VAL_NOUSECLASS, 788 NULL, 789 NULL, 790 NULL, 791 NULL)) 792 { 793 TRACE("'NoUseClass' value found!\n"); 794 RegCloseKey(hClassKey); 795 continue; 796 } 797 798 if ((Flags & DIBCI_NOINSTALLCLASS) && 799 (!RegQueryValueExW(hClassKey, 800 REGSTR_VAL_NOINSTALLCLASS, 801 NULL, 802 NULL, 803 NULL, 804 NULL))) 805 { 806 TRACE("'NoInstallClass' value found!\n"); 807 RegCloseKey(hClassKey); 808 continue; 809 } 810 811 if ((Flags & DIBCI_NODISPLAYCLASS) && 812 (!RegQueryValueExW(hClassKey, 813 REGSTR_VAL_NODISPLAYCLASS, 814 NULL, 815 NULL, 816 NULL, 817 NULL))) 818 { 819 TRACE("'NoDisplayClass' value found!\n"); 820 RegCloseKey(hClassKey); 821 continue; 822 } 823 824 RegCloseKey(hClassKey); 825 826 TRACE("Guid: %s\n", debugstr_w(szKeyName)); 827 if (dwGuidListIndex < ClassGuidListSize) 828 { 829 if (szKeyName[0] == '{' && szKeyName[37] == '}') 830 { 831 szKeyName[37] = 0; 832 } 833 TRACE("Guid: %p\n", &szKeyName[1]); 834 835 UuidFromStringW(&szKeyName[1], 836 &ClassGuidList[dwGuidListIndex]); 837 } 838 839 dwGuidListIndex++; 840 } 841 842 if (lError != ERROR_SUCCESS) 843 break; 844 } 845 846 RegCloseKey(hClassesKey); 847 848 if (RequiredSize != NULL) 849 *RequiredSize = dwGuidListIndex; 850 851 if (ClassGuidListSize < dwGuidListIndex) 852 { 853 SetLastError(ERROR_INSUFFICIENT_BUFFER); 854 return FALSE; 855 } 856 857 return TRUE; 858 } 859 860 /*********************************************************************** 861 * SetupDiClassGuidsFromNameA (SETUPAPI.@) 862 */ 863 BOOL WINAPI SetupDiClassGuidsFromNameA( 864 LPCSTR ClassName, 865 LPGUID ClassGuidList, 866 DWORD ClassGuidListSize, 867 PDWORD RequiredSize) 868 { 869 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList, 870 ClassGuidListSize, RequiredSize, 871 NULL, NULL); 872 } 873 874 /*********************************************************************** 875 * SetupDiClassGuidsFromNameW (SETUPAPI.@) 876 */ 877 BOOL WINAPI SetupDiClassGuidsFromNameW( 878 LPCWSTR ClassName, 879 LPGUID ClassGuidList, 880 DWORD ClassGuidListSize, 881 PDWORD RequiredSize) 882 { 883 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList, 884 ClassGuidListSize, RequiredSize, 885 NULL, NULL); 886 } 887 888 /*********************************************************************** 889 * SetupDiClassGuidsFromNameExA (SETUPAPI.@) 890 */ 891 BOOL WINAPI SetupDiClassGuidsFromNameExA( 892 LPCSTR ClassName, 893 LPGUID ClassGuidList, 894 DWORD ClassGuidListSize, 895 PDWORD RequiredSize, 896 LPCSTR MachineName, 897 PVOID Reserved) 898 { 899 LPWSTR ClassNameW = NULL; 900 LPWSTR MachineNameW = NULL; 901 BOOL bResult; 902 903 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName), ClassGuidList, 904 ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved); 905 906 if (!ClassName) 907 { 908 SetLastError(ERROR_INVALID_PARAMETER); 909 return FALSE; 910 } 911 912 ClassNameW = pSetupMultiByteToUnicode(ClassName, CP_ACP); 913 if (ClassNameW == NULL) 914 return FALSE; 915 916 if (MachineName) 917 { 918 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 919 if (MachineNameW == NULL) 920 { 921 MyFree(ClassNameW); 922 return FALSE; 923 } 924 } 925 926 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList, 927 ClassGuidListSize, RequiredSize, 928 MachineNameW, Reserved); 929 930 MyFree(MachineNameW); 931 MyFree(ClassNameW); 932 933 return bResult; 934 } 935 936 /*********************************************************************** 937 * SetupDiClassGuidsFromNameExW (SETUPAPI.@) 938 */ 939 BOOL WINAPI SetupDiClassGuidsFromNameExW( 940 LPCWSTR ClassName, 941 LPGUID ClassGuidList, 942 DWORD ClassGuidListSize, 943 PDWORD RequiredSize, 944 LPCWSTR MachineName, 945 PVOID Reserved) 946 { 947 WCHAR szKeyName[40]; 948 WCHAR szClassName[MAX_CLASS_NAME_LEN]; 949 HKEY hClassesKey; 950 HKEY hClassKey; 951 DWORD dwLength; 952 DWORD dwIndex; 953 LONG lError; 954 DWORD dwGuidListIndex = 0; 955 956 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList, 957 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved); 958 959 if (!ClassName || !RequiredSize) 960 { 961 SetLastError(ERROR_INVALID_PARAMETER); 962 return FALSE; 963 } 964 if (!ClassGuidList && ClassGuidListSize > 0) 965 { 966 SetLastError(ERROR_INVALID_PARAMETER); 967 return FALSE; 968 } 969 *RequiredSize = 0; 970 971 hClassesKey = SetupDiOpenClassRegKeyExW(NULL, 972 KEY_ENUMERATE_SUB_KEYS, 973 DIOCR_INSTALLER, 974 MachineName, 975 Reserved); 976 if (hClassesKey == INVALID_HANDLE_VALUE) 977 { 978 return FALSE; 979 } 980 981 for (dwIndex = 0; ; dwIndex++) 982 { 983 dwLength = 40; 984 lError = RegEnumKeyExW(hClassesKey, 985 dwIndex, 986 szKeyName, 987 &dwLength, 988 NULL, 989 NULL, 990 NULL, 991 NULL); 992 TRACE("RegEnumKeyExW() returns %d\n", lError); 993 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) 994 { 995 TRACE("Key name: %p\n", szKeyName); 996 997 if (RegOpenKeyExW(hClassesKey, 998 szKeyName, 999 0, 1000 KEY_QUERY_VALUE, 1001 &hClassKey)) 1002 { 1003 RegCloseKey(hClassesKey); 1004 return FALSE; 1005 } 1006 1007 dwLength = MAX_CLASS_NAME_LEN * sizeof(WCHAR); 1008 if (!RegQueryValueExW(hClassKey, 1009 REGSTR_VAL_CLASS, 1010 NULL, 1011 NULL, 1012 (LPBYTE)szClassName, 1013 &dwLength)) 1014 { 1015 TRACE("Class name: %p\n", szClassName); 1016 1017 if (strcmpiW(szClassName, ClassName) == 0) 1018 { 1019 TRACE("Found matching class name\n"); 1020 1021 TRACE("Guid: %p\n", szKeyName); 1022 if (dwGuidListIndex < ClassGuidListSize) 1023 { 1024 if (szKeyName[0] == '{' && szKeyName[37] == '}') 1025 { 1026 szKeyName[37] = 0; 1027 } 1028 TRACE("Guid: %p\n", &szKeyName[1]); 1029 1030 UuidFromStringW(&szKeyName[1], 1031 &ClassGuidList[dwGuidListIndex]); 1032 } 1033 1034 dwGuidListIndex++; 1035 } 1036 } 1037 1038 RegCloseKey(hClassKey); 1039 } 1040 1041 if (lError != ERROR_SUCCESS) 1042 break; 1043 } 1044 1045 RegCloseKey(hClassesKey); 1046 1047 if (RequiredSize != NULL) 1048 *RequiredSize = dwGuidListIndex; 1049 1050 if (ClassGuidListSize < dwGuidListIndex) 1051 { 1052 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1053 return FALSE; 1054 } 1055 1056 return TRUE; 1057 } 1058 1059 /*********************************************************************** 1060 * SetupDiClassNameFromGuidA (SETUPAPI.@) 1061 */ 1062 BOOL WINAPI SetupDiClassNameFromGuidA( 1063 const GUID* ClassGuid, 1064 PSTR ClassName, 1065 DWORD ClassNameSize, 1066 PDWORD RequiredSize) 1067 { 1068 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName, 1069 ClassNameSize, RequiredSize, 1070 NULL, NULL); 1071 } 1072 1073 /*********************************************************************** 1074 * SetupDiClassNameFromGuidW (SETUPAPI.@) 1075 */ 1076 BOOL WINAPI SetupDiClassNameFromGuidW( 1077 const GUID* ClassGuid, 1078 PWSTR ClassName, 1079 DWORD ClassNameSize, 1080 PDWORD RequiredSize) 1081 { 1082 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName, 1083 ClassNameSize, RequiredSize, 1084 NULL, NULL); 1085 } 1086 1087 /*********************************************************************** 1088 * SetupDiClassNameFromGuidExA (SETUPAPI.@) 1089 */ 1090 BOOL WINAPI SetupDiClassNameFromGuidExA( 1091 const GUID* ClassGuid, 1092 PSTR ClassName, 1093 DWORD ClassNameSize, 1094 PDWORD RequiredSize, 1095 PCSTR MachineName, 1096 PVOID Reserved) 1097 { 1098 WCHAR ClassNameW[MAX_CLASS_NAME_LEN]; 1099 LPWSTR MachineNameW = NULL; 1100 BOOL ret; 1101 1102 if (MachineName) 1103 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 1104 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN, 1105 RequiredSize, MachineNameW, Reserved); 1106 if (ret) 1107 { 1108 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName, 1109 ClassNameSize, NULL, NULL); 1110 if (len == 0 || len > ClassNameSize) 1111 { 1112 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1113 ret = FALSE; 1114 } 1115 } 1116 MyFree(MachineNameW); 1117 return ret; 1118 } 1119 1120 /*********************************************************************** 1121 * SetupDiClassNameFromGuidExW (SETUPAPI.@) 1122 */ 1123 BOOL WINAPI SetupDiClassNameFromGuidExW( 1124 const GUID* ClassGuid, 1125 PWSTR ClassName, 1126 DWORD ClassNameSize, 1127 PDWORD RequiredSize, 1128 PCWSTR MachineName, 1129 PVOID Reserved) 1130 { 1131 HKEY hKey; 1132 DWORD dwLength; 1133 DWORD dwRegType; 1134 LONG rc; 1135 PWSTR Buffer; 1136 1137 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName, 1138 ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved); 1139 1140 /* Make sure there's a GUID */ 1141 if (ClassGuid == NULL) 1142 { 1143 SetLastError(ERROR_INVALID_CLASS); /* On Vista: ERROR_INVALID_USER_BUFFER */ 1144 return FALSE; 1145 } 1146 1147 /* Make sure there's a real buffer when there's a size */ 1148 if ((ClassNameSize > 0) && (ClassName == NULL)) 1149 { 1150 SetLastError(ERROR_INVALID_PARAMETER); /* On Vista: ERROR_INVALID_USER_BUFFER */ 1151 return FALSE; 1152 } 1153 1154 /* Open the key for the GUID */ 1155 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, KEY_QUERY_VALUE, DIOCR_INSTALLER, MachineName, Reserved); 1156 1157 if (hKey == INVALID_HANDLE_VALUE) 1158 return FALSE; 1159 1160 /* Retrieve the class name data and close the key */ 1161 rc = QueryRegistryValue(hKey, REGSTR_VAL_CLASS, (LPBYTE *) &Buffer, &dwRegType, &dwLength); 1162 RegCloseKey(hKey); 1163 1164 /* Make sure we got the data */ 1165 if (rc != ERROR_SUCCESS) 1166 { 1167 SetLastError(rc); 1168 return FALSE; 1169 } 1170 1171 /* Make sure the data is a string */ 1172 if (dwRegType != REG_SZ) 1173 { 1174 MyFree(Buffer); 1175 SetLastError(ERROR_GEN_FAILURE); 1176 return FALSE; 1177 } 1178 1179 /* Determine the length of the class name */ 1180 dwLength /= sizeof(WCHAR); 1181 1182 if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL)) 1183 /* Count the null-terminator */ 1184 dwLength++; 1185 1186 /* Inform the caller about the class name */ 1187 if ((ClassName != NULL) && (dwLength <= ClassNameSize)) 1188 { 1189 memcpy(ClassName, Buffer, (dwLength - 1) * sizeof(WCHAR)); 1190 ClassName[dwLength - 1] = UNICODE_NULL; 1191 } 1192 1193 /* Inform the caller about the required size */ 1194 if (RequiredSize != NULL) 1195 *RequiredSize = dwLength; 1196 1197 /* Clean up the buffer */ 1198 MyFree(Buffer); 1199 1200 /* Make sure the buffer was large enough */ 1201 if ((ClassName == NULL) || (dwLength > ClassNameSize)) 1202 { 1203 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1204 return FALSE; 1205 } 1206 1207 return TRUE; 1208 } 1209 1210 /*********************************************************************** 1211 * SetupDiCreateDeviceInfoList (SETUPAPI.@) 1212 */ 1213 HDEVINFO WINAPI 1214 SetupDiCreateDeviceInfoList(const GUID *ClassGuid, 1215 HWND hwndParent) 1216 { 1217 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL); 1218 } 1219 1220 /*********************************************************************** 1221 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@) 1222 */ 1223 HDEVINFO WINAPI 1224 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid, 1225 HWND hwndParent, 1226 PCSTR MachineName, 1227 PVOID Reserved) 1228 { 1229 LPWSTR MachineNameW = NULL; 1230 HDEVINFO hDevInfo; 1231 1232 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent, 1233 debugstr_a(MachineName), Reserved); 1234 1235 if (MachineName) 1236 { 1237 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 1238 if (MachineNameW == NULL) 1239 return INVALID_HANDLE_VALUE; 1240 } 1241 1242 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, 1243 MachineNameW, Reserved); 1244 1245 MyFree(MachineNameW); 1246 1247 return hDevInfo; 1248 } 1249 1250 /*********************************************************************** 1251 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@) 1252 * 1253 * Create an empty DeviceInfoSet list. 1254 * 1255 * PARAMS 1256 * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated 1257 * with this list. 1258 * hwndParent [I] hwnd needed for interface related actions. 1259 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL 1260 * local registry will be used. 1261 * Reserved [I] must be NULL 1262 * 1263 * RETURNS 1264 * Success: empty list. 1265 * Failure: INVALID_HANDLE_VALUE. 1266 */ 1267 HDEVINFO WINAPI 1268 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid, 1269 HWND hwndParent, 1270 PCWSTR MachineName, 1271 PVOID Reserved) 1272 { 1273 struct DeviceInfoSet *list = NULL; 1274 DWORD size = FIELD_OFFSET(struct DeviceInfoSet, szData); 1275 DWORD rc; 1276 CONFIGRET cr; 1277 HDEVINFO ret = INVALID_HANDLE_VALUE; 1278 1279 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent, 1280 debugstr_w(MachineName), Reserved); 1281 1282 if (MachineName != NULL) 1283 { 1284 SIZE_T len = strlenW(MachineName); 1285 if (len >= SP_MAX_MACHINENAME_LENGTH - 4) 1286 { 1287 SetLastError(ERROR_INVALID_MACHINENAME); 1288 goto cleanup; 1289 } 1290 if(len > 0) 1291 size += (len + 3) * sizeof(WCHAR); 1292 else 1293 MachineName = NULL; 1294 } 1295 1296 if (Reserved != NULL) 1297 { 1298 SetLastError(ERROR_INVALID_PARAMETER); 1299 return INVALID_HANDLE_VALUE; 1300 } 1301 1302 list = MyMalloc(size); 1303 if (!list) 1304 { 1305 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1306 return INVALID_HANDLE_VALUE; 1307 } 1308 ZeroMemory(list, FIELD_OFFSET(struct DeviceInfoSet, szData)); 1309 1310 list->magic = SETUP_DEVICE_INFO_SET_MAGIC; 1311 memcpy(&list->ClassGuid, 1312 ClassGuid ? ClassGuid : &GUID_NULL, 1313 sizeof(list->ClassGuid)); 1314 list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 1315 list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS; 1316 list->InstallParams.hwndParent = hwndParent; 1317 if (MachineName) 1318 { 1319 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM); 1320 if (rc != ERROR_SUCCESS) 1321 { 1322 SetLastError(ERROR_INVALID_MACHINENAME); 1323 goto cleanup; 1324 } 1325 1326 list->szData[0] = list->szData[1] = '\\'; 1327 strcpyW(list->szData + 2, MachineName); 1328 list->MachineName = list->szData; 1329 } 1330 else 1331 { 1332 list->HKLM = HKEY_LOCAL_MACHINE; 1333 list->MachineName = NULL; 1334 } 1335 cr = CM_Connect_MachineW(list->MachineName, &list->hMachine); 1336 if (cr != CR_SUCCESS) 1337 { 1338 SetLastError(GetErrorCodeFromCrCode(cr)); 1339 goto cleanup; 1340 } 1341 InitializeListHead(&list->DriverListHead); 1342 InitializeListHead(&list->ListHead); 1343 1344 return (HDEVINFO)list; 1345 1346 cleanup: 1347 if (ret == INVALID_HANDLE_VALUE) 1348 { 1349 if (list) 1350 { 1351 if (list->HKLM != NULL && list->HKLM != HKEY_LOCAL_MACHINE) 1352 RegCloseKey(list->HKLM); 1353 MyFree(list); 1354 } 1355 } 1356 return ret; 1357 } 1358 1359 /*********************************************************************** 1360 * SetupDiCreateDevRegKeyA (SETUPAPI.@) 1361 */ 1362 HKEY WINAPI SetupDiCreateDevRegKeyA( 1363 HDEVINFO DeviceInfoSet, 1364 PSP_DEVINFO_DATA DeviceInfoData, 1365 DWORD Scope, 1366 DWORD HwProfile, 1367 DWORD KeyType, 1368 HINF InfHandle, 1369 PCSTR InfSectionName) 1370 { 1371 PWSTR InfSectionNameW = NULL; 1372 HKEY key; 1373 1374 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope, 1375 HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName)); 1376 1377 if (InfHandle) 1378 { 1379 if (!InfSectionName) 1380 { 1381 SetLastError(ERROR_INVALID_PARAMETER); 1382 return INVALID_HANDLE_VALUE; 1383 } 1384 else 1385 { 1386 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP); 1387 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE; 1388 } 1389 } 1390 key = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, Scope, 1391 HwProfile, KeyType, InfHandle, InfSectionNameW); 1392 MyFree(InfSectionNameW); 1393 return key; 1394 } 1395 1396 static HKEY 1397 OpenHardwareProfileKey( 1398 IN HKEY HKLM, 1399 IN DWORD HwProfile, 1400 IN DWORD samDesired); 1401 1402 /*********************************************************************** 1403 * SetupDiCreateDevRegKeyW (SETUPAPI.@) 1404 */ 1405 HKEY WINAPI SetupDiCreateDevRegKeyW( 1406 HDEVINFO DeviceInfoSet, 1407 PSP_DEVINFO_DATA DeviceInfoData, 1408 DWORD Scope, 1409 DWORD HwProfile, 1410 DWORD KeyType, 1411 HINF InfHandle, 1412 PCWSTR InfSectionName) 1413 { 1414 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 1415 HKEY key = INVALID_HANDLE_VALUE; 1416 LPWSTR lpGuidString = NULL; 1417 LPWSTR DriverKey = NULL; /* {GUID}\Index */ 1418 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */ 1419 DWORD Index; /* Index used in the DriverKey name */ 1420 DWORD dwSize; 1421 DWORD Disposition; 1422 DWORD rc; 1423 HKEY hHWProfileKey = INVALID_HANDLE_VALUE; 1424 HKEY hEnumKey = NULL; 1425 HKEY hClassKey = NULL; 1426 HKEY hDeviceKey = INVALID_HANDLE_VALUE; 1427 HKEY hKey = NULL; 1428 HKEY RootKey; 1429 1430 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData, Scope, 1431 HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName)); 1432 1433 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 1434 { 1435 SetLastError(ERROR_INVALID_HANDLE); 1436 return INVALID_HANDLE_VALUE; 1437 } 1438 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1439 { 1440 SetLastError(ERROR_INVALID_HANDLE); 1441 return INVALID_HANDLE_VALUE; 1442 } 1443 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 1444 || !DeviceInfoData->Reserved) 1445 { 1446 SetLastError(ERROR_INVALID_PARAMETER); 1447 return INVALID_HANDLE_VALUE; 1448 } 1449 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC) 1450 { 1451 SetLastError(ERROR_INVALID_FLAGS); 1452 return INVALID_HANDLE_VALUE; 1453 } 1454 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV) 1455 { 1456 SetLastError(ERROR_INVALID_FLAGS); 1457 return INVALID_HANDLE_VALUE; 1458 } 1459 if (InfHandle && !InfSectionName) 1460 { 1461 SetLastError(ERROR_INVALID_PARAMETER); 1462 return INVALID_HANDLE_VALUE; 1463 } 1464 if (!InfHandle && InfSectionName) 1465 { 1466 SetLastError(ERROR_INVALID_PARAMETER); 1467 return INVALID_HANDLE_VALUE; 1468 } 1469 1470 if (Scope == DICS_FLAG_GLOBAL) 1471 RootKey = set->HKLM; 1472 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */ 1473 { 1474 hHWProfileKey = OpenHardwareProfileKey(set->HKLM, HwProfile, KEY_CREATE_SUB_KEY); 1475 if (hHWProfileKey == INVALID_HANDLE_VALUE) 1476 goto cleanup; 1477 RootKey = hHWProfileKey; 1478 } 1479 1480 if (KeyType == DIREG_DEV) 1481 { 1482 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 1483 1484 rc = RegCreateKeyExW( 1485 RootKey, 1486 REGSTR_PATH_SYSTEMENUM, 1487 0, 1488 NULL, 1489 REG_OPTION_NON_VOLATILE, 1490 KEY_CREATE_SUB_KEY, 1491 NULL, 1492 &hEnumKey, 1493 NULL); 1494 if (rc != ERROR_SUCCESS) 1495 { 1496 SetLastError(rc); 1497 goto cleanup; 1498 } 1499 rc = RegCreateKeyExW( 1500 hEnumKey, 1501 deviceInfo->instanceId, 1502 0, 1503 NULL, 1504 REG_OPTION_NON_VOLATILE, 1505 #if _WIN32_WINNT >= 0x502 1506 KEY_READ | KEY_WRITE, 1507 #else 1508 KEY_ALL_ACCESS, 1509 #endif 1510 NULL, 1511 &hKey, 1512 NULL); 1513 if (rc != ERROR_SUCCESS) 1514 { 1515 SetLastError(rc); 1516 goto cleanup; 1517 } 1518 } 1519 else /* KeyType == DIREG_DRV */ 1520 { 1521 /* Open device key, to read Driver value */ 1522 hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE); 1523 if (hDeviceKey == INVALID_HANDLE_VALUE) 1524 goto cleanup; 1525 1526 rc = RegOpenKeyExW(RootKey, REGSTR_PATH_CLASS_NT, 0, KEY_CREATE_SUB_KEY, &hClassKey); 1527 if (rc != ERROR_SUCCESS) 1528 { 1529 SetLastError(rc); 1530 goto cleanup; 1531 } 1532 1533 rc = RegQueryValueExW(hDeviceKey, REGSTR_VAL_DRIVER, NULL, NULL, NULL, &dwSize); 1534 if (rc != ERROR_SUCCESS) 1535 { 1536 /* Create a new driver key */ 1537 1538 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK) 1539 goto cleanup; 1540 1541 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */ 1542 DriverKey = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); 1543 if (!DriverKey) 1544 { 1545 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1546 goto cleanup; 1547 } 1548 1549 DriverKey[0] = '{'; 1550 strcpyW(&DriverKey[1], lpGuidString); 1551 pDeviceInstance = &DriverKey[strlenW(DriverKey)]; 1552 *pDeviceInstance++ = '}'; 1553 *pDeviceInstance++ = '\\'; 1554 1555 /* Try all values for Index between 0 and 9999 */ 1556 Index = 0; 1557 while (Index <= 9999) 1558 { 1559 sprintfW(pDeviceInstance, InstanceKeyFormat, Index); 1560 rc = RegCreateKeyExW(hClassKey, 1561 DriverKey, 1562 0, 1563 NULL, 1564 REG_OPTION_NON_VOLATILE, 1565 #if _WIN32_WINNT >= 0x502 1566 KEY_READ | KEY_WRITE, 1567 #else 1568 KEY_ALL_ACCESS, 1569 #endif 1570 NULL, 1571 &hKey, 1572 &Disposition); 1573 if (rc != ERROR_SUCCESS) 1574 { 1575 SetLastError(rc); 1576 goto cleanup; 1577 } 1578 if (Disposition == REG_CREATED_NEW_KEY) 1579 break; 1580 RegCloseKey(hKey); 1581 hKey = NULL; 1582 Index++; 1583 } 1584 1585 if (Index > 9999) 1586 { 1587 /* Unable to create more than 9999 devices within the same class */ 1588 SetLastError(ERROR_GEN_FAILURE); 1589 goto cleanup; 1590 } 1591 1592 /* Write the new Driver value */ 1593 rc = RegSetValueExW(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (strlenW(DriverKey) + 1) * sizeof(WCHAR)); 1594 if (rc != ERROR_SUCCESS) 1595 { 1596 SetLastError(rc); 1597 goto cleanup; 1598 } 1599 1600 } 1601 else 1602 { 1603 /* Open the existing driver key */ 1604 1605 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwSize); 1606 if (!DriverKey) 1607 { 1608 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1609 goto cleanup; 1610 } 1611 1612 rc = RegQueryValueExW(hDeviceKey, REGSTR_VAL_DRIVER, NULL, NULL, (LPBYTE)DriverKey, &dwSize); 1613 if (rc != ERROR_SUCCESS) 1614 { 1615 SetLastError(rc); 1616 goto cleanup; 1617 } 1618 1619 rc = RegCreateKeyExW(hClassKey, 1620 DriverKey, 1621 0, 1622 NULL, 1623 REG_OPTION_NON_VOLATILE, 1624 #if _WIN32_WINNT >= 0x502 1625 KEY_READ | KEY_WRITE, 1626 #else 1627 KEY_ALL_ACCESS, 1628 #endif 1629 NULL, 1630 &hKey, 1631 &Disposition); 1632 if (rc != ERROR_SUCCESS) 1633 { 1634 SetLastError(rc); 1635 goto cleanup; 1636 } 1637 } 1638 } 1639 1640 /* Do installation of the specified section */ 1641 if (InfHandle) 1642 { 1643 FIXME("Need to install section %s in file %p\n", 1644 debugstr_w(InfSectionName), InfHandle); 1645 } 1646 key = hKey; 1647 1648 cleanup: 1649 if (lpGuidString) 1650 RpcStringFreeW(&lpGuidString); 1651 HeapFree(GetProcessHeap(), 0, DriverKey); 1652 if (hHWProfileKey != INVALID_HANDLE_VALUE) 1653 RegCloseKey(hHWProfileKey); 1654 if (hEnumKey != NULL) 1655 RegCloseKey(hEnumKey); 1656 if (hClassKey != NULL) 1657 RegCloseKey(hClassKey); 1658 if (hDeviceKey != INVALID_HANDLE_VALUE) 1659 RegCloseKey(hDeviceKey); 1660 if (hKey != NULL && hKey != key) 1661 RegCloseKey(hKey); 1662 1663 TRACE("Returning 0x%p\n", key); 1664 return key; 1665 } 1666 1667 /*********************************************************************** 1668 * SetupDiCreateDeviceInfoA (SETUPAPI.@) 1669 */ 1670 BOOL WINAPI SetupDiCreateDeviceInfoA( 1671 HDEVINFO DeviceInfoSet, 1672 PCSTR DeviceName, 1673 CONST GUID *ClassGuid, 1674 PCSTR DeviceDescription, 1675 HWND hwndParent, 1676 DWORD CreationFlags, 1677 PSP_DEVINFO_DATA DeviceInfoData) 1678 { 1679 BOOL ret; 1680 LPWSTR DeviceNameW = NULL; 1681 LPWSTR DeviceDescriptionW = NULL; 1682 1683 TRACE("\n"); 1684 1685 if (DeviceName) 1686 { 1687 DeviceNameW = pSetupMultiByteToUnicode(DeviceName, CP_ACP); 1688 if (DeviceNameW == NULL) return FALSE; 1689 } 1690 if (DeviceDescription) 1691 { 1692 DeviceDescriptionW = pSetupMultiByteToUnicode(DeviceDescription, CP_ACP); 1693 if (DeviceDescriptionW == NULL) 1694 { 1695 MyFree(DeviceNameW); 1696 return FALSE; 1697 } 1698 } 1699 1700 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW, 1701 hwndParent, CreationFlags, DeviceInfoData); 1702 1703 MyFree(DeviceNameW); 1704 MyFree(DeviceDescriptionW); 1705 1706 return ret; 1707 } 1708 1709 /*********************************************************************** 1710 * SetupDiCreateDeviceInfoW (SETUPAPI.@) 1711 */ 1712 BOOL WINAPI SetupDiCreateDeviceInfoW( 1713 HDEVINFO DeviceInfoSet, 1714 PCWSTR DeviceName, 1715 CONST GUID *ClassGuid, 1716 PCWSTR DeviceDescription, 1717 HWND hwndParent, 1718 DWORD CreationFlags, 1719 PSP_DEVINFO_DATA DeviceInfoData) 1720 { 1721 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 1722 struct DeviceInfo *deviceInfo = NULL; 1723 BOOL ret = FALSE; 1724 CONFIGRET cr; 1725 DEVINST RootDevInst; 1726 DEVINST DevInst; 1727 WCHAR GenInstanceId[MAX_DEVICE_ID_LEN]; 1728 1729 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName), 1730 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription), 1731 hwndParent, CreationFlags, DeviceInfoData); 1732 1733 if (!DeviceName) 1734 { 1735 SetLastError(ERROR_INVALID_DEVINST_NAME); 1736 return FALSE; 1737 } 1738 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 1739 { 1740 SetLastError(ERROR_INVALID_HANDLE); 1741 return FALSE; 1742 } 1743 if (!ClassGuid) 1744 { 1745 SetLastError(ERROR_INVALID_PARAMETER); 1746 return FALSE; 1747 } 1748 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1749 { 1750 SetLastError(ERROR_INVALID_HANDLE); 1751 return FALSE; 1752 } 1753 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) && 1754 !IsEqualGUID(ClassGuid, &set->ClassGuid)) 1755 { 1756 SetLastError(ERROR_CLASS_MISMATCH); 1757 return FALSE; 1758 } 1759 if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS)) 1760 { 1761 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS)); 1762 SetLastError(ERROR_INVALID_FLAGS); 1763 return FALSE; 1764 } 1765 1766 /* Get the root device instance */ 1767 cr = CM_Locate_DevInst_ExW(&RootDevInst, 1768 NULL, 1769 CM_LOCATE_DEVINST_NORMAL, 1770 set->hMachine); 1771 if (cr != CR_SUCCESS) 1772 { 1773 SetLastError(ERROR_INVALID_DATA); 1774 return FALSE; 1775 } 1776 1777 /* Create the new device instance */ 1778 cr = CM_Create_DevInst_ExW(&DevInst, 1779 (DEVINSTID)DeviceName, 1780 RootDevInst, 1781 (CreationFlags & DICD_GENERATE_ID) ? 1782 CM_CREATE_DEVINST_GENERATE_ID : 0, 1783 set->hMachine); 1784 if (cr != CR_SUCCESS) 1785 { 1786 SetLastError(GetErrorCodeFromCrCode(cr)); 1787 return FALSE; 1788 } 1789 1790 if (CreationFlags & DICD_GENERATE_ID) 1791 { 1792 /* Grab the actual instance ID that was created */ 1793 cr = CM_Get_Device_ID_Ex(DevInst, 1794 GenInstanceId, 1795 MAX_DEVICE_ID_LEN, 1796 0, 1797 set->hMachine); 1798 if (cr != CR_SUCCESS) 1799 { 1800 SetLastError(GetErrorCodeFromCrCode(cr)); 1801 return FALSE; 1802 } 1803 1804 DeviceName = GenInstanceId; 1805 TRACE("Using generated instance ID: %s\n", debugstr_w(DeviceName)); 1806 } 1807 1808 if (CreateDeviceInfo(set, DeviceName, ClassGuid, &deviceInfo)) 1809 { 1810 InsertTailList(&set->ListHead, &deviceInfo->ListEntry); 1811 1812 if (!DeviceInfoData) 1813 ret = TRUE; 1814 else 1815 { 1816 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 1817 { 1818 SetLastError(ERROR_INVALID_USER_BUFFER); 1819 } 1820 else 1821 { 1822 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID)); 1823 DeviceInfoData->DevInst = deviceInfo->dnDevInst; 1824 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo; 1825 ret = TRUE; 1826 } 1827 } 1828 } 1829 1830 if (ret == FALSE) 1831 { 1832 if (deviceInfo != NULL) 1833 { 1834 /* Remove deviceInfo from List */ 1835 RemoveEntryList(&deviceInfo->ListEntry); 1836 1837 /* Destroy deviceInfo */ 1838 DestroyDeviceInfo(deviceInfo); 1839 } 1840 } 1841 1842 TRACE("Returning %d\n", ret); 1843 return ret; 1844 } 1845 1846 /*********************************************************************** 1847 * SetupDiRegisterDeviceInfo (SETUPAPI.@) 1848 */ 1849 BOOL WINAPI SetupDiRegisterDeviceInfo( 1850 HDEVINFO DeviceInfoSet, 1851 PSP_DEVINFO_DATA DeviceInfoData, 1852 DWORD Flags, 1853 PSP_DETSIG_CMPPROC CompareProc, 1854 PVOID CompareContext, 1855 PSP_DEVINFO_DATA DupDeviceInfoData) 1856 { 1857 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 1858 WCHAR DevInstId[MAX_DEVICE_ID_LEN]; 1859 DEVINST ParentDevInst; 1860 CONFIGRET cr; 1861 DWORD dwError = ERROR_SUCCESS; 1862 1863 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags, 1864 CompareProc, CompareContext, DupDeviceInfoData); 1865 1866 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 1867 { 1868 SetLastError(ERROR_INVALID_HANDLE); 1869 return FALSE; 1870 } 1871 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1872 { 1873 SetLastError(ERROR_INVALID_HANDLE); 1874 return FALSE; 1875 } 1876 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 1877 || !DeviceInfoData->Reserved) 1878 { 1879 SetLastError(ERROR_INVALID_PARAMETER); 1880 return FALSE; 1881 } 1882 1883 if (Flags & ~SPRDI_FIND_DUPS) 1884 { 1885 TRACE("Unknown flags: 0x%08lx\n", Flags & ~SPRDI_FIND_DUPS); 1886 SetLastError(ERROR_INVALID_FLAGS); 1887 return FALSE; 1888 } 1889 1890 if (Flags & SPRDI_FIND_DUPS) 1891 { 1892 FIXME("Unimplemented codepath!\n"); 1893 } 1894 1895 CM_Get_Device_ID_Ex(DeviceInfoData->DevInst, 1896 DevInstId, 1897 MAX_DEVICE_ID_LEN, 1898 0, 1899 set->hMachine); 1900 1901 CM_Get_Parent_Ex(&ParentDevInst, 1902 DeviceInfoData->DevInst, 1903 0, 1904 set->hMachine); 1905 1906 cr = CM_Create_DevInst_Ex(&DeviceInfoData->DevInst, 1907 DevInstId, 1908 ParentDevInst, 1909 CM_CREATE_DEVINST_NORMAL | CM_CREATE_DEVINST_DO_NOT_INSTALL, 1910 set->hMachine); 1911 if (cr != CR_SUCCESS && 1912 cr != CR_ALREADY_SUCH_DEVINST) 1913 { 1914 dwError = ERROR_NO_SUCH_DEVINST; 1915 } 1916 1917 SetLastError(dwError); 1918 1919 return (dwError == ERROR_SUCCESS); 1920 } 1921 1922 /*********************************************************************** 1923 * SetupDiEnumDeviceInfo (SETUPAPI.@) 1924 */ 1925 BOOL WINAPI SetupDiEnumDeviceInfo( 1926 HDEVINFO devinfo, 1927 DWORD index, 1928 PSP_DEVINFO_DATA info) 1929 { 1930 BOOL ret = FALSE; 1931 1932 TRACE("%p %d %p\n", devinfo, index, info); 1933 1934 if(info==NULL) 1935 { 1936 SetLastError(ERROR_INVALID_PARAMETER); 1937 return FALSE; 1938 } 1939 if (devinfo && devinfo != INVALID_HANDLE_VALUE) 1940 { 1941 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo; 1942 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC) 1943 { 1944 if (info->cbSize != sizeof(SP_DEVINFO_DATA)) 1945 SetLastError(ERROR_INVALID_USER_BUFFER); 1946 else 1947 { 1948 PLIST_ENTRY ItemList = list->ListHead.Flink; 1949 while (ItemList != &list->ListHead && index-- > 0) 1950 ItemList = ItemList->Flink; 1951 if (ItemList == &list->ListHead) 1952 SetLastError(ERROR_NO_MORE_ITEMS); 1953 else 1954 { 1955 struct DeviceInfo *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry); 1956 memcpy(&info->ClassGuid, 1957 &DevInfo->ClassGuid, 1958 sizeof(GUID)); 1959 info->DevInst = DevInfo->dnDevInst; 1960 info->Reserved = (ULONG_PTR)DevInfo; 1961 ret = TRUE; 1962 } 1963 } 1964 } 1965 else 1966 SetLastError(ERROR_INVALID_HANDLE); 1967 } 1968 else 1969 SetLastError(ERROR_INVALID_HANDLE); 1970 return ret; 1971 } 1972 1973 /*********************************************************************** 1974 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@) 1975 */ 1976 BOOL WINAPI SetupDiGetDeviceInstanceIdA( 1977 HDEVINFO DeviceInfoSet, 1978 PSP_DEVINFO_DATA DeviceInfoData, 1979 PSTR DeviceInstanceId, 1980 DWORD DeviceInstanceIdSize, 1981 PDWORD RequiredSize) 1982 { 1983 BOOL ret = FALSE; 1984 DWORD size; 1985 PWSTR instanceId; 1986 1987 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId, 1988 DeviceInstanceIdSize, RequiredSize); 1989 1990 if (!DeviceInstanceId && DeviceInstanceIdSize > 0) 1991 { 1992 SetLastError(ERROR_INVALID_PARAMETER); 1993 return FALSE; 1994 } 1995 1996 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, 1997 DeviceInfoData, 1998 NULL, 1999 0, 2000 &size); 2001 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER) 2002 return FALSE; 2003 instanceId = MyMalloc(size * sizeof(WCHAR)); 2004 if (instanceId) 2005 { 2006 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, 2007 DeviceInfoData, 2008 instanceId, 2009 size, 2010 &size); 2011 if (ret) 2012 { 2013 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1, 2014 DeviceInstanceId, 2015 DeviceInstanceIdSize, NULL, NULL); 2016 2017 if (!len) 2018 ret = FALSE; 2019 else 2020 { 2021 if (len > DeviceInstanceIdSize) 2022 { 2023 SetLastError(ERROR_INSUFFICIENT_BUFFER); 2024 ret = FALSE; 2025 } 2026 if (RequiredSize) 2027 *RequiredSize = len; 2028 } 2029 } 2030 MyFree(instanceId); 2031 } 2032 else 2033 { 2034 if (RequiredSize) 2035 *RequiredSize = size; 2036 SetLastError(ERROR_INSUFFICIENT_BUFFER); 2037 ret = FALSE; 2038 } 2039 return ret; 2040 } 2041 2042 /*********************************************************************** 2043 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@) 2044 */ 2045 BOOL WINAPI SetupDiGetDeviceInstanceIdW( 2046 HDEVINFO DeviceInfoSet, 2047 PSP_DEVINFO_DATA DeviceInfoData, 2048 PWSTR DeviceInstanceId, 2049 DWORD DeviceInstanceIdSize, 2050 PDWORD RequiredSize) 2051 { 2052 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2053 struct DeviceInfo *devInfo; 2054 2055 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId, 2056 DeviceInstanceIdSize, RequiredSize); 2057 2058 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 2059 { 2060 SetLastError(ERROR_INVALID_HANDLE); 2061 return FALSE; 2062 } 2063 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2064 { 2065 SetLastError(ERROR_INVALID_HANDLE); 2066 return FALSE; 2067 } 2068 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 2069 || !DeviceInfoData->Reserved) 2070 { 2071 SetLastError(ERROR_INVALID_PARAMETER); 2072 return FALSE; 2073 } 2074 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 2075 if (!DeviceInstanceId && DeviceInstanceIdSize > 0) 2076 { 2077 SetLastError(ERROR_INVALID_PARAMETER); 2078 return FALSE; 2079 } 2080 if (DeviceInstanceId && DeviceInstanceIdSize == 0) 2081 { 2082 SetLastError(ERROR_INVALID_PARAMETER); 2083 return FALSE; 2084 } 2085 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId)); 2086 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1) 2087 { 2088 SetLastError(ERROR_INSUFFICIENT_BUFFER); 2089 if (RequiredSize) 2090 *RequiredSize = lstrlenW(devInfo->instanceId) + 1; 2091 return FALSE; 2092 } 2093 lstrcpyW(DeviceInstanceId, devInfo->instanceId); 2094 if (RequiredSize) 2095 *RequiredSize = lstrlenW(devInfo->instanceId) + 1; 2096 return TRUE; 2097 } 2098 2099 /*********************************************************************** 2100 * SetupDiGetActualSectionToInstallA (SETUPAPI.@) 2101 */ 2102 BOOL WINAPI SetupDiGetActualSectionToInstallA( 2103 HINF InfHandle, 2104 PCSTR InfSectionName, 2105 PSTR InfSectionWithExt, 2106 DWORD InfSectionWithExtSize, 2107 PDWORD RequiredSize, 2108 PSTR *Extension) 2109 { 2110 return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName, 2111 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize, 2112 Extension, NULL); 2113 } 2114 2115 /*********************************************************************** 2116 * SetupDiGetActualSectionToInstallW (SETUPAPI.@) 2117 */ 2118 BOOL WINAPI SetupDiGetActualSectionToInstallW( 2119 HINF InfHandle, 2120 PCWSTR InfSectionName, 2121 PWSTR InfSectionWithExt, 2122 DWORD InfSectionWithExtSize, 2123 PDWORD RequiredSize, 2124 PWSTR *Extension) 2125 { 2126 return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName, 2127 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize, 2128 Extension, NULL); 2129 } 2130 2131 /*********************************************************************** 2132 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@) 2133 */ 2134 BOOL WINAPI 2135 SetupDiGetActualSectionToInstallExA( 2136 IN HINF InfHandle, 2137 IN PCSTR InfSectionName, 2138 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL, 2139 OUT PSTR InfSectionWithExt OPTIONAL, 2140 IN DWORD InfSectionWithExtSize, 2141 OUT PDWORD RequiredSize OPTIONAL, 2142 OUT PSTR* Extension OPTIONAL, 2143 IN PVOID Reserved) 2144 { 2145 LPWSTR InfSectionNameW = NULL; 2146 LPWSTR InfSectionWithExtW = NULL; 2147 PWSTR ExtensionW; 2148 BOOL bResult = FALSE; 2149 2150 TRACE("\n"); 2151 2152 if (InfSectionName) 2153 { 2154 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP); 2155 if (InfSectionNameW == NULL) 2156 goto cleanup; 2157 } 2158 if (InfSectionWithExt) 2159 { 2160 InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR)); 2161 if (InfSectionWithExtW == NULL) 2162 goto cleanup; 2163 } 2164 2165 bResult = SetupDiGetActualSectionToInstallExW( 2166 InfHandle, InfSectionNameW, AlternatePlatformInfo, 2167 InfSectionWithExt ? InfSectionWithExtW : NULL, 2168 InfSectionWithExtSize, 2169 RequiredSize, 2170 Extension ? &ExtensionW : NULL, 2171 Reserved); 2172 2173 if (bResult && InfSectionWithExt) 2174 { 2175 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt, 2176 InfSectionWithExtSize, NULL, NULL) != 0; 2177 } 2178 if (bResult && Extension) 2179 { 2180 if (ExtensionW == NULL) 2181 *Extension = NULL; 2182 else 2183 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW]; 2184 } 2185 2186 cleanup: 2187 MyFree(InfSectionNameW); 2188 MyFree(InfSectionWithExtW); 2189 2190 return bResult; 2191 } 2192 2193 /*********************************************************************** 2194 * SetupDiGetClassDescriptionA (SETUPAPI.@) 2195 */ 2196 BOOL WINAPI SetupDiGetClassDescriptionA( 2197 const GUID* ClassGuid, 2198 PSTR ClassDescription, 2199 DWORD ClassDescriptionSize, 2200 PDWORD RequiredSize) 2201 { 2202 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription, 2203 ClassDescriptionSize, 2204 RequiredSize, NULL, NULL); 2205 } 2206 2207 /*********************************************************************** 2208 * SetupDiGetClassDescriptionW (SETUPAPI.@) 2209 */ 2210 BOOL WINAPI SetupDiGetClassDescriptionW( 2211 const GUID* ClassGuid, 2212 PWSTR ClassDescription, 2213 DWORD ClassDescriptionSize, 2214 PDWORD RequiredSize) 2215 { 2216 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription, 2217 ClassDescriptionSize, 2218 RequiredSize, NULL, NULL); 2219 } 2220 2221 /*********************************************************************** 2222 * SetupDiGetClassDescriptionExA (SETUPAPI.@) 2223 */ 2224 BOOL WINAPI SetupDiGetClassDescriptionExA( 2225 const GUID* ClassGuid, 2226 PSTR ClassDescription, 2227 DWORD ClassDescriptionSize, 2228 PDWORD RequiredSize, 2229 PCSTR MachineName, 2230 PVOID Reserved) 2231 { 2232 PWCHAR ClassDescriptionW = NULL; 2233 LPWSTR MachineNameW = NULL; 2234 BOOL ret = FALSE; 2235 2236 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription, 2237 ClassDescriptionSize, RequiredSize, debugstr_a(MachineName), Reserved); 2238 2239 if (ClassDescriptionSize > 0) 2240 { 2241 ClassDescriptionW = MyMalloc(ClassDescriptionSize * sizeof(WCHAR)); 2242 if (!ClassDescriptionW) 2243 { 2244 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 2245 goto cleanup; 2246 } 2247 } 2248 2249 if (MachineName) 2250 { 2251 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 2252 if (!MachineNameW) 2253 { 2254 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 2255 goto cleanup; 2256 } 2257 } 2258 2259 ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW, 2260 ClassDescriptionSize * sizeof(WCHAR), RequiredSize, MachineNameW, Reserved); 2261 if (ret) 2262 { 2263 DWORD len = (DWORD)WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription, 2264 ClassDescriptionSize, NULL, NULL); 2265 if (len == 0 || len > ClassDescriptionSize) 2266 { 2267 SetLastError(ERROR_INSUFFICIENT_BUFFER); 2268 ret = FALSE; 2269 } 2270 } 2271 2272 cleanup: 2273 MyFree(ClassDescriptionW); 2274 MyFree(MachineNameW); 2275 return ret; 2276 } 2277 2278 /*********************************************************************** 2279 * SetupDiGetClassDescriptionExW (SETUPAPI.@) 2280 */ 2281 BOOL WINAPI SetupDiGetClassDescriptionExW( 2282 const GUID* ClassGuid, 2283 PWSTR ClassDescription, 2284 DWORD ClassDescriptionSize, 2285 PDWORD RequiredSize, 2286 PCWSTR MachineName, 2287 PVOID Reserved) 2288 { 2289 HKEY hKey; 2290 DWORD dwLength; 2291 DWORD dwRegType; 2292 LONG rc; 2293 PWSTR Buffer; 2294 2295 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription, 2296 ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved); 2297 2298 /* Make sure there's a GUID */ 2299 if (!ClassGuid) 2300 { 2301 SetLastError(ERROR_INVALID_PARAMETER); 2302 return FALSE; 2303 } 2304 2305 /* Make sure there's a real buffer when there's a size */ 2306 if (!ClassDescription && ClassDescriptionSize > 0) 2307 { 2308 SetLastError(ERROR_INVALID_PARAMETER); 2309 return FALSE; 2310 } 2311 2312 /* Open the key for the GUID */ 2313 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, 2314 KEY_QUERY_VALUE, 2315 DIOCR_INSTALLER, 2316 MachineName, 2317 Reserved); 2318 if (hKey == INVALID_HANDLE_VALUE) 2319 return FALSE; 2320 2321 /* Retrieve the class description data and close the key */ 2322 rc = QueryRegistryValue(hKey, NULL, (LPBYTE *) &Buffer, &dwRegType, &dwLength); 2323 RegCloseKey(hKey); 2324 2325 /* Make sure we got the data */ 2326 if (rc != ERROR_SUCCESS) 2327 { 2328 SetLastError(rc); 2329 return FALSE; 2330 } 2331 2332 /* Make sure the data is a string */ 2333 if (dwRegType != REG_SZ) 2334 { 2335 MyFree(Buffer); 2336 SetLastError(ERROR_GEN_FAILURE); 2337 return FALSE; 2338 } 2339 2340 /* Determine the length of the class description */ 2341 dwLength /= sizeof(WCHAR); 2342 2343 /* Count the null-terminator if none is present */ 2344 if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL)) 2345 dwLength++; 2346 2347 /* Inform the caller about the class description */ 2348 if ((ClassDescription != NULL) && (dwLength <= ClassDescriptionSize)) 2349 { 2350 memcpy(ClassDescription, Buffer, (dwLength - 1) * sizeof(WCHAR)); 2351 ClassDescription[dwLength - 1] = UNICODE_NULL; 2352 } 2353 2354 /* Inform the caller about the required size */ 2355 if (RequiredSize != NULL) 2356 *RequiredSize = dwLength; 2357 2358 /* Clean up the buffer */ 2359 MyFree(Buffer); 2360 2361 /* Make sure the buffer was large enough */ 2362 if ((ClassDescription == NULL) || (dwLength > ClassDescriptionSize)) 2363 { 2364 SetLastError(ERROR_INSUFFICIENT_BUFFER); 2365 return FALSE; 2366 } 2367 2368 return TRUE; 2369 } 2370 2371 /*********************************************************************** 2372 * SetupDiGetClassDevsA (SETUPAPI.@) 2373 */ 2374 HDEVINFO WINAPI SetupDiGetClassDevsA( 2375 CONST GUID *class, 2376 LPCSTR enumstr, 2377 HWND parent, 2378 DWORD flags) 2379 { 2380 return SetupDiGetClassDevsExA(class, enumstr, parent, 2381 flags, NULL, NULL, NULL); 2382 } 2383 2384 /*********************************************************************** 2385 * SetupDiGetClassDevsExA (SETUPAPI.@) 2386 */ 2387 HDEVINFO WINAPI SetupDiGetClassDevsExA( 2388 const GUID *class, 2389 PCSTR enumstr, 2390 HWND parent, 2391 DWORD flags, 2392 HDEVINFO deviceset, 2393 PCSTR machine, 2394 PVOID reserved) 2395 { 2396 HDEVINFO ret; 2397 LPWSTR enumstrW = NULL, machineW = NULL; 2398 2399 if (enumstr) 2400 { 2401 enumstrW = pSetupMultiByteToUnicode(enumstr, CP_ACP); 2402 if (!enumstrW) 2403 { 2404 ret = INVALID_HANDLE_VALUE; 2405 goto end; 2406 } 2407 } 2408 if (machine) 2409 { 2410 machineW = pSetupMultiByteToUnicode(machine, CP_ACP); 2411 if (!machineW) 2412 { 2413 MyFree(enumstrW); 2414 ret = INVALID_HANDLE_VALUE; 2415 goto end; 2416 } 2417 } 2418 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset, 2419 machineW, reserved); 2420 MyFree(enumstrW); 2421 MyFree(machineW); 2422 2423 end: 2424 return ret; 2425 } 2426 2427 /*********************************************************************** 2428 * SetupDiGetClassDevsW (SETUPAPI.@) 2429 */ 2430 HDEVINFO WINAPI SetupDiGetClassDevsW( 2431 CONST GUID *class, 2432 LPCWSTR enumstr, 2433 HWND parent, 2434 DWORD flags) 2435 { 2436 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL, 2437 NULL); 2438 } 2439 2440 /*********************************************************************** 2441 * SetupDiGetClassDevsExW (SETUPAPI.@) 2442 */ 2443 HDEVINFO WINAPI SetupDiGetClassDevsExW( 2444 CONST GUID *class, 2445 PCWSTR enumstr, 2446 HWND parent, 2447 DWORD flags, 2448 HDEVINFO deviceset, 2449 PCWSTR machine, 2450 PVOID reserved) 2451 { 2452 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE; 2453 struct DeviceInfoSet *list; 2454 CONST GUID *pClassGuid; 2455 LONG rc; 2456 HDEVINFO set = INVALID_HANDLE_VALUE; 2457 2458 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class), 2459 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine), 2460 reserved); 2461 2462 if (!(flags & DIGCF_ALLCLASSES) && !class) 2463 { 2464 SetLastError(ERROR_INVALID_PARAMETER); 2465 return INVALID_HANDLE_VALUE; 2466 } 2467 2468 /* Create the deviceset if not set */ 2469 if (deviceset) 2470 { 2471 list = (struct DeviceInfoSet *)deviceset; 2472 if (list->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2473 { 2474 SetLastError(ERROR_INVALID_HANDLE); 2475 goto cleanup; 2476 } 2477 hDeviceInfo = deviceset; 2478 } 2479 else 2480 { 2481 hDeviceInfo = SetupDiCreateDeviceInfoListExW( 2482 flags & (DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES) ? NULL : class, 2483 NULL, machine, NULL); 2484 if (hDeviceInfo == INVALID_HANDLE_VALUE) 2485 goto cleanup; 2486 list = (struct DeviceInfoSet *)hDeviceInfo; 2487 } 2488 2489 if (flags & DIGCF_PROFILE) 2490 FIXME(": flag DIGCF_PROFILE ignored\n"); 2491 2492 if (flags & DIGCF_DEVICEINTERFACE) 2493 { 2494 if (!class) 2495 { 2496 SetLastError(ERROR_INVALID_PARAMETER); 2497 goto cleanup; 2498 } 2499 rc = SETUP_CreateInterfaceList(list, machine, class, enumstr, flags & DIGCF_PRESENT); 2500 } 2501 else 2502 { 2503 /* Determine which class(es) should be included in the deviceset */ 2504 if (flags & DIGCF_ALLCLASSES) 2505 { 2506 /* The caller wants all classes. Check if 2507 * the deviceset limits us to one class */ 2508 if (IsEqualIID(&list->ClassGuid, &GUID_NULL)) 2509 pClassGuid = NULL; 2510 else 2511 pClassGuid = &list->ClassGuid; 2512 } 2513 else if (class) 2514 { 2515 /* The caller wants one class. Check if it matches deviceset class */ 2516 if (IsEqualIID(&list->ClassGuid, class) 2517 || IsEqualIID(&list->ClassGuid, &GUID_NULL)) 2518 { 2519 pClassGuid = class; 2520 } 2521 else 2522 { 2523 SetLastError(ERROR_INVALID_PARAMETER); 2524 goto cleanup; 2525 } 2526 } 2527 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL)) 2528 { 2529 /* No class specified. Try to use the one of the deviceset */ 2530 if (IsEqualIID(&list->ClassGuid, &GUID_NULL)) 2531 pClassGuid = &list->ClassGuid; 2532 else 2533 { 2534 SetLastError(ERROR_INVALID_PARAMETER); 2535 goto cleanup; 2536 } 2537 } 2538 else 2539 { 2540 SetLastError(ERROR_INVALID_PARAMETER); 2541 goto cleanup; 2542 } 2543 rc = SETUP_CreateDevicesList(list, machine, pClassGuid, enumstr); 2544 } 2545 if (rc != ERROR_SUCCESS) 2546 { 2547 SetLastError(rc); 2548 goto cleanup; 2549 } 2550 set = hDeviceInfo; 2551 2552 cleanup: 2553 if (!deviceset && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != set) 2554 SetupDiDestroyDeviceInfoList(hDeviceInfo); 2555 return set; 2556 } 2557 2558 /*********************************************************************** 2559 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@) 2560 */ 2561 BOOL WINAPI SetupDiGetDeviceInfoListDetailA( 2562 HDEVINFO DeviceInfoSet, 2563 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData ) 2564 { 2565 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2566 2567 TRACE("%p %p\n", DeviceInfoSet, DevInfoData); 2568 2569 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 2570 { 2571 SetLastError(ERROR_INVALID_HANDLE); 2572 return FALSE; 2573 } 2574 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2575 { 2576 SetLastError(ERROR_INVALID_HANDLE); 2577 return FALSE; 2578 } 2579 if (!DevInfoData || 2580 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A)) 2581 { 2582 SetLastError(ERROR_INVALID_PARAMETER); 2583 return FALSE; 2584 } 2585 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID)); 2586 DevInfoData->RemoteMachineHandle = set->hMachine; 2587 if (set->MachineName) 2588 { 2589 FIXME("Stub\n"); 2590 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2591 return FALSE; 2592 } 2593 else 2594 DevInfoData->RemoteMachineName[0] = 0; 2595 2596 return TRUE; 2597 } 2598 2599 /*********************************************************************** 2600 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@) 2601 */ 2602 BOOL WINAPI SetupDiGetDeviceInfoListDetailW( 2603 HDEVINFO DeviceInfoSet, 2604 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData ) 2605 { 2606 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2607 2608 TRACE("%p %p\n", DeviceInfoSet, DevInfoData); 2609 2610 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 2611 { 2612 SetLastError(ERROR_INVALID_HANDLE); 2613 return FALSE; 2614 } 2615 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2616 { 2617 SetLastError(ERROR_INVALID_HANDLE); 2618 return FALSE; 2619 } 2620 if (!DevInfoData || 2621 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W)) 2622 { 2623 SetLastError(ERROR_INVALID_PARAMETER); 2624 return FALSE; 2625 } 2626 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID)); 2627 DevInfoData->RemoteMachineHandle = set->hMachine; 2628 if (set->MachineName) 2629 strcpyW(DevInfoData->RemoteMachineName, set->MachineName + 2); 2630 else 2631 DevInfoData->RemoteMachineName[0] = 0; 2632 2633 return TRUE; 2634 } 2635 2636 /*********************************************************************** 2637 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@) 2638 */ 2639 BOOL WINAPI SetupDiCreateDeviceInterfaceA( 2640 HDEVINFO DeviceInfoSet, 2641 PSP_DEVINFO_DATA DeviceInfoData, 2642 const GUID *InterfaceClassGuid, 2643 PCSTR ReferenceString, 2644 DWORD CreationFlags, 2645 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 2646 { 2647 BOOL ret; 2648 LPWSTR ReferenceStringW = NULL; 2649 2650 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData, 2651 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString), 2652 CreationFlags, DeviceInterfaceData); 2653 2654 if (ReferenceString) 2655 { 2656 ReferenceStringW = pSetupMultiByteToUnicode(ReferenceString, CP_ACP); 2657 if (ReferenceStringW == NULL) return FALSE; 2658 } 2659 2660 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData, 2661 InterfaceClassGuid, ReferenceStringW, CreationFlags, 2662 DeviceInterfaceData); 2663 2664 MyFree(ReferenceStringW); 2665 2666 return ret; 2667 } 2668 2669 /*********************************************************************** 2670 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@) 2671 */ 2672 BOOL WINAPI SetupDiCreateDeviceInterfaceW( 2673 HDEVINFO DeviceInfoSet, 2674 PSP_DEVINFO_DATA DeviceInfoData, 2675 const GUID *InterfaceClassGuid, 2676 PCWSTR ReferenceString, 2677 DWORD CreationFlags, 2678 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 2679 { 2680 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2681 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData, 2682 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString), 2683 CreationFlags, DeviceInterfaceData); 2684 2685 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 2686 { 2687 SetLastError(ERROR_INVALID_HANDLE); 2688 return FALSE; 2689 } 2690 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2691 { 2692 SetLastError(ERROR_INVALID_HANDLE); 2693 return FALSE; 2694 } 2695 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 2696 || !DeviceInfoData->Reserved) 2697 { 2698 SetLastError(ERROR_INVALID_PARAMETER); 2699 return FALSE; 2700 } 2701 if (!InterfaceClassGuid) 2702 { 2703 SetLastError(ERROR_INVALID_USER_BUFFER); 2704 return FALSE; 2705 } 2706 2707 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData, 2708 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString), 2709 CreationFlags, DeviceInterfaceData); 2710 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2711 return FALSE; 2712 } 2713 2714 /*********************************************************************** 2715 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@) 2716 */ 2717 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA( 2718 HDEVINFO DeviceInfoSet, 2719 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 2720 DWORD Reserved, 2721 REGSAM samDesired, 2722 HINF InfHandle, 2723 PCSTR InfSectionName) 2724 { 2725 HKEY key; 2726 PWSTR InfSectionNameW = NULL; 2727 2728 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved, 2729 samDesired, InfHandle, InfSectionName); 2730 if (InfHandle) 2731 { 2732 if (!InfSectionName) 2733 { 2734 SetLastError(ERROR_INVALID_PARAMETER); 2735 return INVALID_HANDLE_VALUE; 2736 } 2737 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP); 2738 if (!InfSectionNameW) 2739 return INVALID_HANDLE_VALUE; 2740 } 2741 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet, 2742 DeviceInterfaceData, Reserved, samDesired, InfHandle, 2743 InfSectionNameW); 2744 MyFree(InfSectionNameW); 2745 return key; 2746 } 2747 2748 /*********************************************************************** 2749 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@) 2750 */ 2751 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW( 2752 HDEVINFO DeviceInfoSet, 2753 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 2754 DWORD Reserved, 2755 REGSAM samDesired, 2756 HINF InfHandle, 2757 PCWSTR InfSectionName) 2758 { 2759 HKEY hKey, hDevKey; 2760 LPWSTR SymbolicLink; 2761 DWORD Length, Index; 2762 LONG rc; 2763 WCHAR bracedGuidString[39]; 2764 struct DeviceInterface *DevItf; 2765 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2766 2767 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved, 2768 samDesired, InfHandle, InfSectionName); 2769 2770 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 2771 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2772 { 2773 SetLastError(ERROR_INVALID_HANDLE); 2774 return INVALID_HANDLE_VALUE; 2775 } 2776 if (!DeviceInterfaceData || 2777 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || 2778 !DeviceInterfaceData->Reserved) 2779 { 2780 SetLastError(ERROR_INVALID_PARAMETER); 2781 return INVALID_HANDLE_VALUE; 2782 } 2783 if (InfHandle && !InfSectionName) 2784 { 2785 SetLastError(ERROR_INVALID_PARAMETER); 2786 return INVALID_HANDLE_VALUE; 2787 } 2788 2789 hKey = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid, samDesired, DIOCR_INTERFACE, NULL, NULL); 2790 if (hKey == INVALID_HANDLE_VALUE) 2791 { 2792 hKey = SetupDiOpenClassRegKeyExW(NULL, samDesired, DIOCR_INTERFACE, NULL, NULL); 2793 if (hKey == INVALID_HANDLE_VALUE) 2794 { 2795 SetLastError(ERROR_INVALID_PARAMETER); 2796 return INVALID_HANDLE_VALUE; 2797 } 2798 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid, bracedGuidString); 2799 2800 if (RegCreateKeyExW(hKey, bracedGuidString, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL) != ERROR_SUCCESS) 2801 { 2802 SetLastError(ERROR_INVALID_PARAMETER); 2803 return INVALID_HANDLE_VALUE; 2804 } 2805 RegCloseKey(hKey); 2806 hKey = hDevKey; 2807 } 2808 2809 DevItf = (struct DeviceInterface *)DeviceInterfaceData->Reserved; 2810 2811 Length = (wcslen(DevItf->SymbolicLink)+1) * sizeof(WCHAR); 2812 SymbolicLink = HeapAlloc(GetProcessHeap(), 0, Length); 2813 if (!SymbolicLink) 2814 { 2815 RegCloseKey(hKey); 2816 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 2817 return INVALID_HANDLE_VALUE; 2818 } 2819 2820 wcscpy(SymbolicLink, DevItf->SymbolicLink); 2821 2822 Index = 0; 2823 while(SymbolicLink[Index]) 2824 { 2825 if (SymbolicLink[Index] == L'\\') 2826 { 2827 SymbolicLink[Index] = L'#'; 2828 } 2829 Index++; 2830 } 2831 2832 rc = RegCreateKeyExW(hKey, SymbolicLink, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL); 2833 2834 RegCloseKey(hKey); 2835 HeapFree(GetProcessHeap(), 0, SymbolicLink); 2836 2837 if (rc == ERROR_SUCCESS) 2838 { 2839 if (InfHandle && InfSectionName) 2840 { 2841 if (!SetupInstallFromInfSection(NULL /*FIXME */, 2842 InfHandle, 2843 InfSectionName, 2844 SPINST_INIFILES | SPINST_REGISTRY | SPINST_INI2REG | SPINST_FILES | SPINST_BITREG | SPINST_REGSVR | SPINST_UNREGSVR | SPINST_PROFILEITEMS | SPINST_COPYINF, 2845 hDevKey, 2846 NULL, 2847 0, 2848 set->SelectedDevice->InstallParams.InstallMsgHandler, 2849 set->SelectedDevice->InstallParams.InstallMsgHandlerContext, 2850 INVALID_HANDLE_VALUE, 2851 NULL)) 2852 { 2853 RegCloseKey(hDevKey); 2854 return INVALID_HANDLE_VALUE; 2855 } 2856 } 2857 } 2858 2859 SetLastError(rc); 2860 return hDevKey; 2861 } 2862 2863 /*********************************************************************** 2864 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@) 2865 */ 2866 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey( 2867 HDEVINFO DeviceInfoSet, 2868 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 2869 DWORD Reserved) 2870 { 2871 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2872 BOOL ret = FALSE; 2873 2874 TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved); 2875 2876 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 2877 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2878 { 2879 SetLastError(ERROR_INVALID_HANDLE); 2880 return FALSE; 2881 } 2882 if (!DeviceInterfaceData || 2883 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || 2884 !DeviceInterfaceData->Reserved) 2885 { 2886 SetLastError(ERROR_INVALID_PARAMETER); 2887 return FALSE; 2888 } 2889 2890 FIXME("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved); 2891 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2892 return ret; 2893 } 2894 2895 /*********************************************************************** 2896 * SetupDiEnumDeviceInterfaces (SETUPAPI.@) 2897 * 2898 * PARAMS 2899 * DeviceInfoSet [I] Set of devices from which to enumerate 2900 * interfaces 2901 * DeviceInfoData [I] (Optional) If specified, a specific device 2902 * instance from which to enumerate interfaces. 2903 * If it isn't specified, all interfaces for all 2904 * devices in the set are enumerated. 2905 * InterfaceClassGuid [I] The interface class to enumerate. 2906 * MemberIndex [I] An index of the interface instance to enumerate. 2907 * A caller should start with MemberIndex set to 0, 2908 * and continue until the function fails with 2909 * ERROR_NO_MORE_ITEMS. 2910 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize 2911 * member must be set to 2912 * sizeof(SP_DEVICE_INTERFACE_DATA). 2913 * 2914 * RETURNS 2915 * Success: non-zero value. 2916 * Failure: FALSE. Call GetLastError() for more info. 2917 */ 2918 BOOL WINAPI SetupDiEnumDeviceInterfaces( 2919 HDEVINFO DeviceInfoSet, 2920 PSP_DEVINFO_DATA DeviceInfoData, 2921 CONST GUID * InterfaceClassGuid, 2922 DWORD MemberIndex, 2923 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 2924 { 2925 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2926 BOOL ret = FALSE; 2927 2928 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData, 2929 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData); 2930 2931 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 2932 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2933 { 2934 SetLastError(ERROR_INVALID_HANDLE); 2935 return FALSE; 2936 } 2937 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) || 2938 !DeviceInfoData->Reserved)) 2939 { 2940 SetLastError(ERROR_INVALID_PARAMETER); 2941 return FALSE; 2942 } 2943 if (!DeviceInterfaceData || 2944 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA)) 2945 { 2946 SetLastError(ERROR_INVALID_PARAMETER); 2947 return FALSE; 2948 } 2949 if (DeviceInfoData) 2950 { 2951 struct DeviceInfo *devInfo = 2952 (struct DeviceInfo *)DeviceInfoData->Reserved; 2953 BOOL found = FALSE; 2954 PLIST_ENTRY InterfaceListEntry = devInfo->InterfaceListHead.Flink; 2955 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found) 2956 { 2957 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry); 2958 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid)) 2959 { 2960 InterfaceListEntry = InterfaceListEntry->Flink; 2961 continue; 2962 } 2963 if (MemberIndex-- == 0) 2964 { 2965 /* return this item */ 2966 memcpy(&DeviceInterfaceData->InterfaceClassGuid, 2967 &DevItf->InterfaceClassGuid, 2968 sizeof(GUID)); 2969 DeviceInterfaceData->Flags = DevItf->Flags; 2970 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf; 2971 found = TRUE; 2972 ret = TRUE; 2973 } 2974 InterfaceListEntry = InterfaceListEntry->Flink; 2975 } 2976 if (!found) 2977 SetLastError(ERROR_NO_MORE_ITEMS); 2978 } 2979 else 2980 { 2981 BOOL found = FALSE; 2982 PLIST_ENTRY ItemList = set->ListHead.Flink; 2983 while (ItemList != &set->ListHead && !found) 2984 { 2985 PLIST_ENTRY InterfaceListEntry; 2986 struct DeviceInfo *devInfo = 2987 CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry); 2988 InterfaceListEntry = devInfo->InterfaceListHead.Flink; 2989 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found) 2990 { 2991 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry); 2992 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid)) 2993 { 2994 InterfaceListEntry = InterfaceListEntry->Flink; 2995 continue; 2996 } 2997 if (MemberIndex-- == 0) 2998 { 2999 /* return this item */ 3000 memcpy(&DeviceInterfaceData->InterfaceClassGuid, 3001 &DevItf->InterfaceClassGuid, 3002 sizeof(GUID)); 3003 DeviceInterfaceData->Flags = DevItf->Flags; 3004 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf; 3005 found = TRUE; 3006 ret = TRUE; 3007 } 3008 InterfaceListEntry = InterfaceListEntry->Flink; 3009 } 3010 ItemList = ItemList->Flink; 3011 3012 } 3013 if (!found) 3014 SetLastError(ERROR_NO_MORE_ITEMS); 3015 } 3016 return ret; 3017 } 3018 3019 /*********************************************************************** 3020 * SetupDiDestroyDeviceInfoList (SETUPAPI.@) 3021 * 3022 * Destroy a DeviceInfoList and free all used memory of the list. 3023 * 3024 * PARAMS 3025 * devinfo [I] DeviceInfoList pointer to list to destroy 3026 * 3027 * RETURNS 3028 * Success: non zero value. 3029 * Failure: zero value. 3030 */ 3031 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo) 3032 { 3033 BOOL ret = FALSE; 3034 3035 TRACE("%p\n", devinfo); 3036 if (devinfo && devinfo != INVALID_HANDLE_VALUE) 3037 { 3038 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo; 3039 3040 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC) 3041 { 3042 ret = DestroyDeviceInfoSet(list); 3043 } 3044 } 3045 3046 if (ret == FALSE) 3047 SetLastError(ERROR_INVALID_HANDLE); 3048 3049 return ret; 3050 } 3051 3052 /*********************************************************************** 3053 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@) 3054 */ 3055 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA( 3056 HDEVINFO DeviceInfoSet, 3057 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 3058 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData, 3059 DWORD DeviceInterfaceDetailDataSize, 3060 PDWORD RequiredSize, 3061 PSP_DEVINFO_DATA DeviceInfoData) 3062 { 3063 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 3064 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL; 3065 DWORD sizeW = 0, bytesNeeded; 3066 BOOL ret = FALSE; 3067 3068 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet, 3069 DeviceInterfaceData, DeviceInterfaceDetailData, 3070 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); 3071 3072 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 3073 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 3074 { 3075 SetLastError(ERROR_INVALID_HANDLE); 3076 return FALSE; 3077 } 3078 if (!DeviceInterfaceData || 3079 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || 3080 !DeviceInterfaceData->Reserved) 3081 { 3082 SetLastError(ERROR_INVALID_PARAMETER); 3083 return FALSE; 3084 } 3085 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))) 3086 { 3087 SetLastError(ERROR_INVALID_USER_BUFFER); 3088 return FALSE; 3089 } 3090 3091 if((DeviceInterfaceDetailDataSize != 0) && 3092 (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(CHAR)))) 3093 { 3094 SetLastError(ERROR_INVALID_USER_BUFFER); 3095 return FALSE; 3096 } 3097 3098 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize) 3099 { 3100 SetLastError(ERROR_INVALID_USER_BUFFER); 3101 return FALSE; 3102 } 3103 3104 3105 if (DeviceInterfaceDetailData != NULL) 3106 { 3107 sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) 3108 + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR); 3109 DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)MyMalloc(sizeW); 3110 if (!DeviceInterfaceDetailDataW) 3111 { 3112 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3113 } 3114 DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); 3115 } 3116 if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW)) 3117 { 3118 ret = SetupDiGetDeviceInterfaceDetailW( 3119 DeviceInfoSet, 3120 DeviceInterfaceData, 3121 DeviceInterfaceDetailDataW, 3122 sizeW, 3123 &sizeW, 3124 DeviceInfoData); 3125 bytesNeeded = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR) 3126 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath); 3127 if (RequiredSize) 3128 *RequiredSize = bytesNeeded; 3129 if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize >= bytesNeeded) 3130 { 3131 if (!WideCharToMultiByte( 3132 CP_ACP, 0, 3133 DeviceInterfaceDetailDataW->DevicePath, -1, 3134 DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath), 3135 NULL, NULL)) 3136 { 3137 ret = FALSE; 3138 } 3139 } 3140 } 3141 MyFree(DeviceInterfaceDetailDataW); 3142 3143 return ret; 3144 } 3145 3146 /*********************************************************************** 3147 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@) 3148 */ 3149 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW( 3150 HDEVINFO DeviceInfoSet, 3151 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 3152 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData, 3153 DWORD DeviceInterfaceDetailDataSize, 3154 PDWORD RequiredSize, 3155 PSP_DEVINFO_DATA DeviceInfoData) 3156 { 3157 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 3158 BOOL ret = FALSE; 3159 3160 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet, 3161 DeviceInterfaceData, DeviceInterfaceDetailData, 3162 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); 3163 3164 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 3165 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 3166 { 3167 SetLastError(ERROR_INVALID_HANDLE); 3168 return FALSE; 3169 } 3170 if (!DeviceInterfaceData || 3171 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || 3172 !DeviceInterfaceData->Reserved) 3173 { 3174 SetLastError(ERROR_INVALID_PARAMETER); 3175 return FALSE; 3176 } 3177 if (DeviceInterfaceDetailData && DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)) 3178 { 3179 SetLastError(ERROR_INVALID_USER_BUFFER); 3180 return FALSE; 3181 } 3182 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize) 3183 { 3184 SetLastError(ERROR_INVALID_USER_BUFFER); 3185 return FALSE; 3186 } 3187 if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 3188 { 3189 SetLastError(ERROR_INVALID_PARAMETER); 3190 return FALSE; 3191 } 3192 if ((DeviceInterfaceDetailData != NULL) 3193 && (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) + sizeof(WCHAR))) 3194 { 3195 SetLastError(ERROR_INVALID_PARAMETER); 3196 return FALSE; 3197 } 3198 else 3199 { 3200 struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved; 3201 LPCWSTR devName = deviceInterface->SymbolicLink; 3202 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 3203 (lstrlenW(devName) + 1) * sizeof(WCHAR); 3204 3205 if (sizeRequired > DeviceInterfaceDetailDataSize) 3206 { 3207 SetLastError(ERROR_INSUFFICIENT_BUFFER); 3208 if (RequiredSize) 3209 *RequiredSize = sizeRequired; 3210 } 3211 else 3212 { 3213 strcpyW(DeviceInterfaceDetailData->DevicePath, devName); 3214 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath)); 3215 if (DeviceInfoData) 3216 { 3217 memcpy(&DeviceInfoData->ClassGuid, 3218 &deviceInterface->DeviceInfo->ClassGuid, 3219 sizeof(GUID)); 3220 DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst; 3221 DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo; 3222 } 3223 ret = TRUE; 3224 } 3225 } 3226 return ret; 3227 } 3228 3229 struct PropertyMapEntry 3230 { 3231 DWORD regType; 3232 LPCSTR nameA; 3233 LPCWSTR nameW; 3234 }; 3235 3236 static struct PropertyMapEntry PropertyMap[] = { 3237 { REG_SZ, "DeviceDesc", REGSTR_VAL_DEVDESC }, 3238 { REG_MULTI_SZ, "HardwareId", REGSTR_VAL_HARDWAREID }, 3239 { REG_MULTI_SZ, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS }, 3240 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */ 3241 { REG_SZ, "Service", REGSTR_VAL_SERVICE }, 3242 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */ 3243 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */ 3244 { REG_SZ, "Class", REGSTR_VAL_CLASS }, 3245 { REG_SZ, "ClassGUID", REGSTR_VAL_CLASSGUID }, 3246 { REG_SZ, "Driver", REGSTR_VAL_DRIVER }, 3247 { REG_DWORD, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS }, 3248 { REG_SZ, "Mfg", REGSTR_VAL_MFG }, 3249 { REG_SZ, "FriendlyName", REGSTR_VAL_FRIENDLYNAME }, 3250 { REG_SZ, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION }, 3251 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */ 3252 { REG_DWORD, "Capabilities", REGSTR_VAL_CAPABILITIES }, 3253 { REG_DWORD, "UINumber", REGSTR_VAL_UI_NUMBER }, 3254 { REG_MULTI_SZ, "UpperFilters", REGSTR_VAL_UPPERFILTERS }, 3255 { REG_MULTI_SZ, "LowerFilters", REGSTR_VAL_LOWERFILTERS }, 3256 { 0, NULL, NULL }, /* SPDRP_BUSTYPEGUID */ 3257 { 0, NULL, NULL }, /* SPDRP_LEGACYBUSTYPE */ 3258 { 0, NULL, NULL }, /* SPDRP_BUSNUMBER */ 3259 { 0, NULL, NULL }, /* SPDRP_ENUMERATOR_NAME */ 3260 { REG_BINARY, "Security", REGSTR_SECURITY }, 3261 { 0, NULL, NULL }, /* SPDRP_SECURITY_SDS */ 3262 { 0, NULL, NULL }, /* SPDRP_DEVTYPE */ 3263 { 0, NULL, NULL }, /* SPDRP_EXCLUSIVE */ 3264 { 0, NULL, NULL }, /* SPDRP_CHARACTERISTICS */ 3265 { 0, NULL, NULL }, /* SPDRP_ADDRESS */ 3266 { REG_SZ, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT }, 3267 { 0, NULL, NULL }, /* SPDRP_DEVICE_POWER_DATA */ 3268 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY */ 3269 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */ 3270 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_OVERRIDE */ 3271 { 0, NULL, NULL }, /* SPDRP_INSTALL_STATE */ 3272 }; 3273 3274 /*********************************************************************** 3275 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@) 3276 */ 3277 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA( 3278 HDEVINFO DeviceInfoSet, 3279 PSP_DEVINFO_DATA DeviceInfoData, 3280 DWORD Property, 3281 PDWORD PropertyRegDataType, 3282 PBYTE PropertyBuffer, 3283 DWORD PropertyBufferSize, 3284 PDWORD RequiredSize) 3285 { 3286 BOOL ret; 3287 BOOL bIsStringProperty; 3288 DWORD RegType; 3289 DWORD RequiredSizeA, RequiredSizeW; 3290 DWORD PropertyBufferSizeW = 0; 3291 PBYTE PropertyBufferW = NULL; 3292 3293 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, 3294 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, 3295 RequiredSize); 3296 3297 if (PropertyBufferSize != 0) 3298 { 3299 PropertyBufferSizeW = PropertyBufferSize * 2; 3300 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW); 3301 if (!PropertyBufferW) 3302 { 3303 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3304 return FALSE; 3305 } 3306 } 3307 3308 ret = SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, 3309 DeviceInfoData, 3310 Property, 3311 &RegType, 3312 PropertyBufferW, 3313 PropertyBufferSizeW, 3314 &RequiredSizeW); 3315 3316 if (ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER) 3317 { 3318 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ); 3319 3320 if (bIsStringProperty) 3321 RequiredSizeA = RequiredSizeW / sizeof(WCHAR); 3322 else 3323 RequiredSizeA = RequiredSizeW; 3324 if (RequiredSize) 3325 *RequiredSize = RequiredSizeA; 3326 if (PropertyRegDataType) 3327 *PropertyRegDataType = RegType; 3328 } 3329 3330 if (!ret) 3331 { 3332 HeapFree(GetProcessHeap(), 0, PropertyBufferW); 3333 return ret; 3334 } 3335 3336 if (RequiredSizeA <= PropertyBufferSize) 3337 { 3338 if (bIsStringProperty && PropertyBufferSize > 0) 3339 { 3340 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0) 3341 { 3342 /* Last error is already set by WideCharToMultiByte */ 3343 ret = FALSE; 3344 } 3345 } 3346 else 3347 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA); 3348 } 3349 else 3350 { 3351 SetLastError(ERROR_INSUFFICIENT_BUFFER); 3352 ret = FALSE; 3353 } 3354 3355 HeapFree(GetProcessHeap(), 0, PropertyBufferW); 3356 return ret; 3357 } 3358 3359 /*********************************************************************** 3360 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@) 3361 */ 3362 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW( 3363 HDEVINFO DeviceInfoSet, 3364 PSP_DEVINFO_DATA DeviceInfoData, 3365 DWORD Property, 3366 PDWORD PropertyRegDataType, 3367 PBYTE PropertyBuffer, 3368 DWORD PropertyBufferSize, 3369 PDWORD RequiredSize) 3370 { 3371 BOOL ret = FALSE; 3372 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 3373 struct DeviceInfo *devInfo; 3374 3375 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, 3376 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, 3377 RequiredSize); 3378 3379 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 3380 { 3381 SetLastError(ERROR_INVALID_HANDLE); 3382 return FALSE; 3383 } 3384 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 3385 { 3386 SetLastError(ERROR_INVALID_HANDLE); 3387 return FALSE; 3388 } 3389 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 3390 || !DeviceInfoData->Reserved) 3391 { 3392 SetLastError(ERROR_INVALID_PARAMETER); 3393 return FALSE; 3394 } 3395 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 3396 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0]) 3397 && PropertyMap[Property].nameW) 3398 { 3399 DWORD size = PropertyBufferSize; 3400 HKEY hKey; 3401 LONG l; 3402 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); 3403 if (hKey == INVALID_HANDLE_VALUE) 3404 return FALSE; 3405 l = RegQueryValueExW(hKey, PropertyMap[Property].nameW, 3406 NULL, PropertyRegDataType, PropertyBuffer, &size); 3407 RegCloseKey(hKey); 3408 3409 if (RequiredSize) 3410 *RequiredSize = size; 3411 switch(l) { 3412 case ERROR_SUCCESS: 3413 if (PropertyBuffer != NULL || size == 0) 3414 ret = TRUE; 3415 else 3416 SetLastError(ERROR_INSUFFICIENT_BUFFER); 3417 break; 3418 case ERROR_MORE_DATA: 3419 SetLastError(ERROR_INSUFFICIENT_BUFFER); 3420 break; 3421 default: 3422 SetLastError(l); 3423 } 3424 } 3425 else if (Property == SPDRP_PHYSICAL_DEVICE_OBJECT_NAME) 3426 { 3427 DWORD required = (strlenW(devInfo->Data) + 1) * sizeof(WCHAR); 3428 3429 if (PropertyRegDataType) 3430 *PropertyRegDataType = REG_SZ; 3431 if (RequiredSize) 3432 *RequiredSize = required; 3433 if (PropertyBufferSize >= required) 3434 { 3435 strcpyW((LPWSTR)PropertyBuffer, devInfo->Data); 3436 ret = TRUE; 3437 } 3438 else 3439 SetLastError(ERROR_INSUFFICIENT_BUFFER); 3440 } 3441 else 3442 { 3443 ERR("Property 0x%lx not implemented\n", Property); 3444 SetLastError(ERROR_NOT_SUPPORTED); 3445 } 3446 return ret; 3447 } 3448 3449 /*********************************************************************** 3450 * Internal for SetupDiSetDeviceRegistryPropertyA/W 3451 */ 3452 BOOL WINAPI IntSetupDiSetDeviceRegistryPropertyAW( 3453 HDEVINFO DeviceInfoSet, 3454 PSP_DEVINFO_DATA DeviceInfoData, 3455 DWORD Property, 3456 const BYTE *PropertyBuffer, 3457 DWORD PropertyBufferSize, 3458 BOOL isAnsi) 3459 { 3460 BOOL ret = FALSE; 3461 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 3462 3463 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property, 3464 PropertyBuffer, PropertyBufferSize); 3465 3466 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 3467 { 3468 SetLastError(ERROR_INVALID_HANDLE); 3469 return FALSE; 3470 } 3471 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 3472 { 3473 SetLastError(ERROR_INVALID_HANDLE); 3474 return FALSE; 3475 } 3476 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 3477 || !DeviceInfoData->Reserved) 3478 { 3479 SetLastError(ERROR_INVALID_PARAMETER); 3480 return FALSE; 3481 } 3482 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0]) 3483 && PropertyMap[Property].nameW 3484 && PropertyMap[Property].nameA) 3485 { 3486 HKEY hKey; 3487 LONG l; 3488 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE); 3489 if (hKey == INVALID_HANDLE_VALUE) 3490 return FALSE; 3491 /* Write new data */ 3492 if (isAnsi) 3493 { 3494 l = RegSetValueExA( 3495 hKey, PropertyMap[Property].nameA, 0, 3496 PropertyMap[Property].regType, PropertyBuffer, 3497 PropertyBufferSize); 3498 } 3499 else 3500 { 3501 l = RegSetValueExW( 3502 hKey, PropertyMap[Property].nameW, 0, 3503 PropertyMap[Property].regType, PropertyBuffer, 3504 PropertyBufferSize); 3505 } 3506 if (!l) 3507 ret = TRUE; 3508 else 3509 SetLastError(l); 3510 RegCloseKey(hKey); 3511 } 3512 else 3513 { 3514 ERR("Property 0x%lx not implemented\n", Property); 3515 SetLastError(ERROR_NOT_SUPPORTED); 3516 } 3517 3518 TRACE("Returning %d\n", ret); 3519 return ret; 3520 } 3521 /*********************************************************************** 3522 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@) 3523 */ 3524 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA( 3525 HDEVINFO DeviceInfoSet, 3526 PSP_DEVINFO_DATA DeviceInfoData, 3527 DWORD Property, 3528 const BYTE *PropertyBuffer, 3529 DWORD PropertyBufferSize) 3530 { 3531 return IntSetupDiSetDeviceRegistryPropertyAW(DeviceInfoSet, 3532 DeviceInfoData, 3533 Property, 3534 PropertyBuffer, 3535 PropertyBufferSize, 3536 TRUE); 3537 } 3538 3539 /*********************************************************************** 3540 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@) 3541 */ 3542 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW( 3543 HDEVINFO DeviceInfoSet, 3544 PSP_DEVINFO_DATA DeviceInfoData, 3545 DWORD Property, 3546 const BYTE *PropertyBuffer, 3547 DWORD PropertyBufferSize) 3548 { 3549 return IntSetupDiSetDeviceRegistryPropertyAW(DeviceInfoSet, 3550 DeviceInfoData, 3551 Property, 3552 PropertyBuffer, 3553 PropertyBufferSize, 3554 FALSE); 3555 } 3556 3557 /*********************************************************************** 3558 * SetupDiInstallClassA (SETUPAPI.@) 3559 */ 3560 BOOL WINAPI SetupDiInstallClassA( 3561 HWND hwndParent, 3562 PCSTR InfFileName, 3563 DWORD Flags, 3564 HSPFILEQ FileQueue) 3565 { 3566 return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL); 3567 } 3568 3569 /*********************************************************************** 3570 * SetupDiInstallClassExA (SETUPAPI.@) 3571 */ 3572 BOOL WINAPI 3573 SetupDiInstallClassExA( 3574 IN HWND hwndParent OPTIONAL, 3575 IN PCSTR InfFileName OPTIONAL, 3576 IN DWORD Flags, 3577 IN HSPFILEQ FileQueue OPTIONAL, 3578 IN CONST GUID *InterfaceClassGuid OPTIONAL, 3579 IN PVOID Reserved1, 3580 IN PVOID Reserved2) 3581 { 3582 PWSTR InfFileNameW = NULL; 3583 BOOL Result; 3584 3585 if (!InfFileName) 3586 { 3587 SetLastError(ERROR_INVALID_PARAMETER); 3588 return FALSE; 3589 } 3590 else 3591 { 3592 InfFileNameW = pSetupMultiByteToUnicode(InfFileName, CP_ACP); 3593 if (InfFileNameW == NULL) 3594 { 3595 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3596 return FALSE; 3597 } 3598 } 3599 3600 Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags, 3601 FileQueue, InterfaceClassGuid, Reserved1, Reserved2); 3602 3603 MyFree(InfFileNameW); 3604 3605 return Result; 3606 } 3607 3608 HKEY SETUP_CreateClassKey(HINF hInf) 3609 { 3610 WCHAR FullBuffer[MAX_PATH]; 3611 WCHAR Buffer[MAX_PATH]; 3612 DWORD RequiredSize; 3613 HKEY hClassKey; 3614 DWORD Disposition; 3615 3616 /* Obtain the Class GUID for this class */ 3617 if (!SetupGetLineTextW(NULL, 3618 hInf, 3619 Version, 3620 REGSTR_VAL_CLASSGUID, 3621 Buffer, 3622 sizeof(Buffer) / sizeof(WCHAR), 3623 &RequiredSize)) 3624 { 3625 return INVALID_HANDLE_VALUE; 3626 } 3627 3628 /* Build the corresponding registry key name */ 3629 lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT); 3630 lstrcatW(FullBuffer, BackSlash); 3631 lstrcatW(FullBuffer, Buffer); 3632 3633 /* Obtain the Class name for this class */ 3634 if (!SetupGetLineTextW(NULL, 3635 hInf, 3636 Version, 3637 REGSTR_VAL_CLASS, 3638 Buffer, 3639 sizeof(Buffer) / sizeof(WCHAR), 3640 &RequiredSize)) 3641 { 3642 return INVALID_HANDLE_VALUE; 3643 } 3644 3645 /* Try to open or create the registry key */ 3646 TRACE("Opening class key %s\n", debugstr_w(FullBuffer)); 3647 #if 0 // I keep this for reference... 3648 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 3649 FullBuffer, 3650 0, 3651 KEY_SET_VALUE, 3652 &hClassKey)) 3653 { 3654 /* Use RegCreateKeyExW */ 3655 } 3656 #endif 3657 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, 3658 FullBuffer, 3659 0, 3660 NULL, 3661 REG_OPTION_NON_VOLATILE, 3662 KEY_SET_VALUE, 3663 NULL, 3664 &hClassKey, 3665 &Disposition)) 3666 { 3667 ERR("RegCreateKeyExW(%s) failed\n", debugstr_w(FullBuffer)); 3668 return INVALID_HANDLE_VALUE; 3669 } 3670 if (Disposition == REG_CREATED_NEW_KEY) 3671 TRACE("The class key %s was successfully created\n", debugstr_w(FullBuffer)); 3672 else 3673 TRACE("The class key %s was successfully opened\n", debugstr_w(FullBuffer)); 3674 3675 TRACE( "setting value %s to %s\n", debugstr_w(REGSTR_VAL_CLASS), debugstr_w(Buffer) ); 3676 if (RegSetValueExW(hClassKey, 3677 REGSTR_VAL_CLASS, 3678 0, 3679 REG_SZ, 3680 (LPBYTE)Buffer, 3681 RequiredSize * sizeof(WCHAR))) 3682 { 3683 RegCloseKey(hClassKey); 3684 RegDeleteKeyW(HKEY_LOCAL_MACHINE, 3685 FullBuffer); 3686 return INVALID_HANDLE_VALUE; 3687 } 3688 3689 return hClassKey; 3690 } 3691 3692 /*********************************************************************** 3693 * SetupDiInstallClassW (SETUPAPI.@) 3694 */ 3695 BOOL WINAPI SetupDiInstallClassW( 3696 HWND hwndParent, 3697 PCWSTR InfFileName, 3698 DWORD Flags, 3699 HSPFILEQ FileQueue) 3700 { 3701 return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL); 3702 } 3703 3704 3705 /*********************************************************************** 3706 * SetupDiOpenClassRegKey (SETUPAPI.@) 3707 */ 3708 HKEY WINAPI SetupDiOpenClassRegKey( 3709 const GUID* ClassGuid, 3710 REGSAM samDesired) 3711 { 3712 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, 3713 DIOCR_INSTALLER, NULL, NULL); 3714 } 3715 3716 3717 /*********************************************************************** 3718 * SetupDiOpenClassRegKeyExA (SETUPAPI.@) 3719 */ 3720 HKEY WINAPI SetupDiOpenClassRegKeyExA( 3721 const GUID* ClassGuid, 3722 REGSAM samDesired, 3723 DWORD Flags, 3724 PCSTR MachineName, 3725 PVOID Reserved) 3726 { 3727 PWSTR MachineNameW = NULL; 3728 HKEY hKey; 3729 3730 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired, 3731 Flags, debugstr_a(MachineName), Reserved); 3732 3733 if (MachineName) 3734 { 3735 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 3736 if (MachineNameW == NULL) 3737 return INVALID_HANDLE_VALUE; 3738 } 3739 3740 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, 3741 Flags, MachineNameW, Reserved); 3742 3743 MyFree(MachineNameW); 3744 3745 return hKey; 3746 } 3747 3748 3749 /*********************************************************************** 3750 * SetupDiOpenClassRegKeyExW (SETUPAPI.@) 3751 */ 3752 HKEY WINAPI SetupDiOpenClassRegKeyExW( 3753 const GUID* ClassGuid, 3754 REGSAM samDesired, 3755 DWORD Flags, 3756 PCWSTR MachineName, 3757 PVOID Reserved) 3758 { 3759 HKEY HKLM; 3760 HKEY hClassesKey; 3761 HKEY key; 3762 LPCWSTR lpKeyName; 3763 LONG l; 3764 3765 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired, 3766 Flags, debugstr_w(MachineName), Reserved); 3767 3768 if (MachineName != NULL) 3769 { 3770 l = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM); 3771 if (l != ERROR_SUCCESS) 3772 { 3773 SetLastError(l); 3774 return INVALID_HANDLE_VALUE; 3775 } 3776 } 3777 else 3778 HKLM = HKEY_LOCAL_MACHINE; 3779 3780 if (Flags == DIOCR_INSTALLER) 3781 { 3782 lpKeyName = REGSTR_PATH_CLASS_NT; 3783 } 3784 else if (Flags == DIOCR_INTERFACE) 3785 { 3786 lpKeyName = REGSTR_PATH_DEVICE_CLASSES; 3787 } 3788 else 3789 { 3790 ERR("Invalid Flags parameter!\n"); 3791 SetLastError(ERROR_INVALID_FLAGS); 3792 if (MachineName != NULL) RegCloseKey(HKLM); 3793 return INVALID_HANDLE_VALUE; 3794 } 3795 3796 if (!ClassGuid) 3797 { 3798 if ((l = RegOpenKeyExW(HKLM, 3799 lpKeyName, 3800 0, 3801 samDesired, 3802 &hClassesKey))) 3803 { 3804 SetLastError(ERROR_INVALID_CLASS); 3805 hClassesKey = INVALID_HANDLE_VALUE; 3806 } 3807 if (MachineName != NULL) 3808 RegCloseKey(HKLM); 3809 key = hClassesKey; 3810 } 3811 else 3812 { 3813 WCHAR bracedGuidString[39]; 3814 3815 SETUPDI_GuidToString(ClassGuid, bracedGuidString); 3816 3817 if (!(l = RegOpenKeyExW(HKLM, 3818 lpKeyName, 3819 0, 3820 samDesired, 3821 &hClassesKey))) 3822 { 3823 if (MachineName != NULL) 3824 RegCloseKey(HKLM); 3825 3826 if ((l = RegOpenKeyExW(hClassesKey, 3827 bracedGuidString, 3828 0, 3829 samDesired, 3830 &key))) 3831 { 3832 SetLastError(l); 3833 key = INVALID_HANDLE_VALUE; 3834 } 3835 RegCloseKey(hClassesKey); 3836 } 3837 else 3838 { 3839 if (MachineName != NULL) RegCloseKey(HKLM); 3840 SetLastError(l); 3841 key = INVALID_HANDLE_VALUE; 3842 } 3843 } 3844 3845 return key; 3846 } 3847 3848 /*********************************************************************** 3849 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@) 3850 */ 3851 BOOL WINAPI SetupDiOpenDeviceInterfaceW( 3852 HDEVINFO DeviceInfoSet, 3853 PCWSTR DevicePath, 3854 DWORD OpenFlags, 3855 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 3856 { 3857 struct DeviceInfoSet * list; 3858 PCWSTR pEnd; 3859 DWORD dwLength, dwError, dwIndex, dwKeyName, dwSubIndex; 3860 CLSID ClassId; 3861 WCHAR Buffer[MAX_PATH + 1]; 3862 WCHAR SymBuffer[MAX_PATH + 1]; 3863 WCHAR InstancePath[MAX_PATH + 1]; 3864 HKEY hKey, hDevKey, hSymKey; 3865 struct DeviceInfo * deviceInfo; 3866 struct DeviceInterface *deviceInterface; 3867 BOOL Ret; 3868 PLIST_ENTRY ItemList; 3869 PLIST_ENTRY InterfaceListEntry; 3870 3871 TRACE("%p %s %08x %p\n", 3872 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData); 3873 3874 3875 if (DeviceInterfaceData && DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA)) 3876 { 3877 SetLastError(ERROR_INVALID_PARAMETER); 3878 return FALSE; 3879 } 3880 3881 if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 3882 { 3883 SetLastError(ERROR_INVALID_HANDLE); 3884 return FALSE; 3885 } 3886 3887 list = (struct DeviceInfoSet * )DeviceInfoSet; 3888 3889 dwLength = wcslen(DevicePath); 3890 if (dwLength < 39) 3891 { 3892 /* path must be at least a guid length + L'\0' */ 3893 SetLastError(ERROR_BAD_PATHNAME); 3894 return FALSE; 3895 } 3896 3897 if (DevicePath[0] != L'\\' || 3898 DevicePath[1] != L'\\' || 3899 (DevicePath[2] != L'?' && DevicePath[2] != L'.') || 3900 DevicePath[3] != L'\\') 3901 { 3902 /* invalid formatted path */ 3903 SetLastError(ERROR_BAD_PATHNAME); 3904 return FALSE; 3905 } 3906 3907 /* check for reference strings */ 3908 pEnd = wcschr(&DevicePath[4], L'\\'); 3909 if (!pEnd) 3910 { 3911 /* no reference string */ 3912 pEnd = DevicePath + dwLength; 3913 } 3914 3915 /* copy guid */ 3916 wcscpy(Buffer, pEnd - 37); 3917 Buffer[36] = L'\0'; 3918 3919 dwError = UuidFromStringW(Buffer, &ClassId); 3920 if (dwError != NOERROR) 3921 { 3922 /* invalid formatted path */ 3923 SetLastError(ERROR_BAD_PATHNAME); 3924 return FALSE; 3925 } 3926 3927 hKey = SetupDiOpenClassRegKeyExW(&ClassId, KEY_READ, DIOCR_INTERFACE, list->MachineName, NULL); 3928 3929 if (hKey == INVALID_HANDLE_VALUE) 3930 { 3931 /* invalid device class */ 3932 return FALSE; 3933 } 3934 3935 ItemList = list->ListHead.Flink; 3936 while (ItemList != &list->ListHead) 3937 { 3938 deviceInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry); 3939 InterfaceListEntry = deviceInfo->InterfaceListHead.Flink; 3940 while (InterfaceListEntry != &deviceInfo->InterfaceListHead) 3941 { 3942 deviceInterface = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry); 3943 if (!IsEqualIID(&deviceInterface->InterfaceClassGuid, &ClassId)) 3944 { 3945 InterfaceListEntry = InterfaceListEntry->Flink; 3946 continue; 3947 } 3948 3949 if (!wcsicmp(deviceInterface->SymbolicLink, DevicePath)) 3950 { 3951 if (DeviceInterfaceData) 3952 { 3953 DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface; 3954 DeviceInterfaceData->Flags = deviceInterface->Flags; 3955 CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID)); 3956 } 3957 3958 return TRUE; 3959 } 3960 3961 } 3962 } 3963 3964 3965 dwIndex = 0; 3966 do 3967 { 3968 Buffer[0] = 0; 3969 dwKeyName = sizeof(Buffer) / sizeof(WCHAR); 3970 dwError = RegEnumKeyExW(hKey, dwIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL); 3971 3972 if (dwError != ERROR_SUCCESS) 3973 break; 3974 3975 if (RegOpenKeyExW(hKey, Buffer, 0, KEY_READ, &hDevKey) != ERROR_SUCCESS) 3976 break; 3977 3978 dwSubIndex = 0; 3979 InstancePath[0] = 0; 3980 dwKeyName = sizeof(InstancePath); 3981 3982 dwError = RegQueryValueExW(hDevKey, L"DeviceInstance", NULL, NULL, (LPBYTE)InstancePath, &dwKeyName); 3983 3984 while(TRUE) 3985 { 3986 Buffer[0] = 0; 3987 dwKeyName = sizeof(Buffer) / sizeof(WCHAR); 3988 dwError = RegEnumKeyExW(hDevKey, dwSubIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL); 3989 3990 if (dwError != ERROR_SUCCESS) 3991 break; 3992 3993 dwError = RegOpenKeyExW(hDevKey, Buffer, 0, KEY_READ, &hSymKey); 3994 if (dwError != ERROR_SUCCESS) 3995 break; 3996 3997 /* query for symbolic link */ 3998 dwKeyName = sizeof(SymBuffer); 3999 SymBuffer[0] = L'\0'; 4000 dwError = RegQueryValueExW(hSymKey, L"SymbolicLink", NULL, NULL, (LPBYTE)SymBuffer, &dwKeyName); 4001 4002 if (dwError != ERROR_SUCCESS) 4003 { 4004 RegCloseKey(hSymKey); 4005 break; 4006 } 4007 4008 if (!wcsicmp(SymBuffer, DevicePath)) 4009 { 4010 Ret = CreateDeviceInfo(list, InstancePath, &ClassId, &deviceInfo); 4011 RegCloseKey(hSymKey); 4012 RegCloseKey(hDevKey); 4013 RegCloseKey(hKey); 4014 4015 if (Ret) 4016 { 4017 deviceInterface = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface) + (wcslen(SymBuffer) + 1) * sizeof(WCHAR)); 4018 if (deviceInterface) 4019 { 4020 4021 CopyMemory(&deviceInterface->InterfaceClassGuid, &ClassId, sizeof(GUID)); 4022 deviceInterface->DeviceInfo = deviceInfo; 4023 deviceInterface->Flags = SPINT_ACTIVE; //FIXME 4024 4025 wcscpy(deviceInterface->SymbolicLink, SymBuffer); 4026 4027 InsertTailList(&deviceInfo->InterfaceListHead, &deviceInterface->ListEntry); 4028 InsertTailList(&list->ListHead, &deviceInfo->ListEntry); 4029 4030 4031 if (DeviceInterfaceData) 4032 { 4033 DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface; 4034 DeviceInterfaceData->Flags = deviceInterface->Flags; 4035 CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID)); 4036 } 4037 else 4038 { 4039 Ret = FALSE; 4040 SetLastError(ERROR_INVALID_USER_BUFFER); 4041 } 4042 } 4043 } 4044 else 4045 { 4046 HeapFree(GetProcessHeap(), 0, deviceInfo); 4047 Ret = FALSE; 4048 } 4049 return Ret; 4050 } 4051 RegCloseKey(hSymKey); 4052 dwSubIndex++; 4053 } 4054 4055 RegCloseKey(hDevKey); 4056 dwIndex++; 4057 } while(TRUE); 4058 4059 RegCloseKey(hKey); 4060 return FALSE; 4061 } 4062 4063 /*********************************************************************** 4064 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@) 4065 */ 4066 BOOL WINAPI SetupDiOpenDeviceInterfaceA( 4067 HDEVINFO DeviceInfoSet, 4068 PCSTR DevicePath, 4069 DWORD OpenFlags, 4070 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 4071 { 4072 LPWSTR DevicePathW = NULL; 4073 BOOL bResult; 4074 4075 TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData); 4076 4077 DevicePathW = pSetupMultiByteToUnicode(DevicePath, CP_ACP); 4078 if (DevicePathW == NULL) 4079 return FALSE; 4080 4081 bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet, 4082 DevicePathW, OpenFlags, DeviceInterfaceData); 4083 4084 MyFree(DevicePathW); 4085 4086 return bResult; 4087 } 4088 4089 /*********************************************************************** 4090 * SetupDiSetClassInstallParamsA (SETUPAPI.@) 4091 */ 4092 BOOL WINAPI SetupDiSetClassInstallParamsA( 4093 HDEVINFO DeviceInfoSet, 4094 PSP_DEVINFO_DATA DeviceInfoData, 4095 PSP_CLASSINSTALL_HEADER ClassInstallParams, 4096 DWORD ClassInstallParamsSize) 4097 { 4098 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData, 4099 ClassInstallParams->InstallFunction, ClassInstallParamsSize); 4100 return FALSE; 4101 } 4102 4103 static BOOL WINAPI 4104 IntSetupDiRegisterDeviceInfo( 4105 IN HDEVINFO DeviceInfoSet, 4106 IN OUT PSP_DEVINFO_DATA DeviceInfoData) 4107 { 4108 return SetupDiRegisterDeviceInfo(DeviceInfoSet, DeviceInfoData, 0, NULL, NULL, NULL); 4109 } 4110 4111 /*********************************************************************** 4112 * SetupDiCallClassInstaller (SETUPAPI.@) 4113 */ 4114 BOOL WINAPI SetupDiCallClassInstaller( 4115 DI_FUNCTION InstallFunction, 4116 HDEVINFO DeviceInfoSet, 4117 PSP_DEVINFO_DATA DeviceInfoData) 4118 { 4119 BOOL ret = FALSE; 4120 4121 TRACE("%u %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData); 4122 4123 if (!DeviceInfoSet) 4124 SetLastError(ERROR_INVALID_PARAMETER); 4125 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 4126 SetLastError(ERROR_INVALID_HANDLE); 4127 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4128 SetLastError(ERROR_INVALID_HANDLE); 4129 else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE) 4130 SetLastError(ERROR_INVALID_HANDLE); 4131 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4132 SetLastError(ERROR_INVALID_USER_BUFFER); 4133 else 4134 { 4135 SP_DEVINSTALL_PARAMS_W InstallParams; 4136 #define CLASS_COINSTALLER 0x1 4137 #define DEVICE_COINSTALLER 0x2 4138 #define CLASS_INSTALLER 0x4 4139 UCHAR CanHandle = 0; 4140 DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL; 4141 4142 switch (InstallFunction) 4143 { 4144 case DIF_ADDPROPERTYPAGE_ADVANCED: 4145 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4146 break; 4147 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED: 4148 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4149 break; 4150 case DIF_ALLOW_INSTALL: 4151 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4152 break; 4153 case DIF_DETECT: 4154 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4155 break; 4156 case DIF_DESTROYPRIVATEDATA: 4157 CanHandle = CLASS_INSTALLER; 4158 break; 4159 case DIF_INSTALLDEVICE: 4160 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4161 DefaultHandler = SetupDiInstallDevice; 4162 break; 4163 case DIF_INSTALLDEVICEFILES: 4164 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4165 DefaultHandler = SetupDiInstallDriverFiles; 4166 break; 4167 case DIF_INSTALLINTERFACES: 4168 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4169 DefaultHandler = SetupDiInstallDeviceInterfaces; 4170 break; 4171 case DIF_NEWDEVICEWIZARD_FINISHINSTALL: 4172 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4173 break; 4174 case DIF_NEWDEVICEWIZARD_POSTANALYZE: 4175 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4176 break; 4177 case DIF_NEWDEVICEWIZARD_PREANALYZE: 4178 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4179 break; 4180 case DIF_NEWDEVICEWIZARD_PRESELECT: 4181 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4182 break; 4183 case DIF_NEWDEVICEWIZARD_SELECT: 4184 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4185 break; 4186 case DIF_POWERMESSAGEWAKE: 4187 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4188 break; 4189 case DIF_PROPERTYCHANGE: 4190 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4191 DefaultHandler = SetupDiChangeState; 4192 break; 4193 case DIF_REGISTER_COINSTALLERS: 4194 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4195 DefaultHandler = SetupDiRegisterCoDeviceInstallers; 4196 break; 4197 case DIF_REGISTERDEVICE: 4198 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4199 DefaultHandler = IntSetupDiRegisterDeviceInfo; 4200 break; 4201 case DIF_REMOVE: 4202 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4203 DefaultHandler = SetupDiRemoveDevice; 4204 break; 4205 case DIF_SELECTBESTCOMPATDRV: 4206 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4207 DefaultHandler = SetupDiSelectBestCompatDrv; 4208 break; 4209 case DIF_SELECTDEVICE: 4210 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4211 DefaultHandler = SetupDiSelectDevice; 4212 break; 4213 case DIF_TROUBLESHOOTER: 4214 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4215 break; 4216 case DIF_UNREMOVE: 4217 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4218 DefaultHandler = SetupDiUnremoveDevice; 4219 break; 4220 default: 4221 ERR("Install function %u not supported\n", InstallFunction); 4222 SetLastError(ERROR_NOT_SUPPORTED); 4223 } 4224 4225 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 4226 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams)) 4227 /* Don't process this call, as a parameter is invalid */ 4228 CanHandle = 0; 4229 4230 if (CanHandle != 0) 4231 { 4232 LIST_ENTRY ClassCoInstallersListHead; 4233 LIST_ENTRY DeviceCoInstallersListHead; 4234 HMODULE ClassInstallerLibrary = NULL; 4235 CLASS_INSTALL_PROC ClassInstaller = NULL; 4236 COINSTALLER_CONTEXT_DATA Context; 4237 PLIST_ENTRY ListEntry; 4238 HKEY hKey; 4239 DWORD dwRegType, dwLength; 4240 DWORD rc = NO_ERROR; 4241 4242 InitializeListHead(&ClassCoInstallersListHead); 4243 InitializeListHead(&DeviceCoInstallersListHead); 4244 4245 if (CanHandle & DEVICE_COINSTALLER) 4246 { 4247 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE); 4248 if (hKey != INVALID_HANDLE_VALUE) 4249 { 4250 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, &dwRegType, NULL, &dwLength); 4251 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ) 4252 { 4253 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); 4254 if (KeyBuffer != NULL) 4255 { 4256 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); 4257 if (rc == ERROR_SUCCESS) 4258 { 4259 LPWSTR ptr; 4260 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1) 4261 { 4262 /* Add coinstaller to DeviceCoInstallersListHead list */ 4263 struct CoInstallerElement *coinstaller; 4264 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr)); 4265 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement)); 4266 if (!coinstaller) 4267 continue; 4268 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement)); 4269 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS) 4270 InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry); 4271 else 4272 HeapFree(GetProcessHeap(), 0, coinstaller); 4273 } 4274 } 4275 HeapFree(GetProcessHeap(), 0, KeyBuffer); 4276 } 4277 } 4278 RegCloseKey(hKey); 4279 } 4280 } 4281 if (CanHandle & CLASS_COINSTALLER) 4282 { 4283 rc = RegOpenKeyExW( 4284 HKEY_LOCAL_MACHINE, 4285 REGSTR_PATH_CODEVICEINSTALLERS, 4286 0, /* Options */ 4287 KEY_QUERY_VALUE, 4288 &hKey); 4289 if (rc == ERROR_SUCCESS) 4290 { 4291 LPWSTR lpGuidString; 4292 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK) 4293 { 4294 rc = RegQueryValueExW(hKey, lpGuidString, NULL, &dwRegType, NULL, &dwLength); 4295 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ) 4296 { 4297 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); 4298 if (KeyBuffer != NULL) 4299 { 4300 rc = RegQueryValueExW(hKey, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); 4301 if (rc == ERROR_SUCCESS) 4302 { 4303 LPWSTR ptr; 4304 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1) 4305 { 4306 /* Add coinstaller to ClassCoInstallersListHead list */ 4307 struct CoInstallerElement *coinstaller; 4308 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr)); 4309 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement)); 4310 if (!coinstaller) 4311 continue; 4312 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement)); 4313 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS) 4314 InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry); 4315 else 4316 HeapFree(GetProcessHeap(), 0, coinstaller); 4317 } 4318 } 4319 HeapFree(GetProcessHeap(), 0, KeyBuffer); 4320 } 4321 } 4322 RpcStringFreeW(&lpGuidString); 4323 } 4324 RegCloseKey(hKey); 4325 } 4326 } 4327 if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED)) 4328 { 4329 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE); 4330 if (hKey != INVALID_HANDLE_VALUE) 4331 { 4332 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength); 4333 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ) 4334 { 4335 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); 4336 if (KeyBuffer != NULL) 4337 { 4338 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); 4339 if (rc == ERROR_SUCCESS) 4340 { 4341 /* Get ClassInstaller function pointer */ 4342 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer)); 4343 if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS) 4344 { 4345 InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED; 4346 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 4347 } 4348 } 4349 HeapFree(GetProcessHeap(), 0, KeyBuffer); 4350 } 4351 } 4352 RegCloseKey(hKey); 4353 } 4354 } 4355 4356 /* Call Class co-installers */ 4357 Context.PostProcessing = FALSE; 4358 rc = NO_ERROR; 4359 ListEntry = ClassCoInstallersListHead.Flink; 4360 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead) 4361 { 4362 struct CoInstallerElement *coinstaller; 4363 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 4364 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 4365 coinstaller->PrivateData = Context.PrivateData; 4366 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED) 4367 { 4368 coinstaller->DoPostProcessing = TRUE; 4369 rc = NO_ERROR; 4370 } 4371 ListEntry = ListEntry->Flink; 4372 } 4373 4374 /* Call Device co-installers */ 4375 ListEntry = DeviceCoInstallersListHead.Flink; 4376 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead) 4377 { 4378 struct CoInstallerElement *coinstaller; 4379 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 4380 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 4381 coinstaller->PrivateData = Context.PrivateData; 4382 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED) 4383 { 4384 coinstaller->DoPostProcessing = TRUE; 4385 rc = NO_ERROR; 4386 } 4387 ListEntry = ListEntry->Flink; 4388 } 4389 4390 /* Call Class installer */ 4391 if (ClassInstaller) 4392 { 4393 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData); 4394 FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller); 4395 } 4396 else 4397 rc = ERROR_DI_DO_DEFAULT; 4398 4399 /* Call default handler */ 4400 if (rc == ERROR_DI_DO_DEFAULT) 4401 { 4402 if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION)) 4403 { 4404 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData)) 4405 rc = NO_ERROR; 4406 else 4407 rc = GetLastError(); 4408 } 4409 else 4410 rc = NO_ERROR; 4411 } 4412 4413 /* Call Class co-installers that required postprocessing */ 4414 Context.PostProcessing = TRUE; 4415 ListEntry = ClassCoInstallersListHead.Flink; 4416 while (ListEntry != &ClassCoInstallersListHead) 4417 { 4418 struct CoInstallerElement *coinstaller; 4419 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 4420 if (coinstaller->DoPostProcessing) 4421 { 4422 Context.InstallResult = rc; 4423 Context.PrivateData = coinstaller->PrivateData; 4424 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 4425 } 4426 FreeFunctionPointer(coinstaller->Module, coinstaller->Function); 4427 ListEntry = ListEntry->Flink; 4428 } 4429 4430 /* Call Device co-installers that required postprocessing */ 4431 ListEntry = DeviceCoInstallersListHead.Flink; 4432 while (ListEntry != &DeviceCoInstallersListHead) 4433 { 4434 struct CoInstallerElement *coinstaller; 4435 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 4436 if (coinstaller->DoPostProcessing) 4437 { 4438 Context.InstallResult = rc; 4439 Context.PrivateData = coinstaller->PrivateData; 4440 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 4441 } 4442 FreeFunctionPointer(coinstaller->Module, coinstaller->Function); 4443 ListEntry = ListEntry->Flink; 4444 } 4445 4446 /* Free allocated memory */ 4447 while (!IsListEmpty(&ClassCoInstallersListHead)) 4448 { 4449 ListEntry = RemoveHeadList(&ClassCoInstallersListHead); 4450 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry)); 4451 } 4452 while (!IsListEmpty(&DeviceCoInstallersListHead)) 4453 { 4454 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead); 4455 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry)); 4456 } 4457 4458 ret = (rc == NO_ERROR); 4459 } 4460 } 4461 4462 TRACE("Returning %d\n", ret); 4463 return ret; 4464 } 4465 4466 /*********************************************************************** 4467 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@) 4468 */ 4469 BOOL WINAPI SetupDiGetDeviceInstallParamsA( 4470 HDEVINFO DeviceInfoSet, 4471 PSP_DEVINFO_DATA DeviceInfoData, 4472 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams) 4473 { 4474 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW; 4475 BOOL ret = FALSE; 4476 4477 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 4478 4479 if (DeviceInstallParams == NULL) 4480 SetLastError(ERROR_INVALID_PARAMETER); 4481 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A)) 4482 SetLastError(ERROR_INVALID_USER_BUFFER); 4483 else 4484 { 4485 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 4486 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW); 4487 4488 if (ret) 4489 { 4490 /* Do W->A conversion */ 4491 memcpy( 4492 DeviceInstallParams, 4493 &deviceInstallParamsW, 4494 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath)); 4495 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1, 4496 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0) 4497 { 4498 DeviceInstallParams->DriverPath[0] = '\0'; 4499 ret = FALSE; 4500 } 4501 } 4502 } 4503 4504 TRACE("Returning %d\n", ret); 4505 return ret; 4506 } 4507 4508 /*********************************************************************** 4509 * SetupDiGetDeviceInfoListClass (SETUPAPI.@) 4510 */ 4511 BOOL WINAPI 4512 SetupDiGetDeviceInfoListClass( 4513 IN HDEVINFO DeviceInfoSet, 4514 OUT LPGUID ClassGuid) 4515 { 4516 struct DeviceInfoSet *list; 4517 BOOL ret = FALSE; 4518 4519 TRACE("%p %p\n", DeviceInfoSet, ClassGuid); 4520 4521 if (!DeviceInfoSet) 4522 SetLastError(ERROR_INVALID_HANDLE); 4523 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4524 SetLastError(ERROR_INVALID_HANDLE); 4525 else if (IsEqualIID(&list->ClassGuid, &GUID_NULL)) 4526 SetLastError(ERROR_NO_ASSOCIATED_CLASS); 4527 else 4528 { 4529 memcpy(&ClassGuid, &list->ClassGuid, sizeof(GUID)); 4530 4531 ret = TRUE; 4532 } 4533 4534 TRACE("Returning %d\n", ret); 4535 return ret; 4536 } 4537 4538 /*********************************************************************** 4539 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@) 4540 */ 4541 BOOL WINAPI 4542 SetupDiGetDeviceInstallParamsW( 4543 IN HDEVINFO DeviceInfoSet, 4544 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 4545 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams) 4546 { 4547 struct DeviceInfoSet *list; 4548 BOOL ret = FALSE; 4549 4550 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 4551 4552 if (!DeviceInfoSet) 4553 SetLastError(ERROR_INVALID_HANDLE); 4554 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4555 SetLastError(ERROR_INVALID_HANDLE); 4556 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4557 SetLastError(ERROR_INVALID_USER_BUFFER); 4558 else if (!DeviceInstallParams) 4559 SetLastError(ERROR_INVALID_PARAMETER); 4560 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W)) 4561 SetLastError(ERROR_INVALID_USER_BUFFER); 4562 else 4563 { 4564 PSP_DEVINSTALL_PARAMS_W Source; 4565 4566 if (DeviceInfoData) 4567 Source = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams; 4568 else 4569 Source = &list->InstallParams; 4570 4571 ret = TRUE; 4572 4573 _SEH2_TRY 4574 { 4575 memcpy(DeviceInstallParams, Source, Source->cbSize); 4576 } 4577 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 4578 { 4579 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); 4580 ret = FALSE; 4581 } 4582 _SEH2_END; 4583 } 4584 4585 TRACE("Returning %d\n", ret); 4586 return ret; 4587 } 4588 4589 static BOOL 4590 CheckDeviceInstallParameters( 4591 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams) 4592 { 4593 DWORD SupportedFlags = 4594 DI_NOVCP | /* 0x00000008 */ 4595 DI_DIDCOMPAT | /* 0x00000010 */ 4596 DI_DIDCLASS | /* 0x00000020 */ 4597 DI_NEEDRESTART | /* 0x00000080 */ 4598 DI_NEEDREBOOT | /* 0x00000100 */ 4599 DI_RESOURCEPAGE_ADDED | /* 0x00002000 */ 4600 DI_PROPERTIES_CHANGE | /* 0x00004000 */ 4601 DI_ENUMSINGLEINF | /* 0x00010000 */ 4602 DI_DONOTCALLCONFIGMG | /* 0x00020000 */ 4603 DI_CLASSINSTALLPARAMS | /* 0x00100000 */ 4604 DI_NODI_DEFAULTACTION | /* 0x00200000 */ 4605 DI_QUIETINSTALL | /* 0x00800000 */ 4606 DI_NOFILECOPY | /* 0x01000000 */ 4607 DI_DRIVERPAGE_ADDED; /* 0x04000000 */ 4608 DWORD SupportedFlagsEx = 4609 DI_FLAGSEX_CI_FAILED | /* 0x00000004 */ 4610 DI_FLAGSEX_DIDINFOLIST | /* 0x00000010 */ 4611 DI_FLAGSEX_DIDCOMPATINFO | /* 0x00000020 */ 4612 DI_FLAGSEX_ALLOWEXCLUDEDDRVS | /* 0x00000800 */ 4613 DI_FLAGSEX_NO_DRVREG_MODIFY | /* 0x00008000 */ 4614 DI_FLAGSEX_INSTALLEDDRIVER; /* 0x04000000 */ 4615 BOOL ret = FALSE; 4616 4617 /* FIXME: add support for more flags */ 4618 4619 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used. 4620 * It should be checked before accessing to other values 4621 * of the SP_DEVINSTALL_PARAMS structure */ 4622 4623 if (DeviceInstallParams->Flags & ~SupportedFlags) 4624 { 4625 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams->Flags & ~SupportedFlags); 4626 SetLastError(ERROR_INVALID_FLAGS); 4627 } 4628 else if (DeviceInstallParams->FlagsEx & ~SupportedFlagsEx) 4629 { 4630 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams->FlagsEx & ~SupportedFlagsEx); 4631 SetLastError(ERROR_INVALID_FLAGS); 4632 } 4633 else if ((DeviceInstallParams->Flags & DI_NOVCP) 4634 && (DeviceInstallParams->FileQueue == NULL || DeviceInstallParams->FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE)) 4635 SetLastError(ERROR_INVALID_USER_BUFFER); 4636 else 4637 { 4638 /* FIXME: check Reserved field */ 4639 ret = TRUE; 4640 } 4641 4642 return ret; 4643 } 4644 4645 /*********************************************************************** 4646 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@) 4647 */ 4648 BOOL WINAPI 4649 SetupDiSetDeviceInstallParamsW( 4650 IN HDEVINFO DeviceInfoSet, 4651 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 4652 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams) 4653 { 4654 struct DeviceInfoSet *list; 4655 BOOL ret = FALSE; 4656 4657 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 4658 4659 if (!DeviceInfoSet) 4660 SetLastError(ERROR_INVALID_HANDLE); 4661 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4662 SetLastError(ERROR_INVALID_HANDLE); 4663 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4664 SetLastError(ERROR_INVALID_USER_BUFFER); 4665 else if (!DeviceInstallParams) 4666 SetLastError(ERROR_INVALID_PARAMETER); 4667 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W)) 4668 SetLastError(ERROR_INVALID_USER_BUFFER); 4669 else if (CheckDeviceInstallParameters(DeviceInstallParams)) 4670 { 4671 PSP_DEVINSTALL_PARAMS_W Destination; 4672 4673 if (DeviceInfoData) 4674 Destination = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams; 4675 else 4676 Destination = &list->InstallParams; 4677 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize); 4678 ret = TRUE; 4679 } 4680 4681 TRACE("Returning %d\n", ret); 4682 return ret; 4683 } 4684 4685 /*********************************************************************** 4686 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@) 4687 */ 4688 BOOL WINAPI 4689 SetupDiSetDeviceInstallParamsA( 4690 HDEVINFO DeviceInfoSet, 4691 PSP_DEVINFO_DATA DeviceInfoData, 4692 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams) 4693 { 4694 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW; 4695 int len = 0; 4696 BOOL ret = FALSE; 4697 4698 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 4699 4700 if (DeviceInstallParams == NULL) 4701 SetLastError(ERROR_INVALID_PARAMETER); 4702 else if (DeviceInstallParams->cbSize < sizeof(SP_DEVINSTALL_PARAMS_A)) 4703 SetLastError(ERROR_INVALID_USER_BUFFER); 4704 else 4705 { 4706 memcpy(&deviceInstallParamsW, DeviceInstallParams, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A, DriverPath)); 4707 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 4708 len = MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, NULL, 0); 4709 if (!len) 4710 { 4711 ERR("DrivePath is NULL\n"); 4712 ret = FALSE; 4713 } 4714 else 4715 { 4716 MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, deviceInstallParamsW.DriverPath, len); 4717 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW); 4718 } 4719 } 4720 4721 TRACE("Returning %d\n", ret); 4722 return ret; 4723 } 4724 4725 static HKEY 4726 OpenHardwareProfileKey( 4727 IN HKEY HKLM, 4728 IN DWORD HwProfile, 4729 IN DWORD samDesired) 4730 { 4731 HKEY hHWProfilesKey = NULL; 4732 HKEY hHWProfileKey = NULL; 4733 HKEY ret = INVALID_HANDLE_VALUE; 4734 LONG rc; 4735 4736 rc = RegOpenKeyExW(HKLM, 4737 REGSTR_PATH_HWPROFILES, 4738 0, 4739 READ_CONTROL, 4740 &hHWProfilesKey); 4741 if (rc != ERROR_SUCCESS) 4742 { 4743 SetLastError(rc); 4744 goto cleanup; 4745 } 4746 if (HwProfile == 0) 4747 { 4748 rc = RegOpenKeyExW(hHWProfilesKey, 4749 REGSTR_KEY_CURRENT, 4750 0, 4751 KEY_CREATE_SUB_KEY, 4752 &hHWProfileKey); 4753 } 4754 else 4755 { 4756 WCHAR subKey[5]; 4757 snprintfW(subKey, 4, InstanceKeyFormat, HwProfile); 4758 subKey[4] = '\0'; 4759 rc = RegOpenKeyExW(hHWProfilesKey, 4760 subKey, 4761 0, 4762 KEY_CREATE_SUB_KEY, 4763 &hHWProfileKey); 4764 } 4765 if (rc != ERROR_SUCCESS) 4766 { 4767 SetLastError(rc); 4768 goto cleanup; 4769 } 4770 ret = hHWProfileKey; 4771 4772 cleanup: 4773 if (hHWProfilesKey != NULL) 4774 RegCloseKey(hHWProfilesKey); 4775 if (hHWProfileKey != NULL && hHWProfileKey != ret) 4776 RegCloseKey(hHWProfileKey); 4777 return ret; 4778 } 4779 4780 static BOOL 4781 IsDeviceInfoInDeviceInfoSet( 4782 struct DeviceInfoSet *deviceInfoSet, 4783 struct DeviceInfo *deviceInfo) 4784 { 4785 PLIST_ENTRY ListEntry; 4786 4787 ListEntry = deviceInfoSet->ListHead.Flink; 4788 while (ListEntry != &deviceInfoSet->ListHead) 4789 { 4790 if (deviceInfo == CONTAINING_RECORD(ListEntry, struct DeviceInfo, ListEntry)) 4791 return TRUE; 4792 4793 ListEntry = ListEntry->Flink; 4794 } 4795 4796 return FALSE; 4797 } 4798 4799 /*********************************************************************** 4800 * SetupDiDeleteDeviceInfo (SETUPAPI.@) 4801 */ 4802 BOOL WINAPI 4803 SetupDiDeleteDeviceInfo( 4804 IN HDEVINFO DeviceInfoSet, 4805 IN PSP_DEVINFO_DATA DeviceInfoData) 4806 { 4807 struct DeviceInfoSet *deviceInfoSet; 4808 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData; 4809 BOOL ret = FALSE; 4810 4811 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 4812 4813 if (!DeviceInfoSet) 4814 SetLastError(ERROR_INVALID_HANDLE); 4815 else if ((deviceInfoSet = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4816 SetLastError(ERROR_INVALID_HANDLE); 4817 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4818 SetLastError(ERROR_INVALID_USER_BUFFER); 4819 else if (!IsDeviceInfoInDeviceInfoSet(deviceInfoSet, deviceInfo)) 4820 SetLastError(ERROR_INVALID_PARAMETER); 4821 else 4822 { 4823 RemoveEntryList(&deviceInfo->ListEntry); 4824 DestroyDeviceInfo(deviceInfo); 4825 ret = TRUE; 4826 } 4827 4828 return ret; 4829 } 4830 4831 4832 /*********************************************************************** 4833 * SetupDiOpenDeviceInfoA (SETUPAPI.@) 4834 */ 4835 BOOL WINAPI 4836 SetupDiOpenDeviceInfoA( 4837 IN HDEVINFO DeviceInfoSet, 4838 IN PCSTR DeviceInstanceId, 4839 IN HWND hwndParent OPTIONAL, 4840 IN DWORD OpenFlags, 4841 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 4842 { 4843 LPWSTR DeviceInstanceIdW = NULL; 4844 BOOL bResult; 4845 4846 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData); 4847 4848 DeviceInstanceIdW = pSetupMultiByteToUnicode(DeviceInstanceId, CP_ACP); 4849 if (DeviceInstanceIdW == NULL) 4850 return FALSE; 4851 4852 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet, 4853 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData); 4854 4855 MyFree(DeviceInstanceIdW); 4856 4857 return bResult; 4858 } 4859 4860 4861 /*********************************************************************** 4862 * SetupDiOpenDeviceInfoW (SETUPAPI.@) 4863 */ 4864 BOOL WINAPI 4865 SetupDiOpenDeviceInfoW( 4866 IN HDEVINFO DeviceInfoSet, 4867 IN PCWSTR DeviceInstanceId, 4868 IN HWND hwndParent OPTIONAL, 4869 IN DWORD OpenFlags, 4870 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 4871 { 4872 struct DeviceInfoSet *list; 4873 HKEY hEnumKey, hKey = NULL; 4874 DWORD rc, dwSize; 4875 BOOL ret = FALSE; 4876 4877 TRACE("%p %s %p %lx %p\n", 4878 DeviceInfoSet, debugstr_w(DeviceInstanceId), 4879 hwndParent, OpenFlags, DeviceInfoData); 4880 4881 if (OpenFlags & DIOD_CANCEL_REMOVE) 4882 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n"); 4883 4884 if (!DeviceInfoSet) 4885 SetLastError(ERROR_INVALID_HANDLE); 4886 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4887 SetLastError(ERROR_INVALID_HANDLE); 4888 else if (!DeviceInstanceId) 4889 SetLastError(ERROR_INVALID_PARAMETER); 4890 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS)) 4891 { 4892 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS)); 4893 SetLastError(ERROR_INVALID_FLAGS); 4894 } 4895 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4896 SetLastError(ERROR_INVALID_USER_BUFFER); 4897 else 4898 { 4899 struct DeviceInfo *deviceInfo = NULL; 4900 /* Search if device already exists in DeviceInfoSet. 4901 * If yes, return the existing element 4902 * If no, create a new element using information in registry 4903 */ 4904 PLIST_ENTRY ItemList = list->ListHead.Flink; 4905 while (ItemList != &list->ListHead) 4906 { 4907 deviceInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry); 4908 if (!wcscmp(deviceInfo->instanceId, DeviceInstanceId)) 4909 break; 4910 deviceInfo = NULL; 4911 ItemList = ItemList->Flink; 4912 } 4913 4914 if (deviceInfo) 4915 { 4916 /* good one found */ 4917 ret = TRUE; 4918 } 4919 else 4920 { 4921 GUID ClassGUID; 4922 WCHAR szClassGuid[MAX_GUID_STRING_LEN]; 4923 4924 /* Open supposed registry key */ 4925 rc = RegOpenKeyExW( 4926 list->HKLM, 4927 REGSTR_PATH_SYSTEMENUM, 4928 0, /* Options */ 4929 READ_CONTROL, 4930 &hEnumKey); 4931 if (rc != ERROR_SUCCESS) 4932 { 4933 SetLastError(rc); 4934 goto cleanup; 4935 } 4936 rc = RegOpenKeyExW( 4937 hEnumKey, 4938 DeviceInstanceId, 4939 0, /* Options */ 4940 KEY_QUERY_VALUE, 4941 &hKey); 4942 RegCloseKey(hEnumKey); 4943 if (rc != ERROR_SUCCESS) 4944 { 4945 if (rc == ERROR_FILE_NOT_FOUND) 4946 rc = ERROR_NO_SUCH_DEVINST; 4947 SetLastError(rc); 4948 goto cleanup; 4949 } 4950 4951 ClassGUID = GUID_NULL; 4952 dwSize = MAX_GUID_STRING_LEN * sizeof(WCHAR); 4953 4954 if (RegQueryValueExW(hKey, 4955 REGSTR_VAL_CLASSGUID, 4956 NULL, 4957 NULL, 4958 (LPBYTE)szClassGuid, 4959 &dwSize) == ERROR_SUCCESS) 4960 { 4961 szClassGuid[MAX_GUID_STRING_LEN - 2] = UNICODE_NULL; 4962 4963 /* Convert a string to a ClassGuid */ 4964 UuidFromStringW(&szClassGuid[1], &ClassGUID); 4965 } 4966 4967 if (!CreateDeviceInfo(list, DeviceInstanceId, &ClassGUID, &deviceInfo)) 4968 goto cleanup; 4969 4970 InsertTailList(&list->ListHead, &deviceInfo->ListEntry); 4971 4972 ret = TRUE; 4973 } 4974 4975 if (ret && deviceInfo && DeviceInfoData) 4976 { 4977 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID)); 4978 DeviceInfoData->DevInst = deviceInfo->dnDevInst; 4979 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo; 4980 } 4981 } 4982 4983 cleanup: 4984 if (hKey != NULL) 4985 RegCloseKey(hKey); 4986 return ret; 4987 } 4988 4989 4990 /*********************************************************************** 4991 * SetupDiGetSelectedDevice (SETUPAPI.@) 4992 */ 4993 BOOL WINAPI 4994 SetupDiGetSelectedDevice( 4995 IN HDEVINFO DeviceInfoSet, 4996 OUT PSP_DEVINFO_DATA DeviceInfoData) 4997 { 4998 struct DeviceInfoSet *list; 4999 BOOL ret = FALSE; 5000 5001 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 5002 5003 if (!DeviceInfoSet) 5004 SetLastError(ERROR_INVALID_HANDLE); 5005 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5006 SetLastError(ERROR_INVALID_HANDLE); 5007 else if (list->SelectedDevice == NULL) 5008 SetLastError(ERROR_NO_DEVICE_SELECTED); 5009 else if (!DeviceInfoData) 5010 SetLastError(ERROR_INVALID_PARAMETER); 5011 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 5012 SetLastError(ERROR_INVALID_USER_BUFFER); 5013 else 5014 { 5015 memcpy(&DeviceInfoData->ClassGuid, 5016 &list->SelectedDevice->ClassGuid, 5017 sizeof(GUID)); 5018 DeviceInfoData->DevInst = list->SelectedDevice->dnDevInst; 5019 DeviceInfoData->Reserved = (ULONG_PTR)list->SelectedDevice; 5020 ret = TRUE; 5021 } 5022 5023 TRACE("Returning %d\n", ret); 5024 return ret; 5025 } 5026 5027 5028 /*********************************************************************** 5029 * SetupDiSetSelectedDevice (SETUPAPI.@) 5030 */ 5031 BOOL WINAPI 5032 SetupDiSetSelectedDevice( 5033 IN HDEVINFO DeviceInfoSet, 5034 IN PSP_DEVINFO_DATA DeviceInfoData) 5035 { 5036 struct DeviceInfoSet *list; 5037 BOOL ret = FALSE; 5038 5039 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 5040 5041 if (!DeviceInfoSet) 5042 SetLastError(ERROR_INVALID_HANDLE); 5043 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5044 SetLastError(ERROR_INVALID_HANDLE); 5045 else if (!DeviceInfoData) 5046 SetLastError(ERROR_INVALID_PARAMETER); 5047 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 5048 SetLastError(ERROR_INVALID_USER_BUFFER); 5049 else if (DeviceInfoData->Reserved == 0) 5050 SetLastError(ERROR_INVALID_USER_BUFFER); 5051 else 5052 { 5053 list->SelectedDevice = (struct DeviceInfo *)DeviceInfoData->Reserved; 5054 ret = TRUE; 5055 } 5056 5057 TRACE("Returning %d\n", ret); 5058 return ret; 5059 } 5060 5061 5062 /* Return the current hardware profile id, or -1 if error */ 5063 static DWORD 5064 SETUPAPI_GetCurrentHwProfile( 5065 IN HDEVINFO DeviceInfoSet) 5066 { 5067 HKEY hKey = NULL; 5068 DWORD dwRegType, dwLength; 5069 DWORD hwProfile; 5070 LONG rc; 5071 DWORD ret = (DWORD)-1; 5072 5073 rc = RegOpenKeyExW(((struct DeviceInfoSet *)DeviceInfoSet)->HKLM, 5074 REGSTR_PATH_IDCONFIGDB, 5075 0, /* Options */ 5076 KEY_QUERY_VALUE, 5077 &hKey); 5078 if (rc != ERROR_SUCCESS) 5079 { 5080 SetLastError(rc); 5081 goto cleanup; 5082 } 5083 5084 dwLength = sizeof(DWORD); 5085 rc = RegQueryValueExW(hKey, 5086 REGSTR_VAL_CURRENTCONFIG, 5087 NULL, 5088 &dwRegType, 5089 (LPBYTE)&hwProfile, &dwLength); 5090 if (rc != ERROR_SUCCESS) 5091 { 5092 SetLastError(rc); 5093 goto cleanup; 5094 } 5095 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD)) 5096 { 5097 SetLastError(ERROR_GEN_FAILURE); 5098 goto cleanup; 5099 } 5100 5101 ret = hwProfile; 5102 5103 cleanup: 5104 if (hKey != NULL) 5105 RegCloseKey(hKey); 5106 5107 return ret; 5108 } 5109 5110 static BOOL 5111 ResetDevice( 5112 IN HDEVINFO DeviceInfoSet, 5113 IN PSP_DEVINFO_DATA DeviceInfoData) 5114 { 5115 #ifndef __WINESRC__ 5116 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 5117 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 5118 CONFIGRET cr; 5119 5120 cr = CM_Enable_DevNode_Ex(deviceInfo->dnDevInst, 0, set->hMachine); 5121 if (cr != CR_SUCCESS) 5122 { 5123 SetLastError(GetErrorCodeFromCrCode(cr)); 5124 return FALSE; 5125 } 5126 5127 return TRUE; 5128 #else 5129 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData); 5130 return TRUE; 5131 #endif 5132 } 5133 5134 static BOOL StopDevice( 5135 IN HDEVINFO DeviceInfoSet, 5136 IN PSP_DEVINFO_DATA DeviceInfoData) 5137 { 5138 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData); 5139 return TRUE; 5140 } 5141 5142 /*********************************************************************** 5143 * SetupDiChangeState (SETUPAPI.@) 5144 */ 5145 BOOL WINAPI 5146 SetupDiChangeState( 5147 IN HDEVINFO DeviceInfoSet, 5148 IN OUT PSP_DEVINFO_DATA DeviceInfoData) 5149 { 5150 PSP_PROPCHANGE_PARAMS PropChange; 5151 HKEY hKey = INVALID_HANDLE_VALUE; 5152 LPCWSTR RegistryValueName; 5153 DWORD dwConfigFlags, dwLength, dwRegType; 5154 LONG rc; 5155 BOOL ret = FALSE; 5156 5157 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 5158 5159 if (!DeviceInfoData) 5160 PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChangeParams; 5161 else 5162 PropChange = ((struct DeviceInfo *)DeviceInfoData->Reserved)->ClassInstallParams.PropChangeParams; 5163 if (!PropChange) 5164 { 5165 SetLastError(ERROR_INVALID_PARAMETER); 5166 goto cleanup; 5167 } 5168 5169 if (PropChange->Scope == DICS_FLAG_GLOBAL) 5170 RegistryValueName = REGSTR_VAL_CONFIGFLAGS; 5171 else 5172 RegistryValueName = REGSTR_VAL_CSCONFIGFLAGS; 5173 5174 switch (PropChange->StateChange) 5175 { 5176 case DICS_ENABLE: 5177 case DICS_DISABLE: 5178 { 5179 /* Enable/disable device in registry */ 5180 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE); 5181 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) 5182 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, NULL, NULL); 5183 if (hKey == INVALID_HANDLE_VALUE) 5184 break; 5185 dwLength = sizeof(DWORD); 5186 rc = RegQueryValueExW( 5187 hKey, 5188 RegistryValueName, 5189 NULL, 5190 &dwRegType, 5191 (LPBYTE)&dwConfigFlags, &dwLength); 5192 if (rc == ERROR_FILE_NOT_FOUND) 5193 dwConfigFlags = 0; 5194 else if (rc != ERROR_SUCCESS) 5195 { 5196 SetLastError(rc); 5197 goto cleanup; 5198 } 5199 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD)) 5200 { 5201 SetLastError(ERROR_GEN_FAILURE); 5202 goto cleanup; 5203 } 5204 if (PropChange->StateChange == DICS_ENABLE) 5205 dwConfigFlags &= ~(PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED); 5206 else 5207 dwConfigFlags |= (PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED); 5208 rc = RegSetValueExW( 5209 hKey, 5210 RegistryValueName, 5211 0, 5212 REG_DWORD, 5213 (LPBYTE)&dwConfigFlags, sizeof(DWORD)); 5214 if (rc != ERROR_SUCCESS) 5215 { 5216 SetLastError(rc); 5217 goto cleanup; 5218 } 5219 5220 /* Enable/disable device if needed */ 5221 if (PropChange->Scope == DICS_FLAG_GLOBAL 5222 || PropChange->HwProfile == 0 5223 || PropChange->HwProfile == SETUPAPI_GetCurrentHwProfile(DeviceInfoSet)) 5224 { 5225 if (PropChange->StateChange == DICS_ENABLE) 5226 ret = ResetDevice(DeviceInfoSet, DeviceInfoData); 5227 else 5228 ret = StopDevice(DeviceInfoSet, DeviceInfoData); 5229 } 5230 else 5231 ret = TRUE; 5232 break; 5233 } 5234 case DICS_PROPCHANGE: 5235 { 5236 ret = ResetDevice(DeviceInfoSet, DeviceInfoData); 5237 break; 5238 } 5239 default: 5240 { 5241 ERR("Unknown StateChange 0x%lx\n", PropChange->StateChange); 5242 SetLastError(ERROR_NOT_SUPPORTED); 5243 } 5244 } 5245 5246 cleanup: 5247 if (hKey != INVALID_HANDLE_VALUE) 5248 RegCloseKey(hKey); 5249 5250 TRACE("Returning %d\n", ret); 5251 return ret; 5252 } 5253 5254 /*********************************************************************** 5255 * SetupDiSelectDevice (SETUPAPI.@) 5256 */ 5257 BOOL WINAPI 5258 SetupDiSelectDevice( 5259 IN HDEVINFO DeviceInfoSet, 5260 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 5261 { 5262 FIXME("%p %p\n", DeviceInfoSet, DeviceInfoData); 5263 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 5264 return FALSE; 5265 } 5266 5267 5268 /*********************************************************************** 5269 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@) 5270 */ 5271 BOOL WINAPI 5272 SetupDiRegisterCoDeviceInstallers( 5273 IN HDEVINFO DeviceInfoSet, 5274 IN PSP_DEVINFO_DATA DeviceInfoData) 5275 { 5276 BOOL ret = FALSE; /* Return value */ 5277 5278 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 5279 5280 if (!DeviceInfoSet) 5281 SetLastError(ERROR_INVALID_PARAMETER); 5282 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 5283 SetLastError(ERROR_INVALID_HANDLE); 5284 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5285 SetLastError(ERROR_INVALID_HANDLE); 5286 else if (!DeviceInfoData) 5287 SetLastError(ERROR_INVALID_PARAMETER); 5288 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 5289 SetLastError(ERROR_INVALID_USER_BUFFER); 5290 else 5291 { 5292 SP_DEVINSTALL_PARAMS_W InstallParams; 5293 struct DriverInfoElement *SelectedDriver; 5294 BOOL Result; 5295 DWORD DoAction; 5296 WCHAR SectionName[MAX_PATH]; 5297 DWORD SectionNameLength = 0; 5298 HKEY hKey = INVALID_HANDLE_VALUE; 5299 PVOID Context = NULL; 5300 5301 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 5302 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 5303 if (!Result) 5304 goto cleanup; 5305 5306 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved; 5307 if (SelectedDriver == NULL) 5308 { 5309 SetLastError(ERROR_NO_DRIVER_SELECTED); 5310 goto cleanup; 5311 } 5312 5313 /* Get .CoInstallers section name */ 5314 Result = SetupDiGetActualSectionToInstallW( 5315 SelectedDriver->InfFileDetails->hInf, 5316 SelectedDriver->Details.SectionName, 5317 SectionName, MAX_PATH, &SectionNameLength, NULL); 5318 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotCoInstallers) - 1) 5319 goto cleanup; 5320 lstrcatW(SectionName, DotCoInstallers); 5321 5322 /* Open/Create driver key information */ 5323 #if _WIN32_WINNT >= 0x502 5324 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE); 5325 #else 5326 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS); 5327 #endif 5328 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) 5329 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL); 5330 if (hKey == INVALID_HANDLE_VALUE) 5331 goto cleanup; 5332 5333 /* Install .CoInstallers section */ 5334 DoAction = SPINST_REGISTRY; 5335 if (!(InstallParams.Flags & DI_NOFILECOPY)) 5336 { 5337 DoAction |= SPINST_FILES; 5338 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent); 5339 if (!Context) 5340 goto cleanup; 5341 } 5342 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent, 5343 SelectedDriver->InfFileDetails->hInf, SectionName, 5344 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, 5345 SetupDefaultQueueCallbackW, Context, 5346 DeviceInfoSet, DeviceInfoData); 5347 if (!Result) 5348 goto cleanup; 5349 5350 ret = TRUE; 5351 5352 cleanup: 5353 if (Context) 5354 SetupTermDefaultQueueCallback(Context); 5355 if (hKey != INVALID_HANDLE_VALUE) 5356 RegCloseKey(hKey); 5357 } 5358 5359 TRACE("Returning %d\n", ret); 5360 return ret; 5361 } 5362 5363 static BOOL 5364 InfIsFromOEMLocation( 5365 IN PCWSTR FullName, 5366 OUT LPBOOL IsOEMLocation) 5367 { 5368 PWCHAR last; 5369 5370 last = strrchrW(FullName, '\\'); 5371 if (!last) 5372 { 5373 /* No directory specified */ 5374 *IsOEMLocation = FALSE; 5375 } 5376 else 5377 { 5378 LPWSTR Windir; 5379 UINT ret; 5380 5381 Windir = MyMalloc((MAX_PATH + 1 + strlenW(InfDirectory)) * sizeof(WCHAR)); 5382 if (!Windir) 5383 { 5384 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 5385 return FALSE; 5386 } 5387 5388 ret = GetSystemWindowsDirectoryW(Windir, MAX_PATH); 5389 if (ret == 0 || ret > MAX_PATH) 5390 { 5391 MyFree(Windir); 5392 SetLastError(ERROR_GEN_FAILURE); 5393 return FALSE; 5394 } 5395 if (*Windir && Windir[strlenW(Windir) - 1] != '\\') 5396 strcatW(Windir, BackSlash); 5397 strcatW(Windir, InfDirectory); 5398 5399 if (strncmpiW(FullName, Windir, last - FullName) == 0) 5400 { 5401 /* The path is %SYSTEMROOT%\Inf */ 5402 *IsOEMLocation = FALSE; 5403 } 5404 else 5405 { 5406 /* The file is in another place */ 5407 *IsOEMLocation = TRUE; 5408 } 5409 MyFree(Windir); 5410 } 5411 return TRUE; 5412 } 5413 5414 /*********************************************************************** 5415 * SetupDiInstallDevice (SETUPAPI.@) 5416 */ 5417 BOOL WINAPI 5418 SetupDiInstallDevice( 5419 IN HDEVINFO DeviceInfoSet, 5420 IN OUT PSP_DEVINFO_DATA DeviceInfoData) 5421 { 5422 SP_DEVINSTALL_PARAMS_W InstallParams; 5423 struct DriverInfoElement *SelectedDriver; 5424 SYSTEMTIME DriverDate; 5425 WCHAR SectionName[MAX_PATH]; 5426 WCHAR Buffer[32]; 5427 DWORD SectionNameLength = 0; 5428 BOOL Result = FALSE; 5429 ULONG DoAction; 5430 DWORD RequiredSize; 5431 LPWSTR pSectionName = NULL; 5432 WCHAR ClassName[MAX_CLASS_NAME_LEN]; 5433 GUID ClassGuid; 5434 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL; 5435 BOOL RebootRequired = FALSE; 5436 HKEY hKey = INVALID_HANDLE_VALUE; 5437 BOOL NeedtoCopyFile; 5438 LARGE_INTEGER fullVersion; 5439 LONG rc; 5440 PVOID Context = NULL; 5441 BOOL ret = FALSE; /* Return value */ 5442 5443 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 5444 5445 if (!DeviceInfoSet) 5446 SetLastError(ERROR_INVALID_PARAMETER); 5447 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 5448 SetLastError(ERROR_INVALID_HANDLE); 5449 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5450 SetLastError(ERROR_INVALID_HANDLE); 5451 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 5452 SetLastError(ERROR_INVALID_USER_BUFFER); 5453 else 5454 Result = TRUE; 5455 5456 if (!Result) 5457 { 5458 /* One parameter is bad */ 5459 goto cleanup; 5460 } 5461 5462 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 5463 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 5464 if (!Result) 5465 goto cleanup; 5466 5467 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL) 5468 { 5469 /* Set FAILEDINSTALL in ConfigFlags registry value */ 5470 DWORD ConfigFlags, regType; 5471 Result = SetupDiGetDeviceRegistryPropertyW( 5472 DeviceInfoSet, 5473 DeviceInfoData, 5474 SPDRP_CONFIGFLAGS, 5475 ®Type, 5476 (PBYTE)&ConfigFlags, 5477 sizeof(ConfigFlags), 5478 NULL); 5479 if (!Result || regType != REG_DWORD) 5480 { 5481 SetLastError(ERROR_GEN_FAILURE); 5482 goto cleanup; 5483 } 5484 ConfigFlags |= DNF_DISABLED; 5485 Result = SetupDiSetDeviceRegistryPropertyW( 5486 DeviceInfoSet, 5487 DeviceInfoData, 5488 SPDRP_CONFIGFLAGS, 5489 (PBYTE)&ConfigFlags, 5490 sizeof(ConfigFlags)); 5491 if (!Result) 5492 { 5493 SetLastError(ERROR_GEN_FAILURE); 5494 goto cleanup; 5495 } 5496 5497 ret = TRUE; 5498 goto cleanup; 5499 } 5500 5501 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved; 5502 if (SelectedDriver == NULL) 5503 { 5504 SetLastError(ERROR_NO_DRIVER_SELECTED); 5505 goto cleanup; 5506 } 5507 5508 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate); 5509 5510 Result = SetupDiGetActualSectionToInstallW( 5511 SelectedDriver->InfFileDetails->hInf, 5512 SelectedDriver->Details.SectionName, 5513 SectionName, MAX_PATH, &SectionNameLength, NULL); 5514 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotServices)) 5515 goto cleanup; 5516 pSectionName = &SectionName[strlenW(SectionName)]; 5517 5518 /* Get information from [Version] section */ 5519 if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize)) 5520 goto cleanup; 5521 /* Format ClassGuid to a string */ 5522 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK) 5523 goto cleanup; 5524 RequiredSize = lstrlenW(lpGuidString); 5525 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR)); 5526 if (!lpFullGuidString) 5527 { 5528 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 5529 goto cleanup; 5530 } 5531 lpFullGuidString[0] = '{'; 5532 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR)); 5533 lpFullGuidString[RequiredSize + 1] = '}'; 5534 lpFullGuidString[RequiredSize + 2] = '\0'; 5535 5536 /* Copy .inf file to Inf\ directory (if needed) */ 5537 Result = InfIsFromOEMLocation(SelectedDriver->Details.InfFileName, &NeedtoCopyFile); 5538 if (!Result) 5539 goto cleanup; 5540 if (NeedtoCopyFile) 5541 { 5542 WCHAR NewFileName[MAX_PATH]; 5543 struct InfFileDetails *newInfFileDetails; 5544 Result = SetupCopyOEMInfW( 5545 SelectedDriver->Details.InfFileName, 5546 NULL, 5547 SPOST_NONE, 5548 SP_COPY_NOOVERWRITE, 5549 NewFileName, MAX_PATH, 5550 NULL, 5551 NULL); 5552 if (!Result && GetLastError() != ERROR_FILE_EXISTS) 5553 goto cleanup; 5554 /* Create a new struct InfFileDetails, and set it to 5555 * SelectedDriver->InfFileDetails, to release use of 5556 * current InfFile */ 5557 newInfFileDetails = CreateInfFileDetails(NewFileName); 5558 if (!newInfFileDetails) 5559 goto cleanup; 5560 DereferenceInfFile(SelectedDriver->InfFileDetails); 5561 SelectedDriver->InfFileDetails = newInfFileDetails; 5562 strcpyW(SelectedDriver->Details.InfFileName, NewFileName); 5563 } 5564 5565 /* Open/Create driver key information */ 5566 #if _WIN32_WINNT >= 0x502 5567 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE); 5568 #else 5569 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS); 5570 #endif 5571 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) 5572 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL); 5573 if (hKey == INVALID_HANDLE_VALUE) 5574 goto cleanup; 5575 5576 /* Install main section */ 5577 DoAction = 0; 5578 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY)) 5579 DoAction |= SPINST_REGISTRY; 5580 if (!(InstallParams.Flags & DI_NOFILECOPY)) 5581 { 5582 DoAction |= SPINST_FILES; 5583 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent); 5584 if (!Context) 5585 goto cleanup; 5586 } 5587 *pSectionName = '\0'; 5588 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent, 5589 SelectedDriver->InfFileDetails->hInf, SectionName, 5590 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, 5591 SetupDefaultQueueCallbackW, Context, 5592 DeviceInfoSet, DeviceInfoData); 5593 if (!Result) 5594 goto cleanup; 5595 InstallParams.Flags |= DI_NOFILECOPY; 5596 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 5597 5598 /* Write information to driver key */ 5599 *pSectionName = UNICODE_NULL; 5600 memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER)); 5601 TRACE("Write information to driver key\n"); 5602 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear); 5603 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description)); 5604 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff); 5605 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver->InfFileDetails->FileName)); 5606 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver->Details.SectionName)); 5607 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName[strlenW(SelectedDriver->Details.SectionName)])); 5608 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver->MatchingId)); 5609 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver->Info.ProviderName)); 5610 sprintfW(Buffer, DateFormat, DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear); 5611 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR)); 5612 if (rc == ERROR_SUCCESS) 5613 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE_DATA, 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME)); 5614 if (rc == ERROR_SUCCESS) 5615 rc = RegSetValueExW(hKey, REGSTR_VAL_DRVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR)); 5616 if (rc == ERROR_SUCCESS) 5617 { 5618 sprintfW(Buffer, VersionFormat, fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff); 5619 rc = RegSetValueExW(hKey, REGSTR_DRIVER_VERSION, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR)); 5620 } 5621 if (rc == ERROR_SUCCESS) 5622 rc = RegSetValueExW(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->InfFileDetails->FileName, (strlenW(SelectedDriver->InfFileDetails->FileName) + 1) * sizeof(WCHAR)); 5623 if (rc == ERROR_SUCCESS) 5624 rc = RegSetValueExW(hKey, REGSTR_VAL_INFSECTION, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR)); 5625 if (rc == ERROR_SUCCESS) 5626 rc = RegSetValueExW(hKey, REGSTR_VAL_INFSECTIONEXT, 0, REG_SZ, (const BYTE *)&SectionName[strlenW(SelectedDriver->Details.SectionName)], (strlenW(SectionName) - strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR)); 5627 if (rc == ERROR_SUCCESS) 5628 rc = RegSetValueExW(hKey, REGSTR_VAL_MATCHINGDEVID, 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (strlenW(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR)); 5629 if (rc == ERROR_SUCCESS) 5630 rc = RegSetValueExW(hKey, REGSTR_VAL_PROVIDER_NAME, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (strlenW(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR)); 5631 if (rc != ERROR_SUCCESS) 5632 { 5633 SetLastError(rc); 5634 goto cleanup; 5635 } 5636 RegCloseKey(hKey); 5637 hKey = INVALID_HANDLE_VALUE; 5638 5639 /* FIXME: Process .LogConfigOverride section */ 5640 5641 /* Install .Services section */ 5642 strcpyW(pSectionName, DotServices); 5643 Result = SetupInstallServicesFromInfSectionExW( 5644 SelectedDriver->InfFileDetails->hInf, 5645 SectionName, 5646 0, 5647 DeviceInfoSet, 5648 DeviceInfoData, 5649 NULL, 5650 NULL); 5651 if (!Result) 5652 goto cleanup; 5653 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED) 5654 RebootRequired = TRUE; 5655 5656 /* Open device registry key */ 5657 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE); 5658 if (hKey == INVALID_HANDLE_VALUE) 5659 goto cleanup; 5660 5661 /* Install .HW section */ 5662 DoAction = 0; 5663 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY)) 5664 DoAction |= SPINST_REGISTRY; 5665 strcpyW(pSectionName, DotHW); 5666 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent, 5667 SelectedDriver->InfFileDetails->hInf, SectionName, 5668 DoAction, hKey, NULL, 0, 5669 NULL, NULL, 5670 DeviceInfoSet, DeviceInfoData); 5671 if (!Result) 5672 goto cleanup; 5673 5674 /* Write information to enum key */ 5675 TRACE("Write information to enum key\n"); 5676 TRACE("Class : '%s'\n", debugstr_w(ClassName)); 5677 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString)); 5678 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description)); 5679 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver->Info.MfgName)); 5680 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (strlenW(ClassName) + 1) * sizeof(WCHAR)); 5681 if (rc == ERROR_SUCCESS) 5682 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (strlenW(lpFullGuidString) + 1) * sizeof(WCHAR)); 5683 if (rc == ERROR_SUCCESS) 5684 rc = RegSetValueExW(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR)); 5685 if (rc == ERROR_SUCCESS) 5686 rc = RegSetValueExW(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (strlenW(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR)); 5687 if (rc != ERROR_SUCCESS) 5688 { 5689 SetLastError(rc); 5690 goto cleanup; 5691 } 5692 5693 /* Start the device */ 5694 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG))) 5695 ret = ResetDevice(DeviceInfoSet, DeviceInfoData); 5696 else 5697 ret = TRUE; 5698 5699 cleanup: 5700 /* End of installation */ 5701 if (hKey != INVALID_HANDLE_VALUE) 5702 RegCloseKey(hKey); 5703 if (lpGuidString) 5704 RpcStringFreeW(&lpGuidString); 5705 HeapFree(GetProcessHeap(), 0, lpFullGuidString); 5706 if (Context) 5707 SetupTermDefaultQueueCallback(Context); 5708 TRACE("Returning %d\n", ret); 5709 return ret; 5710 } 5711 5712 static HKEY SETUPDI_OpenDevKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired) 5713 { 5714 HKEY enumKey, key = INVALID_HANDLE_VALUE; 5715 LONG l; 5716 5717 l = RegOpenKeyExW(RootKey, REGSTR_PATH_SYSTEMENUM, 0, READ_CONTROL, &enumKey); 5718 if (!l) 5719 { 5720 l = RegOpenKeyExW(enumKey, devInfo->instanceId, 0, samDesired, &key); 5721 RegCloseKey(enumKey); 5722 } 5723 if (l) 5724 SetLastError(l); 5725 return key; 5726 } 5727 5728 static HKEY SETUPDI_OpenDrvKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired) 5729 { 5730 LPWSTR DriverKey = NULL; 5731 DWORD dwLength = 0; 5732 DWORD dwRegType; 5733 DWORD rc; 5734 HKEY hEnumKey = NULL; 5735 HKEY hKey = NULL; 5736 HKEY key = INVALID_HANDLE_VALUE; 5737 5738 hKey = SETUPDI_OpenDevKey(RootKey, devInfo, KEY_QUERY_VALUE); 5739 if (hKey == INVALID_HANDLE_VALUE) 5740 goto cleanup; 5741 /* Read the 'Driver' key */ 5742 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, NULL, &dwLength); 5743 if (rc != ERROR_SUCCESS) 5744 { 5745 SetLastError(rc); 5746 goto cleanup; 5747 } 5748 else if (dwRegType != REG_SZ) 5749 { 5750 SetLastError(ERROR_GEN_FAILURE); 5751 goto cleanup; 5752 } 5753 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength); 5754 if (!DriverKey) 5755 { 5756 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 5757 goto cleanup; 5758 } 5759 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength); 5760 if (rc != ERROR_SUCCESS) 5761 { 5762 SetLastError(rc); 5763 goto cleanup; 5764 } 5765 RegCloseKey(hKey); 5766 hKey = NULL; 5767 /* Need to open the driver key */ 5768 rc = RegOpenKeyExW( 5769 RootKey, 5770 REGSTR_PATH_CLASS_NT, 5771 0, /* Options */ 5772 READ_CONTROL, 5773 &hEnumKey); 5774 if (rc != ERROR_SUCCESS) 5775 { 5776 SetLastError(rc); 5777 goto cleanup; 5778 } 5779 rc = RegOpenKeyExW( 5780 hEnumKey, 5781 DriverKey, 5782 0, /* Options */ 5783 samDesired, 5784 &hKey); 5785 if (rc != ERROR_SUCCESS) 5786 { 5787 SetLastError(rc); 5788 goto cleanup; 5789 } 5790 key = hKey; 5791 5792 cleanup: 5793 if (hEnumKey != NULL) 5794 RegCloseKey(hEnumKey); 5795 if (hKey != NULL && hKey != key) 5796 RegCloseKey(hKey); 5797 if (DriverKey) 5798 HeapFree(GetProcessHeap(), 0, DriverKey); 5799 return key; 5800 } 5801 5802 /*********************************************************************** 5803 * SetupDiOpenDevRegKey (SETUPAPI.@) 5804 */ 5805 HKEY WINAPI SetupDiOpenDevRegKey( 5806 HDEVINFO DeviceInfoSet, 5807 PSP_DEVINFO_DATA DeviceInfoData, 5808 DWORD Scope, 5809 DWORD HwProfile, 5810 DWORD KeyType, 5811 REGSAM samDesired) 5812 { 5813 struct DeviceInfoSet *set = DeviceInfoSet; 5814 struct DeviceInfo *devInfo; 5815 HKEY key = INVALID_HANDLE_VALUE; 5816 HKEY RootKey; 5817 5818 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData, 5819 Scope, HwProfile, KeyType, samDesired); 5820 5821 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 5822 { 5823 SetLastError(ERROR_INVALID_HANDLE); 5824 return INVALID_HANDLE_VALUE; 5825 } 5826 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5827 { 5828 SetLastError(ERROR_INVALID_HANDLE); 5829 return INVALID_HANDLE_VALUE; 5830 } 5831 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 5832 || !DeviceInfoData->Reserved) 5833 { 5834 SetLastError(ERROR_INVALID_PARAMETER); 5835 return INVALID_HANDLE_VALUE; 5836 } 5837 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC) 5838 { 5839 SetLastError(ERROR_INVALID_FLAGS); 5840 return INVALID_HANDLE_VALUE; 5841 } 5842 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV) 5843 { 5844 SetLastError(ERROR_INVALID_FLAGS); 5845 return INVALID_HANDLE_VALUE; 5846 } 5847 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 5848 if (devInfo->set != set) 5849 { 5850 SetLastError(ERROR_INVALID_PARAMETER); 5851 return INVALID_HANDLE_VALUE; 5852 } 5853 if (Scope != DICS_FLAG_GLOBAL) 5854 { 5855 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0); 5856 if (RootKey == INVALID_HANDLE_VALUE) 5857 return INVALID_HANDLE_VALUE; 5858 } 5859 else 5860 RootKey = set->HKLM; 5861 switch (KeyType) 5862 { 5863 case DIREG_DEV: 5864 key = SETUPDI_OpenDevKey(RootKey, devInfo, samDesired); 5865 break; 5866 case DIREG_DRV: 5867 key = SETUPDI_OpenDrvKey(RootKey, devInfo, samDesired); 5868 break; 5869 default: 5870 WARN("unknown KeyType %d\n", KeyType); 5871 } 5872 if (RootKey != set->HKLM) 5873 RegCloseKey(RootKey); 5874 return key; 5875 } 5876 5877 static BOOL SETUPDI_DeleteDevKey(HKEY RootKey, struct DeviceInfo *devInfo) 5878 { 5879 FIXME("\n"); 5880 return FALSE; 5881 } 5882 5883 static BOOL SETUPDI_DeleteDrvKey(HKEY RootKey, struct DeviceInfo *devInfo) 5884 { 5885 FIXME("\n"); 5886 return FALSE; 5887 } 5888 5889 /*********************************************************************** 5890 * SetupDiDeleteDevRegKey (SETUPAPI.@) 5891 */ 5892 BOOL WINAPI SetupDiDeleteDevRegKey( 5893 HDEVINFO DeviceInfoSet, 5894 PSP_DEVINFO_DATA DeviceInfoData, 5895 DWORD Scope, 5896 DWORD HwProfile, 5897 DWORD KeyType) 5898 { 5899 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 5900 struct DeviceInfo *devInfo; 5901 BOOL ret = FALSE; 5902 HKEY RootKey; 5903 5904 TRACE("%p %p %d %d %d\n", DeviceInfoSet, DeviceInfoData, Scope, HwProfile, 5905 KeyType); 5906 5907 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 5908 { 5909 SetLastError(ERROR_INVALID_HANDLE); 5910 return FALSE; 5911 } 5912 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5913 { 5914 SetLastError(ERROR_INVALID_HANDLE); 5915 return FALSE; 5916 } 5917 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 5918 || !DeviceInfoData->Reserved) 5919 { 5920 SetLastError(ERROR_INVALID_PARAMETER); 5921 return FALSE; 5922 } 5923 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC) 5924 { 5925 SetLastError(ERROR_INVALID_FLAGS); 5926 return FALSE; 5927 } 5928 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV && KeyType != DIREG_BOTH) 5929 { 5930 SetLastError(ERROR_INVALID_FLAGS); 5931 return FALSE; 5932 } 5933 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 5934 if (devInfo->set != set) 5935 { 5936 SetLastError(ERROR_INVALID_PARAMETER); 5937 return FALSE; 5938 } 5939 if (Scope != DICS_FLAG_GLOBAL) 5940 { 5941 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0); 5942 if (RootKey == INVALID_HANDLE_VALUE) 5943 return FALSE; 5944 } 5945 else 5946 RootKey = set->HKLM; 5947 switch (KeyType) 5948 { 5949 case DIREG_DEV: 5950 ret = SETUPDI_DeleteDevKey(RootKey, devInfo); 5951 break; 5952 case DIREG_DRV: 5953 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo); 5954 break; 5955 case DIREG_BOTH: 5956 ret = SETUPDI_DeleteDevKey(RootKey, devInfo); 5957 if (ret) 5958 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo); 5959 break; 5960 default: 5961 WARN("unknown KeyType %d\n", KeyType); 5962 } 5963 if (RootKey != set->HKLM) 5964 RegCloseKey(RootKey); 5965 return ret; 5966 } 5967