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 WCHAR szGuidString[40]; 4292 if (pSetupStringFromGuid(&DeviceInfoData->ClassGuid, szGuidString, ARRAYSIZE(szGuidString)) == ERROR_SUCCESS) 4293 { 4294 rc = RegQueryValueExW(hKey, szGuidString, 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, szGuidString, 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 } 4323 RegCloseKey(hKey); 4324 } 4325 } 4326 if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED)) 4327 { 4328 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE); 4329 if (hKey != INVALID_HANDLE_VALUE) 4330 { 4331 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength); 4332 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ) 4333 { 4334 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); 4335 if (KeyBuffer != NULL) 4336 { 4337 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); 4338 if (rc == ERROR_SUCCESS) 4339 { 4340 /* Get ClassInstaller function pointer */ 4341 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer)); 4342 if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS) 4343 { 4344 InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED; 4345 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 4346 } 4347 } 4348 HeapFree(GetProcessHeap(), 0, KeyBuffer); 4349 } 4350 } 4351 RegCloseKey(hKey); 4352 } 4353 } 4354 4355 /* Call Class co-installers */ 4356 Context.PostProcessing = FALSE; 4357 rc = NO_ERROR; 4358 ListEntry = ClassCoInstallersListHead.Flink; 4359 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead) 4360 { 4361 struct CoInstallerElement *coinstaller; 4362 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 4363 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 4364 coinstaller->PrivateData = Context.PrivateData; 4365 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED) 4366 { 4367 coinstaller->DoPostProcessing = TRUE; 4368 rc = NO_ERROR; 4369 } 4370 ListEntry = ListEntry->Flink; 4371 } 4372 4373 /* Call Device co-installers */ 4374 ListEntry = DeviceCoInstallersListHead.Flink; 4375 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead) 4376 { 4377 struct CoInstallerElement *coinstaller; 4378 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 4379 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 4380 coinstaller->PrivateData = Context.PrivateData; 4381 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED) 4382 { 4383 coinstaller->DoPostProcessing = TRUE; 4384 rc = NO_ERROR; 4385 } 4386 ListEntry = ListEntry->Flink; 4387 } 4388 4389 /* Call Class installer */ 4390 if (ClassInstaller) 4391 { 4392 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData); 4393 FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller); 4394 } 4395 else 4396 rc = ERROR_DI_DO_DEFAULT; 4397 4398 /* Call default handler */ 4399 if (rc == ERROR_DI_DO_DEFAULT) 4400 { 4401 if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION)) 4402 { 4403 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData)) 4404 rc = NO_ERROR; 4405 else 4406 rc = GetLastError(); 4407 } 4408 else 4409 rc = NO_ERROR; 4410 } 4411 4412 /* Call Class co-installers that required postprocessing */ 4413 Context.PostProcessing = TRUE; 4414 ListEntry = ClassCoInstallersListHead.Flink; 4415 while (ListEntry != &ClassCoInstallersListHead) 4416 { 4417 struct CoInstallerElement *coinstaller; 4418 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 4419 if (coinstaller->DoPostProcessing) 4420 { 4421 Context.InstallResult = rc; 4422 Context.PrivateData = coinstaller->PrivateData; 4423 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 4424 } 4425 FreeFunctionPointer(coinstaller->Module, coinstaller->Function); 4426 ListEntry = ListEntry->Flink; 4427 } 4428 4429 /* Call Device co-installers that required postprocessing */ 4430 ListEntry = DeviceCoInstallersListHead.Flink; 4431 while (ListEntry != &DeviceCoInstallersListHead) 4432 { 4433 struct CoInstallerElement *coinstaller; 4434 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 4435 if (coinstaller->DoPostProcessing) 4436 { 4437 Context.InstallResult = rc; 4438 Context.PrivateData = coinstaller->PrivateData; 4439 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 4440 } 4441 FreeFunctionPointer(coinstaller->Module, coinstaller->Function); 4442 ListEntry = ListEntry->Flink; 4443 } 4444 4445 /* Free allocated memory */ 4446 while (!IsListEmpty(&ClassCoInstallersListHead)) 4447 { 4448 ListEntry = RemoveHeadList(&ClassCoInstallersListHead); 4449 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry)); 4450 } 4451 while (!IsListEmpty(&DeviceCoInstallersListHead)) 4452 { 4453 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead); 4454 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry)); 4455 } 4456 4457 ret = (rc == NO_ERROR); 4458 } 4459 } 4460 4461 TRACE("Returning %d\n", ret); 4462 return ret; 4463 } 4464 4465 /*********************************************************************** 4466 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@) 4467 */ 4468 BOOL WINAPI SetupDiGetDeviceInstallParamsA( 4469 HDEVINFO DeviceInfoSet, 4470 PSP_DEVINFO_DATA DeviceInfoData, 4471 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams) 4472 { 4473 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW; 4474 BOOL ret = FALSE; 4475 4476 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 4477 4478 if (DeviceInstallParams == NULL) 4479 SetLastError(ERROR_INVALID_PARAMETER); 4480 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A)) 4481 SetLastError(ERROR_INVALID_USER_BUFFER); 4482 else 4483 { 4484 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 4485 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW); 4486 4487 if (ret) 4488 { 4489 /* Do W->A conversion */ 4490 memcpy( 4491 DeviceInstallParams, 4492 &deviceInstallParamsW, 4493 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath)); 4494 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1, 4495 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0) 4496 { 4497 DeviceInstallParams->DriverPath[0] = '\0'; 4498 ret = FALSE; 4499 } 4500 } 4501 } 4502 4503 TRACE("Returning %d\n", ret); 4504 return ret; 4505 } 4506 4507 /*********************************************************************** 4508 * SetupDiGetDeviceInfoListClass (SETUPAPI.@) 4509 */ 4510 BOOL WINAPI 4511 SetupDiGetDeviceInfoListClass( 4512 IN HDEVINFO DeviceInfoSet, 4513 OUT LPGUID ClassGuid) 4514 { 4515 struct DeviceInfoSet *list; 4516 BOOL ret = FALSE; 4517 4518 TRACE("%p %p\n", DeviceInfoSet, ClassGuid); 4519 4520 if (!DeviceInfoSet) 4521 SetLastError(ERROR_INVALID_HANDLE); 4522 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4523 SetLastError(ERROR_INVALID_HANDLE); 4524 else if (IsEqualIID(&list->ClassGuid, &GUID_NULL)) 4525 SetLastError(ERROR_NO_ASSOCIATED_CLASS); 4526 else 4527 { 4528 memcpy(&ClassGuid, &list->ClassGuid, sizeof(GUID)); 4529 4530 ret = TRUE; 4531 } 4532 4533 TRACE("Returning %d\n", ret); 4534 return ret; 4535 } 4536 4537 /*********************************************************************** 4538 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@) 4539 */ 4540 BOOL WINAPI 4541 SetupDiGetDeviceInstallParamsW( 4542 IN HDEVINFO DeviceInfoSet, 4543 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 4544 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams) 4545 { 4546 struct DeviceInfoSet *list; 4547 BOOL ret = FALSE; 4548 4549 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 4550 4551 if (!DeviceInfoSet) 4552 SetLastError(ERROR_INVALID_HANDLE); 4553 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4554 SetLastError(ERROR_INVALID_HANDLE); 4555 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4556 SetLastError(ERROR_INVALID_USER_BUFFER); 4557 else if (!DeviceInstallParams) 4558 SetLastError(ERROR_INVALID_PARAMETER); 4559 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W)) 4560 SetLastError(ERROR_INVALID_USER_BUFFER); 4561 else 4562 { 4563 PSP_DEVINSTALL_PARAMS_W Source; 4564 4565 if (DeviceInfoData) 4566 Source = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams; 4567 else 4568 Source = &list->InstallParams; 4569 4570 ret = TRUE; 4571 4572 _SEH2_TRY 4573 { 4574 memcpy(DeviceInstallParams, Source, Source->cbSize); 4575 } 4576 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 4577 { 4578 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); 4579 ret = FALSE; 4580 } 4581 _SEH2_END; 4582 } 4583 4584 TRACE("Returning %d\n", ret); 4585 return ret; 4586 } 4587 4588 static BOOL 4589 CheckDeviceInstallParameters( 4590 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams) 4591 { 4592 DWORD SupportedFlags = 4593 DI_NOVCP | /* 0x00000008 */ 4594 DI_DIDCOMPAT | /* 0x00000010 */ 4595 DI_DIDCLASS | /* 0x00000020 */ 4596 DI_NEEDRESTART | /* 0x00000080 */ 4597 DI_NEEDREBOOT | /* 0x00000100 */ 4598 DI_RESOURCEPAGE_ADDED | /* 0x00002000 */ 4599 DI_PROPERTIES_CHANGE | /* 0x00004000 */ 4600 DI_ENUMSINGLEINF | /* 0x00010000 */ 4601 DI_DONOTCALLCONFIGMG | /* 0x00020000 */ 4602 DI_CLASSINSTALLPARAMS | /* 0x00100000 */ 4603 DI_NODI_DEFAULTACTION | /* 0x00200000 */ 4604 DI_QUIETINSTALL | /* 0x00800000 */ 4605 DI_NOFILECOPY | /* 0x01000000 */ 4606 DI_DRIVERPAGE_ADDED; /* 0x04000000 */ 4607 DWORD SupportedFlagsEx = 4608 DI_FLAGSEX_CI_FAILED | /* 0x00000004 */ 4609 DI_FLAGSEX_DIDINFOLIST | /* 0x00000010 */ 4610 DI_FLAGSEX_DIDCOMPATINFO | /* 0x00000020 */ 4611 DI_FLAGSEX_ALLOWEXCLUDEDDRVS | /* 0x00000800 */ 4612 DI_FLAGSEX_NO_DRVREG_MODIFY | /* 0x00008000 */ 4613 DI_FLAGSEX_INSTALLEDDRIVER; /* 0x04000000 */ 4614 BOOL ret = FALSE; 4615 4616 /* FIXME: add support for more flags */ 4617 4618 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used. 4619 * It should be checked before accessing to other values 4620 * of the SP_DEVINSTALL_PARAMS structure */ 4621 4622 if (DeviceInstallParams->Flags & ~SupportedFlags) 4623 { 4624 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams->Flags & ~SupportedFlags); 4625 SetLastError(ERROR_INVALID_FLAGS); 4626 } 4627 else if (DeviceInstallParams->FlagsEx & ~SupportedFlagsEx) 4628 { 4629 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams->FlagsEx & ~SupportedFlagsEx); 4630 SetLastError(ERROR_INVALID_FLAGS); 4631 } 4632 else if ((DeviceInstallParams->Flags & DI_NOVCP) 4633 && (DeviceInstallParams->FileQueue == NULL || DeviceInstallParams->FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE)) 4634 SetLastError(ERROR_INVALID_USER_BUFFER); 4635 else 4636 { 4637 /* FIXME: check Reserved field */ 4638 ret = TRUE; 4639 } 4640 4641 return ret; 4642 } 4643 4644 /*********************************************************************** 4645 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@) 4646 */ 4647 BOOL WINAPI 4648 SetupDiSetDeviceInstallParamsW( 4649 IN HDEVINFO DeviceInfoSet, 4650 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 4651 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams) 4652 { 4653 struct DeviceInfoSet *list; 4654 BOOL ret = FALSE; 4655 4656 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 4657 4658 if (!DeviceInfoSet) 4659 SetLastError(ERROR_INVALID_HANDLE); 4660 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4661 SetLastError(ERROR_INVALID_HANDLE); 4662 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4663 SetLastError(ERROR_INVALID_USER_BUFFER); 4664 else if (!DeviceInstallParams) 4665 SetLastError(ERROR_INVALID_PARAMETER); 4666 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W)) 4667 SetLastError(ERROR_INVALID_USER_BUFFER); 4668 else if (CheckDeviceInstallParameters(DeviceInstallParams)) 4669 { 4670 PSP_DEVINSTALL_PARAMS_W Destination; 4671 4672 if (DeviceInfoData) 4673 Destination = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams; 4674 else 4675 Destination = &list->InstallParams; 4676 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize); 4677 ret = TRUE; 4678 } 4679 4680 TRACE("Returning %d\n", ret); 4681 return ret; 4682 } 4683 4684 /*********************************************************************** 4685 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@) 4686 */ 4687 BOOL WINAPI 4688 SetupDiSetDeviceInstallParamsA( 4689 HDEVINFO DeviceInfoSet, 4690 PSP_DEVINFO_DATA DeviceInfoData, 4691 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams) 4692 { 4693 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW; 4694 int len = 0; 4695 BOOL ret = FALSE; 4696 4697 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 4698 4699 if (DeviceInstallParams == NULL) 4700 SetLastError(ERROR_INVALID_PARAMETER); 4701 else if (DeviceInstallParams->cbSize < sizeof(SP_DEVINSTALL_PARAMS_A)) 4702 SetLastError(ERROR_INVALID_USER_BUFFER); 4703 else 4704 { 4705 memcpy(&deviceInstallParamsW, DeviceInstallParams, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A, DriverPath)); 4706 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 4707 len = MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, NULL, 0); 4708 if (!len) 4709 { 4710 ERR("DrivePath is NULL\n"); 4711 ret = FALSE; 4712 } 4713 else 4714 { 4715 MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, deviceInstallParamsW.DriverPath, len); 4716 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW); 4717 } 4718 } 4719 4720 TRACE("Returning %d\n", ret); 4721 return ret; 4722 } 4723 4724 static HKEY 4725 OpenHardwareProfileKey( 4726 IN HKEY HKLM, 4727 IN DWORD HwProfile, 4728 IN DWORD samDesired) 4729 { 4730 HKEY hHWProfilesKey = NULL; 4731 HKEY hHWProfileKey = NULL; 4732 HKEY ret = INVALID_HANDLE_VALUE; 4733 LONG rc; 4734 4735 rc = RegOpenKeyExW(HKLM, 4736 REGSTR_PATH_HWPROFILES, 4737 0, 4738 READ_CONTROL, 4739 &hHWProfilesKey); 4740 if (rc != ERROR_SUCCESS) 4741 { 4742 SetLastError(rc); 4743 goto cleanup; 4744 } 4745 if (HwProfile == 0) 4746 { 4747 rc = RegOpenKeyExW(hHWProfilesKey, 4748 REGSTR_KEY_CURRENT, 4749 0, 4750 KEY_CREATE_SUB_KEY, 4751 &hHWProfileKey); 4752 } 4753 else 4754 { 4755 WCHAR subKey[5]; 4756 snprintfW(subKey, 4, InstanceKeyFormat, HwProfile); 4757 subKey[4] = '\0'; 4758 rc = RegOpenKeyExW(hHWProfilesKey, 4759 subKey, 4760 0, 4761 KEY_CREATE_SUB_KEY, 4762 &hHWProfileKey); 4763 } 4764 if (rc != ERROR_SUCCESS) 4765 { 4766 SetLastError(rc); 4767 goto cleanup; 4768 } 4769 ret = hHWProfileKey; 4770 4771 cleanup: 4772 if (hHWProfilesKey != NULL) 4773 RegCloseKey(hHWProfilesKey); 4774 if (hHWProfileKey != NULL && hHWProfileKey != ret) 4775 RegCloseKey(hHWProfileKey); 4776 return ret; 4777 } 4778 4779 static BOOL 4780 IsDeviceInfoInDeviceInfoSet( 4781 struct DeviceInfoSet *deviceInfoSet, 4782 struct DeviceInfo *deviceInfo) 4783 { 4784 PLIST_ENTRY ListEntry; 4785 4786 ListEntry = deviceInfoSet->ListHead.Flink; 4787 while (ListEntry != &deviceInfoSet->ListHead) 4788 { 4789 if (deviceInfo == CONTAINING_RECORD(ListEntry, struct DeviceInfo, ListEntry)) 4790 return TRUE; 4791 4792 ListEntry = ListEntry->Flink; 4793 } 4794 4795 return FALSE; 4796 } 4797 4798 /*********************************************************************** 4799 * SetupDiDeleteDeviceInfo (SETUPAPI.@) 4800 */ 4801 BOOL WINAPI 4802 SetupDiDeleteDeviceInfo( 4803 IN HDEVINFO DeviceInfoSet, 4804 IN PSP_DEVINFO_DATA DeviceInfoData) 4805 { 4806 struct DeviceInfoSet *deviceInfoSet; 4807 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData; 4808 BOOL ret = FALSE; 4809 4810 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 4811 4812 if (!DeviceInfoSet) 4813 SetLastError(ERROR_INVALID_HANDLE); 4814 else if ((deviceInfoSet = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4815 SetLastError(ERROR_INVALID_HANDLE); 4816 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4817 SetLastError(ERROR_INVALID_USER_BUFFER); 4818 else if (!IsDeviceInfoInDeviceInfoSet(deviceInfoSet, deviceInfo)) 4819 SetLastError(ERROR_INVALID_PARAMETER); 4820 else 4821 { 4822 RemoveEntryList(&deviceInfo->ListEntry); 4823 DestroyDeviceInfo(deviceInfo); 4824 ret = TRUE; 4825 } 4826 4827 return ret; 4828 } 4829 4830 4831 /*********************************************************************** 4832 * SetupDiOpenDeviceInfoA (SETUPAPI.@) 4833 */ 4834 BOOL WINAPI 4835 SetupDiOpenDeviceInfoA( 4836 IN HDEVINFO DeviceInfoSet, 4837 IN PCSTR DeviceInstanceId, 4838 IN HWND hwndParent OPTIONAL, 4839 IN DWORD OpenFlags, 4840 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 4841 { 4842 LPWSTR DeviceInstanceIdW = NULL; 4843 BOOL bResult; 4844 4845 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData); 4846 4847 DeviceInstanceIdW = pSetupMultiByteToUnicode(DeviceInstanceId, CP_ACP); 4848 if (DeviceInstanceIdW == NULL) 4849 return FALSE; 4850 4851 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet, 4852 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData); 4853 4854 MyFree(DeviceInstanceIdW); 4855 4856 return bResult; 4857 } 4858 4859 4860 /*********************************************************************** 4861 * SetupDiOpenDeviceInfoW (SETUPAPI.@) 4862 */ 4863 BOOL WINAPI 4864 SetupDiOpenDeviceInfoW( 4865 IN HDEVINFO DeviceInfoSet, 4866 IN PCWSTR DeviceInstanceId, 4867 IN HWND hwndParent OPTIONAL, 4868 IN DWORD OpenFlags, 4869 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 4870 { 4871 struct DeviceInfoSet *list; 4872 HKEY hEnumKey, hKey = NULL; 4873 DWORD rc, dwSize; 4874 BOOL ret = FALSE; 4875 4876 TRACE("%p %s %p %lx %p\n", 4877 DeviceInfoSet, debugstr_w(DeviceInstanceId), 4878 hwndParent, OpenFlags, DeviceInfoData); 4879 4880 if (OpenFlags & DIOD_CANCEL_REMOVE) 4881 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n"); 4882 4883 if (!DeviceInfoSet) 4884 SetLastError(ERROR_INVALID_HANDLE); 4885 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4886 SetLastError(ERROR_INVALID_HANDLE); 4887 else if (!DeviceInstanceId) 4888 SetLastError(ERROR_INVALID_PARAMETER); 4889 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS)) 4890 { 4891 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS)); 4892 SetLastError(ERROR_INVALID_FLAGS); 4893 } 4894 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4895 SetLastError(ERROR_INVALID_USER_BUFFER); 4896 else 4897 { 4898 struct DeviceInfo *deviceInfo = NULL; 4899 /* Search if device already exists in DeviceInfoSet. 4900 * If yes, return the existing element 4901 * If no, create a new element using information in registry 4902 */ 4903 PLIST_ENTRY ItemList = list->ListHead.Flink; 4904 while (ItemList != &list->ListHead) 4905 { 4906 deviceInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry); 4907 if (!wcscmp(deviceInfo->instanceId, DeviceInstanceId)) 4908 break; 4909 deviceInfo = NULL; 4910 ItemList = ItemList->Flink; 4911 } 4912 4913 if (deviceInfo) 4914 { 4915 /* good one found */ 4916 ret = TRUE; 4917 } 4918 else 4919 { 4920 GUID ClassGUID; 4921 WCHAR szClassGuid[MAX_GUID_STRING_LEN]; 4922 4923 /* Open supposed registry key */ 4924 rc = RegOpenKeyExW( 4925 list->HKLM, 4926 REGSTR_PATH_SYSTEMENUM, 4927 0, /* Options */ 4928 READ_CONTROL, 4929 &hEnumKey); 4930 if (rc != ERROR_SUCCESS) 4931 { 4932 SetLastError(rc); 4933 goto cleanup; 4934 } 4935 rc = RegOpenKeyExW( 4936 hEnumKey, 4937 DeviceInstanceId, 4938 0, /* Options */ 4939 KEY_QUERY_VALUE, 4940 &hKey); 4941 RegCloseKey(hEnumKey); 4942 if (rc != ERROR_SUCCESS) 4943 { 4944 if (rc == ERROR_FILE_NOT_FOUND) 4945 rc = ERROR_NO_SUCH_DEVINST; 4946 SetLastError(rc); 4947 goto cleanup; 4948 } 4949 4950 ClassGUID = GUID_NULL; 4951 dwSize = MAX_GUID_STRING_LEN * sizeof(WCHAR); 4952 4953 if (RegQueryValueExW(hKey, 4954 REGSTR_VAL_CLASSGUID, 4955 NULL, 4956 NULL, 4957 (LPBYTE)szClassGuid, 4958 &dwSize) == ERROR_SUCCESS) 4959 { 4960 szClassGuid[MAX_GUID_STRING_LEN - 2] = UNICODE_NULL; 4961 4962 /* Convert a string to a ClassGuid */ 4963 UuidFromStringW(&szClassGuid[1], &ClassGUID); 4964 } 4965 4966 if (!CreateDeviceInfo(list, DeviceInstanceId, &ClassGUID, &deviceInfo)) 4967 goto cleanup; 4968 4969 InsertTailList(&list->ListHead, &deviceInfo->ListEntry); 4970 4971 ret = TRUE; 4972 } 4973 4974 if (ret && deviceInfo && DeviceInfoData) 4975 { 4976 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID)); 4977 DeviceInfoData->DevInst = deviceInfo->dnDevInst; 4978 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo; 4979 } 4980 } 4981 4982 cleanup: 4983 if (hKey != NULL) 4984 RegCloseKey(hKey); 4985 return ret; 4986 } 4987 4988 4989 /*********************************************************************** 4990 * SetupDiGetSelectedDevice (SETUPAPI.@) 4991 */ 4992 BOOL WINAPI 4993 SetupDiGetSelectedDevice( 4994 IN HDEVINFO DeviceInfoSet, 4995 OUT PSP_DEVINFO_DATA DeviceInfoData) 4996 { 4997 struct DeviceInfoSet *list; 4998 BOOL ret = FALSE; 4999 5000 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 5001 5002 if (!DeviceInfoSet) 5003 SetLastError(ERROR_INVALID_HANDLE); 5004 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5005 SetLastError(ERROR_INVALID_HANDLE); 5006 else if (list->SelectedDevice == NULL) 5007 SetLastError(ERROR_NO_DEVICE_SELECTED); 5008 else if (!DeviceInfoData) 5009 SetLastError(ERROR_INVALID_PARAMETER); 5010 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 5011 SetLastError(ERROR_INVALID_USER_BUFFER); 5012 else 5013 { 5014 memcpy(&DeviceInfoData->ClassGuid, 5015 &list->SelectedDevice->ClassGuid, 5016 sizeof(GUID)); 5017 DeviceInfoData->DevInst = list->SelectedDevice->dnDevInst; 5018 DeviceInfoData->Reserved = (ULONG_PTR)list->SelectedDevice; 5019 ret = TRUE; 5020 } 5021 5022 TRACE("Returning %d\n", ret); 5023 return ret; 5024 } 5025 5026 5027 /*********************************************************************** 5028 * SetupDiSetSelectedDevice (SETUPAPI.@) 5029 */ 5030 BOOL WINAPI 5031 SetupDiSetSelectedDevice( 5032 IN HDEVINFO DeviceInfoSet, 5033 IN PSP_DEVINFO_DATA DeviceInfoData) 5034 { 5035 struct DeviceInfoSet *list; 5036 BOOL ret = FALSE; 5037 5038 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 5039 5040 if (!DeviceInfoSet) 5041 SetLastError(ERROR_INVALID_HANDLE); 5042 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5043 SetLastError(ERROR_INVALID_HANDLE); 5044 else if (!DeviceInfoData) 5045 SetLastError(ERROR_INVALID_PARAMETER); 5046 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 5047 SetLastError(ERROR_INVALID_USER_BUFFER); 5048 else if (DeviceInfoData->Reserved == 0) 5049 SetLastError(ERROR_INVALID_USER_BUFFER); 5050 else 5051 { 5052 list->SelectedDevice = (struct DeviceInfo *)DeviceInfoData->Reserved; 5053 ret = TRUE; 5054 } 5055 5056 TRACE("Returning %d\n", ret); 5057 return ret; 5058 } 5059 5060 5061 /* Return the current hardware profile id, or -1 if error */ 5062 static DWORD 5063 SETUPAPI_GetCurrentHwProfile( 5064 IN HDEVINFO DeviceInfoSet) 5065 { 5066 HKEY hKey = NULL; 5067 DWORD dwRegType, dwLength; 5068 DWORD hwProfile; 5069 LONG rc; 5070 DWORD ret = (DWORD)-1; 5071 5072 rc = RegOpenKeyExW(((struct DeviceInfoSet *)DeviceInfoSet)->HKLM, 5073 REGSTR_PATH_IDCONFIGDB, 5074 0, /* Options */ 5075 KEY_QUERY_VALUE, 5076 &hKey); 5077 if (rc != ERROR_SUCCESS) 5078 { 5079 SetLastError(rc); 5080 goto cleanup; 5081 } 5082 5083 dwLength = sizeof(DWORD); 5084 rc = RegQueryValueExW(hKey, 5085 REGSTR_VAL_CURRENTCONFIG, 5086 NULL, 5087 &dwRegType, 5088 (LPBYTE)&hwProfile, &dwLength); 5089 if (rc != ERROR_SUCCESS) 5090 { 5091 SetLastError(rc); 5092 goto cleanup; 5093 } 5094 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD)) 5095 { 5096 SetLastError(ERROR_GEN_FAILURE); 5097 goto cleanup; 5098 } 5099 5100 ret = hwProfile; 5101 5102 cleanup: 5103 if (hKey != NULL) 5104 RegCloseKey(hKey); 5105 5106 return ret; 5107 } 5108 5109 static BOOL 5110 ResetDevice( 5111 IN HDEVINFO DeviceInfoSet, 5112 IN PSP_DEVINFO_DATA DeviceInfoData) 5113 { 5114 #ifndef __WINESRC__ 5115 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 5116 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 5117 CONFIGRET cr; 5118 5119 cr = CM_Enable_DevNode_Ex(deviceInfo->dnDevInst, 0, set->hMachine); 5120 if (cr != CR_SUCCESS) 5121 { 5122 SetLastError(GetErrorCodeFromCrCode(cr)); 5123 return FALSE; 5124 } 5125 5126 return TRUE; 5127 #else 5128 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData); 5129 return TRUE; 5130 #endif 5131 } 5132 5133 static BOOL StopDevice( 5134 IN HDEVINFO DeviceInfoSet, 5135 IN PSP_DEVINFO_DATA DeviceInfoData) 5136 { 5137 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData); 5138 return TRUE; 5139 } 5140 5141 /*********************************************************************** 5142 * SetupDiChangeState (SETUPAPI.@) 5143 */ 5144 BOOL WINAPI 5145 SetupDiChangeState( 5146 IN HDEVINFO DeviceInfoSet, 5147 IN OUT PSP_DEVINFO_DATA DeviceInfoData) 5148 { 5149 PSP_PROPCHANGE_PARAMS PropChange; 5150 HKEY hKey = INVALID_HANDLE_VALUE; 5151 LPCWSTR RegistryValueName; 5152 DWORD dwConfigFlags, dwLength, dwRegType; 5153 LONG rc; 5154 BOOL ret = FALSE; 5155 5156 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 5157 5158 if (!DeviceInfoData) 5159 PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChangeParams; 5160 else 5161 PropChange = ((struct DeviceInfo *)DeviceInfoData->Reserved)->ClassInstallParams.PropChangeParams; 5162 if (!PropChange) 5163 { 5164 SetLastError(ERROR_INVALID_PARAMETER); 5165 goto cleanup; 5166 } 5167 5168 if (PropChange->Scope == DICS_FLAG_GLOBAL) 5169 RegistryValueName = REGSTR_VAL_CONFIGFLAGS; 5170 else 5171 RegistryValueName = REGSTR_VAL_CSCONFIGFLAGS; 5172 5173 switch (PropChange->StateChange) 5174 { 5175 case DICS_ENABLE: 5176 case DICS_DISABLE: 5177 { 5178 /* Enable/disable device in registry */ 5179 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE); 5180 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) 5181 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, NULL, NULL); 5182 if (hKey == INVALID_HANDLE_VALUE) 5183 break; 5184 dwLength = sizeof(DWORD); 5185 rc = RegQueryValueExW( 5186 hKey, 5187 RegistryValueName, 5188 NULL, 5189 &dwRegType, 5190 (LPBYTE)&dwConfigFlags, &dwLength); 5191 if (rc == ERROR_FILE_NOT_FOUND) 5192 dwConfigFlags = 0; 5193 else if (rc != ERROR_SUCCESS) 5194 { 5195 SetLastError(rc); 5196 goto cleanup; 5197 } 5198 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD)) 5199 { 5200 SetLastError(ERROR_GEN_FAILURE); 5201 goto cleanup; 5202 } 5203 if (PropChange->StateChange == DICS_ENABLE) 5204 dwConfigFlags &= ~(PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED); 5205 else 5206 dwConfigFlags |= (PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED); 5207 rc = RegSetValueExW( 5208 hKey, 5209 RegistryValueName, 5210 0, 5211 REG_DWORD, 5212 (LPBYTE)&dwConfigFlags, sizeof(DWORD)); 5213 if (rc != ERROR_SUCCESS) 5214 { 5215 SetLastError(rc); 5216 goto cleanup; 5217 } 5218 5219 /* Enable/disable device if needed */ 5220 if (PropChange->Scope == DICS_FLAG_GLOBAL 5221 || PropChange->HwProfile == 0 5222 || PropChange->HwProfile == SETUPAPI_GetCurrentHwProfile(DeviceInfoSet)) 5223 { 5224 if (PropChange->StateChange == DICS_ENABLE) 5225 ret = ResetDevice(DeviceInfoSet, DeviceInfoData); 5226 else 5227 ret = StopDevice(DeviceInfoSet, DeviceInfoData); 5228 } 5229 else 5230 ret = TRUE; 5231 break; 5232 } 5233 case DICS_PROPCHANGE: 5234 { 5235 ret = ResetDevice(DeviceInfoSet, DeviceInfoData); 5236 break; 5237 } 5238 default: 5239 { 5240 ERR("Unknown StateChange 0x%lx\n", PropChange->StateChange); 5241 SetLastError(ERROR_NOT_SUPPORTED); 5242 } 5243 } 5244 5245 cleanup: 5246 if (hKey != INVALID_HANDLE_VALUE) 5247 RegCloseKey(hKey); 5248 5249 TRACE("Returning %d\n", ret); 5250 return ret; 5251 } 5252 5253 /*********************************************************************** 5254 * SetupDiSelectDevice (SETUPAPI.@) 5255 */ 5256 BOOL WINAPI 5257 SetupDiSelectDevice( 5258 IN HDEVINFO DeviceInfoSet, 5259 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 5260 { 5261 FIXME("%p %p\n", DeviceInfoSet, DeviceInfoData); 5262 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 5263 return FALSE; 5264 } 5265 5266 5267 /*********************************************************************** 5268 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@) 5269 */ 5270 BOOL WINAPI 5271 SetupDiRegisterCoDeviceInstallers( 5272 IN HDEVINFO DeviceInfoSet, 5273 IN PSP_DEVINFO_DATA DeviceInfoData) 5274 { 5275 BOOL ret = FALSE; /* Return value */ 5276 5277 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 5278 5279 if (!DeviceInfoSet) 5280 SetLastError(ERROR_INVALID_PARAMETER); 5281 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 5282 SetLastError(ERROR_INVALID_HANDLE); 5283 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5284 SetLastError(ERROR_INVALID_HANDLE); 5285 else if (!DeviceInfoData) 5286 SetLastError(ERROR_INVALID_PARAMETER); 5287 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 5288 SetLastError(ERROR_INVALID_USER_BUFFER); 5289 else 5290 { 5291 SP_DEVINSTALL_PARAMS_W InstallParams; 5292 struct DriverInfoElement *SelectedDriver; 5293 BOOL Result; 5294 DWORD DoAction; 5295 WCHAR SectionName[MAX_PATH]; 5296 DWORD SectionNameLength = 0; 5297 HKEY hKey = INVALID_HANDLE_VALUE; 5298 PVOID Context = NULL; 5299 5300 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 5301 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 5302 if (!Result) 5303 goto cleanup; 5304 5305 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved; 5306 if (SelectedDriver == NULL) 5307 { 5308 SetLastError(ERROR_NO_DRIVER_SELECTED); 5309 goto cleanup; 5310 } 5311 5312 /* Get .CoInstallers section name */ 5313 Result = SetupDiGetActualSectionToInstallW( 5314 SelectedDriver->InfFileDetails->hInf, 5315 SelectedDriver->Details.SectionName, 5316 SectionName, MAX_PATH, &SectionNameLength, NULL); 5317 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotCoInstallers) - 1) 5318 goto cleanup; 5319 lstrcatW(SectionName, DotCoInstallers); 5320 5321 /* Open/Create driver key information */ 5322 #if _WIN32_WINNT >= 0x502 5323 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE); 5324 #else 5325 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS); 5326 #endif 5327 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) 5328 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL); 5329 if (hKey == INVALID_HANDLE_VALUE) 5330 goto cleanup; 5331 5332 /* Install .CoInstallers section */ 5333 DoAction = SPINST_REGISTRY; 5334 if (!(InstallParams.Flags & DI_NOFILECOPY)) 5335 { 5336 DoAction |= SPINST_FILES; 5337 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent); 5338 if (!Context) 5339 goto cleanup; 5340 } 5341 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent, 5342 SelectedDriver->InfFileDetails->hInf, SectionName, 5343 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, 5344 SetupDefaultQueueCallbackW, Context, 5345 DeviceInfoSet, DeviceInfoData); 5346 if (!Result) 5347 goto cleanup; 5348 5349 ret = TRUE; 5350 5351 cleanup: 5352 if (Context) 5353 SetupTermDefaultQueueCallback(Context); 5354 if (hKey != INVALID_HANDLE_VALUE) 5355 RegCloseKey(hKey); 5356 } 5357 5358 TRACE("Returning %d\n", ret); 5359 return ret; 5360 } 5361 5362 static BOOL 5363 InfIsFromOEMLocation( 5364 IN PCWSTR FullName, 5365 OUT LPBOOL IsOEMLocation) 5366 { 5367 PWCHAR last; 5368 5369 last = strrchrW(FullName, '\\'); 5370 if (!last) 5371 { 5372 /* No directory specified */ 5373 *IsOEMLocation = FALSE; 5374 } 5375 else 5376 { 5377 LPWSTR Windir; 5378 UINT ret; 5379 5380 Windir = MyMalloc((MAX_PATH + 1 + strlenW(InfDirectory)) * sizeof(WCHAR)); 5381 if (!Windir) 5382 { 5383 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 5384 return FALSE; 5385 } 5386 5387 ret = GetSystemWindowsDirectoryW(Windir, MAX_PATH); 5388 if (ret == 0 || ret > MAX_PATH) 5389 { 5390 MyFree(Windir); 5391 SetLastError(ERROR_GEN_FAILURE); 5392 return FALSE; 5393 } 5394 if (*Windir && Windir[strlenW(Windir) - 1] != '\\') 5395 strcatW(Windir, BackSlash); 5396 strcatW(Windir, InfDirectory); 5397 5398 if (strncmpiW(FullName, Windir, last - FullName) == 0) 5399 { 5400 /* The path is %SYSTEMROOT%\Inf */ 5401 *IsOEMLocation = FALSE; 5402 } 5403 else 5404 { 5405 /* The file is in another place */ 5406 *IsOEMLocation = TRUE; 5407 } 5408 MyFree(Windir); 5409 } 5410 return TRUE; 5411 } 5412 5413 /*********************************************************************** 5414 * SetupDiInstallDevice (SETUPAPI.@) 5415 */ 5416 BOOL WINAPI 5417 SetupDiInstallDevice( 5418 IN HDEVINFO DeviceInfoSet, 5419 IN OUT PSP_DEVINFO_DATA DeviceInfoData) 5420 { 5421 SP_DEVINSTALL_PARAMS_W InstallParams; 5422 struct DriverInfoElement *SelectedDriver; 5423 SYSTEMTIME DriverDate; 5424 WCHAR SectionName[MAX_PATH]; 5425 WCHAR Buffer[32]; 5426 DWORD SectionNameLength = 0; 5427 BOOL Result = FALSE; 5428 ULONG DoAction; 5429 DWORD RequiredSize; 5430 LPWSTR pSectionName = NULL; 5431 WCHAR ClassName[MAX_CLASS_NAME_LEN]; 5432 GUID ClassGuid; 5433 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL; 5434 BOOL RebootRequired = FALSE; 5435 HKEY hKey = INVALID_HANDLE_VALUE; 5436 BOOL NeedtoCopyFile; 5437 LARGE_INTEGER fullVersion; 5438 LONG rc; 5439 PVOID Context = NULL; 5440 BOOL ret = FALSE; /* Return value */ 5441 5442 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 5443 5444 if (!DeviceInfoSet) 5445 SetLastError(ERROR_INVALID_PARAMETER); 5446 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 5447 SetLastError(ERROR_INVALID_HANDLE); 5448 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5449 SetLastError(ERROR_INVALID_HANDLE); 5450 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 5451 SetLastError(ERROR_INVALID_USER_BUFFER); 5452 else 5453 Result = TRUE; 5454 5455 if (!Result) 5456 { 5457 /* One parameter is bad */ 5458 goto cleanup; 5459 } 5460 5461 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 5462 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 5463 if (!Result) 5464 goto cleanup; 5465 5466 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL) 5467 { 5468 /* Set FAILEDINSTALL in ConfigFlags registry value */ 5469 DWORD ConfigFlags, regType; 5470 Result = SetupDiGetDeviceRegistryPropertyW( 5471 DeviceInfoSet, 5472 DeviceInfoData, 5473 SPDRP_CONFIGFLAGS, 5474 ®Type, 5475 (PBYTE)&ConfigFlags, 5476 sizeof(ConfigFlags), 5477 NULL); 5478 if (!Result || regType != REG_DWORD) 5479 { 5480 SetLastError(ERROR_GEN_FAILURE); 5481 goto cleanup; 5482 } 5483 ConfigFlags |= DNF_DISABLED; 5484 Result = SetupDiSetDeviceRegistryPropertyW( 5485 DeviceInfoSet, 5486 DeviceInfoData, 5487 SPDRP_CONFIGFLAGS, 5488 (PBYTE)&ConfigFlags, 5489 sizeof(ConfigFlags)); 5490 if (!Result) 5491 { 5492 SetLastError(ERROR_GEN_FAILURE); 5493 goto cleanup; 5494 } 5495 5496 ret = TRUE; 5497 goto cleanup; 5498 } 5499 5500 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved; 5501 if (SelectedDriver == NULL) 5502 { 5503 SetLastError(ERROR_NO_DRIVER_SELECTED); 5504 goto cleanup; 5505 } 5506 5507 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate); 5508 5509 Result = SetupDiGetActualSectionToInstallW( 5510 SelectedDriver->InfFileDetails->hInf, 5511 SelectedDriver->Details.SectionName, 5512 SectionName, MAX_PATH, &SectionNameLength, NULL); 5513 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotServices)) 5514 goto cleanup; 5515 pSectionName = &SectionName[strlenW(SectionName)]; 5516 5517 /* Get information from [Version] section */ 5518 if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize)) 5519 goto cleanup; 5520 /* Format ClassGuid to a string */ 5521 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK) 5522 goto cleanup; 5523 RequiredSize = lstrlenW(lpGuidString); 5524 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR)); 5525 if (!lpFullGuidString) 5526 { 5527 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 5528 goto cleanup; 5529 } 5530 lpFullGuidString[0] = '{'; 5531 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR)); 5532 lpFullGuidString[RequiredSize + 1] = '}'; 5533 lpFullGuidString[RequiredSize + 2] = '\0'; 5534 5535 /* Copy .inf file to Inf\ directory (if needed) */ 5536 Result = InfIsFromOEMLocation(SelectedDriver->Details.InfFileName, &NeedtoCopyFile); 5537 if (!Result) 5538 goto cleanup; 5539 if (NeedtoCopyFile) 5540 { 5541 WCHAR NewFileName[MAX_PATH]; 5542 struct InfFileDetails *newInfFileDetails; 5543 Result = SetupCopyOEMInfW( 5544 SelectedDriver->Details.InfFileName, 5545 NULL, 5546 SPOST_NONE, 5547 SP_COPY_NOOVERWRITE, 5548 NewFileName, MAX_PATH, 5549 NULL, 5550 NULL); 5551 if (!Result && GetLastError() != ERROR_FILE_EXISTS) 5552 goto cleanup; 5553 /* Create a new struct InfFileDetails, and set it to 5554 * SelectedDriver->InfFileDetails, to release use of 5555 * current InfFile */ 5556 newInfFileDetails = CreateInfFileDetails(NewFileName); 5557 if (!newInfFileDetails) 5558 goto cleanup; 5559 DereferenceInfFile(SelectedDriver->InfFileDetails); 5560 SelectedDriver->InfFileDetails = newInfFileDetails; 5561 strcpyW(SelectedDriver->Details.InfFileName, NewFileName); 5562 } 5563 5564 /* Open/Create driver key information */ 5565 #if _WIN32_WINNT >= 0x502 5566 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE); 5567 #else 5568 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS); 5569 #endif 5570 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) 5571 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL); 5572 if (hKey == INVALID_HANDLE_VALUE) 5573 goto cleanup; 5574 5575 /* Install main section */ 5576 DoAction = 0; 5577 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY)) 5578 DoAction |= SPINST_REGISTRY; 5579 if (!(InstallParams.Flags & DI_NOFILECOPY)) 5580 { 5581 DoAction |= SPINST_FILES; 5582 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent); 5583 if (!Context) 5584 goto cleanup; 5585 } 5586 *pSectionName = '\0'; 5587 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent, 5588 SelectedDriver->InfFileDetails->hInf, SectionName, 5589 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, 5590 SetupDefaultQueueCallbackW, Context, 5591 DeviceInfoSet, DeviceInfoData); 5592 if (!Result) 5593 goto cleanup; 5594 InstallParams.Flags |= DI_NOFILECOPY; 5595 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 5596 5597 /* Write information to driver key */ 5598 *pSectionName = UNICODE_NULL; 5599 memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER)); 5600 TRACE("Write information to driver key\n"); 5601 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear); 5602 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description)); 5603 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff); 5604 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver->InfFileDetails->FileName)); 5605 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver->Details.SectionName)); 5606 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName[strlenW(SelectedDriver->Details.SectionName)])); 5607 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver->MatchingId)); 5608 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver->Info.ProviderName)); 5609 sprintfW(Buffer, DateFormat, DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear); 5610 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR)); 5611 if (rc == ERROR_SUCCESS) 5612 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE_DATA, 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME)); 5613 if (rc == ERROR_SUCCESS) 5614 rc = RegSetValueExW(hKey, REGSTR_VAL_DRVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR)); 5615 if (rc == ERROR_SUCCESS) 5616 { 5617 sprintfW(Buffer, VersionFormat, fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff); 5618 rc = RegSetValueExW(hKey, REGSTR_DRIVER_VERSION, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR)); 5619 } 5620 if (rc == ERROR_SUCCESS) 5621 rc = RegSetValueExW(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->InfFileDetails->FileName, (strlenW(SelectedDriver->InfFileDetails->FileName) + 1) * sizeof(WCHAR)); 5622 if (rc == ERROR_SUCCESS) 5623 rc = RegSetValueExW(hKey, REGSTR_VAL_INFSECTION, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR)); 5624 if (rc == ERROR_SUCCESS) 5625 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)); 5626 if (rc == ERROR_SUCCESS) 5627 rc = RegSetValueExW(hKey, REGSTR_VAL_MATCHINGDEVID, 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (strlenW(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR)); 5628 if (rc == ERROR_SUCCESS) 5629 rc = RegSetValueExW(hKey, REGSTR_VAL_PROVIDER_NAME, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (strlenW(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR)); 5630 if (rc != ERROR_SUCCESS) 5631 { 5632 SetLastError(rc); 5633 goto cleanup; 5634 } 5635 RegCloseKey(hKey); 5636 hKey = INVALID_HANDLE_VALUE; 5637 5638 /* FIXME: Process .LogConfigOverride section */ 5639 5640 /* Install .Services section */ 5641 strcpyW(pSectionName, DotServices); 5642 Result = SetupInstallServicesFromInfSectionExW( 5643 SelectedDriver->InfFileDetails->hInf, 5644 SectionName, 5645 0, 5646 DeviceInfoSet, 5647 DeviceInfoData, 5648 NULL, 5649 NULL); 5650 if (!Result) 5651 goto cleanup; 5652 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED) 5653 RebootRequired = TRUE; 5654 5655 /* Open device registry key */ 5656 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE); 5657 if (hKey == INVALID_HANDLE_VALUE) 5658 goto cleanup; 5659 5660 /* Install .HW section */ 5661 DoAction = 0; 5662 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY)) 5663 DoAction |= SPINST_REGISTRY; 5664 strcpyW(pSectionName, DotHW); 5665 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent, 5666 SelectedDriver->InfFileDetails->hInf, SectionName, 5667 DoAction, hKey, NULL, 0, 5668 NULL, NULL, 5669 DeviceInfoSet, DeviceInfoData); 5670 if (!Result) 5671 goto cleanup; 5672 5673 /* Write information to enum key */ 5674 TRACE("Write information to enum key\n"); 5675 TRACE("Class : '%s'\n", debugstr_w(ClassName)); 5676 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString)); 5677 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description)); 5678 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver->Info.MfgName)); 5679 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (strlenW(ClassName) + 1) * sizeof(WCHAR)); 5680 if (rc == ERROR_SUCCESS) 5681 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (strlenW(lpFullGuidString) + 1) * sizeof(WCHAR)); 5682 if (rc == ERROR_SUCCESS) 5683 rc = RegSetValueExW(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR)); 5684 if (rc == ERROR_SUCCESS) 5685 rc = RegSetValueExW(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (strlenW(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR)); 5686 if (rc != ERROR_SUCCESS) 5687 { 5688 SetLastError(rc); 5689 goto cleanup; 5690 } 5691 5692 /* Start the device */ 5693 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG))) 5694 ret = ResetDevice(DeviceInfoSet, DeviceInfoData); 5695 else 5696 ret = TRUE; 5697 5698 cleanup: 5699 /* End of installation */ 5700 if (hKey != INVALID_HANDLE_VALUE) 5701 RegCloseKey(hKey); 5702 if (lpGuidString) 5703 RpcStringFreeW(&lpGuidString); 5704 HeapFree(GetProcessHeap(), 0, lpFullGuidString); 5705 if (Context) 5706 SetupTermDefaultQueueCallback(Context); 5707 TRACE("Returning %d\n", ret); 5708 return ret; 5709 } 5710 5711 static HKEY SETUPDI_OpenDevKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired) 5712 { 5713 HKEY enumKey, key = INVALID_HANDLE_VALUE; 5714 LONG l; 5715 5716 l = RegOpenKeyExW(RootKey, REGSTR_PATH_SYSTEMENUM, 0, READ_CONTROL, &enumKey); 5717 if (!l) 5718 { 5719 l = RegOpenKeyExW(enumKey, devInfo->instanceId, 0, samDesired, &key); 5720 RegCloseKey(enumKey); 5721 } 5722 if (l) 5723 SetLastError(l); 5724 return key; 5725 } 5726 5727 static HKEY SETUPDI_OpenDrvKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired) 5728 { 5729 LPWSTR DriverKey = NULL; 5730 DWORD dwLength = 0; 5731 DWORD dwRegType; 5732 DWORD rc; 5733 HKEY hEnumKey = NULL; 5734 HKEY hKey = NULL; 5735 HKEY key = INVALID_HANDLE_VALUE; 5736 5737 hKey = SETUPDI_OpenDevKey(RootKey, devInfo, KEY_QUERY_VALUE); 5738 if (hKey == INVALID_HANDLE_VALUE) 5739 goto cleanup; 5740 /* Read the 'Driver' key */ 5741 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, NULL, &dwLength); 5742 if (rc != ERROR_SUCCESS) 5743 { 5744 SetLastError(rc); 5745 goto cleanup; 5746 } 5747 else if (dwRegType != REG_SZ) 5748 { 5749 SetLastError(ERROR_GEN_FAILURE); 5750 goto cleanup; 5751 } 5752 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength); 5753 if (!DriverKey) 5754 { 5755 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 5756 goto cleanup; 5757 } 5758 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength); 5759 if (rc != ERROR_SUCCESS) 5760 { 5761 SetLastError(rc); 5762 goto cleanup; 5763 } 5764 RegCloseKey(hKey); 5765 hKey = NULL; 5766 /* Need to open the driver key */ 5767 rc = RegOpenKeyExW( 5768 RootKey, 5769 REGSTR_PATH_CLASS_NT, 5770 0, /* Options */ 5771 READ_CONTROL, 5772 &hEnumKey); 5773 if (rc != ERROR_SUCCESS) 5774 { 5775 SetLastError(rc); 5776 goto cleanup; 5777 } 5778 rc = RegOpenKeyExW( 5779 hEnumKey, 5780 DriverKey, 5781 0, /* Options */ 5782 samDesired, 5783 &hKey); 5784 if (rc != ERROR_SUCCESS) 5785 { 5786 SetLastError(rc); 5787 goto cleanup; 5788 } 5789 key = hKey; 5790 5791 cleanup: 5792 if (hEnumKey != NULL) 5793 RegCloseKey(hEnumKey); 5794 if (hKey != NULL && hKey != key) 5795 RegCloseKey(hKey); 5796 if (DriverKey) 5797 HeapFree(GetProcessHeap(), 0, DriverKey); 5798 return key; 5799 } 5800 5801 /*********************************************************************** 5802 * SetupDiOpenDevRegKey (SETUPAPI.@) 5803 */ 5804 HKEY WINAPI SetupDiOpenDevRegKey( 5805 HDEVINFO DeviceInfoSet, 5806 PSP_DEVINFO_DATA DeviceInfoData, 5807 DWORD Scope, 5808 DWORD HwProfile, 5809 DWORD KeyType, 5810 REGSAM samDesired) 5811 { 5812 struct DeviceInfoSet *set = DeviceInfoSet; 5813 struct DeviceInfo *devInfo; 5814 HKEY key = INVALID_HANDLE_VALUE; 5815 HKEY RootKey; 5816 5817 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData, 5818 Scope, HwProfile, KeyType, samDesired); 5819 5820 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 5821 { 5822 SetLastError(ERROR_INVALID_HANDLE); 5823 return INVALID_HANDLE_VALUE; 5824 } 5825 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5826 { 5827 SetLastError(ERROR_INVALID_HANDLE); 5828 return INVALID_HANDLE_VALUE; 5829 } 5830 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 5831 || !DeviceInfoData->Reserved) 5832 { 5833 SetLastError(ERROR_INVALID_PARAMETER); 5834 return INVALID_HANDLE_VALUE; 5835 } 5836 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC) 5837 { 5838 SetLastError(ERROR_INVALID_FLAGS); 5839 return INVALID_HANDLE_VALUE; 5840 } 5841 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV) 5842 { 5843 SetLastError(ERROR_INVALID_FLAGS); 5844 return INVALID_HANDLE_VALUE; 5845 } 5846 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 5847 if (devInfo->set != set) 5848 { 5849 SetLastError(ERROR_INVALID_PARAMETER); 5850 return INVALID_HANDLE_VALUE; 5851 } 5852 if (Scope != DICS_FLAG_GLOBAL) 5853 { 5854 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0); 5855 if (RootKey == INVALID_HANDLE_VALUE) 5856 return INVALID_HANDLE_VALUE; 5857 } 5858 else 5859 RootKey = set->HKLM; 5860 switch (KeyType) 5861 { 5862 case DIREG_DEV: 5863 key = SETUPDI_OpenDevKey(RootKey, devInfo, samDesired); 5864 break; 5865 case DIREG_DRV: 5866 key = SETUPDI_OpenDrvKey(RootKey, devInfo, samDesired); 5867 break; 5868 default: 5869 WARN("unknown KeyType %d\n", KeyType); 5870 } 5871 if (RootKey != set->HKLM) 5872 RegCloseKey(RootKey); 5873 return key; 5874 } 5875 5876 static BOOL SETUPDI_DeleteDevKey(HKEY RootKey, struct DeviceInfo *devInfo) 5877 { 5878 FIXME("\n"); 5879 return FALSE; 5880 } 5881 5882 static BOOL SETUPDI_DeleteDrvKey(HKEY RootKey, struct DeviceInfo *devInfo) 5883 { 5884 FIXME("\n"); 5885 return FALSE; 5886 } 5887 5888 /*********************************************************************** 5889 * SetupDiDeleteDevRegKey (SETUPAPI.@) 5890 */ 5891 BOOL WINAPI SetupDiDeleteDevRegKey( 5892 HDEVINFO DeviceInfoSet, 5893 PSP_DEVINFO_DATA DeviceInfoData, 5894 DWORD Scope, 5895 DWORD HwProfile, 5896 DWORD KeyType) 5897 { 5898 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 5899 struct DeviceInfo *devInfo; 5900 BOOL ret = FALSE; 5901 HKEY RootKey; 5902 5903 TRACE("%p %p %d %d %d\n", DeviceInfoSet, DeviceInfoData, Scope, HwProfile, 5904 KeyType); 5905 5906 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 5907 { 5908 SetLastError(ERROR_INVALID_HANDLE); 5909 return FALSE; 5910 } 5911 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5912 { 5913 SetLastError(ERROR_INVALID_HANDLE); 5914 return FALSE; 5915 } 5916 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 5917 || !DeviceInfoData->Reserved) 5918 { 5919 SetLastError(ERROR_INVALID_PARAMETER); 5920 return FALSE; 5921 } 5922 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC) 5923 { 5924 SetLastError(ERROR_INVALID_FLAGS); 5925 return FALSE; 5926 } 5927 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV && KeyType != DIREG_BOTH) 5928 { 5929 SetLastError(ERROR_INVALID_FLAGS); 5930 return FALSE; 5931 } 5932 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 5933 if (devInfo->set != set) 5934 { 5935 SetLastError(ERROR_INVALID_PARAMETER); 5936 return FALSE; 5937 } 5938 if (Scope != DICS_FLAG_GLOBAL) 5939 { 5940 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0); 5941 if (RootKey == INVALID_HANDLE_VALUE) 5942 return FALSE; 5943 } 5944 else 5945 RootKey = set->HKLM; 5946 switch (KeyType) 5947 { 5948 case DIREG_DEV: 5949 ret = SETUPDI_DeleteDevKey(RootKey, devInfo); 5950 break; 5951 case DIREG_DRV: 5952 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo); 5953 break; 5954 case DIREG_BOTH: 5955 ret = SETUPDI_DeleteDevKey(RootKey, devInfo); 5956 if (ret) 5957 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo); 5958 break; 5959 default: 5960 WARN("unknown KeyType %d\n", KeyType); 5961 } 5962 if (RootKey != set->HKLM) 5963 RegCloseKey(RootKey); 5964 return ret; 5965 } 5966