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(%s %p 0x%x 0x%x)\n", 153 __FUNCTION__, 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("%s(%p %s %p %p %lu %p %p %p)\n", __FUNCTION__, 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("%s(0x%lx %p %lu %p %s %p)\n", __FUNCTION__, 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("%s(0x%lx %p %lu %p %s %p)\n", __FUNCTION__, 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(%s %p %lu %p %s %p)\n", __FUNCTION__, 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(%s %p %lu %p %s %p)\n", __FUNCTION__, 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(%s %p %lu %p %s %p)\n", __FUNCTION__, 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(%s %p %s %p)\n", __FUNCTION__, 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(%s %p %s %p)\n", __FUNCTION__, 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("%s(%p %p %d %d %d %p %s)\n", __FUNCTION__, 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 struct DeviceInfo *deviceInfo; 1416 HKEY key = INVALID_HANDLE_VALUE; 1417 DWORD rc; 1418 HKEY hHWProfileKey = INVALID_HANDLE_VALUE; 1419 HKEY hKey = NULL; 1420 HKEY RootKey; 1421 1422 TRACE("%s(%p %p %lu %lu %lu %p %s)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, Scope, 1423 HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName)); 1424 1425 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 1426 { 1427 SetLastError(ERROR_INVALID_HANDLE); 1428 return INVALID_HANDLE_VALUE; 1429 } 1430 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1431 { 1432 SetLastError(ERROR_INVALID_HANDLE); 1433 return INVALID_HANDLE_VALUE; 1434 } 1435 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 1436 || !DeviceInfoData->Reserved) 1437 { 1438 SetLastError(ERROR_INVALID_PARAMETER); 1439 return INVALID_HANDLE_VALUE; 1440 } 1441 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC) 1442 { 1443 SetLastError(ERROR_INVALID_FLAGS); 1444 return INVALID_HANDLE_VALUE; 1445 } 1446 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV) 1447 { 1448 SetLastError(ERROR_INVALID_FLAGS); 1449 return INVALID_HANDLE_VALUE; 1450 } 1451 if (InfHandle && !InfSectionName) 1452 { 1453 SetLastError(ERROR_INVALID_PARAMETER); 1454 return INVALID_HANDLE_VALUE; 1455 } 1456 if (!InfHandle && InfSectionName) 1457 { 1458 SetLastError(ERROR_INVALID_PARAMETER); 1459 return INVALID_HANDLE_VALUE; 1460 } 1461 1462 deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 1463 1464 if (Scope == DICS_FLAG_GLOBAL) 1465 RootKey = set->HKLM; 1466 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */ 1467 { 1468 hHWProfileKey = OpenHardwareProfileKey(set->HKLM, HwProfile, KEY_CREATE_SUB_KEY); 1469 if (hHWProfileKey == INVALID_HANDLE_VALUE) 1470 goto cleanup; 1471 RootKey = hHWProfileKey; 1472 } 1473 1474 if (KeyType == DIREG_DEV) 1475 { 1476 #if _WIN32_WINNT >= 0x502 1477 hKey = SETUPDI_CreateDevKey(RootKey, deviceInfo, KEY_READ | KEY_WRITE); 1478 #else 1479 hKey = SETUPDI_CreateDevKey(RootKey, deviceInfo, KEY_ALL_ACCESS); 1480 #endif 1481 if (hKey == INVALID_HANDLE_VALUE) 1482 goto cleanup; 1483 1484 if (Scope == DICS_FLAG_GLOBAL) 1485 { 1486 HKEY hTempKey = hKey; 1487 1488 rc = RegCreateKeyExW(hTempKey, 1489 L"Device Parameters", 1490 0, 1491 NULL, 1492 REG_OPTION_NON_VOLATILE, 1493 #if _WIN32_WINNT >= 0x502 1494 KEY_READ | KEY_WRITE, 1495 #else 1496 KEY_ALL_ACCESS, 1497 #endif 1498 NULL, 1499 &hKey, 1500 NULL); 1501 if (rc == ERROR_SUCCESS) 1502 RegCloseKey(hTempKey); 1503 } 1504 } 1505 else /* KeyType == DIREG_DRV */ 1506 { 1507 #if _WIN32_WINNT >= 0x502 1508 hKey = SETUPDI_CreateDrvKey(RootKey, deviceInfo, (UUID*)&DeviceInfoData->ClassGuid, KEY_READ | KEY_WRITE); 1509 #else 1510 hKey = SETUPDI_CreateDrvKey(RootKey, deviceInfo, (UUID*)&DeviceInfoData->ClassGuid, KEY_ALL_ACCESS); 1511 #endif 1512 if (hKey == INVALID_HANDLE_VALUE) 1513 goto cleanup; 1514 } 1515 1516 /* Do installation of the specified section */ 1517 if (InfHandle) 1518 { 1519 FIXME("Need to install section %s in file %p\n", 1520 debugstr_w(InfSectionName), InfHandle); 1521 } 1522 key = hKey; 1523 1524 cleanup: 1525 if (hHWProfileKey != INVALID_HANDLE_VALUE) 1526 RegCloseKey(hHWProfileKey); 1527 if (hKey != NULL && hKey != key) 1528 RegCloseKey(hKey); 1529 1530 TRACE("Returning 0x%p\n", key); 1531 return key; 1532 } 1533 1534 /*********************************************************************** 1535 * SetupDiCreateDeviceInfoA (SETUPAPI.@) 1536 */ 1537 BOOL WINAPI SetupDiCreateDeviceInfoA( 1538 HDEVINFO DeviceInfoSet, 1539 PCSTR DeviceName, 1540 CONST GUID *ClassGuid, 1541 PCSTR DeviceDescription, 1542 HWND hwndParent, 1543 DWORD CreationFlags, 1544 PSP_DEVINFO_DATA DeviceInfoData) 1545 { 1546 BOOL ret; 1547 LPWSTR DeviceNameW = NULL; 1548 LPWSTR DeviceDescriptionW = NULL; 1549 1550 TRACE("\n"); 1551 1552 if (DeviceName) 1553 { 1554 DeviceNameW = pSetupMultiByteToUnicode(DeviceName, CP_ACP); 1555 if (DeviceNameW == NULL) return FALSE; 1556 } 1557 if (DeviceDescription) 1558 { 1559 DeviceDescriptionW = pSetupMultiByteToUnicode(DeviceDescription, CP_ACP); 1560 if (DeviceDescriptionW == NULL) 1561 { 1562 MyFree(DeviceNameW); 1563 return FALSE; 1564 } 1565 } 1566 1567 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW, 1568 hwndParent, CreationFlags, DeviceInfoData); 1569 1570 MyFree(DeviceNameW); 1571 MyFree(DeviceDescriptionW); 1572 1573 return ret; 1574 } 1575 1576 /*********************************************************************** 1577 * SetupDiCreateDeviceInfoW (SETUPAPI.@) 1578 */ 1579 BOOL WINAPI SetupDiCreateDeviceInfoW( 1580 HDEVINFO DeviceInfoSet, 1581 PCWSTR DeviceName, 1582 CONST GUID *ClassGuid, 1583 PCWSTR DeviceDescription, 1584 HWND hwndParent, 1585 DWORD CreationFlags, 1586 PSP_DEVINFO_DATA DeviceInfoData) 1587 { 1588 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 1589 struct DeviceInfo *deviceInfo = NULL; 1590 BOOL ret = FALSE; 1591 CONFIGRET cr; 1592 DEVINST RootDevInst; 1593 DEVINST DevInst; 1594 WCHAR GenInstanceId[MAX_DEVICE_ID_LEN]; 1595 1596 TRACE("%s(%p %s %s %s %p %x %p)\n", __FUNCTION__, DeviceInfoSet, debugstr_w(DeviceName), 1597 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription), 1598 hwndParent, CreationFlags, DeviceInfoData); 1599 1600 if (!DeviceName) 1601 { 1602 SetLastError(ERROR_INVALID_DEVINST_NAME); 1603 return FALSE; 1604 } 1605 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 1606 { 1607 SetLastError(ERROR_INVALID_HANDLE); 1608 return FALSE; 1609 } 1610 if (!ClassGuid) 1611 { 1612 SetLastError(ERROR_INVALID_PARAMETER); 1613 return FALSE; 1614 } 1615 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1616 { 1617 SetLastError(ERROR_INVALID_HANDLE); 1618 return FALSE; 1619 } 1620 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) && 1621 !IsEqualGUID(ClassGuid, &set->ClassGuid)) 1622 { 1623 SetLastError(ERROR_CLASS_MISMATCH); 1624 return FALSE; 1625 } 1626 if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS)) 1627 { 1628 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS)); 1629 SetLastError(ERROR_INVALID_FLAGS); 1630 return FALSE; 1631 } 1632 1633 /* Get the root device instance */ 1634 cr = CM_Locate_DevInst_ExW(&RootDevInst, 1635 NULL, 1636 CM_LOCATE_DEVINST_NORMAL, 1637 set->hMachine); 1638 if (cr != CR_SUCCESS) 1639 { 1640 SetLastError(ERROR_INVALID_DATA); 1641 return FALSE; 1642 } 1643 1644 /* Create the new device instance */ 1645 cr = CM_Create_DevInst_ExW(&DevInst, 1646 (DEVINSTID)DeviceName, 1647 RootDevInst, 1648 (CreationFlags & DICD_GENERATE_ID) ? 1649 CM_CREATE_DEVINST_GENERATE_ID : 0, 1650 set->hMachine); 1651 if (cr != CR_SUCCESS) 1652 { 1653 SetLastError(GetErrorCodeFromCrCode(cr)); 1654 return FALSE; 1655 } 1656 1657 if (CreationFlags & DICD_GENERATE_ID) 1658 { 1659 /* Grab the actual instance ID that was created */ 1660 cr = CM_Get_Device_ID_Ex(DevInst, 1661 GenInstanceId, 1662 MAX_DEVICE_ID_LEN, 1663 0, 1664 set->hMachine); 1665 if (cr != CR_SUCCESS) 1666 { 1667 SetLastError(GetErrorCodeFromCrCode(cr)); 1668 return FALSE; 1669 } 1670 1671 DeviceName = GenInstanceId; 1672 TRACE("Using generated instance ID: %s\n", debugstr_w(DeviceName)); 1673 } 1674 1675 if (CreateDeviceInfo(set, DeviceName, ClassGuid, &deviceInfo)) 1676 { 1677 InsertTailList(&set->ListHead, &deviceInfo->ListEntry); 1678 1679 if (!DeviceInfoData) 1680 ret = TRUE; 1681 else 1682 { 1683 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 1684 { 1685 SetLastError(ERROR_INVALID_USER_BUFFER); 1686 } 1687 else 1688 { 1689 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID)); 1690 DeviceInfoData->DevInst = deviceInfo->dnDevInst; 1691 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo; 1692 ret = TRUE; 1693 } 1694 } 1695 } 1696 1697 if (ret == FALSE) 1698 { 1699 if (deviceInfo != NULL) 1700 { 1701 /* Remove deviceInfo from List */ 1702 RemoveEntryList(&deviceInfo->ListEntry); 1703 1704 /* Destroy deviceInfo */ 1705 DestroyDeviceInfo(deviceInfo); 1706 } 1707 } 1708 1709 TRACE("Returning %d\n", ret); 1710 return ret; 1711 } 1712 1713 /*********************************************************************** 1714 * SetupDiRegisterDeviceInfo (SETUPAPI.@) 1715 */ 1716 BOOL WINAPI SetupDiRegisterDeviceInfo( 1717 HDEVINFO DeviceInfoSet, 1718 PSP_DEVINFO_DATA DeviceInfoData, 1719 DWORD Flags, 1720 PSP_DETSIG_CMPPROC CompareProc, 1721 PVOID CompareContext, 1722 PSP_DEVINFO_DATA DupDeviceInfoData) 1723 { 1724 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 1725 WCHAR DevInstId[MAX_DEVICE_ID_LEN]; 1726 DEVINST ParentDevInst; 1727 CONFIGRET cr; 1728 DWORD dwError = ERROR_SUCCESS; 1729 1730 TRACE("%s(%p %p %08x %p %p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, Flags, 1731 CompareProc, CompareContext, DupDeviceInfoData); 1732 1733 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 1734 { 1735 SetLastError(ERROR_INVALID_HANDLE); 1736 return FALSE; 1737 } 1738 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1739 { 1740 SetLastError(ERROR_INVALID_HANDLE); 1741 return FALSE; 1742 } 1743 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 1744 || !DeviceInfoData->Reserved) 1745 { 1746 SetLastError(ERROR_INVALID_PARAMETER); 1747 return FALSE; 1748 } 1749 1750 if (Flags & ~SPRDI_FIND_DUPS) 1751 { 1752 TRACE("Unknown flags: 0x%08lx\n", Flags & ~SPRDI_FIND_DUPS); 1753 SetLastError(ERROR_INVALID_FLAGS); 1754 return FALSE; 1755 } 1756 1757 if (Flags & SPRDI_FIND_DUPS) 1758 { 1759 FIXME("Unimplemented codepath!\n"); 1760 } 1761 1762 CM_Get_Device_ID_Ex(DeviceInfoData->DevInst, 1763 DevInstId, 1764 MAX_DEVICE_ID_LEN, 1765 0, 1766 set->hMachine); 1767 1768 CM_Get_Parent_Ex(&ParentDevInst, 1769 DeviceInfoData->DevInst, 1770 0, 1771 set->hMachine); 1772 1773 cr = CM_Create_DevInst_Ex(&DeviceInfoData->DevInst, 1774 DevInstId, 1775 ParentDevInst, 1776 CM_CREATE_DEVINST_NORMAL | CM_CREATE_DEVINST_DO_NOT_INSTALL, 1777 set->hMachine); 1778 if (cr != CR_SUCCESS && 1779 cr != CR_ALREADY_SUCH_DEVINST) 1780 { 1781 dwError = ERROR_NO_SUCH_DEVINST; 1782 } 1783 1784 SetLastError(dwError); 1785 1786 return (dwError == ERROR_SUCCESS); 1787 } 1788 1789 /*********************************************************************** 1790 * SetupDiEnumDeviceInfo (SETUPAPI.@) 1791 */ 1792 BOOL WINAPI SetupDiEnumDeviceInfo( 1793 HDEVINFO devinfo, 1794 DWORD index, 1795 PSP_DEVINFO_DATA info) 1796 { 1797 BOOL ret = FALSE; 1798 1799 TRACE("%s(%p %d %p)\n", __FUNCTION__, devinfo, index, info); 1800 1801 if(info==NULL) 1802 { 1803 SetLastError(ERROR_INVALID_PARAMETER); 1804 return FALSE; 1805 } 1806 if (devinfo && devinfo != INVALID_HANDLE_VALUE) 1807 { 1808 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo; 1809 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC) 1810 { 1811 if (info->cbSize != sizeof(SP_DEVINFO_DATA)) 1812 SetLastError(ERROR_INVALID_USER_BUFFER); 1813 else 1814 { 1815 PLIST_ENTRY ItemList = list->ListHead.Flink; 1816 while (ItemList != &list->ListHead && index-- > 0) 1817 ItemList = ItemList->Flink; 1818 if (ItemList == &list->ListHead) 1819 SetLastError(ERROR_NO_MORE_ITEMS); 1820 else 1821 { 1822 struct DeviceInfo *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry); 1823 memcpy(&info->ClassGuid, 1824 &DevInfo->ClassGuid, 1825 sizeof(GUID)); 1826 info->DevInst = DevInfo->dnDevInst; 1827 info->Reserved = (ULONG_PTR)DevInfo; 1828 ret = TRUE; 1829 } 1830 } 1831 } 1832 else 1833 SetLastError(ERROR_INVALID_HANDLE); 1834 } 1835 else 1836 SetLastError(ERROR_INVALID_HANDLE); 1837 return ret; 1838 } 1839 1840 /*********************************************************************** 1841 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@) 1842 */ 1843 BOOL WINAPI SetupDiGetDeviceInstanceIdA( 1844 HDEVINFO DeviceInfoSet, 1845 PSP_DEVINFO_DATA DeviceInfoData, 1846 PSTR DeviceInstanceId, 1847 DWORD DeviceInstanceIdSize, 1848 PDWORD RequiredSize) 1849 { 1850 BOOL ret = FALSE; 1851 DWORD size; 1852 PWSTR instanceId; 1853 1854 TRACE("%s(%p %p %p %d %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, DeviceInstanceId, 1855 DeviceInstanceIdSize, RequiredSize); 1856 1857 if (!DeviceInstanceId && DeviceInstanceIdSize > 0) 1858 { 1859 SetLastError(ERROR_INVALID_PARAMETER); 1860 return FALSE; 1861 } 1862 1863 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, 1864 DeviceInfoData, 1865 NULL, 1866 0, 1867 &size); 1868 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER) 1869 return FALSE; 1870 instanceId = MyMalloc(size * sizeof(WCHAR)); 1871 if (instanceId) 1872 { 1873 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, 1874 DeviceInfoData, 1875 instanceId, 1876 size, 1877 &size); 1878 if (ret) 1879 { 1880 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1, 1881 DeviceInstanceId, 1882 DeviceInstanceIdSize, NULL, NULL); 1883 1884 if (!len) 1885 ret = FALSE; 1886 else 1887 { 1888 if (len > DeviceInstanceIdSize) 1889 { 1890 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1891 ret = FALSE; 1892 } 1893 if (RequiredSize) 1894 *RequiredSize = len; 1895 } 1896 } 1897 MyFree(instanceId); 1898 } 1899 else 1900 { 1901 if (RequiredSize) 1902 *RequiredSize = size; 1903 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1904 ret = FALSE; 1905 } 1906 return ret; 1907 } 1908 1909 /*********************************************************************** 1910 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@) 1911 */ 1912 BOOL WINAPI SetupDiGetDeviceInstanceIdW( 1913 HDEVINFO DeviceInfoSet, 1914 PSP_DEVINFO_DATA DeviceInfoData, 1915 PWSTR DeviceInstanceId, 1916 DWORD DeviceInstanceIdSize, 1917 PDWORD RequiredSize) 1918 { 1919 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 1920 struct DeviceInfo *devInfo; 1921 1922 TRACE("%s(%p %p %p %d %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, DeviceInstanceId, 1923 DeviceInstanceIdSize, RequiredSize); 1924 1925 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 1926 { 1927 SetLastError(ERROR_INVALID_HANDLE); 1928 return FALSE; 1929 } 1930 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1931 { 1932 SetLastError(ERROR_INVALID_HANDLE); 1933 return FALSE; 1934 } 1935 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 1936 || !DeviceInfoData->Reserved) 1937 { 1938 SetLastError(ERROR_INVALID_PARAMETER); 1939 return FALSE; 1940 } 1941 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 1942 if (!DeviceInstanceId && DeviceInstanceIdSize > 0) 1943 { 1944 SetLastError(ERROR_INVALID_PARAMETER); 1945 return FALSE; 1946 } 1947 if (DeviceInstanceId && DeviceInstanceIdSize == 0) 1948 { 1949 SetLastError(ERROR_INVALID_PARAMETER); 1950 return FALSE; 1951 } 1952 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId)); 1953 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1) 1954 { 1955 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1956 if (RequiredSize) 1957 *RequiredSize = lstrlenW(devInfo->instanceId) + 1; 1958 return FALSE; 1959 } 1960 lstrcpyW(DeviceInstanceId, devInfo->instanceId); 1961 if (RequiredSize) 1962 *RequiredSize = lstrlenW(devInfo->instanceId) + 1; 1963 return TRUE; 1964 } 1965 1966 /*********************************************************************** 1967 * SetupDiGetActualSectionToInstallA (SETUPAPI.@) 1968 */ 1969 BOOL WINAPI SetupDiGetActualSectionToInstallA( 1970 HINF InfHandle, 1971 PCSTR InfSectionName, 1972 PSTR InfSectionWithExt, 1973 DWORD InfSectionWithExtSize, 1974 PDWORD RequiredSize, 1975 PSTR *Extension) 1976 { 1977 return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName, 1978 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize, 1979 Extension, NULL); 1980 } 1981 1982 /*********************************************************************** 1983 * SetupDiGetActualSectionToInstallW (SETUPAPI.@) 1984 */ 1985 BOOL WINAPI SetupDiGetActualSectionToInstallW( 1986 HINF InfHandle, 1987 PCWSTR InfSectionName, 1988 PWSTR InfSectionWithExt, 1989 DWORD InfSectionWithExtSize, 1990 PDWORD RequiredSize, 1991 PWSTR *Extension) 1992 { 1993 return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName, 1994 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize, 1995 Extension, NULL); 1996 } 1997 1998 /*********************************************************************** 1999 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@) 2000 */ 2001 BOOL WINAPI 2002 SetupDiGetActualSectionToInstallExA( 2003 IN HINF InfHandle, 2004 IN PCSTR InfSectionName, 2005 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL, 2006 OUT PSTR InfSectionWithExt OPTIONAL, 2007 IN DWORD InfSectionWithExtSize, 2008 OUT PDWORD RequiredSize OPTIONAL, 2009 OUT PSTR* Extension OPTIONAL, 2010 IN PVOID Reserved) 2011 { 2012 LPWSTR InfSectionNameW = NULL; 2013 LPWSTR InfSectionWithExtW = NULL; 2014 PWSTR ExtensionW; 2015 BOOL bResult = FALSE; 2016 2017 TRACE("%s()\n", __FUNCTION__); 2018 2019 if (InfSectionName) 2020 { 2021 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP); 2022 if (InfSectionNameW == NULL) 2023 goto cleanup; 2024 } 2025 if (InfSectionWithExt) 2026 { 2027 InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR)); 2028 if (InfSectionWithExtW == NULL) 2029 goto cleanup; 2030 } 2031 2032 bResult = SetupDiGetActualSectionToInstallExW( 2033 InfHandle, InfSectionNameW, AlternatePlatformInfo, 2034 InfSectionWithExt ? InfSectionWithExtW : NULL, 2035 InfSectionWithExtSize, 2036 RequiredSize, 2037 Extension ? &ExtensionW : NULL, 2038 Reserved); 2039 2040 if (bResult && InfSectionWithExt) 2041 { 2042 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt, 2043 InfSectionWithExtSize, NULL, NULL) != 0; 2044 } 2045 if (bResult && Extension) 2046 { 2047 if (ExtensionW == NULL) 2048 *Extension = NULL; 2049 else 2050 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW]; 2051 } 2052 2053 cleanup: 2054 MyFree(InfSectionNameW); 2055 MyFree(InfSectionWithExtW); 2056 2057 return bResult; 2058 } 2059 2060 /*********************************************************************** 2061 * SetupDiGetClassDescriptionA (SETUPAPI.@) 2062 */ 2063 BOOL WINAPI SetupDiGetClassDescriptionA( 2064 const GUID* ClassGuid, 2065 PSTR ClassDescription, 2066 DWORD ClassDescriptionSize, 2067 PDWORD RequiredSize) 2068 { 2069 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription, 2070 ClassDescriptionSize, 2071 RequiredSize, NULL, NULL); 2072 } 2073 2074 /*********************************************************************** 2075 * SetupDiGetClassDescriptionW (SETUPAPI.@) 2076 */ 2077 BOOL WINAPI SetupDiGetClassDescriptionW( 2078 const GUID* ClassGuid, 2079 PWSTR ClassDescription, 2080 DWORD ClassDescriptionSize, 2081 PDWORD RequiredSize) 2082 { 2083 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription, 2084 ClassDescriptionSize, 2085 RequiredSize, NULL, NULL); 2086 } 2087 2088 /*********************************************************************** 2089 * SetupDiGetClassDescriptionExA (SETUPAPI.@) 2090 */ 2091 BOOL WINAPI SetupDiGetClassDescriptionExA( 2092 const GUID* ClassGuid, 2093 PSTR ClassDescription, 2094 DWORD ClassDescriptionSize, 2095 PDWORD RequiredSize, 2096 PCSTR MachineName, 2097 PVOID Reserved) 2098 { 2099 PWCHAR ClassDescriptionW = NULL; 2100 LPWSTR MachineNameW = NULL; 2101 BOOL ret = FALSE; 2102 2103 TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__, debugstr_guid(ClassGuid), ClassDescription, 2104 ClassDescriptionSize, RequiredSize, debugstr_a(MachineName), Reserved); 2105 2106 if (ClassDescriptionSize > 0) 2107 { 2108 ClassDescriptionW = MyMalloc(ClassDescriptionSize * sizeof(WCHAR)); 2109 if (!ClassDescriptionW) 2110 { 2111 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 2112 goto cleanup; 2113 } 2114 } 2115 2116 if (MachineName) 2117 { 2118 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 2119 if (!MachineNameW) 2120 { 2121 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 2122 goto cleanup; 2123 } 2124 } 2125 2126 ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW, 2127 ClassDescriptionSize * sizeof(WCHAR), RequiredSize, MachineNameW, Reserved); 2128 if (ret) 2129 { 2130 DWORD len = (DWORD)WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription, 2131 ClassDescriptionSize, NULL, NULL); 2132 if (len == 0 || len > ClassDescriptionSize) 2133 { 2134 SetLastError(ERROR_INSUFFICIENT_BUFFER); 2135 ret = FALSE; 2136 } 2137 } 2138 2139 cleanup: 2140 MyFree(ClassDescriptionW); 2141 MyFree(MachineNameW); 2142 return ret; 2143 } 2144 2145 /*********************************************************************** 2146 * SetupDiGetClassDescriptionExW (SETUPAPI.@) 2147 */ 2148 BOOL WINAPI SetupDiGetClassDescriptionExW( 2149 const GUID* ClassGuid, 2150 PWSTR ClassDescription, 2151 DWORD ClassDescriptionSize, 2152 PDWORD RequiredSize, 2153 PCWSTR MachineName, 2154 PVOID Reserved) 2155 { 2156 HKEY hKey; 2157 DWORD dwLength; 2158 DWORD dwRegType; 2159 LONG rc; 2160 PWSTR Buffer; 2161 2162 TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__, debugstr_guid(ClassGuid), ClassDescription, 2163 ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved); 2164 2165 /* Make sure there's a GUID */ 2166 if (!ClassGuid) 2167 { 2168 SetLastError(ERROR_INVALID_PARAMETER); 2169 return FALSE; 2170 } 2171 2172 /* Make sure there's a real buffer when there's a size */ 2173 if (!ClassDescription && ClassDescriptionSize > 0) 2174 { 2175 SetLastError(ERROR_INVALID_PARAMETER); 2176 return FALSE; 2177 } 2178 2179 /* Open the key for the GUID */ 2180 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, 2181 KEY_QUERY_VALUE, 2182 DIOCR_INSTALLER, 2183 MachineName, 2184 Reserved); 2185 if (hKey == INVALID_HANDLE_VALUE) 2186 return FALSE; 2187 2188 /* Retrieve the class description data and close the key */ 2189 rc = QueryRegistryValue(hKey, NULL, (LPBYTE *) &Buffer, &dwRegType, &dwLength); 2190 RegCloseKey(hKey); 2191 2192 /* Make sure we got the data */ 2193 if (rc != ERROR_SUCCESS) 2194 { 2195 SetLastError(rc); 2196 return FALSE; 2197 } 2198 2199 /* Make sure the data is a string */ 2200 if (dwRegType != REG_SZ) 2201 { 2202 MyFree(Buffer); 2203 SetLastError(ERROR_GEN_FAILURE); 2204 return FALSE; 2205 } 2206 2207 /* Determine the length of the class description */ 2208 dwLength /= sizeof(WCHAR); 2209 2210 /* Count the null-terminator if none is present */ 2211 if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL)) 2212 dwLength++; 2213 2214 /* Inform the caller about the class description */ 2215 if ((ClassDescription != NULL) && (dwLength <= ClassDescriptionSize)) 2216 { 2217 memcpy(ClassDescription, Buffer, (dwLength - 1) * sizeof(WCHAR)); 2218 ClassDescription[dwLength - 1] = UNICODE_NULL; 2219 } 2220 2221 /* Inform the caller about the required size */ 2222 if (RequiredSize != NULL) 2223 *RequiredSize = dwLength; 2224 2225 /* Clean up the buffer */ 2226 MyFree(Buffer); 2227 2228 /* Make sure the buffer was large enough */ 2229 if ((ClassDescription == NULL) || (dwLength > ClassDescriptionSize)) 2230 { 2231 SetLastError(ERROR_INSUFFICIENT_BUFFER); 2232 return FALSE; 2233 } 2234 2235 return TRUE; 2236 } 2237 2238 /*********************************************************************** 2239 * SetupDiGetClassDevsA (SETUPAPI.@) 2240 */ 2241 HDEVINFO WINAPI SetupDiGetClassDevsA( 2242 CONST GUID *class, 2243 LPCSTR enumstr, 2244 HWND parent, 2245 DWORD flags) 2246 { 2247 return SetupDiGetClassDevsExA(class, enumstr, parent, 2248 flags, NULL, NULL, NULL); 2249 } 2250 2251 /*********************************************************************** 2252 * SetupDiGetClassDevsExA (SETUPAPI.@) 2253 */ 2254 HDEVINFO WINAPI SetupDiGetClassDevsExA( 2255 const GUID *class, 2256 PCSTR enumstr, 2257 HWND parent, 2258 DWORD flags, 2259 HDEVINFO deviceset, 2260 PCSTR machine, 2261 PVOID reserved) 2262 { 2263 HDEVINFO ret; 2264 LPWSTR enumstrW = NULL, machineW = NULL; 2265 2266 if (enumstr) 2267 { 2268 enumstrW = pSetupMultiByteToUnicode(enumstr, CP_ACP); 2269 if (!enumstrW) 2270 { 2271 ret = INVALID_HANDLE_VALUE; 2272 goto end; 2273 } 2274 } 2275 if (machine) 2276 { 2277 machineW = pSetupMultiByteToUnicode(machine, CP_ACP); 2278 if (!machineW) 2279 { 2280 MyFree(enumstrW); 2281 ret = INVALID_HANDLE_VALUE; 2282 goto end; 2283 } 2284 } 2285 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset, 2286 machineW, reserved); 2287 MyFree(enumstrW); 2288 MyFree(machineW); 2289 2290 end: 2291 return ret; 2292 } 2293 2294 /*********************************************************************** 2295 * SetupDiGetClassDevsW (SETUPAPI.@) 2296 */ 2297 HDEVINFO WINAPI SetupDiGetClassDevsW( 2298 CONST GUID *class, 2299 LPCWSTR enumstr, 2300 HWND parent, 2301 DWORD flags) 2302 { 2303 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL, 2304 NULL); 2305 } 2306 2307 /*********************************************************************** 2308 * SetupDiGetClassDevsExW (SETUPAPI.@) 2309 */ 2310 HDEVINFO WINAPI SetupDiGetClassDevsExW( 2311 CONST GUID *class, 2312 PCWSTR enumstr, 2313 HWND parent, 2314 DWORD flags, 2315 HDEVINFO deviceset, 2316 PCWSTR machine, 2317 PVOID reserved) 2318 { 2319 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE; 2320 struct DeviceInfoSet *list; 2321 CONST GUID *pClassGuid; 2322 LONG rc; 2323 HDEVINFO set = INVALID_HANDLE_VALUE; 2324 2325 TRACE("%s(%s %s %p 0x%08x %p %s %p)\n", __FUNCTION__, debugstr_guid(class), 2326 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine), 2327 reserved); 2328 2329 if (!(flags & DIGCF_ALLCLASSES) && !class) 2330 { 2331 SetLastError(ERROR_INVALID_PARAMETER); 2332 return INVALID_HANDLE_VALUE; 2333 } 2334 2335 /* Create the deviceset if not set */ 2336 if (deviceset) 2337 { 2338 list = (struct DeviceInfoSet *)deviceset; 2339 if (list->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2340 { 2341 SetLastError(ERROR_INVALID_HANDLE); 2342 goto cleanup; 2343 } 2344 hDeviceInfo = deviceset; 2345 } 2346 else 2347 { 2348 hDeviceInfo = SetupDiCreateDeviceInfoListExW( 2349 flags & (DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES) ? NULL : class, 2350 NULL, machine, NULL); 2351 if (hDeviceInfo == INVALID_HANDLE_VALUE) 2352 goto cleanup; 2353 list = (struct DeviceInfoSet *)hDeviceInfo; 2354 } 2355 2356 if (flags & DIGCF_PROFILE) 2357 FIXME(": flag DIGCF_PROFILE ignored\n"); 2358 2359 if (flags & DIGCF_DEVICEINTERFACE) 2360 { 2361 if (!class) 2362 { 2363 SetLastError(ERROR_INVALID_PARAMETER); 2364 goto cleanup; 2365 } 2366 rc = SETUP_CreateInterfaceList(list, machine, class, enumstr, flags & DIGCF_PRESENT); 2367 } 2368 else 2369 { 2370 /* Determine which class(es) should be included in the deviceset */ 2371 if (flags & DIGCF_ALLCLASSES) 2372 { 2373 /* The caller wants all classes. Check if 2374 * the deviceset limits us to one class */ 2375 if (IsEqualIID(&list->ClassGuid, &GUID_NULL)) 2376 pClassGuid = NULL; 2377 else 2378 pClassGuid = &list->ClassGuid; 2379 } 2380 else if (class) 2381 { 2382 /* The caller wants one class. Check if it matches deviceset class */ 2383 if (IsEqualIID(&list->ClassGuid, class) 2384 || IsEqualIID(&list->ClassGuid, &GUID_NULL)) 2385 { 2386 pClassGuid = class; 2387 } 2388 else 2389 { 2390 SetLastError(ERROR_INVALID_PARAMETER); 2391 goto cleanup; 2392 } 2393 } 2394 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL)) 2395 { 2396 /* No class specified. Try to use the one of the deviceset */ 2397 if (IsEqualIID(&list->ClassGuid, &GUID_NULL)) 2398 pClassGuid = &list->ClassGuid; 2399 else 2400 { 2401 SetLastError(ERROR_INVALID_PARAMETER); 2402 goto cleanup; 2403 } 2404 } 2405 else 2406 { 2407 SetLastError(ERROR_INVALID_PARAMETER); 2408 goto cleanup; 2409 } 2410 rc = SETUP_CreateDevicesList(list, machine, pClassGuid, enumstr); 2411 } 2412 if (rc != ERROR_SUCCESS) 2413 { 2414 SetLastError(rc); 2415 goto cleanup; 2416 } 2417 set = hDeviceInfo; 2418 2419 cleanup: 2420 if (!deviceset && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != set) 2421 SetupDiDestroyDeviceInfoList(hDeviceInfo); 2422 return set; 2423 } 2424 2425 /*********************************************************************** 2426 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@) 2427 */ 2428 BOOL WINAPI SetupDiGetDeviceInfoListDetailA( 2429 HDEVINFO DeviceInfoSet, 2430 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData ) 2431 { 2432 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2433 2434 TRACE("%s(%p %p)\n", __FUNCTION__, DeviceInfoSet, DevInfoData); 2435 2436 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 2437 { 2438 SetLastError(ERROR_INVALID_HANDLE); 2439 return FALSE; 2440 } 2441 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2442 { 2443 SetLastError(ERROR_INVALID_HANDLE); 2444 return FALSE; 2445 } 2446 if (!DevInfoData || 2447 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A)) 2448 { 2449 SetLastError(ERROR_INVALID_PARAMETER); 2450 return FALSE; 2451 } 2452 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID)); 2453 DevInfoData->RemoteMachineHandle = set->hMachine; 2454 if (set->MachineName) 2455 { 2456 FIXME("Stub\n"); 2457 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2458 return FALSE; 2459 } 2460 else 2461 DevInfoData->RemoteMachineName[0] = 0; 2462 2463 return TRUE; 2464 } 2465 2466 /*********************************************************************** 2467 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@) 2468 */ 2469 BOOL WINAPI SetupDiGetDeviceInfoListDetailW( 2470 HDEVINFO DeviceInfoSet, 2471 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData ) 2472 { 2473 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2474 2475 TRACE("%s(%p %p)\n", __FUNCTION__, DeviceInfoSet, DevInfoData); 2476 2477 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 2478 { 2479 SetLastError(ERROR_INVALID_HANDLE); 2480 return FALSE; 2481 } 2482 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2483 { 2484 SetLastError(ERROR_INVALID_HANDLE); 2485 return FALSE; 2486 } 2487 if (!DevInfoData || 2488 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W)) 2489 { 2490 SetLastError(ERROR_INVALID_PARAMETER); 2491 return FALSE; 2492 } 2493 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID)); 2494 DevInfoData->RemoteMachineHandle = set->hMachine; 2495 if (set->MachineName) 2496 strcpyW(DevInfoData->RemoteMachineName, set->MachineName + 2); 2497 else 2498 DevInfoData->RemoteMachineName[0] = 0; 2499 2500 return TRUE; 2501 } 2502 2503 /*********************************************************************** 2504 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@) 2505 */ 2506 BOOL WINAPI SetupDiCreateDeviceInterfaceA( 2507 HDEVINFO DeviceInfoSet, 2508 PSP_DEVINFO_DATA DeviceInfoData, 2509 const GUID *InterfaceClassGuid, 2510 PCSTR ReferenceString, 2511 DWORD CreationFlags, 2512 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 2513 { 2514 BOOL ret; 2515 LPWSTR ReferenceStringW = NULL; 2516 2517 TRACE("%s(%p %p %s %s %08x %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, 2518 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString), 2519 CreationFlags, DeviceInterfaceData); 2520 2521 if (ReferenceString) 2522 { 2523 ReferenceStringW = pSetupMultiByteToUnicode(ReferenceString, CP_ACP); 2524 if (ReferenceStringW == NULL) return FALSE; 2525 } 2526 2527 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData, 2528 InterfaceClassGuid, ReferenceStringW, CreationFlags, 2529 DeviceInterfaceData); 2530 2531 MyFree(ReferenceStringW); 2532 2533 return ret; 2534 } 2535 2536 /*********************************************************************** 2537 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@) 2538 */ 2539 BOOL WINAPI SetupDiCreateDeviceInterfaceW( 2540 HDEVINFO DeviceInfoSet, 2541 PSP_DEVINFO_DATA DeviceInfoData, 2542 const GUID *InterfaceClassGuid, 2543 PCWSTR ReferenceString, 2544 DWORD CreationFlags, 2545 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 2546 { 2547 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2548 TRACE("%s(%p %p %s %s %08x %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, 2549 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString), 2550 CreationFlags, DeviceInterfaceData); 2551 2552 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 2553 { 2554 SetLastError(ERROR_INVALID_HANDLE); 2555 return FALSE; 2556 } 2557 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2558 { 2559 SetLastError(ERROR_INVALID_HANDLE); 2560 return FALSE; 2561 } 2562 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 2563 || !DeviceInfoData->Reserved) 2564 { 2565 SetLastError(ERROR_INVALID_PARAMETER); 2566 return FALSE; 2567 } 2568 if (!InterfaceClassGuid) 2569 { 2570 SetLastError(ERROR_INVALID_USER_BUFFER); 2571 return FALSE; 2572 } 2573 2574 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData, 2575 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString), 2576 CreationFlags, DeviceInterfaceData); 2577 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2578 return FALSE; 2579 } 2580 2581 /*********************************************************************** 2582 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@) 2583 */ 2584 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA( 2585 HDEVINFO DeviceInfoSet, 2586 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 2587 DWORD Reserved, 2588 REGSAM samDesired, 2589 HINF InfHandle, 2590 PCSTR InfSectionName) 2591 { 2592 HKEY key; 2593 PWSTR InfSectionNameW = NULL; 2594 2595 TRACE("%s(%p %p %d %08x %p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInterfaceData, Reserved, 2596 samDesired, InfHandle, InfSectionName); 2597 if (InfHandle) 2598 { 2599 if (!InfSectionName) 2600 { 2601 SetLastError(ERROR_INVALID_PARAMETER); 2602 return INVALID_HANDLE_VALUE; 2603 } 2604 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP); 2605 if (!InfSectionNameW) 2606 return INVALID_HANDLE_VALUE; 2607 } 2608 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet, 2609 DeviceInterfaceData, Reserved, samDesired, InfHandle, 2610 InfSectionNameW); 2611 MyFree(InfSectionNameW); 2612 return key; 2613 } 2614 2615 /*********************************************************************** 2616 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@) 2617 */ 2618 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW( 2619 HDEVINFO DeviceInfoSet, 2620 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 2621 DWORD Reserved, 2622 REGSAM samDesired, 2623 HINF InfHandle, 2624 PCWSTR InfSectionName) 2625 { 2626 HKEY hKey, hDevKey; 2627 LPWSTR SymbolicLink; 2628 DWORD Length, Index; 2629 LONG rc; 2630 WCHAR bracedGuidString[39]; 2631 struct DeviceInterface *DevItf; 2632 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2633 2634 TRACE("%s(%p %p %d %08x %p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInterfaceData, Reserved, 2635 samDesired, InfHandle, InfSectionName); 2636 2637 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 2638 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2639 { 2640 SetLastError(ERROR_INVALID_HANDLE); 2641 return INVALID_HANDLE_VALUE; 2642 } 2643 if (!DeviceInterfaceData || 2644 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || 2645 !DeviceInterfaceData->Reserved) 2646 { 2647 SetLastError(ERROR_INVALID_PARAMETER); 2648 return INVALID_HANDLE_VALUE; 2649 } 2650 if (InfHandle && !InfSectionName) 2651 { 2652 SetLastError(ERROR_INVALID_PARAMETER); 2653 return INVALID_HANDLE_VALUE; 2654 } 2655 2656 hKey = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid, samDesired, DIOCR_INTERFACE, NULL, NULL); 2657 if (hKey == INVALID_HANDLE_VALUE) 2658 { 2659 hKey = SetupDiOpenClassRegKeyExW(NULL, samDesired, DIOCR_INTERFACE, NULL, NULL); 2660 if (hKey == INVALID_HANDLE_VALUE) 2661 { 2662 SetLastError(ERROR_INVALID_PARAMETER); 2663 return INVALID_HANDLE_VALUE; 2664 } 2665 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid, bracedGuidString); 2666 2667 if (RegCreateKeyExW(hKey, bracedGuidString, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL) != ERROR_SUCCESS) 2668 { 2669 SetLastError(ERROR_INVALID_PARAMETER); 2670 return INVALID_HANDLE_VALUE; 2671 } 2672 RegCloseKey(hKey); 2673 hKey = hDevKey; 2674 } 2675 2676 DevItf = (struct DeviceInterface *)DeviceInterfaceData->Reserved; 2677 2678 Length = (wcslen(DevItf->SymbolicLink)+1) * sizeof(WCHAR); 2679 SymbolicLink = HeapAlloc(GetProcessHeap(), 0, Length); 2680 if (!SymbolicLink) 2681 { 2682 RegCloseKey(hKey); 2683 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 2684 return INVALID_HANDLE_VALUE; 2685 } 2686 2687 wcscpy(SymbolicLink, DevItf->SymbolicLink); 2688 2689 Index = 0; 2690 while(SymbolicLink[Index]) 2691 { 2692 if (SymbolicLink[Index] == L'\\') 2693 { 2694 SymbolicLink[Index] = L'#'; 2695 } 2696 Index++; 2697 } 2698 2699 rc = RegCreateKeyExW(hKey, SymbolicLink, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL); 2700 2701 RegCloseKey(hKey); 2702 HeapFree(GetProcessHeap(), 0, SymbolicLink); 2703 2704 if (rc == ERROR_SUCCESS) 2705 { 2706 if (InfHandle && InfSectionName) 2707 { 2708 if (!SetupInstallFromInfSection(NULL /*FIXME */, 2709 InfHandle, 2710 InfSectionName, 2711 SPINST_INIFILES | SPINST_REGISTRY | SPINST_INI2REG | SPINST_FILES | SPINST_BITREG | SPINST_REGSVR | SPINST_UNREGSVR | SPINST_PROFILEITEMS | SPINST_COPYINF, 2712 hDevKey, 2713 NULL, 2714 0, 2715 set->SelectedDevice->InstallParams.InstallMsgHandler, 2716 set->SelectedDevice->InstallParams.InstallMsgHandlerContext, 2717 INVALID_HANDLE_VALUE, 2718 NULL)) 2719 { 2720 RegCloseKey(hDevKey); 2721 return INVALID_HANDLE_VALUE; 2722 } 2723 } 2724 } 2725 2726 SetLastError(rc); 2727 return hDevKey; 2728 } 2729 2730 /*********************************************************************** 2731 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@) 2732 */ 2733 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey( 2734 HDEVINFO DeviceInfoSet, 2735 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 2736 DWORD Reserved) 2737 { 2738 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2739 BOOL ret = FALSE; 2740 2741 TRACE("%s(%p %p %d)\n", __FUNCTION__, DeviceInfoSet, DeviceInterfaceData, Reserved); 2742 2743 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 2744 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2745 { 2746 SetLastError(ERROR_INVALID_HANDLE); 2747 return FALSE; 2748 } 2749 if (!DeviceInterfaceData || 2750 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || 2751 !DeviceInterfaceData->Reserved) 2752 { 2753 SetLastError(ERROR_INVALID_PARAMETER); 2754 return FALSE; 2755 } 2756 2757 FIXME("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved); 2758 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2759 return ret; 2760 } 2761 2762 /*********************************************************************** 2763 * SetupDiEnumDeviceInterfaces (SETUPAPI.@) 2764 * 2765 * PARAMS 2766 * DeviceInfoSet [I] Set of devices from which to enumerate 2767 * interfaces 2768 * DeviceInfoData [I] (Optional) If specified, a specific device 2769 * instance from which to enumerate interfaces. 2770 * If it isn't specified, all interfaces for all 2771 * devices in the set are enumerated. 2772 * InterfaceClassGuid [I] The interface class to enumerate. 2773 * MemberIndex [I] An index of the interface instance to enumerate. 2774 * A caller should start with MemberIndex set to 0, 2775 * and continue until the function fails with 2776 * ERROR_NO_MORE_ITEMS. 2777 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize 2778 * member must be set to 2779 * sizeof(SP_DEVICE_INTERFACE_DATA). 2780 * 2781 * RETURNS 2782 * Success: non-zero value. 2783 * Failure: FALSE. Call GetLastError() for more info. 2784 */ 2785 BOOL WINAPI SetupDiEnumDeviceInterfaces( 2786 HDEVINFO DeviceInfoSet, 2787 PSP_DEVINFO_DATA DeviceInfoData, 2788 CONST GUID * InterfaceClassGuid, 2789 DWORD MemberIndex, 2790 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 2791 { 2792 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2793 BOOL ret = FALSE; 2794 2795 TRACE("%s(%p, %p, %s, %d, %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, 2796 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData); 2797 2798 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 2799 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2800 { 2801 SetLastError(ERROR_INVALID_HANDLE); 2802 return FALSE; 2803 } 2804 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) || 2805 !DeviceInfoData->Reserved)) 2806 { 2807 SetLastError(ERROR_INVALID_PARAMETER); 2808 return FALSE; 2809 } 2810 if (!DeviceInterfaceData || 2811 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA)) 2812 { 2813 SetLastError(ERROR_INVALID_PARAMETER); 2814 return FALSE; 2815 } 2816 if (DeviceInfoData) 2817 { 2818 struct DeviceInfo *devInfo = 2819 (struct DeviceInfo *)DeviceInfoData->Reserved; 2820 BOOL found = FALSE; 2821 PLIST_ENTRY InterfaceListEntry = devInfo->InterfaceListHead.Flink; 2822 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found) 2823 { 2824 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry); 2825 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid)) 2826 { 2827 InterfaceListEntry = InterfaceListEntry->Flink; 2828 continue; 2829 } 2830 if (MemberIndex-- == 0) 2831 { 2832 /* return this item */ 2833 memcpy(&DeviceInterfaceData->InterfaceClassGuid, 2834 &DevItf->InterfaceClassGuid, 2835 sizeof(GUID)); 2836 DeviceInterfaceData->Flags = DevItf->Flags; 2837 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf; 2838 found = TRUE; 2839 ret = TRUE; 2840 } 2841 InterfaceListEntry = InterfaceListEntry->Flink; 2842 } 2843 if (!found) 2844 SetLastError(ERROR_NO_MORE_ITEMS); 2845 } 2846 else 2847 { 2848 BOOL found = FALSE; 2849 PLIST_ENTRY ItemList = set->ListHead.Flink; 2850 while (ItemList != &set->ListHead && !found) 2851 { 2852 PLIST_ENTRY InterfaceListEntry; 2853 struct DeviceInfo *devInfo = 2854 CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry); 2855 InterfaceListEntry = devInfo->InterfaceListHead.Flink; 2856 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found) 2857 { 2858 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry); 2859 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid)) 2860 { 2861 InterfaceListEntry = InterfaceListEntry->Flink; 2862 continue; 2863 } 2864 if (MemberIndex-- == 0) 2865 { 2866 /* return this item */ 2867 memcpy(&DeviceInterfaceData->InterfaceClassGuid, 2868 &DevItf->InterfaceClassGuid, 2869 sizeof(GUID)); 2870 DeviceInterfaceData->Flags = DevItf->Flags; 2871 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf; 2872 found = TRUE; 2873 ret = TRUE; 2874 } 2875 InterfaceListEntry = InterfaceListEntry->Flink; 2876 } 2877 ItemList = ItemList->Flink; 2878 2879 } 2880 if (!found) 2881 SetLastError(ERROR_NO_MORE_ITEMS); 2882 } 2883 return ret; 2884 } 2885 2886 /*********************************************************************** 2887 * SetupDiDestroyDeviceInfoList (SETUPAPI.@) 2888 * 2889 * Destroy a DeviceInfoList and free all used memory of the list. 2890 * 2891 * PARAMS 2892 * devinfo [I] DeviceInfoList pointer to list to destroy 2893 * 2894 * RETURNS 2895 * Success: non zero value. 2896 * Failure: zero value. 2897 */ 2898 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo) 2899 { 2900 BOOL ret = FALSE; 2901 2902 TRACE("%s(%p)\n", __FUNCTION__, devinfo); 2903 if (devinfo && devinfo != INVALID_HANDLE_VALUE) 2904 { 2905 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo; 2906 2907 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC) 2908 { 2909 ret = DestroyDeviceInfoSet(list); 2910 } 2911 } 2912 2913 if (ret == FALSE) 2914 SetLastError(ERROR_INVALID_HANDLE); 2915 2916 return ret; 2917 } 2918 2919 /*********************************************************************** 2920 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@) 2921 */ 2922 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA( 2923 HDEVINFO DeviceInfoSet, 2924 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 2925 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData, 2926 DWORD DeviceInterfaceDetailDataSize, 2927 PDWORD RequiredSize, 2928 PSP_DEVINFO_DATA DeviceInfoData) 2929 { 2930 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 2931 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL; 2932 DWORD sizeW = 0, bytesNeeded; 2933 BOOL ret = FALSE; 2934 2935 TRACE("%s(%p, %p, %p, %d, %p, %p)\n", __FUNCTION__, DeviceInfoSet, 2936 DeviceInterfaceData, DeviceInterfaceDetailData, 2937 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); 2938 2939 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 2940 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 2941 { 2942 SetLastError(ERROR_INVALID_HANDLE); 2943 return FALSE; 2944 } 2945 if (!DeviceInterfaceData || 2946 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || 2947 !DeviceInterfaceData->Reserved) 2948 { 2949 SetLastError(ERROR_INVALID_PARAMETER); 2950 return FALSE; 2951 } 2952 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))) 2953 { 2954 SetLastError(ERROR_INVALID_USER_BUFFER); 2955 return FALSE; 2956 } 2957 2958 if((DeviceInterfaceDetailDataSize != 0) && 2959 (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(CHAR)))) 2960 { 2961 SetLastError(ERROR_INVALID_USER_BUFFER); 2962 return FALSE; 2963 } 2964 2965 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize) 2966 { 2967 SetLastError(ERROR_INVALID_USER_BUFFER); 2968 return FALSE; 2969 } 2970 2971 2972 if (DeviceInterfaceDetailData != NULL) 2973 { 2974 sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) 2975 + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR); 2976 DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)MyMalloc(sizeW); 2977 if (!DeviceInterfaceDetailDataW) 2978 { 2979 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 2980 } 2981 DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); 2982 } 2983 if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW)) 2984 { 2985 ret = SetupDiGetDeviceInterfaceDetailW( 2986 DeviceInfoSet, 2987 DeviceInterfaceData, 2988 DeviceInterfaceDetailDataW, 2989 sizeW, 2990 &sizeW, 2991 DeviceInfoData); 2992 bytesNeeded = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR) 2993 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath); 2994 if (RequiredSize) 2995 *RequiredSize = bytesNeeded; 2996 if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize >= bytesNeeded) 2997 { 2998 if (!WideCharToMultiByte( 2999 CP_ACP, 0, 3000 DeviceInterfaceDetailDataW->DevicePath, -1, 3001 DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath), 3002 NULL, NULL)) 3003 { 3004 ret = FALSE; 3005 } 3006 } 3007 } 3008 MyFree(DeviceInterfaceDetailDataW); 3009 3010 return ret; 3011 } 3012 3013 /*********************************************************************** 3014 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@) 3015 */ 3016 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW( 3017 HDEVINFO DeviceInfoSet, 3018 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 3019 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData, 3020 DWORD DeviceInterfaceDetailDataSize, 3021 PDWORD RequiredSize, 3022 PSP_DEVINFO_DATA DeviceInfoData) 3023 { 3024 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 3025 BOOL ret = FALSE; 3026 3027 TRACE("%s(%p, %p, %p, %d, %p, %p)\n", __FUNCTION__, DeviceInfoSet, 3028 DeviceInterfaceData, DeviceInterfaceDetailData, 3029 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); 3030 3031 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 3032 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 3033 { 3034 SetLastError(ERROR_INVALID_HANDLE); 3035 return FALSE; 3036 } 3037 if (!DeviceInterfaceData || 3038 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || 3039 !DeviceInterfaceData->Reserved) 3040 { 3041 SetLastError(ERROR_INVALID_PARAMETER); 3042 return FALSE; 3043 } 3044 if (DeviceInterfaceDetailData && DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)) 3045 { 3046 SetLastError(ERROR_INVALID_USER_BUFFER); 3047 return FALSE; 3048 } 3049 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize) 3050 { 3051 SetLastError(ERROR_INVALID_USER_BUFFER); 3052 return FALSE; 3053 } 3054 if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 3055 { 3056 SetLastError(ERROR_INVALID_PARAMETER); 3057 return FALSE; 3058 } 3059 if ((DeviceInterfaceDetailData != NULL) 3060 && (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) + sizeof(WCHAR))) 3061 { 3062 SetLastError(ERROR_INVALID_PARAMETER); 3063 return FALSE; 3064 } 3065 else 3066 { 3067 struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved; 3068 LPCWSTR devName = deviceInterface->SymbolicLink; 3069 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 3070 (lstrlenW(devName) + 1) * sizeof(WCHAR); 3071 3072 if (sizeRequired > DeviceInterfaceDetailDataSize) 3073 { 3074 SetLastError(ERROR_INSUFFICIENT_BUFFER); 3075 if (RequiredSize) 3076 *RequiredSize = sizeRequired; 3077 } 3078 else 3079 { 3080 strcpyW(DeviceInterfaceDetailData->DevicePath, devName); 3081 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath)); 3082 if (DeviceInfoData) 3083 { 3084 memcpy(&DeviceInfoData->ClassGuid, 3085 &deviceInterface->DeviceInfo->ClassGuid, 3086 sizeof(GUID)); 3087 DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst; 3088 DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo; 3089 } 3090 ret = TRUE; 3091 } 3092 } 3093 return ret; 3094 } 3095 3096 struct PropertyMapEntry 3097 { 3098 DWORD regType; 3099 LPCSTR nameA; 3100 LPCWSTR nameW; 3101 }; 3102 3103 static struct PropertyMapEntry PropertyMap[] = { 3104 { REG_SZ, "DeviceDesc", REGSTR_VAL_DEVDESC }, 3105 { REG_MULTI_SZ, "HardwareId", REGSTR_VAL_HARDWAREID }, 3106 { REG_MULTI_SZ, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS }, 3107 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */ 3108 { REG_SZ, "Service", REGSTR_VAL_SERVICE }, 3109 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */ 3110 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */ 3111 { REG_SZ, "Class", REGSTR_VAL_CLASS }, 3112 { REG_SZ, "ClassGUID", REGSTR_VAL_CLASSGUID }, 3113 { REG_SZ, "Driver", REGSTR_VAL_DRIVER }, 3114 { REG_DWORD, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS }, 3115 { REG_SZ, "Mfg", REGSTR_VAL_MFG }, 3116 { REG_SZ, "FriendlyName", REGSTR_VAL_FRIENDLYNAME }, 3117 { REG_SZ, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION }, 3118 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */ 3119 { REG_DWORD, "Capabilities", REGSTR_VAL_CAPABILITIES }, 3120 { REG_DWORD, "UINumber", REGSTR_VAL_UI_NUMBER }, 3121 { REG_MULTI_SZ, "UpperFilters", REGSTR_VAL_UPPERFILTERS }, 3122 { REG_MULTI_SZ, "LowerFilters", REGSTR_VAL_LOWERFILTERS }, 3123 { 0, NULL, NULL }, /* SPDRP_BUSTYPEGUID */ 3124 { 0, NULL, NULL }, /* SPDRP_LEGACYBUSTYPE */ 3125 { 0, NULL, NULL }, /* SPDRP_BUSNUMBER */ 3126 { 0, NULL, NULL }, /* SPDRP_ENUMERATOR_NAME */ 3127 { REG_BINARY, "Security", REGSTR_SECURITY }, 3128 { 0, NULL, NULL }, /* SPDRP_SECURITY_SDS */ 3129 { 0, NULL, NULL }, /* SPDRP_DEVTYPE */ 3130 { 0, NULL, NULL }, /* SPDRP_EXCLUSIVE */ 3131 { 0, NULL, NULL }, /* SPDRP_CHARACTERISTICS */ 3132 { 0, NULL, NULL }, /* SPDRP_ADDRESS */ 3133 { REG_SZ, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT }, 3134 { 0, NULL, NULL }, /* SPDRP_DEVICE_POWER_DATA */ 3135 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY */ 3136 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */ 3137 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_OVERRIDE */ 3138 { 0, NULL, NULL }, /* SPDRP_INSTALL_STATE */ 3139 }; 3140 3141 /*********************************************************************** 3142 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@) 3143 */ 3144 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA( 3145 HDEVINFO DeviceInfoSet, 3146 PSP_DEVINFO_DATA DeviceInfoData, 3147 DWORD Property, 3148 PDWORD PropertyRegDataType, 3149 PBYTE PropertyBuffer, 3150 DWORD PropertyBufferSize, 3151 PDWORD RequiredSize) 3152 { 3153 BOOL ret; 3154 BOOL bIsStringProperty; 3155 DWORD RegType; 3156 DWORD RequiredSizeA, RequiredSizeW; 3157 DWORD PropertyBufferSizeW = 0; 3158 PBYTE PropertyBufferW = NULL; 3159 3160 TRACE("%s(%p %p %d %p %p %d %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, 3161 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, 3162 RequiredSize); 3163 3164 if (PropertyBufferSize != 0) 3165 { 3166 PropertyBufferSizeW = PropertyBufferSize * 2; 3167 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW); 3168 if (!PropertyBufferW) 3169 { 3170 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3171 return FALSE; 3172 } 3173 } 3174 3175 ret = SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, 3176 DeviceInfoData, 3177 Property, 3178 &RegType, 3179 PropertyBufferW, 3180 PropertyBufferSizeW, 3181 &RequiredSizeW); 3182 3183 if (ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER) 3184 { 3185 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ); 3186 3187 if (bIsStringProperty) 3188 RequiredSizeA = RequiredSizeW / sizeof(WCHAR); 3189 else 3190 RequiredSizeA = RequiredSizeW; 3191 if (RequiredSize) 3192 *RequiredSize = RequiredSizeA; 3193 if (PropertyRegDataType) 3194 *PropertyRegDataType = RegType; 3195 } 3196 3197 if (!ret) 3198 { 3199 HeapFree(GetProcessHeap(), 0, PropertyBufferW); 3200 return ret; 3201 } 3202 3203 if (RequiredSizeA <= PropertyBufferSize) 3204 { 3205 if (bIsStringProperty && PropertyBufferSize > 0) 3206 { 3207 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0) 3208 { 3209 /* Last error is already set by WideCharToMultiByte */ 3210 ret = FALSE; 3211 } 3212 } 3213 else 3214 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA); 3215 } 3216 else 3217 { 3218 SetLastError(ERROR_INSUFFICIENT_BUFFER); 3219 ret = FALSE; 3220 } 3221 3222 HeapFree(GetProcessHeap(), 0, PropertyBufferW); 3223 return ret; 3224 } 3225 3226 /*********************************************************************** 3227 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@) 3228 */ 3229 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW( 3230 HDEVINFO DeviceInfoSet, 3231 PSP_DEVINFO_DATA DeviceInfoData, 3232 DWORD Property, 3233 PDWORD PropertyRegDataType, 3234 PBYTE PropertyBuffer, 3235 DWORD PropertyBufferSize, 3236 PDWORD RequiredSize) 3237 { 3238 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 3239 struct DeviceInfo *devInfo; 3240 CONFIGRET cr; 3241 LONG lError = ERROR_SUCCESS; 3242 DWORD size; 3243 3244 TRACE("%s(%p %p %d %p %p %d %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, 3245 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, 3246 RequiredSize); 3247 3248 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 3249 { 3250 SetLastError(ERROR_INVALID_HANDLE); 3251 return FALSE; 3252 } 3253 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 3254 { 3255 SetLastError(ERROR_INVALID_HANDLE); 3256 return FALSE; 3257 } 3258 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 3259 || !DeviceInfoData->Reserved) 3260 { 3261 SetLastError(ERROR_INVALID_PARAMETER); 3262 return FALSE; 3263 } 3264 3265 if (Property >= SPDRP_MAXIMUM_PROPERTY) 3266 { 3267 SetLastError(ERROR_INVALID_REG_PROPERTY); 3268 return FALSE; 3269 } 3270 3271 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 3272 3273 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0]) 3274 && PropertyMap[Property].nameW) 3275 { 3276 HKEY hKey; 3277 size = PropertyBufferSize; 3278 hKey = SETUPDI_OpenDevKey(set->HKLM, devInfo, KEY_QUERY_VALUE); 3279 if (hKey == INVALID_HANDLE_VALUE) 3280 return FALSE; 3281 lError = RegQueryValueExW(hKey, PropertyMap[Property].nameW, 3282 NULL, PropertyRegDataType, PropertyBuffer, &size); 3283 RegCloseKey(hKey); 3284 3285 if (RequiredSize) 3286 *RequiredSize = size; 3287 3288 switch (lError) 3289 { 3290 case ERROR_SUCCESS: 3291 if (PropertyBuffer == NULL && size != 0) 3292 lError = ERROR_INSUFFICIENT_BUFFER; 3293 break; 3294 case ERROR_MORE_DATA: 3295 lError = ERROR_INSUFFICIENT_BUFFER; 3296 break; 3297 default: 3298 break; 3299 } 3300 } 3301 else if (Property == SPDRP_PHYSICAL_DEVICE_OBJECT_NAME) 3302 { 3303 size = (strlenW(devInfo->Data) + 1) * sizeof(WCHAR); 3304 3305 if (PropertyRegDataType) 3306 *PropertyRegDataType = REG_SZ; 3307 if (RequiredSize) 3308 *RequiredSize = size; 3309 if (PropertyBufferSize >= size) 3310 { 3311 strcpyW((LPWSTR)PropertyBuffer, devInfo->Data); 3312 } 3313 else 3314 lError = ERROR_INSUFFICIENT_BUFFER; 3315 } 3316 else 3317 { 3318 size = PropertyBufferSize; 3319 3320 cr = CM_Get_DevNode_Registry_Property_ExW(devInfo->dnDevInst, 3321 Property + (CM_DRP_DEVICEDESC - SPDRP_DEVICEDESC), 3322 PropertyRegDataType, 3323 PropertyBuffer, 3324 &size, 3325 0, 3326 set->hMachine); 3327 if ((cr == CR_SUCCESS) || (cr == CR_BUFFER_SMALL)) 3328 { 3329 if (RequiredSize) 3330 *RequiredSize = size; 3331 } 3332 3333 if (cr != CR_SUCCESS) 3334 { 3335 switch (cr) 3336 { 3337 case CR_INVALID_DEVINST: 3338 lError = ERROR_NO_SUCH_DEVINST; 3339 break; 3340 3341 case CR_INVALID_PROPERTY: 3342 lError = ERROR_INVALID_REG_PROPERTY; 3343 break; 3344 3345 case CR_BUFFER_SMALL: 3346 lError = ERROR_INSUFFICIENT_BUFFER; 3347 break; 3348 3349 default : 3350 lError = ERROR_INVALID_DATA; 3351 break; 3352 } 3353 } 3354 } 3355 3356 SetLastError(lError); 3357 return (lError == ERROR_SUCCESS); 3358 } 3359 3360 /*********************************************************************** 3361 * Internal for SetupDiSetDeviceRegistryPropertyA/W 3362 */ 3363 BOOL WINAPI IntSetupDiSetDeviceRegistryPropertyAW( 3364 HDEVINFO DeviceInfoSet, 3365 PSP_DEVINFO_DATA DeviceInfoData, 3366 DWORD Property, 3367 const BYTE *PropertyBuffer, 3368 DWORD PropertyBufferSize, 3369 BOOL isAnsi) 3370 { 3371 BOOL ret = FALSE; 3372 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 3373 struct DeviceInfo *deviceInfo; 3374 3375 TRACE("%s(%p %p %d %p %d)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, Property, 3376 PropertyBuffer, PropertyBufferSize); 3377 3378 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 3379 { 3380 SetLastError(ERROR_INVALID_HANDLE); 3381 return FALSE; 3382 } 3383 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 3384 { 3385 SetLastError(ERROR_INVALID_HANDLE); 3386 return FALSE; 3387 } 3388 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 3389 || !DeviceInfoData->Reserved) 3390 { 3391 SetLastError(ERROR_INVALID_PARAMETER); 3392 return FALSE; 3393 } 3394 3395 deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 3396 3397 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0]) 3398 && PropertyMap[Property].nameW 3399 && PropertyMap[Property].nameA) 3400 { 3401 HKEY hKey; 3402 LONG l; 3403 hKey = SETUPDI_OpenDevKey(set->HKLM, deviceInfo, KEY_SET_VALUE); 3404 if (hKey == INVALID_HANDLE_VALUE) 3405 return FALSE; 3406 /* Write new data */ 3407 if (isAnsi) 3408 { 3409 l = RegSetValueExA( 3410 hKey, PropertyMap[Property].nameA, 0, 3411 PropertyMap[Property].regType, PropertyBuffer, 3412 PropertyBufferSize); 3413 } 3414 else 3415 { 3416 l = RegSetValueExW( 3417 hKey, PropertyMap[Property].nameW, 0, 3418 PropertyMap[Property].regType, PropertyBuffer, 3419 PropertyBufferSize); 3420 } 3421 if (!l) 3422 ret = TRUE; 3423 else 3424 SetLastError(l); 3425 RegCloseKey(hKey); 3426 } 3427 else 3428 { 3429 ERR("Property 0x%lx not implemented\n", Property); 3430 SetLastError(ERROR_NOT_SUPPORTED); 3431 } 3432 3433 TRACE("Returning %d\n", ret); 3434 return ret; 3435 } 3436 /*********************************************************************** 3437 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@) 3438 */ 3439 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA( 3440 HDEVINFO DeviceInfoSet, 3441 PSP_DEVINFO_DATA DeviceInfoData, 3442 DWORD Property, 3443 const BYTE *PropertyBuffer, 3444 DWORD PropertyBufferSize) 3445 { 3446 return IntSetupDiSetDeviceRegistryPropertyAW(DeviceInfoSet, 3447 DeviceInfoData, 3448 Property, 3449 PropertyBuffer, 3450 PropertyBufferSize, 3451 TRUE); 3452 } 3453 3454 /*********************************************************************** 3455 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@) 3456 */ 3457 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW( 3458 HDEVINFO DeviceInfoSet, 3459 PSP_DEVINFO_DATA DeviceInfoData, 3460 DWORD Property, 3461 const BYTE *PropertyBuffer, 3462 DWORD PropertyBufferSize) 3463 { 3464 return IntSetupDiSetDeviceRegistryPropertyAW(DeviceInfoSet, 3465 DeviceInfoData, 3466 Property, 3467 PropertyBuffer, 3468 PropertyBufferSize, 3469 FALSE); 3470 } 3471 3472 /*********************************************************************** 3473 * SetupDiInstallClassA (SETUPAPI.@) 3474 */ 3475 BOOL WINAPI SetupDiInstallClassA( 3476 HWND hwndParent, 3477 PCSTR InfFileName, 3478 DWORD Flags, 3479 HSPFILEQ FileQueue) 3480 { 3481 return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL); 3482 } 3483 3484 /*********************************************************************** 3485 * SetupDiInstallClassExA (SETUPAPI.@) 3486 */ 3487 BOOL WINAPI 3488 SetupDiInstallClassExA( 3489 IN HWND hwndParent OPTIONAL, 3490 IN PCSTR InfFileName OPTIONAL, 3491 IN DWORD Flags, 3492 IN HSPFILEQ FileQueue OPTIONAL, 3493 IN CONST GUID *InterfaceClassGuid OPTIONAL, 3494 IN PVOID Reserved1, 3495 IN PVOID Reserved2) 3496 { 3497 PWSTR InfFileNameW = NULL; 3498 BOOL Result; 3499 3500 if (!InfFileName) 3501 { 3502 SetLastError(ERROR_INVALID_PARAMETER); 3503 return FALSE; 3504 } 3505 else 3506 { 3507 InfFileNameW = pSetupMultiByteToUnicode(InfFileName, CP_ACP); 3508 if (InfFileNameW == NULL) 3509 { 3510 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3511 return FALSE; 3512 } 3513 } 3514 3515 Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags, 3516 FileQueue, InterfaceClassGuid, Reserved1, Reserved2); 3517 3518 MyFree(InfFileNameW); 3519 3520 return Result; 3521 } 3522 3523 HKEY SETUP_CreateClassKey(HINF hInf) 3524 { 3525 WCHAR FullBuffer[MAX_PATH]; 3526 WCHAR Buffer[MAX_PATH]; 3527 DWORD RequiredSize; 3528 HKEY hClassKey; 3529 DWORD Disposition; 3530 3531 /* Obtain the Class GUID for this class */ 3532 if (!SetupGetLineTextW(NULL, 3533 hInf, 3534 Version, 3535 REGSTR_VAL_CLASSGUID, 3536 Buffer, 3537 sizeof(Buffer) / sizeof(WCHAR), 3538 &RequiredSize)) 3539 { 3540 return INVALID_HANDLE_VALUE; 3541 } 3542 3543 /* Build the corresponding registry key name */ 3544 lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT); 3545 lstrcatW(FullBuffer, BackSlash); 3546 lstrcatW(FullBuffer, Buffer); 3547 3548 /* Obtain the Class name for this class */ 3549 if (!SetupGetLineTextW(NULL, 3550 hInf, 3551 Version, 3552 REGSTR_VAL_CLASS, 3553 Buffer, 3554 sizeof(Buffer) / sizeof(WCHAR), 3555 &RequiredSize)) 3556 { 3557 return INVALID_HANDLE_VALUE; 3558 } 3559 3560 /* Try to open or create the registry key */ 3561 TRACE("Opening class key %s\n", debugstr_w(FullBuffer)); 3562 #if 0 // I keep this for reference... 3563 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 3564 FullBuffer, 3565 0, 3566 KEY_SET_VALUE, 3567 &hClassKey)) 3568 { 3569 /* Use RegCreateKeyExW */ 3570 } 3571 #endif 3572 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, 3573 FullBuffer, 3574 0, 3575 NULL, 3576 REG_OPTION_NON_VOLATILE, 3577 KEY_SET_VALUE, 3578 NULL, 3579 &hClassKey, 3580 &Disposition)) 3581 { 3582 ERR("RegCreateKeyExW(%s) failed\n", debugstr_w(FullBuffer)); 3583 return INVALID_HANDLE_VALUE; 3584 } 3585 if (Disposition == REG_CREATED_NEW_KEY) 3586 TRACE("The class key %s was successfully created\n", debugstr_w(FullBuffer)); 3587 else 3588 TRACE("The class key %s was successfully opened\n", debugstr_w(FullBuffer)); 3589 3590 TRACE( "setting value %s to %s\n", debugstr_w(REGSTR_VAL_CLASS), debugstr_w(Buffer) ); 3591 if (RegSetValueExW(hClassKey, 3592 REGSTR_VAL_CLASS, 3593 0, 3594 REG_SZ, 3595 (LPBYTE)Buffer, 3596 RequiredSize * sizeof(WCHAR))) 3597 { 3598 RegCloseKey(hClassKey); 3599 RegDeleteKeyW(HKEY_LOCAL_MACHINE, 3600 FullBuffer); 3601 return INVALID_HANDLE_VALUE; 3602 } 3603 3604 return hClassKey; 3605 } 3606 3607 /*********************************************************************** 3608 * SetupDiInstallClassW (SETUPAPI.@) 3609 */ 3610 BOOL WINAPI SetupDiInstallClassW( 3611 HWND hwndParent, 3612 PCWSTR InfFileName, 3613 DWORD Flags, 3614 HSPFILEQ FileQueue) 3615 { 3616 return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL); 3617 } 3618 3619 3620 /*********************************************************************** 3621 * SetupDiOpenClassRegKey (SETUPAPI.@) 3622 */ 3623 HKEY WINAPI SetupDiOpenClassRegKey( 3624 const GUID* ClassGuid, 3625 REGSAM samDesired) 3626 { 3627 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, 3628 DIOCR_INSTALLER, NULL, NULL); 3629 } 3630 3631 3632 /*********************************************************************** 3633 * SetupDiOpenClassRegKeyExA (SETUPAPI.@) 3634 */ 3635 HKEY WINAPI SetupDiOpenClassRegKeyExA( 3636 const GUID* ClassGuid, 3637 REGSAM samDesired, 3638 DWORD Flags, 3639 PCSTR MachineName, 3640 PVOID Reserved) 3641 { 3642 PWSTR MachineNameW = NULL; 3643 HKEY hKey; 3644 3645 TRACE("%s(%s 0x%lx 0x%lx %s %p)\n", __FUNCTION__, debugstr_guid(ClassGuid), samDesired, 3646 Flags, debugstr_a(MachineName), Reserved); 3647 3648 if (MachineName) 3649 { 3650 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 3651 if (MachineNameW == NULL) 3652 return INVALID_HANDLE_VALUE; 3653 } 3654 3655 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, 3656 Flags, MachineNameW, Reserved); 3657 3658 MyFree(MachineNameW); 3659 3660 return hKey; 3661 } 3662 3663 3664 /*********************************************************************** 3665 * SetupDiOpenClassRegKeyExW (SETUPAPI.@) 3666 */ 3667 HKEY WINAPI SetupDiOpenClassRegKeyExW( 3668 const GUID* ClassGuid, 3669 REGSAM samDesired, 3670 DWORD Flags, 3671 PCWSTR MachineName, 3672 PVOID Reserved) 3673 { 3674 HKEY HKLM; 3675 HKEY hClassesKey; 3676 HKEY key; 3677 LPCWSTR lpKeyName; 3678 LONG l; 3679 3680 TRACE("%s(%s 0x%lx 0x%lx %s %p)\n", __FUNCTION__, debugstr_guid(ClassGuid), samDesired, 3681 Flags, debugstr_w(MachineName), Reserved); 3682 3683 if (MachineName != NULL) 3684 { 3685 l = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM); 3686 if (l != ERROR_SUCCESS) 3687 { 3688 SetLastError(l); 3689 return INVALID_HANDLE_VALUE; 3690 } 3691 } 3692 else 3693 HKLM = HKEY_LOCAL_MACHINE; 3694 3695 if (Flags == DIOCR_INSTALLER) 3696 { 3697 lpKeyName = REGSTR_PATH_CLASS_NT; 3698 } 3699 else if (Flags == DIOCR_INTERFACE) 3700 { 3701 lpKeyName = REGSTR_PATH_DEVICE_CLASSES; 3702 } 3703 else 3704 { 3705 ERR("Invalid Flags parameter!\n"); 3706 SetLastError(ERROR_INVALID_FLAGS); 3707 if (MachineName != NULL) RegCloseKey(HKLM); 3708 return INVALID_HANDLE_VALUE; 3709 } 3710 3711 if (!ClassGuid) 3712 { 3713 if ((l = RegOpenKeyExW(HKLM, 3714 lpKeyName, 3715 0, 3716 samDesired, 3717 &hClassesKey))) 3718 { 3719 SetLastError(ERROR_INVALID_CLASS); 3720 hClassesKey = INVALID_HANDLE_VALUE; 3721 } 3722 if (MachineName != NULL) 3723 RegCloseKey(HKLM); 3724 key = hClassesKey; 3725 } 3726 else 3727 { 3728 WCHAR bracedGuidString[39]; 3729 3730 SETUPDI_GuidToString(ClassGuid, bracedGuidString); 3731 3732 if (!(l = RegOpenKeyExW(HKLM, 3733 lpKeyName, 3734 0, 3735 samDesired, 3736 &hClassesKey))) 3737 { 3738 if (MachineName != NULL) 3739 RegCloseKey(HKLM); 3740 3741 if ((l = RegOpenKeyExW(hClassesKey, 3742 bracedGuidString, 3743 0, 3744 samDesired, 3745 &key))) 3746 { 3747 SetLastError(l); 3748 key = INVALID_HANDLE_VALUE; 3749 } 3750 RegCloseKey(hClassesKey); 3751 } 3752 else 3753 { 3754 if (MachineName != NULL) RegCloseKey(HKLM); 3755 SetLastError(l); 3756 key = INVALID_HANDLE_VALUE; 3757 } 3758 } 3759 3760 return key; 3761 } 3762 3763 /*********************************************************************** 3764 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@) 3765 */ 3766 BOOL WINAPI SetupDiOpenDeviceInterfaceW( 3767 HDEVINFO DeviceInfoSet, 3768 PCWSTR DevicePath, 3769 DWORD OpenFlags, 3770 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 3771 { 3772 struct DeviceInfoSet * list; 3773 PCWSTR pEnd; 3774 DWORD dwLength, dwError, dwIndex, dwKeyName, dwSubIndex; 3775 CLSID ClassId; 3776 WCHAR Buffer[MAX_PATH + 1]; 3777 WCHAR SymBuffer[MAX_PATH + 1]; 3778 WCHAR InstancePath[MAX_PATH + 1]; 3779 HKEY hKey, hDevKey, hSymKey; 3780 struct DeviceInfo * deviceInfo; 3781 struct DeviceInterface *deviceInterface; 3782 BOOL Ret; 3783 PLIST_ENTRY ItemList; 3784 PLIST_ENTRY InterfaceListEntry; 3785 3786 TRACE("%s(%p %s %08x %p)\n", __FUNCTION__, 3787 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData); 3788 3789 3790 if (DeviceInterfaceData && DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA)) 3791 { 3792 SetLastError(ERROR_INVALID_PARAMETER); 3793 return FALSE; 3794 } 3795 3796 if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 3797 { 3798 SetLastError(ERROR_INVALID_HANDLE); 3799 return FALSE; 3800 } 3801 3802 list = (struct DeviceInfoSet * )DeviceInfoSet; 3803 3804 dwLength = wcslen(DevicePath); 3805 if (dwLength < 39) 3806 { 3807 /* path must be at least a guid length + L'\0' */ 3808 SetLastError(ERROR_BAD_PATHNAME); 3809 return FALSE; 3810 } 3811 3812 if (DevicePath[0] != L'\\' || 3813 DevicePath[1] != L'\\' || 3814 (DevicePath[2] != L'?' && DevicePath[2] != L'.') || 3815 DevicePath[3] != L'\\') 3816 { 3817 /* invalid formatted path */ 3818 SetLastError(ERROR_BAD_PATHNAME); 3819 return FALSE; 3820 } 3821 3822 /* check for reference strings */ 3823 pEnd = wcschr(&DevicePath[4], L'\\'); 3824 if (!pEnd) 3825 { 3826 /* no reference string */ 3827 pEnd = DevicePath + dwLength; 3828 } 3829 3830 /* copy guid */ 3831 wcscpy(Buffer, pEnd - 37); 3832 Buffer[36] = L'\0'; 3833 3834 dwError = UuidFromStringW(Buffer, &ClassId); 3835 if (dwError != NOERROR) 3836 { 3837 /* invalid formatted path */ 3838 SetLastError(ERROR_BAD_PATHNAME); 3839 return FALSE; 3840 } 3841 3842 hKey = SetupDiOpenClassRegKeyExW(&ClassId, KEY_READ, DIOCR_INTERFACE, list->MachineName, NULL); 3843 3844 if (hKey == INVALID_HANDLE_VALUE) 3845 { 3846 /* invalid device class */ 3847 return FALSE; 3848 } 3849 3850 ItemList = list->ListHead.Flink; 3851 while (ItemList != &list->ListHead) 3852 { 3853 deviceInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry); 3854 InterfaceListEntry = deviceInfo->InterfaceListHead.Flink; 3855 while (InterfaceListEntry != &deviceInfo->InterfaceListHead) 3856 { 3857 deviceInterface = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry); 3858 if (!IsEqualIID(&deviceInterface->InterfaceClassGuid, &ClassId)) 3859 { 3860 InterfaceListEntry = InterfaceListEntry->Flink; 3861 continue; 3862 } 3863 3864 if (!wcsicmp(deviceInterface->SymbolicLink, DevicePath)) 3865 { 3866 if (DeviceInterfaceData) 3867 { 3868 DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface; 3869 DeviceInterfaceData->Flags = deviceInterface->Flags; 3870 CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID)); 3871 } 3872 3873 return TRUE; 3874 } 3875 3876 } 3877 } 3878 3879 3880 dwIndex = 0; 3881 do 3882 { 3883 Buffer[0] = 0; 3884 dwKeyName = sizeof(Buffer) / sizeof(WCHAR); 3885 dwError = RegEnumKeyExW(hKey, dwIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL); 3886 3887 if (dwError != ERROR_SUCCESS) 3888 break; 3889 3890 if (RegOpenKeyExW(hKey, Buffer, 0, KEY_READ, &hDevKey) != ERROR_SUCCESS) 3891 break; 3892 3893 dwSubIndex = 0; 3894 InstancePath[0] = 0; 3895 dwKeyName = sizeof(InstancePath); 3896 3897 dwError = RegQueryValueExW(hDevKey, L"DeviceInstance", NULL, NULL, (LPBYTE)InstancePath, &dwKeyName); 3898 3899 while(TRUE) 3900 { 3901 Buffer[0] = 0; 3902 dwKeyName = sizeof(Buffer) / sizeof(WCHAR); 3903 dwError = RegEnumKeyExW(hDevKey, dwSubIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL); 3904 3905 if (dwError != ERROR_SUCCESS) 3906 break; 3907 3908 dwError = RegOpenKeyExW(hDevKey, Buffer, 0, KEY_READ, &hSymKey); 3909 if (dwError != ERROR_SUCCESS) 3910 break; 3911 3912 /* query for symbolic link */ 3913 dwKeyName = sizeof(SymBuffer); 3914 SymBuffer[0] = L'\0'; 3915 dwError = RegQueryValueExW(hSymKey, L"SymbolicLink", NULL, NULL, (LPBYTE)SymBuffer, &dwKeyName); 3916 3917 if (dwError != ERROR_SUCCESS) 3918 { 3919 RegCloseKey(hSymKey); 3920 break; 3921 } 3922 3923 if (!wcsicmp(SymBuffer, DevicePath)) 3924 { 3925 Ret = CreateDeviceInfo(list, InstancePath, &ClassId, &deviceInfo); 3926 RegCloseKey(hSymKey); 3927 RegCloseKey(hDevKey); 3928 RegCloseKey(hKey); 3929 3930 if (Ret) 3931 { 3932 deviceInterface = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface) + (wcslen(SymBuffer) + 1) * sizeof(WCHAR)); 3933 if (deviceInterface) 3934 { 3935 3936 CopyMemory(&deviceInterface->InterfaceClassGuid, &ClassId, sizeof(GUID)); 3937 deviceInterface->DeviceInfo = deviceInfo; 3938 deviceInterface->Flags = SPINT_ACTIVE; //FIXME 3939 3940 wcscpy(deviceInterface->SymbolicLink, SymBuffer); 3941 3942 InsertTailList(&deviceInfo->InterfaceListHead, &deviceInterface->ListEntry); 3943 InsertTailList(&list->ListHead, &deviceInfo->ListEntry); 3944 3945 3946 if (DeviceInterfaceData) 3947 { 3948 DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface; 3949 DeviceInterfaceData->Flags = deviceInterface->Flags; 3950 CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID)); 3951 } 3952 else 3953 { 3954 Ret = FALSE; 3955 SetLastError(ERROR_INVALID_USER_BUFFER); 3956 } 3957 } 3958 } 3959 else 3960 { 3961 HeapFree(GetProcessHeap(), 0, deviceInfo); 3962 Ret = FALSE; 3963 } 3964 return Ret; 3965 } 3966 RegCloseKey(hSymKey); 3967 dwSubIndex++; 3968 } 3969 3970 RegCloseKey(hDevKey); 3971 dwIndex++; 3972 } while(TRUE); 3973 3974 RegCloseKey(hKey); 3975 return FALSE; 3976 } 3977 3978 /*********************************************************************** 3979 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@) 3980 */ 3981 BOOL WINAPI SetupDiOpenDeviceInterfaceA( 3982 HDEVINFO DeviceInfoSet, 3983 PCSTR DevicePath, 3984 DWORD OpenFlags, 3985 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 3986 { 3987 LPWSTR DevicePathW = NULL; 3988 BOOL bResult; 3989 3990 TRACE("%s(%p %s %08lx %p)\n", __FUNCTION__, DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData); 3991 3992 DevicePathW = pSetupMultiByteToUnicode(DevicePath, CP_ACP); 3993 if (DevicePathW == NULL) 3994 return FALSE; 3995 3996 bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet, 3997 DevicePathW, OpenFlags, DeviceInterfaceData); 3998 3999 MyFree(DevicePathW); 4000 4001 return bResult; 4002 } 4003 4004 /*********************************************************************** 4005 * SetupDiSetClassInstallParamsA (SETUPAPI.@) 4006 */ 4007 BOOL WINAPI SetupDiSetClassInstallParamsA( 4008 HDEVINFO DeviceInfoSet, 4009 PSP_DEVINFO_DATA DeviceInfoData, 4010 PSP_CLASSINSTALL_HEADER ClassInstallParams, 4011 DWORD ClassInstallParamsSize) 4012 { 4013 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData, 4014 ClassInstallParams->InstallFunction, ClassInstallParamsSize); 4015 return FALSE; 4016 } 4017 4018 static BOOL WINAPI 4019 IntSetupDiRegisterDeviceInfo( 4020 IN HDEVINFO DeviceInfoSet, 4021 IN OUT PSP_DEVINFO_DATA DeviceInfoData) 4022 { 4023 return SetupDiRegisterDeviceInfo(DeviceInfoSet, DeviceInfoData, 0, NULL, NULL, NULL); 4024 } 4025 4026 /*********************************************************************** 4027 * SetupDiCallClassInstaller (SETUPAPI.@) 4028 */ 4029 BOOL WINAPI SetupDiCallClassInstaller( 4030 DI_FUNCTION InstallFunction, 4031 HDEVINFO DeviceInfoSet, 4032 PSP_DEVINFO_DATA DeviceInfoData) 4033 { 4034 BOOL ret = FALSE; 4035 4036 TRACE("%s(%u %p %p)\n", __FUNCTION__, InstallFunction, DeviceInfoSet, DeviceInfoData); 4037 4038 if (!DeviceInfoSet) 4039 SetLastError(ERROR_INVALID_PARAMETER); 4040 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 4041 SetLastError(ERROR_INVALID_HANDLE); 4042 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4043 SetLastError(ERROR_INVALID_HANDLE); 4044 else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE) 4045 SetLastError(ERROR_INVALID_HANDLE); 4046 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4047 SetLastError(ERROR_INVALID_USER_BUFFER); 4048 else 4049 { 4050 SP_DEVINSTALL_PARAMS_W InstallParams; 4051 #define CLASS_COINSTALLER 0x1 4052 #define DEVICE_COINSTALLER 0x2 4053 #define CLASS_INSTALLER 0x4 4054 UCHAR CanHandle = 0; 4055 DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL; 4056 4057 switch (InstallFunction) 4058 { 4059 case DIF_ADDPROPERTYPAGE_ADVANCED: 4060 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4061 break; 4062 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED: 4063 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4064 break; 4065 case DIF_ALLOW_INSTALL: 4066 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4067 break; 4068 case DIF_DETECT: 4069 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4070 break; 4071 case DIF_DESTROYPRIVATEDATA: 4072 CanHandle = CLASS_INSTALLER; 4073 break; 4074 case DIF_INSTALLDEVICE: 4075 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4076 DefaultHandler = SetupDiInstallDevice; 4077 break; 4078 case DIF_INSTALLDEVICEFILES: 4079 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4080 DefaultHandler = SetupDiInstallDriverFiles; 4081 break; 4082 case DIF_INSTALLINTERFACES: 4083 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4084 DefaultHandler = SetupDiInstallDeviceInterfaces; 4085 break; 4086 case DIF_NEWDEVICEWIZARD_FINISHINSTALL: 4087 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4088 break; 4089 case DIF_NEWDEVICEWIZARD_POSTANALYZE: 4090 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4091 break; 4092 case DIF_NEWDEVICEWIZARD_PREANALYZE: 4093 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4094 break; 4095 case DIF_NEWDEVICEWIZARD_PRESELECT: 4096 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4097 break; 4098 case DIF_NEWDEVICEWIZARD_SELECT: 4099 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4100 break; 4101 case DIF_POWERMESSAGEWAKE: 4102 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4103 break; 4104 case DIF_PROPERTYCHANGE: 4105 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4106 DefaultHandler = SetupDiChangeState; 4107 break; 4108 case DIF_REGISTER_COINSTALLERS: 4109 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4110 DefaultHandler = SetupDiRegisterCoDeviceInstallers; 4111 break; 4112 case DIF_REGISTERDEVICE: 4113 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4114 DefaultHandler = IntSetupDiRegisterDeviceInfo; 4115 break; 4116 case DIF_REMOVE: 4117 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4118 DefaultHandler = SetupDiRemoveDevice; 4119 break; 4120 case DIF_SELECTBESTCOMPATDRV: 4121 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4122 DefaultHandler = SetupDiSelectBestCompatDrv; 4123 break; 4124 case DIF_SELECTDEVICE: 4125 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 4126 DefaultHandler = SetupDiSelectDevice; 4127 break; 4128 case DIF_TROUBLESHOOTER: 4129 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4130 break; 4131 case DIF_UNREMOVE: 4132 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 4133 DefaultHandler = SetupDiUnremoveDevice; 4134 break; 4135 default: 4136 ERR("Install function %u not supported\n", InstallFunction); 4137 SetLastError(ERROR_NOT_SUPPORTED); 4138 } 4139 4140 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 4141 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams)) 4142 /* Don't process this call, as a parameter is invalid */ 4143 CanHandle = 0; 4144 4145 if (CanHandle != 0) 4146 { 4147 LIST_ENTRY ClassCoInstallersListHead; 4148 LIST_ENTRY DeviceCoInstallersListHead; 4149 HMODULE ClassInstallerLibrary = NULL; 4150 CLASS_INSTALL_PROC ClassInstaller = NULL; 4151 COINSTALLER_CONTEXT_DATA Context; 4152 PLIST_ENTRY ListEntry; 4153 HKEY hKey; 4154 DWORD dwRegType, dwLength; 4155 DWORD rc = NO_ERROR; 4156 4157 InitializeListHead(&ClassCoInstallersListHead); 4158 InitializeListHead(&DeviceCoInstallersListHead); 4159 4160 if (CanHandle & DEVICE_COINSTALLER) 4161 { 4162 hKey = SETUPDI_OpenDrvKey(((struct DeviceInfoSet *)DeviceInfoSet)->HKLM, (struct DeviceInfo *)DeviceInfoData->Reserved, KEY_QUERY_VALUE); 4163 if (hKey != INVALID_HANDLE_VALUE) 4164 { 4165 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, &dwRegType, NULL, &dwLength); 4166 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ) 4167 { 4168 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); 4169 if (KeyBuffer != NULL) 4170 { 4171 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); 4172 if (rc == ERROR_SUCCESS) 4173 { 4174 LPWSTR ptr; 4175 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1) 4176 { 4177 /* Add coinstaller to DeviceCoInstallersListHead list */ 4178 struct CoInstallerElement *coinstaller; 4179 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr)); 4180 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement)); 4181 if (!coinstaller) 4182 continue; 4183 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement)); 4184 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS) 4185 InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry); 4186 else 4187 HeapFree(GetProcessHeap(), 0, coinstaller); 4188 } 4189 } 4190 HeapFree(GetProcessHeap(), 0, KeyBuffer); 4191 } 4192 } 4193 RegCloseKey(hKey); 4194 } 4195 } 4196 if (CanHandle & CLASS_COINSTALLER) 4197 { 4198 rc = RegOpenKeyExW( 4199 HKEY_LOCAL_MACHINE, 4200 REGSTR_PATH_CODEVICEINSTALLERS, 4201 0, /* Options */ 4202 KEY_QUERY_VALUE, 4203 &hKey); 4204 if (rc == ERROR_SUCCESS) 4205 { 4206 WCHAR szGuidString[40]; 4207 if (pSetupStringFromGuid(&DeviceInfoData->ClassGuid, szGuidString, ARRAYSIZE(szGuidString)) == ERROR_SUCCESS) 4208 { 4209 rc = RegQueryValueExW(hKey, szGuidString, NULL, &dwRegType, NULL, &dwLength); 4210 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ) 4211 { 4212 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); 4213 if (KeyBuffer != NULL) 4214 { 4215 rc = RegQueryValueExW(hKey, szGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); 4216 if (rc == ERROR_SUCCESS) 4217 { 4218 LPWSTR ptr; 4219 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1) 4220 { 4221 /* Add coinstaller to ClassCoInstallersListHead list */ 4222 struct CoInstallerElement *coinstaller; 4223 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr)); 4224 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement)); 4225 if (!coinstaller) 4226 continue; 4227 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement)); 4228 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS) 4229 InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry); 4230 else 4231 HeapFree(GetProcessHeap(), 0, coinstaller); 4232 } 4233 } 4234 HeapFree(GetProcessHeap(), 0, KeyBuffer); 4235 } 4236 } 4237 } 4238 RegCloseKey(hKey); 4239 } 4240 } 4241 if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED)) 4242 { 4243 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE); 4244 if (hKey != INVALID_HANDLE_VALUE) 4245 { 4246 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength); 4247 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ) 4248 { 4249 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); 4250 if (KeyBuffer != NULL) 4251 { 4252 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); 4253 if (rc == ERROR_SUCCESS) 4254 { 4255 /* Get ClassInstaller function pointer */ 4256 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer)); 4257 if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS) 4258 { 4259 InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED; 4260 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 4261 } 4262 } 4263 HeapFree(GetProcessHeap(), 0, KeyBuffer); 4264 } 4265 } 4266 RegCloseKey(hKey); 4267 } 4268 } 4269 4270 /* Call Class co-installers */ 4271 Context.PostProcessing = FALSE; 4272 rc = NO_ERROR; 4273 ListEntry = ClassCoInstallersListHead.Flink; 4274 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead) 4275 { 4276 struct CoInstallerElement *coinstaller; 4277 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 4278 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 4279 coinstaller->PrivateData = Context.PrivateData; 4280 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED) 4281 { 4282 coinstaller->DoPostProcessing = TRUE; 4283 rc = NO_ERROR; 4284 } 4285 ListEntry = ListEntry->Flink; 4286 } 4287 4288 /* Call Device co-installers */ 4289 ListEntry = DeviceCoInstallersListHead.Flink; 4290 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead) 4291 { 4292 struct CoInstallerElement *coinstaller; 4293 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 4294 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 4295 coinstaller->PrivateData = Context.PrivateData; 4296 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED) 4297 { 4298 coinstaller->DoPostProcessing = TRUE; 4299 rc = NO_ERROR; 4300 } 4301 ListEntry = ListEntry->Flink; 4302 } 4303 4304 /* Call Class installer */ 4305 if (ClassInstaller) 4306 { 4307 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData); 4308 FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller); 4309 } 4310 else 4311 rc = ERROR_DI_DO_DEFAULT; 4312 4313 /* Call default handler */ 4314 if (rc == ERROR_DI_DO_DEFAULT) 4315 { 4316 if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION)) 4317 { 4318 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData)) 4319 rc = NO_ERROR; 4320 else 4321 rc = GetLastError(); 4322 } 4323 else 4324 rc = NO_ERROR; 4325 } 4326 4327 /* Call Class co-installers that required postprocessing */ 4328 Context.PostProcessing = TRUE; 4329 ListEntry = ClassCoInstallersListHead.Flink; 4330 while (ListEntry != &ClassCoInstallersListHead) 4331 { 4332 struct CoInstallerElement *coinstaller; 4333 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 4334 if (coinstaller->DoPostProcessing) 4335 { 4336 Context.InstallResult = rc; 4337 Context.PrivateData = coinstaller->PrivateData; 4338 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 4339 } 4340 FreeFunctionPointer(coinstaller->Module, coinstaller->Function); 4341 ListEntry = ListEntry->Flink; 4342 } 4343 4344 /* Call Device co-installers that required postprocessing */ 4345 ListEntry = DeviceCoInstallersListHead.Flink; 4346 while (ListEntry != &DeviceCoInstallersListHead) 4347 { 4348 struct CoInstallerElement *coinstaller; 4349 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 4350 if (coinstaller->DoPostProcessing) 4351 { 4352 Context.InstallResult = rc; 4353 Context.PrivateData = coinstaller->PrivateData; 4354 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 4355 } 4356 FreeFunctionPointer(coinstaller->Module, coinstaller->Function); 4357 ListEntry = ListEntry->Flink; 4358 } 4359 4360 /* Free allocated memory */ 4361 while (!IsListEmpty(&ClassCoInstallersListHead)) 4362 { 4363 ListEntry = RemoveHeadList(&ClassCoInstallersListHead); 4364 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry)); 4365 } 4366 while (!IsListEmpty(&DeviceCoInstallersListHead)) 4367 { 4368 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead); 4369 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry)); 4370 } 4371 4372 ret = (rc == NO_ERROR); 4373 } 4374 } 4375 4376 TRACE("Returning %d\n", ret); 4377 return ret; 4378 } 4379 4380 /*********************************************************************** 4381 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@) 4382 */ 4383 BOOL WINAPI SetupDiGetDeviceInstallParamsA( 4384 HDEVINFO DeviceInfoSet, 4385 PSP_DEVINFO_DATA DeviceInfoData, 4386 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams) 4387 { 4388 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW; 4389 BOOL ret = FALSE; 4390 4391 TRACE("%s(%p %p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 4392 4393 if (DeviceInstallParams == NULL) 4394 SetLastError(ERROR_INVALID_PARAMETER); 4395 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A)) 4396 SetLastError(ERROR_INVALID_USER_BUFFER); 4397 else 4398 { 4399 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 4400 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW); 4401 4402 if (ret) 4403 { 4404 /* Do W->A conversion */ 4405 memcpy( 4406 DeviceInstallParams, 4407 &deviceInstallParamsW, 4408 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath)); 4409 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1, 4410 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0) 4411 { 4412 DeviceInstallParams->DriverPath[0] = '\0'; 4413 ret = FALSE; 4414 } 4415 } 4416 } 4417 4418 TRACE("Returning %d\n", ret); 4419 return ret; 4420 } 4421 4422 /*********************************************************************** 4423 * SetupDiGetDeviceInfoListClass (SETUPAPI.@) 4424 */ 4425 BOOL WINAPI 4426 SetupDiGetDeviceInfoListClass( 4427 IN HDEVINFO DeviceInfoSet, 4428 OUT LPGUID ClassGuid) 4429 { 4430 struct DeviceInfoSet *list; 4431 BOOL ret = FALSE; 4432 4433 TRACE("%s(%p %p)\n", __FUNCTION__, DeviceInfoSet, ClassGuid); 4434 4435 if (!DeviceInfoSet) 4436 SetLastError(ERROR_INVALID_HANDLE); 4437 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4438 SetLastError(ERROR_INVALID_HANDLE); 4439 else if (IsEqualIID(&list->ClassGuid, &GUID_NULL)) 4440 SetLastError(ERROR_NO_ASSOCIATED_CLASS); 4441 else 4442 { 4443 *ClassGuid = list->ClassGuid; 4444 4445 ret = TRUE; 4446 } 4447 4448 TRACE("Returning %d\n", ret); 4449 return ret; 4450 } 4451 4452 /*********************************************************************** 4453 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@) 4454 */ 4455 BOOL WINAPI 4456 SetupDiGetDeviceInstallParamsW( 4457 IN HDEVINFO DeviceInfoSet, 4458 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 4459 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams) 4460 { 4461 struct DeviceInfoSet *list; 4462 BOOL ret = FALSE; 4463 4464 TRACE("%s(%p %p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 4465 4466 if (!DeviceInfoSet) 4467 SetLastError(ERROR_INVALID_HANDLE); 4468 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4469 SetLastError(ERROR_INVALID_HANDLE); 4470 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4471 SetLastError(ERROR_INVALID_USER_BUFFER); 4472 else if (!DeviceInstallParams) 4473 SetLastError(ERROR_INVALID_PARAMETER); 4474 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W)) 4475 SetLastError(ERROR_INVALID_USER_BUFFER); 4476 else 4477 { 4478 PSP_DEVINSTALL_PARAMS_W Source; 4479 4480 if (DeviceInfoData) 4481 Source = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams; 4482 else 4483 Source = &list->InstallParams; 4484 4485 ret = TRUE; 4486 4487 _SEH2_TRY 4488 { 4489 memcpy(DeviceInstallParams, Source, Source->cbSize); 4490 } 4491 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 4492 { 4493 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); 4494 ret = FALSE; 4495 } 4496 _SEH2_END; 4497 } 4498 4499 TRACE("Returning %d\n", ret); 4500 return ret; 4501 } 4502 4503 static BOOL 4504 CheckDeviceInstallParameters( 4505 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams) 4506 { 4507 DWORD SupportedFlags = 4508 DI_NOVCP | /* 0x00000008 */ 4509 DI_DIDCOMPAT | /* 0x00000010 */ 4510 DI_DIDCLASS | /* 0x00000020 */ 4511 DI_NEEDRESTART | /* 0x00000080 */ 4512 DI_NEEDREBOOT | /* 0x00000100 */ 4513 DI_RESOURCEPAGE_ADDED | /* 0x00002000 */ 4514 DI_PROPERTIES_CHANGE | /* 0x00004000 */ 4515 DI_ENUMSINGLEINF | /* 0x00010000 */ 4516 DI_DONOTCALLCONFIGMG | /* 0x00020000 */ 4517 DI_CLASSINSTALLPARAMS | /* 0x00100000 */ 4518 DI_NODI_DEFAULTACTION | /* 0x00200000 */ 4519 DI_QUIETINSTALL | /* 0x00800000 */ 4520 DI_NOFILECOPY | /* 0x01000000 */ 4521 DI_DRIVERPAGE_ADDED; /* 0x04000000 */ 4522 DWORD SupportedFlagsEx = 4523 DI_FLAGSEX_CI_FAILED | /* 0x00000004 */ 4524 DI_FLAGSEX_DIDINFOLIST | /* 0x00000010 */ 4525 DI_FLAGSEX_DIDCOMPATINFO | /* 0x00000020 */ 4526 DI_FLAGSEX_ALLOWEXCLUDEDDRVS | /* 0x00000800 */ 4527 DI_FLAGSEX_NO_DRVREG_MODIFY | /* 0x00008000 */ 4528 DI_FLAGSEX_INSTALLEDDRIVER; /* 0x04000000 */ 4529 BOOL ret = FALSE; 4530 4531 /* FIXME: add support for more flags */ 4532 4533 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used. 4534 * It should be checked before accessing to other values 4535 * of the SP_DEVINSTALL_PARAMS structure */ 4536 4537 if (DeviceInstallParams->Flags & ~SupportedFlags) 4538 { 4539 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams->Flags & ~SupportedFlags); 4540 SetLastError(ERROR_INVALID_FLAGS); 4541 } 4542 else if (DeviceInstallParams->FlagsEx & ~SupportedFlagsEx) 4543 { 4544 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams->FlagsEx & ~SupportedFlagsEx); 4545 SetLastError(ERROR_INVALID_FLAGS); 4546 } 4547 else if ((DeviceInstallParams->Flags & DI_NOVCP) 4548 && (DeviceInstallParams->FileQueue == NULL || DeviceInstallParams->FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE)) 4549 SetLastError(ERROR_INVALID_USER_BUFFER); 4550 else 4551 { 4552 /* FIXME: check Reserved field */ 4553 ret = TRUE; 4554 } 4555 4556 return ret; 4557 } 4558 4559 /*********************************************************************** 4560 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@) 4561 */ 4562 BOOL WINAPI 4563 SetupDiSetDeviceInstallParamsW( 4564 IN HDEVINFO DeviceInfoSet, 4565 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 4566 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams) 4567 { 4568 struct DeviceInfoSet *list; 4569 BOOL ret = FALSE; 4570 4571 TRACE("%s(%p %p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 4572 4573 if (!DeviceInfoSet) 4574 SetLastError(ERROR_INVALID_HANDLE); 4575 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4576 SetLastError(ERROR_INVALID_HANDLE); 4577 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4578 SetLastError(ERROR_INVALID_USER_BUFFER); 4579 else if (!DeviceInstallParams) 4580 SetLastError(ERROR_INVALID_PARAMETER); 4581 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W)) 4582 SetLastError(ERROR_INVALID_USER_BUFFER); 4583 else if (CheckDeviceInstallParameters(DeviceInstallParams)) 4584 { 4585 PSP_DEVINSTALL_PARAMS_W Destination; 4586 4587 if (DeviceInfoData) 4588 Destination = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams; 4589 else 4590 Destination = &list->InstallParams; 4591 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize); 4592 ret = TRUE; 4593 } 4594 4595 TRACE("Returning %d\n", ret); 4596 return ret; 4597 } 4598 4599 /*********************************************************************** 4600 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@) 4601 */ 4602 BOOL WINAPI 4603 SetupDiSetDeviceInstallParamsA( 4604 HDEVINFO DeviceInfoSet, 4605 PSP_DEVINFO_DATA DeviceInfoData, 4606 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams) 4607 { 4608 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW; 4609 int len = 0; 4610 BOOL ret = FALSE; 4611 4612 TRACE("%s(%p %p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 4613 4614 if (DeviceInstallParams == NULL) 4615 SetLastError(ERROR_INVALID_PARAMETER); 4616 else if (DeviceInstallParams->cbSize < sizeof(SP_DEVINSTALL_PARAMS_A)) 4617 SetLastError(ERROR_INVALID_USER_BUFFER); 4618 else 4619 { 4620 memcpy(&deviceInstallParamsW, DeviceInstallParams, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A, DriverPath)); 4621 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 4622 len = MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, NULL, 0); 4623 if (!len) 4624 { 4625 ERR("DrivePath is NULL\n"); 4626 ret = FALSE; 4627 } 4628 else 4629 { 4630 MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, deviceInstallParamsW.DriverPath, len); 4631 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW); 4632 } 4633 } 4634 4635 TRACE("Returning %d\n", ret); 4636 return ret; 4637 } 4638 4639 static HKEY 4640 OpenHardwareProfileKey( 4641 IN HKEY HKLM, 4642 IN DWORD HwProfile, 4643 IN DWORD samDesired) 4644 { 4645 HKEY hHWProfilesKey = NULL; 4646 HKEY hHWProfileKey = NULL; 4647 HKEY ret = INVALID_HANDLE_VALUE; 4648 LONG rc; 4649 4650 rc = RegOpenKeyExW(HKLM, 4651 REGSTR_PATH_HWPROFILES, 4652 0, 4653 READ_CONTROL, 4654 &hHWProfilesKey); 4655 if (rc != ERROR_SUCCESS) 4656 { 4657 SetLastError(rc); 4658 goto cleanup; 4659 } 4660 if (HwProfile == 0) 4661 { 4662 rc = RegOpenKeyExW(hHWProfilesKey, 4663 REGSTR_KEY_CURRENT, 4664 0, 4665 KEY_CREATE_SUB_KEY, 4666 &hHWProfileKey); 4667 } 4668 else 4669 { 4670 WCHAR subKey[5]; 4671 snprintfW(subKey, 4, InstanceKeyFormat, HwProfile); 4672 subKey[4] = '\0'; 4673 rc = RegOpenKeyExW(hHWProfilesKey, 4674 subKey, 4675 0, 4676 KEY_CREATE_SUB_KEY, 4677 &hHWProfileKey); 4678 } 4679 if (rc != ERROR_SUCCESS) 4680 { 4681 SetLastError(rc); 4682 goto cleanup; 4683 } 4684 ret = hHWProfileKey; 4685 4686 cleanup: 4687 if (hHWProfilesKey != NULL) 4688 RegCloseKey(hHWProfilesKey); 4689 if (hHWProfileKey != NULL && hHWProfileKey != ret) 4690 RegCloseKey(hHWProfileKey); 4691 return ret; 4692 } 4693 4694 static BOOL 4695 IsDeviceInfoInDeviceInfoSet( 4696 struct DeviceInfoSet *deviceInfoSet, 4697 struct DeviceInfo *deviceInfo) 4698 { 4699 PLIST_ENTRY ListEntry; 4700 4701 ListEntry = deviceInfoSet->ListHead.Flink; 4702 while (ListEntry != &deviceInfoSet->ListHead) 4703 { 4704 if (deviceInfo == CONTAINING_RECORD(ListEntry, struct DeviceInfo, ListEntry)) 4705 return TRUE; 4706 4707 ListEntry = ListEntry->Flink; 4708 } 4709 4710 return FALSE; 4711 } 4712 4713 /*********************************************************************** 4714 * SetupDiDeleteDeviceInfo (SETUPAPI.@) 4715 */ 4716 BOOL WINAPI 4717 SetupDiDeleteDeviceInfo( 4718 IN HDEVINFO DeviceInfoSet, 4719 IN PSP_DEVINFO_DATA DeviceInfoData) 4720 { 4721 struct DeviceInfoSet *deviceInfoSet; 4722 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData; 4723 BOOL ret = FALSE; 4724 4725 TRACE("%s(%p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData); 4726 4727 if (!DeviceInfoSet) 4728 SetLastError(ERROR_INVALID_HANDLE); 4729 else if ((deviceInfoSet = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4730 SetLastError(ERROR_INVALID_HANDLE); 4731 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4732 SetLastError(ERROR_INVALID_USER_BUFFER); 4733 else if (!IsDeviceInfoInDeviceInfoSet(deviceInfoSet, deviceInfo)) 4734 SetLastError(ERROR_INVALID_PARAMETER); 4735 else 4736 { 4737 RemoveEntryList(&deviceInfo->ListEntry); 4738 DestroyDeviceInfo(deviceInfo); 4739 ret = TRUE; 4740 } 4741 4742 return ret; 4743 } 4744 4745 4746 /*********************************************************************** 4747 * SetupDiOpenDeviceInfoA (SETUPAPI.@) 4748 */ 4749 BOOL WINAPI 4750 SetupDiOpenDeviceInfoA( 4751 IN HDEVINFO DeviceInfoSet, 4752 IN PCSTR DeviceInstanceId, 4753 IN HWND hwndParent OPTIONAL, 4754 IN DWORD OpenFlags, 4755 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 4756 { 4757 LPWSTR DeviceInstanceIdW = NULL; 4758 BOOL bResult; 4759 4760 TRACE("%s(%p %s %p %lx %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData); 4761 4762 DeviceInstanceIdW = pSetupMultiByteToUnicode(DeviceInstanceId, CP_ACP); 4763 if (DeviceInstanceIdW == NULL) 4764 return FALSE; 4765 4766 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet, 4767 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData); 4768 4769 MyFree(DeviceInstanceIdW); 4770 4771 return bResult; 4772 } 4773 4774 4775 /*********************************************************************** 4776 * SetupDiOpenDeviceInfoW (SETUPAPI.@) 4777 */ 4778 BOOL WINAPI 4779 SetupDiOpenDeviceInfoW( 4780 IN HDEVINFO DeviceInfoSet, 4781 IN PCWSTR DeviceInstanceId, 4782 IN HWND hwndParent OPTIONAL, 4783 IN DWORD OpenFlags, 4784 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 4785 { 4786 struct DeviceInfoSet *list; 4787 HKEY hEnumKey, hKey = NULL; 4788 DWORD rc, dwSize; 4789 BOOL ret = FALSE; 4790 4791 TRACE("%s(%p %s %p %lx %p)\n", __FUNCTION__, 4792 DeviceInfoSet, debugstr_w(DeviceInstanceId), 4793 hwndParent, OpenFlags, DeviceInfoData); 4794 4795 if (OpenFlags & DIOD_CANCEL_REMOVE) 4796 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n"); 4797 4798 if (!DeviceInfoSet) 4799 SetLastError(ERROR_INVALID_HANDLE); 4800 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4801 SetLastError(ERROR_INVALID_HANDLE); 4802 else if (!DeviceInstanceId) 4803 SetLastError(ERROR_INVALID_PARAMETER); 4804 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS)) 4805 { 4806 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS)); 4807 SetLastError(ERROR_INVALID_FLAGS); 4808 } 4809 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4810 SetLastError(ERROR_INVALID_USER_BUFFER); 4811 else 4812 { 4813 struct DeviceInfo *deviceInfo = NULL; 4814 /* Search if device already exists in DeviceInfoSet. 4815 * If yes, return the existing element 4816 * If no, create a new element using information in registry 4817 */ 4818 PLIST_ENTRY ItemList = list->ListHead.Flink; 4819 while (ItemList != &list->ListHead) 4820 { 4821 deviceInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry); 4822 if (!wcscmp(deviceInfo->instanceId, DeviceInstanceId)) 4823 break; 4824 deviceInfo = NULL; 4825 ItemList = ItemList->Flink; 4826 } 4827 4828 if (deviceInfo) 4829 { 4830 /* good one found */ 4831 ret = TRUE; 4832 } 4833 else 4834 { 4835 GUID ClassGUID; 4836 WCHAR szClassGuid[MAX_GUID_STRING_LEN]; 4837 4838 /* Open supposed registry key */ 4839 rc = RegOpenKeyExW( 4840 list->HKLM, 4841 REGSTR_PATH_SYSTEMENUM, 4842 0, /* Options */ 4843 READ_CONTROL, 4844 &hEnumKey); 4845 if (rc != ERROR_SUCCESS) 4846 { 4847 SetLastError(rc); 4848 goto cleanup; 4849 } 4850 rc = RegOpenKeyExW( 4851 hEnumKey, 4852 DeviceInstanceId, 4853 0, /* Options */ 4854 KEY_QUERY_VALUE, 4855 &hKey); 4856 RegCloseKey(hEnumKey); 4857 if (rc != ERROR_SUCCESS) 4858 { 4859 if (rc == ERROR_FILE_NOT_FOUND) 4860 rc = ERROR_NO_SUCH_DEVINST; 4861 SetLastError(rc); 4862 goto cleanup; 4863 } 4864 4865 ClassGUID = GUID_NULL; 4866 dwSize = MAX_GUID_STRING_LEN * sizeof(WCHAR); 4867 4868 if (RegQueryValueExW(hKey, 4869 REGSTR_VAL_CLASSGUID, 4870 NULL, 4871 NULL, 4872 (LPBYTE)szClassGuid, 4873 &dwSize) == ERROR_SUCCESS) 4874 { 4875 szClassGuid[MAX_GUID_STRING_LEN - 2] = UNICODE_NULL; 4876 4877 /* Convert a string to a ClassGuid */ 4878 UuidFromStringW(&szClassGuid[1], &ClassGUID); 4879 } 4880 4881 if (!CreateDeviceInfo(list, DeviceInstanceId, &ClassGUID, &deviceInfo)) 4882 goto cleanup; 4883 4884 InsertTailList(&list->ListHead, &deviceInfo->ListEntry); 4885 4886 ret = TRUE; 4887 } 4888 4889 if (ret && deviceInfo && DeviceInfoData) 4890 { 4891 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID)); 4892 DeviceInfoData->DevInst = deviceInfo->dnDevInst; 4893 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo; 4894 } 4895 } 4896 4897 cleanup: 4898 if (hKey != NULL) 4899 RegCloseKey(hKey); 4900 return ret; 4901 } 4902 4903 4904 /*********************************************************************** 4905 * SetupDiGetSelectedDevice (SETUPAPI.@) 4906 */ 4907 BOOL WINAPI 4908 SetupDiGetSelectedDevice( 4909 IN HDEVINFO DeviceInfoSet, 4910 OUT PSP_DEVINFO_DATA DeviceInfoData) 4911 { 4912 struct DeviceInfoSet *list; 4913 BOOL ret = FALSE; 4914 4915 TRACE("%s(%p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData); 4916 4917 if (!DeviceInfoSet) 4918 SetLastError(ERROR_INVALID_HANDLE); 4919 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4920 SetLastError(ERROR_INVALID_HANDLE); 4921 else if (list->SelectedDevice == NULL) 4922 SetLastError(ERROR_NO_DEVICE_SELECTED); 4923 else if (!DeviceInfoData) 4924 SetLastError(ERROR_INVALID_PARAMETER); 4925 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4926 SetLastError(ERROR_INVALID_USER_BUFFER); 4927 else 4928 { 4929 memcpy(&DeviceInfoData->ClassGuid, 4930 &list->SelectedDevice->ClassGuid, 4931 sizeof(GUID)); 4932 DeviceInfoData->DevInst = list->SelectedDevice->dnDevInst; 4933 DeviceInfoData->Reserved = (ULONG_PTR)list->SelectedDevice; 4934 ret = TRUE; 4935 } 4936 4937 TRACE("Returning %d\n", ret); 4938 return ret; 4939 } 4940 4941 4942 /*********************************************************************** 4943 * SetupDiSetSelectedDevice (SETUPAPI.@) 4944 */ 4945 BOOL WINAPI 4946 SetupDiSetSelectedDevice( 4947 IN HDEVINFO DeviceInfoSet, 4948 IN PSP_DEVINFO_DATA DeviceInfoData) 4949 { 4950 struct DeviceInfoSet *list; 4951 BOOL ret = FALSE; 4952 4953 TRACE("%s(%p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData); 4954 4955 if (!DeviceInfoSet) 4956 SetLastError(ERROR_INVALID_HANDLE); 4957 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 4958 SetLastError(ERROR_INVALID_HANDLE); 4959 else if (!DeviceInfoData) 4960 SetLastError(ERROR_INVALID_PARAMETER); 4961 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 4962 SetLastError(ERROR_INVALID_USER_BUFFER); 4963 else if (DeviceInfoData->Reserved == 0) 4964 SetLastError(ERROR_INVALID_USER_BUFFER); 4965 else 4966 { 4967 list->SelectedDevice = (struct DeviceInfo *)DeviceInfoData->Reserved; 4968 ret = TRUE; 4969 } 4970 4971 TRACE("Returning %d\n", ret); 4972 return ret; 4973 } 4974 4975 4976 /* Return the current hardware profile id, or -1 if error */ 4977 static DWORD 4978 SETUPAPI_GetCurrentHwProfile( 4979 IN HDEVINFO DeviceInfoSet) 4980 { 4981 HKEY hKey = NULL; 4982 DWORD dwRegType, dwLength; 4983 DWORD hwProfile; 4984 LONG rc; 4985 DWORD ret = (DWORD)-1; 4986 4987 rc = RegOpenKeyExW(((struct DeviceInfoSet *)DeviceInfoSet)->HKLM, 4988 REGSTR_PATH_IDCONFIGDB, 4989 0, /* Options */ 4990 KEY_QUERY_VALUE, 4991 &hKey); 4992 if (rc != ERROR_SUCCESS) 4993 { 4994 SetLastError(rc); 4995 goto cleanup; 4996 } 4997 4998 dwLength = sizeof(DWORD); 4999 rc = RegQueryValueExW(hKey, 5000 REGSTR_VAL_CURRENTCONFIG, 5001 NULL, 5002 &dwRegType, 5003 (LPBYTE)&hwProfile, &dwLength); 5004 if (rc != ERROR_SUCCESS) 5005 { 5006 SetLastError(rc); 5007 goto cleanup; 5008 } 5009 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD)) 5010 { 5011 SetLastError(ERROR_GEN_FAILURE); 5012 goto cleanup; 5013 } 5014 5015 ret = hwProfile; 5016 5017 cleanup: 5018 if (hKey != NULL) 5019 RegCloseKey(hKey); 5020 5021 return ret; 5022 } 5023 5024 static BOOL 5025 ResetDevice( 5026 IN HDEVINFO DeviceInfoSet, 5027 IN PSP_DEVINFO_DATA DeviceInfoData) 5028 { 5029 #ifndef __WINESRC__ 5030 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 5031 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 5032 CONFIGRET cr; 5033 5034 cr = CM_Enable_DevNode_Ex(deviceInfo->dnDevInst, 0, set->hMachine); 5035 if (cr != CR_SUCCESS) 5036 { 5037 SetLastError(GetErrorCodeFromCrCode(cr)); 5038 return FALSE; 5039 } 5040 5041 return TRUE; 5042 #else 5043 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData); 5044 return TRUE; 5045 #endif 5046 } 5047 5048 static BOOL 5049 StopDevice( 5050 IN HDEVINFO DeviceInfoSet, 5051 IN PSP_DEVINFO_DATA DeviceInfoData) 5052 { 5053 #ifndef __WINESRC__ 5054 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 5055 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 5056 CONFIGRET cr; 5057 5058 cr = CM_Disable_DevNode_Ex(deviceInfo->dnDevInst, 0, set->hMachine); 5059 if (cr != CR_SUCCESS) 5060 { 5061 SetLastError(GetErrorCodeFromCrCode(cr)); 5062 return FALSE; 5063 } 5064 5065 return TRUE; 5066 #else 5067 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData); 5068 return TRUE; 5069 #endif 5070 } 5071 5072 /*********************************************************************** 5073 * SetupDiChangeState (SETUPAPI.@) 5074 */ 5075 BOOL WINAPI 5076 SetupDiChangeState( 5077 IN HDEVINFO DeviceInfoSet, 5078 IN OUT PSP_DEVINFO_DATA DeviceInfoData) 5079 { 5080 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 5081 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 5082 PSP_PROPCHANGE_PARAMS PropChange; 5083 HKEY hRootKey = INVALID_HANDLE_VALUE, hKey = INVALID_HANDLE_VALUE; 5084 LPCWSTR RegistryValueName; 5085 DWORD dwConfigFlags, dwLength, dwRegType; 5086 LONG rc; 5087 BOOL ret = FALSE; 5088 5089 TRACE("%s(%p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData); 5090 5091 if (!DeviceInfoData) 5092 PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChangeParams; 5093 else 5094 PropChange = ((struct DeviceInfo *)DeviceInfoData->Reserved)->ClassInstallParams.PropChangeParams; 5095 if (!PropChange) 5096 { 5097 SetLastError(ERROR_INVALID_PARAMETER); 5098 goto cleanup; 5099 } 5100 5101 if (PropChange->Scope == DICS_FLAG_GLOBAL) 5102 RegistryValueName = REGSTR_VAL_CONFIGFLAGS; 5103 else 5104 RegistryValueName = REGSTR_VAL_CSCONFIGFLAGS; 5105 5106 switch (PropChange->StateChange) 5107 { 5108 case DICS_ENABLE: 5109 case DICS_DISABLE: 5110 { 5111 if (PropChange->Scope == DICS_FLAG_GLOBAL) 5112 hRootKey = set->HKLM; 5113 else /* PropChange->Scope == DICS_FLAG_CONFIGSPECIFIC */ 5114 { 5115 hRootKey = OpenHardwareProfileKey(set->HKLM, PropChange->HwProfile, KEY_CREATE_SUB_KEY); 5116 if (hRootKey == INVALID_HANDLE_VALUE) 5117 goto cleanup; 5118 } 5119 5120 /* Enable/disable device in registry */ 5121 hKey = SETUPDI_OpenDrvKey(hRootKey, deviceInfo, KEY_QUERY_VALUE | KEY_SET_VALUE); 5122 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) 5123 hKey = SETUPDI_CreateDevKey(hRootKey, deviceInfo, KEY_QUERY_VALUE | KEY_SET_VALUE); 5124 if (hKey == INVALID_HANDLE_VALUE) 5125 break; 5126 dwLength = sizeof(DWORD); 5127 rc = RegQueryValueExW( 5128 hKey, 5129 RegistryValueName, 5130 NULL, 5131 &dwRegType, 5132 (LPBYTE)&dwConfigFlags, &dwLength); 5133 if (rc == ERROR_FILE_NOT_FOUND) 5134 dwConfigFlags = 0; 5135 else if (rc != ERROR_SUCCESS) 5136 { 5137 SetLastError(rc); 5138 goto cleanup; 5139 } 5140 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD)) 5141 { 5142 SetLastError(ERROR_GEN_FAILURE); 5143 goto cleanup; 5144 } 5145 if (PropChange->StateChange == DICS_ENABLE) 5146 dwConfigFlags &= ~(PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED); 5147 else 5148 dwConfigFlags |= (PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED); 5149 rc = RegSetValueExW( 5150 hKey, 5151 RegistryValueName, 5152 0, 5153 REG_DWORD, 5154 (LPBYTE)&dwConfigFlags, sizeof(DWORD)); 5155 if (rc != ERROR_SUCCESS) 5156 { 5157 SetLastError(rc); 5158 goto cleanup; 5159 } 5160 5161 /* Enable/disable device if needed */ 5162 if (PropChange->Scope == DICS_FLAG_GLOBAL 5163 || PropChange->HwProfile == 0 5164 || PropChange->HwProfile == SETUPAPI_GetCurrentHwProfile(DeviceInfoSet)) 5165 { 5166 if (PropChange->StateChange == DICS_ENABLE) 5167 ret = ResetDevice(DeviceInfoSet, DeviceInfoData); 5168 else 5169 ret = StopDevice(DeviceInfoSet, DeviceInfoData); 5170 } 5171 else 5172 ret = TRUE; 5173 break; 5174 } 5175 case DICS_PROPCHANGE: 5176 { 5177 ret = ResetDevice(DeviceInfoSet, DeviceInfoData); 5178 break; 5179 } 5180 default: 5181 { 5182 ERR("Unknown StateChange 0x%lx\n", PropChange->StateChange); 5183 SetLastError(ERROR_NOT_SUPPORTED); 5184 } 5185 } 5186 5187 cleanup: 5188 if (hRootKey != INVALID_HANDLE_VALUE && hRootKey != set->HKLM) 5189 RegCloseKey(hRootKey); 5190 5191 if (hKey != INVALID_HANDLE_VALUE) 5192 RegCloseKey(hKey); 5193 5194 TRACE("Returning %d\n", ret); 5195 return ret; 5196 } 5197 5198 /*********************************************************************** 5199 * SetupDiSelectDevice (SETUPAPI.@) 5200 */ 5201 BOOL WINAPI 5202 SetupDiSelectDevice( 5203 IN HDEVINFO DeviceInfoSet, 5204 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 5205 { 5206 FIXME("%p %p\n", DeviceInfoSet, DeviceInfoData); 5207 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 5208 return FALSE; 5209 } 5210 5211 5212 /*********************************************************************** 5213 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@) 5214 */ 5215 BOOL WINAPI 5216 SetupDiRegisterCoDeviceInstallers( 5217 IN HDEVINFO DeviceInfoSet, 5218 IN PSP_DEVINFO_DATA DeviceInfoData) 5219 { 5220 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 5221 struct DeviceInfo *deviceInfo; 5222 BOOL ret = FALSE; /* Return value */ 5223 5224 TRACE("%s(%p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData); 5225 5226 if (!DeviceInfoSet) 5227 SetLastError(ERROR_INVALID_PARAMETER); 5228 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 5229 SetLastError(ERROR_INVALID_HANDLE); 5230 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5231 SetLastError(ERROR_INVALID_HANDLE); 5232 else if (!DeviceInfoData) 5233 SetLastError(ERROR_INVALID_PARAMETER); 5234 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 5235 SetLastError(ERROR_INVALID_USER_BUFFER); 5236 else 5237 { 5238 SP_DEVINSTALL_PARAMS_W InstallParams; 5239 struct DriverInfoElement *SelectedDriver; 5240 BOOL Result; 5241 DWORD DoAction; 5242 WCHAR SectionName[MAX_PATH]; 5243 DWORD SectionNameLength = 0; 5244 HKEY hKey = INVALID_HANDLE_VALUE; 5245 PVOID Context = NULL; 5246 5247 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 5248 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 5249 if (!Result) 5250 goto cleanup; 5251 5252 SelectedDriver = (struct DriverInfoElement *)InstallParams.ClassInstallReserved; 5253 if (SelectedDriver == NULL) 5254 { 5255 SetLastError(ERROR_NO_DRIVER_SELECTED); 5256 goto cleanup; 5257 } 5258 5259 /* Get .CoInstallers section name */ 5260 Result = SetupDiGetActualSectionToInstallW( 5261 SelectedDriver->InfFileDetails->hInf, 5262 SelectedDriver->Details.SectionName, 5263 SectionName, MAX_PATH, &SectionNameLength, NULL); 5264 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotCoInstallers) - 1) 5265 goto cleanup; 5266 lstrcatW(SectionName, DotCoInstallers); 5267 5268 deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 5269 5270 /* Open/Create driver key information */ 5271 #if _WIN32_WINNT >= 0x502 5272 hKey = SETUPDI_OpenDrvKey(set->HKLM, deviceInfo, KEY_READ | KEY_WRITE); 5273 #else 5274 hKey = SETUPDI_OpenDrvKey(set->HKLM, deviceInfo, KEY_ALL_ACCESS); 5275 #endif 5276 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) 5277 #if _WIN32_WINNT >= 0x502 5278 hKey = SETUPDI_CreateDrvKey(set->HKLM, deviceInfo, (UUID*)&DeviceInfoData->ClassGuid, KEY_READ | KEY_WRITE); 5279 #else 5280 hKey = SETUPDI_CreateDrvKey(set->HKLM, deviceInfo, (UUID*)&DeviceInfoData->ClassGuid, KEY_ALL_ACCESS); 5281 #endif 5282 if (hKey == INVALID_HANDLE_VALUE) 5283 goto cleanup; 5284 5285 /* Install .CoInstallers section */ 5286 DoAction = SPINST_REGISTRY; 5287 if (!(InstallParams.Flags & DI_NOFILECOPY)) 5288 { 5289 DoAction |= SPINST_FILES; 5290 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent); 5291 if (!Context) 5292 goto cleanup; 5293 } 5294 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent, 5295 SelectedDriver->InfFileDetails->hInf, SectionName, 5296 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, 5297 SetupDefaultQueueCallbackW, Context, 5298 DeviceInfoSet, DeviceInfoData); 5299 if (!Result) 5300 goto cleanup; 5301 5302 ret = TRUE; 5303 5304 cleanup: 5305 if (Context) 5306 SetupTermDefaultQueueCallback(Context); 5307 if (hKey != INVALID_HANDLE_VALUE) 5308 RegCloseKey(hKey); 5309 } 5310 5311 TRACE("Returning %d\n", ret); 5312 return ret; 5313 } 5314 5315 static BOOL 5316 InfIsFromOEMLocation( 5317 IN PCWSTR FullName, 5318 OUT LPBOOL IsOEMLocation) 5319 { 5320 PWCHAR last; 5321 5322 last = strrchrW(FullName, '\\'); 5323 if (!last) 5324 { 5325 /* No directory specified */ 5326 *IsOEMLocation = FALSE; 5327 } 5328 else 5329 { 5330 LPWSTR Windir; 5331 UINT ret; 5332 5333 Windir = MyMalloc((MAX_PATH + 1 + strlenW(InfDirectory)) * sizeof(WCHAR)); 5334 if (!Windir) 5335 { 5336 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 5337 return FALSE; 5338 } 5339 5340 ret = GetSystemWindowsDirectoryW(Windir, MAX_PATH); 5341 if (ret == 0 || ret > MAX_PATH) 5342 { 5343 MyFree(Windir); 5344 SetLastError(ERROR_GEN_FAILURE); 5345 return FALSE; 5346 } 5347 if (*Windir && Windir[strlenW(Windir) - 1] != '\\') 5348 strcatW(Windir, BackSlash); 5349 strcatW(Windir, InfDirectory); 5350 5351 if (strncmpiW(FullName, Windir, last - FullName) == 0) 5352 { 5353 /* The path is %SYSTEMROOT%\Inf */ 5354 *IsOEMLocation = FALSE; 5355 } 5356 else 5357 { 5358 /* The file is in another place */ 5359 *IsOEMLocation = TRUE; 5360 } 5361 MyFree(Windir); 5362 } 5363 return TRUE; 5364 } 5365 5366 /*********************************************************************** 5367 * SetupDiInstallDevice (SETUPAPI.@) 5368 */ 5369 BOOL WINAPI 5370 SetupDiInstallDevice( 5371 IN HDEVINFO DeviceInfoSet, 5372 IN OUT PSP_DEVINFO_DATA DeviceInfoData) 5373 { 5374 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 5375 struct DeviceInfo *deviceInfo; 5376 SP_DEVINSTALL_PARAMS_W InstallParams; 5377 struct DriverInfoElement *SelectedDriver; 5378 SYSTEMTIME DriverDate; 5379 WCHAR SectionName[MAX_PATH]; 5380 WCHAR Buffer[32]; 5381 DWORD SectionNameLength = 0; 5382 BOOL Result = FALSE; 5383 ULONG DoAction; 5384 DWORD RequiredSize; 5385 LPWSTR pSectionName = NULL; 5386 WCHAR ClassName[MAX_CLASS_NAME_LEN]; 5387 GUID ClassGuid; 5388 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL; 5389 BOOL RebootRequired = FALSE; 5390 HKEY hKey = INVALID_HANDLE_VALUE; 5391 BOOL NeedtoCopyFile; 5392 LARGE_INTEGER fullVersion; 5393 LONG rc; 5394 PVOID Context = NULL; 5395 BOOL ret = FALSE; /* Return value */ 5396 5397 TRACE("%s(%p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData); 5398 5399 if (!DeviceInfoSet) 5400 SetLastError(ERROR_INVALID_PARAMETER); 5401 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 5402 SetLastError(ERROR_INVALID_HANDLE); 5403 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5404 SetLastError(ERROR_INVALID_HANDLE); 5405 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 5406 SetLastError(ERROR_INVALID_USER_BUFFER); 5407 else 5408 Result = TRUE; 5409 5410 if (!Result) 5411 { 5412 /* One parameter is bad */ 5413 goto cleanup; 5414 } 5415 5416 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 5417 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 5418 if (!Result) 5419 goto cleanup; 5420 5421 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL) 5422 { 5423 /* Set FAILEDINSTALL in ConfigFlags registry value */ 5424 DWORD ConfigFlags, regType; 5425 Result = SetupDiGetDeviceRegistryPropertyW( 5426 DeviceInfoSet, 5427 DeviceInfoData, 5428 SPDRP_CONFIGFLAGS, 5429 ®Type, 5430 (PBYTE)&ConfigFlags, 5431 sizeof(ConfigFlags), 5432 NULL); 5433 if (!Result || regType != REG_DWORD) 5434 { 5435 SetLastError(ERROR_GEN_FAILURE); 5436 goto cleanup; 5437 } 5438 ConfigFlags |= CONFIGFLAG_FAILEDINSTALL; 5439 Result = SetupDiSetDeviceRegistryPropertyW( 5440 DeviceInfoSet, 5441 DeviceInfoData, 5442 SPDRP_CONFIGFLAGS, 5443 (PBYTE)&ConfigFlags, 5444 sizeof(ConfigFlags)); 5445 if (!Result) 5446 { 5447 SetLastError(ERROR_GEN_FAILURE); 5448 goto cleanup; 5449 } 5450 5451 ret = TRUE; 5452 goto cleanup; 5453 } 5454 5455 SelectedDriver = (struct DriverInfoElement *)InstallParams.ClassInstallReserved; 5456 if (SelectedDriver == NULL) 5457 { 5458 SetLastError(ERROR_NO_DRIVER_SELECTED); 5459 goto cleanup; 5460 } 5461 5462 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate); 5463 5464 Result = SetupDiGetActualSectionToInstallW( 5465 SelectedDriver->InfFileDetails->hInf, 5466 SelectedDriver->Details.SectionName, 5467 SectionName, MAX_PATH, &SectionNameLength, NULL); 5468 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotServices)) 5469 goto cleanup; 5470 pSectionName = &SectionName[strlenW(SectionName)]; 5471 5472 /* Get information from [Version] section */ 5473 if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize)) 5474 goto cleanup; 5475 /* Format ClassGuid to a string */ 5476 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK) 5477 goto cleanup; 5478 RequiredSize = lstrlenW(lpGuidString); 5479 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR)); 5480 if (!lpFullGuidString) 5481 { 5482 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 5483 goto cleanup; 5484 } 5485 lpFullGuidString[0] = '{'; 5486 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR)); 5487 lpFullGuidString[RequiredSize + 1] = '}'; 5488 lpFullGuidString[RequiredSize + 2] = '\0'; 5489 5490 /* Copy .inf file to Inf\ directory (if needed) */ 5491 Result = InfIsFromOEMLocation(SelectedDriver->Details.InfFileName, &NeedtoCopyFile); 5492 if (!Result) 5493 goto cleanup; 5494 if (NeedtoCopyFile) 5495 { 5496 WCHAR NewFileName[MAX_PATH]; 5497 struct InfFileDetails *newInfFileDetails; 5498 Result = SetupCopyOEMInfW( 5499 SelectedDriver->Details.InfFileName, 5500 NULL, 5501 SPOST_NONE, 5502 SP_COPY_NOOVERWRITE, 5503 NewFileName, MAX_PATH, 5504 NULL, 5505 NULL); 5506 if (!Result && GetLastError() != ERROR_FILE_EXISTS) 5507 goto cleanup; 5508 /* Create a new struct InfFileDetails, and set it to 5509 * SelectedDriver->InfFileDetails, to release use of 5510 * current InfFile */ 5511 newInfFileDetails = CreateInfFileDetails(NewFileName); 5512 if (!newInfFileDetails) 5513 goto cleanup; 5514 DereferenceInfFile(SelectedDriver->InfFileDetails); 5515 SelectedDriver->InfFileDetails = newInfFileDetails; 5516 strcpyW(SelectedDriver->Details.InfFileName, NewFileName); 5517 } 5518 5519 deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 5520 5521 /* Open/Create driver key information */ 5522 #if _WIN32_WINNT >= 0x502 5523 hKey = SETUPDI_OpenDrvKey(set->HKLM, deviceInfo, KEY_READ | KEY_WRITE); 5524 #else 5525 hKey = SETUPDI_OpenDrvKey(set->HKLM, deviceInfo, KEY_ALL_ACCESS); 5526 #endif 5527 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) 5528 #if _WIN32_WINNT >= 0x502 5529 hKey = SETUPDI_CreateDrvKey(set->HKLM, deviceInfo, (UUID*)&DeviceInfoData->ClassGuid, KEY_READ | KEY_WRITE); 5530 #else 5531 hKey = SETUPDI_CreateDrvKey(set->HKLM, deviceInfo, (UUID*)&DeviceInfoData->ClassGuid, KEY_ALL_ACCESS); 5532 #endif 5533 if (hKey == INVALID_HANDLE_VALUE) 5534 goto cleanup; 5535 5536 /* Install main section */ 5537 DoAction = 0; 5538 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY)) 5539 DoAction |= SPINST_REGISTRY; 5540 if (!(InstallParams.Flags & DI_NOFILECOPY)) 5541 { 5542 DoAction |= SPINST_FILES; 5543 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent); 5544 if (!Context) 5545 goto cleanup; 5546 } 5547 *pSectionName = '\0'; 5548 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent, 5549 SelectedDriver->InfFileDetails->hInf, SectionName, 5550 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, 5551 SetupDefaultQueueCallbackW, Context, 5552 DeviceInfoSet, DeviceInfoData); 5553 if (!Result) 5554 goto cleanup; 5555 InstallParams.Flags |= DI_NOFILECOPY; 5556 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 5557 5558 /* Write information to driver key */ 5559 *pSectionName = UNICODE_NULL; 5560 memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER)); 5561 TRACE("Write information to driver key\n"); 5562 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear); 5563 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description)); 5564 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff); 5565 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver->InfFileDetails->FileName)); 5566 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver->Details.SectionName)); 5567 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName[strlenW(SelectedDriver->Details.SectionName)])); 5568 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver->MatchingId)); 5569 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver->Info.ProviderName)); 5570 sprintfW(Buffer, DateFormat, DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear); 5571 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR)); 5572 if (rc == ERROR_SUCCESS) 5573 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE_DATA, 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME)); 5574 if (rc == ERROR_SUCCESS) 5575 rc = RegSetValueExW(hKey, REGSTR_VAL_DRVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR)); 5576 if (rc == ERROR_SUCCESS) 5577 { 5578 sprintfW(Buffer, VersionFormat, fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff); 5579 rc = RegSetValueExW(hKey, REGSTR_DRIVER_VERSION, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR)); 5580 } 5581 if (rc == ERROR_SUCCESS) 5582 rc = RegSetValueExW(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->InfFileDetails->FileName, (strlenW(SelectedDriver->InfFileDetails->FileName) + 1) * sizeof(WCHAR)); 5583 if (rc == ERROR_SUCCESS) 5584 rc = RegSetValueExW(hKey, REGSTR_VAL_INFSECTION, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR)); 5585 if (rc == ERROR_SUCCESS) 5586 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)); 5587 if (rc == ERROR_SUCCESS) 5588 rc = RegSetValueExW(hKey, REGSTR_VAL_MATCHINGDEVID, 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (strlenW(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR)); 5589 if (rc == ERROR_SUCCESS) 5590 rc = RegSetValueExW(hKey, REGSTR_VAL_PROVIDER_NAME, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (strlenW(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR)); 5591 if (rc != ERROR_SUCCESS) 5592 { 5593 SetLastError(rc); 5594 goto cleanup; 5595 } 5596 RegCloseKey(hKey); 5597 hKey = INVALID_HANDLE_VALUE; 5598 5599 /* FIXME: Process .LogConfigOverride section */ 5600 5601 /* Install .Services section */ 5602 strcpyW(pSectionName, DotServices); 5603 Result = SetupInstallServicesFromInfSectionExW( 5604 SelectedDriver->InfFileDetails->hInf, 5605 SectionName, 5606 0, 5607 DeviceInfoSet, 5608 DeviceInfoData, 5609 NULL, 5610 NULL); 5611 if (!Result) 5612 goto cleanup; 5613 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED) 5614 RebootRequired = TRUE; 5615 5616 /* Open device registry key */ 5617 hKey = SETUPDI_OpenDevKey(((struct DeviceInfoSet *)DeviceInfoSet)->HKLM, (struct DeviceInfo *)DeviceInfoData->Reserved, KEY_SET_VALUE); 5618 if (hKey == INVALID_HANDLE_VALUE) 5619 goto cleanup; 5620 5621 /* Install .HW section */ 5622 DoAction = 0; 5623 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY)) 5624 DoAction |= SPINST_REGISTRY; 5625 strcpyW(pSectionName, DotHW); 5626 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent, 5627 SelectedDriver->InfFileDetails->hInf, SectionName, 5628 DoAction, hKey, NULL, 0, 5629 NULL, NULL, 5630 DeviceInfoSet, DeviceInfoData); 5631 if (!Result) 5632 goto cleanup; 5633 5634 /* Write information to enum key */ 5635 TRACE("Write information to enum key\n"); 5636 TRACE("Class : '%s'\n", debugstr_w(ClassName)); 5637 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString)); 5638 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description)); 5639 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver->Info.MfgName)); 5640 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (strlenW(ClassName) + 1) * sizeof(WCHAR)); 5641 if (rc == ERROR_SUCCESS) 5642 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (strlenW(lpFullGuidString) + 1) * sizeof(WCHAR)); 5643 if (rc == ERROR_SUCCESS) 5644 rc = RegSetValueExW(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR)); 5645 if (rc == ERROR_SUCCESS) 5646 rc = RegSetValueExW(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (strlenW(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR)); 5647 if (rc != ERROR_SUCCESS) 5648 { 5649 SetLastError(rc); 5650 goto cleanup; 5651 } 5652 5653 /* Start the device */ 5654 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG))) 5655 ret = ResetDevice(DeviceInfoSet, DeviceInfoData); 5656 else 5657 ret = TRUE; 5658 5659 cleanup: 5660 /* End of installation */ 5661 if (hKey != INVALID_HANDLE_VALUE) 5662 RegCloseKey(hKey); 5663 if (lpGuidString) 5664 RpcStringFreeW(&lpGuidString); 5665 HeapFree(GetProcessHeap(), 0, lpFullGuidString); 5666 if (Context) 5667 SetupTermDefaultQueueCallback(Context); 5668 TRACE("Returning %d\n", ret); 5669 return ret; 5670 } 5671 5672 HKEY SETUPDI_CreateDevKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired) 5673 { 5674 HKEY enumKey, key = INVALID_HANDLE_VALUE; 5675 LONG l; 5676 5677 l = RegCreateKeyExW(RootKey, REGSTR_PATH_SYSTEMENUM, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &enumKey, NULL); 5678 if (!l) 5679 { 5680 l = RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, REG_OPTION_NON_VOLATILE, samDesired, NULL, &key, NULL); 5681 RegCloseKey(enumKey); 5682 } 5683 if (l) 5684 SetLastError(l); 5685 return key; 5686 } 5687 5688 HKEY SETUPDI_CreateDrvKey(HKEY RootKey, struct DeviceInfo *devInfo, UUID *ClassGuid, REGSAM samDesired) 5689 { 5690 HKEY key = INVALID_HANDLE_VALUE; 5691 LPWSTR lpGuidString = NULL; 5692 LPWSTR DriverKey = NULL; /* {GUID}\Index */ 5693 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */ 5694 DWORD Index; /* Index used in the DriverKey name */ 5695 DWORD dwSize; 5696 DWORD Disposition; 5697 DWORD rc; 5698 HKEY hHWProfileKey = INVALID_HANDLE_VALUE; 5699 HKEY hEnumKey = NULL; 5700 HKEY hClassKey = NULL; 5701 HKEY hDeviceKey = INVALID_HANDLE_VALUE; 5702 HKEY hKey = NULL; 5703 5704 /* Open device key, to read Driver value */ 5705 hDeviceKey = SETUPDI_OpenDevKey(RootKey, devInfo, KEY_QUERY_VALUE | KEY_SET_VALUE); 5706 if (hDeviceKey == INVALID_HANDLE_VALUE) 5707 goto cleanup; 5708 5709 rc = RegOpenKeyExW(RootKey, REGSTR_PATH_CLASS_NT, 0, KEY_CREATE_SUB_KEY, &hClassKey); 5710 if (rc != ERROR_SUCCESS) 5711 { 5712 SetLastError(rc); 5713 goto cleanup; 5714 } 5715 5716 rc = RegQueryValueExW(hDeviceKey, REGSTR_VAL_DRIVER, NULL, NULL, NULL, &dwSize); 5717 if (rc != ERROR_SUCCESS) 5718 { 5719 /* Create a new driver key */ 5720 5721 if (UuidToStringW(ClassGuid, &lpGuidString) != RPC_S_OK) 5722 goto cleanup; 5723 5724 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */ 5725 DriverKey = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); 5726 if (!DriverKey) 5727 { 5728 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 5729 goto cleanup; 5730 } 5731 5732 DriverKey[0] = '{'; 5733 strcpyW(&DriverKey[1], lpGuidString); 5734 pDeviceInstance = &DriverKey[strlenW(DriverKey)]; 5735 *pDeviceInstance++ = '}'; 5736 *pDeviceInstance++ = '\\'; 5737 5738 /* Try all values for Index between 0 and 9999 */ 5739 Index = 0; 5740 while (Index <= 9999) 5741 { 5742 sprintfW(pDeviceInstance, InstanceKeyFormat, Index); 5743 rc = RegCreateKeyExW(hClassKey, 5744 DriverKey, 5745 0, 5746 NULL, 5747 REG_OPTION_NON_VOLATILE, 5748 #if _WIN32_WINNT >= 0x502 5749 KEY_READ | KEY_WRITE, 5750 #else 5751 KEY_ALL_ACCESS, 5752 #endif 5753 NULL, 5754 &hKey, 5755 &Disposition); 5756 if (rc != ERROR_SUCCESS) 5757 { 5758 SetLastError(rc); 5759 goto cleanup; 5760 } 5761 if (Disposition == REG_CREATED_NEW_KEY) 5762 break; 5763 RegCloseKey(hKey); 5764 hKey = NULL; 5765 Index++; 5766 } 5767 5768 if (Index > 9999) 5769 { 5770 /* Unable to create more than 9999 devices within the same class */ 5771 SetLastError(ERROR_GEN_FAILURE); 5772 goto cleanup; 5773 } 5774 5775 /* Write the new Driver value */ 5776 rc = RegSetValueExW(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (strlenW(DriverKey) + 1) * sizeof(WCHAR)); 5777 if (rc != ERROR_SUCCESS) 5778 { 5779 SetLastError(rc); 5780 goto cleanup; 5781 } 5782 } 5783 else 5784 { 5785 /* Open the existing driver key */ 5786 5787 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwSize); 5788 if (!DriverKey) 5789 { 5790 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 5791 goto cleanup; 5792 } 5793 5794 rc = RegQueryValueExW(hDeviceKey, REGSTR_VAL_DRIVER, NULL, NULL, (LPBYTE)DriverKey, &dwSize); 5795 if (rc != ERROR_SUCCESS) 5796 { 5797 SetLastError(rc); 5798 goto cleanup; 5799 } 5800 5801 rc = RegCreateKeyExW(hClassKey, 5802 DriverKey, 5803 0, 5804 NULL, 5805 REG_OPTION_NON_VOLATILE, 5806 #if _WIN32_WINNT >= 0x502 5807 KEY_READ | KEY_WRITE, 5808 #else 5809 KEY_ALL_ACCESS, 5810 #endif 5811 NULL, 5812 &hKey, 5813 &Disposition); 5814 if (rc != ERROR_SUCCESS) 5815 { 5816 SetLastError(rc); 5817 goto cleanup; 5818 } 5819 } 5820 5821 key = hKey; 5822 5823 cleanup: 5824 if (lpGuidString) 5825 RpcStringFreeW(&lpGuidString); 5826 HeapFree(GetProcessHeap(), 0, DriverKey); 5827 if (hHWProfileKey != INVALID_HANDLE_VALUE) 5828 RegCloseKey(hHWProfileKey); 5829 if (hEnumKey != NULL) 5830 RegCloseKey(hEnumKey); 5831 if (hClassKey != NULL) 5832 RegCloseKey(hClassKey); 5833 if (hDeviceKey != INVALID_HANDLE_VALUE) 5834 RegCloseKey(hDeviceKey); 5835 if (hKey != NULL && hKey != key) 5836 RegCloseKey(hKey); 5837 5838 TRACE("Returning 0x%p\n", hKey); 5839 return hKey; 5840 } 5841 5842 HKEY SETUPDI_OpenDevKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired) 5843 { 5844 HKEY enumKey, key = INVALID_HANDLE_VALUE; 5845 LONG l; 5846 5847 l = RegOpenKeyExW(RootKey, REGSTR_PATH_SYSTEMENUM, 0, READ_CONTROL, &enumKey); 5848 if (!l) 5849 { 5850 l = RegOpenKeyExW(enumKey, devInfo->instanceId, 0, samDesired, &key); 5851 RegCloseKey(enumKey); 5852 } 5853 if (l) 5854 SetLastError(l); 5855 return key; 5856 } 5857 5858 HKEY SETUPDI_OpenDrvKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired) 5859 { 5860 LPWSTR DriverKey = NULL; 5861 DWORD dwLength = 0; 5862 DWORD dwRegType; 5863 DWORD rc; 5864 HKEY hEnumKey = NULL; 5865 HKEY hKey = NULL; 5866 HKEY key = INVALID_HANDLE_VALUE; 5867 5868 hKey = SETUPDI_OpenDevKey(RootKey, devInfo, KEY_QUERY_VALUE); 5869 if (hKey == INVALID_HANDLE_VALUE) 5870 goto cleanup; 5871 /* Read the 'Driver' key */ 5872 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, NULL, &dwLength); 5873 if (rc != ERROR_SUCCESS) 5874 { 5875 SetLastError(rc); 5876 goto cleanup; 5877 } 5878 else if (dwRegType != REG_SZ) 5879 { 5880 SetLastError(ERROR_GEN_FAILURE); 5881 goto cleanup; 5882 } 5883 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength); 5884 if (!DriverKey) 5885 { 5886 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 5887 goto cleanup; 5888 } 5889 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength); 5890 if (rc != ERROR_SUCCESS) 5891 { 5892 SetLastError(rc); 5893 goto cleanup; 5894 } 5895 RegCloseKey(hKey); 5896 hKey = NULL; 5897 /* Need to open the driver key */ 5898 rc = RegOpenKeyExW( 5899 RootKey, 5900 REGSTR_PATH_CLASS_NT, 5901 0, /* Options */ 5902 READ_CONTROL, 5903 &hEnumKey); 5904 if (rc != ERROR_SUCCESS) 5905 { 5906 SetLastError(rc); 5907 goto cleanup; 5908 } 5909 rc = RegOpenKeyExW( 5910 hEnumKey, 5911 DriverKey, 5912 0, /* Options */ 5913 samDesired, 5914 &hKey); 5915 if (rc != ERROR_SUCCESS) 5916 { 5917 SetLastError(rc); 5918 goto cleanup; 5919 } 5920 key = hKey; 5921 5922 cleanup: 5923 if (hEnumKey != NULL) 5924 RegCloseKey(hEnumKey); 5925 if (hKey != NULL && hKey != key) 5926 RegCloseKey(hKey); 5927 if (DriverKey) 5928 HeapFree(GetProcessHeap(), 0, DriverKey); 5929 return key; 5930 } 5931 5932 /*********************************************************************** 5933 * SetupDiOpenDevRegKey (SETUPAPI.@) 5934 */ 5935 HKEY WINAPI SetupDiOpenDevRegKey( 5936 HDEVINFO DeviceInfoSet, 5937 PSP_DEVINFO_DATA DeviceInfoData, 5938 DWORD Scope, 5939 DWORD HwProfile, 5940 DWORD KeyType, 5941 REGSAM samDesired) 5942 { 5943 struct DeviceInfoSet *set = DeviceInfoSet; 5944 struct DeviceInfo *devInfo; 5945 HKEY key = INVALID_HANDLE_VALUE; 5946 HKEY RootKey; 5947 5948 TRACE("%s(%p %p %d %d %d %x)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, 5949 Scope, HwProfile, KeyType, samDesired); 5950 5951 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 5952 { 5953 SetLastError(ERROR_INVALID_HANDLE); 5954 return INVALID_HANDLE_VALUE; 5955 } 5956 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 5957 { 5958 SetLastError(ERROR_INVALID_HANDLE); 5959 return INVALID_HANDLE_VALUE; 5960 } 5961 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 5962 || !DeviceInfoData->Reserved) 5963 { 5964 SetLastError(ERROR_INVALID_PARAMETER); 5965 return INVALID_HANDLE_VALUE; 5966 } 5967 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC) 5968 { 5969 SetLastError(ERROR_INVALID_FLAGS); 5970 return INVALID_HANDLE_VALUE; 5971 } 5972 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV) 5973 { 5974 SetLastError(ERROR_INVALID_FLAGS); 5975 return INVALID_HANDLE_VALUE; 5976 } 5977 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 5978 if (devInfo->set != set) 5979 { 5980 SetLastError(ERROR_INVALID_PARAMETER); 5981 return INVALID_HANDLE_VALUE; 5982 } 5983 if (Scope != DICS_FLAG_GLOBAL) 5984 { 5985 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0); 5986 if (RootKey == INVALID_HANDLE_VALUE) 5987 return INVALID_HANDLE_VALUE; 5988 } 5989 else 5990 RootKey = set->HKLM; 5991 switch (KeyType) 5992 { 5993 case DIREG_DEV: 5994 key = SETUPDI_OpenDevKey(RootKey, devInfo, samDesired); 5995 if (Scope == DICS_FLAG_GLOBAL) 5996 { 5997 LONG rc; 5998 HKEY hTempKey = key; 5999 rc = RegOpenKeyExW(hTempKey, 6000 L"Device Parameters", 6001 0, 6002 samDesired, 6003 &key); 6004 if (rc == ERROR_SUCCESS) 6005 RegCloseKey(hTempKey); 6006 } 6007 break; 6008 case DIREG_DRV: 6009 key = SETUPDI_OpenDrvKey(RootKey, devInfo, samDesired); 6010 break; 6011 default: 6012 WARN("unknown KeyType %d\n", KeyType); 6013 } 6014 if (RootKey != set->HKLM) 6015 RegCloseKey(RootKey); 6016 return key; 6017 } 6018 6019 static BOOL SETUPDI_DeleteDevKey(HKEY RootKey, struct DeviceInfo *devInfo) 6020 { 6021 FIXME("\n"); 6022 return FALSE; 6023 } 6024 6025 static BOOL SETUPDI_DeleteDrvKey(HKEY RootKey, struct DeviceInfo *devInfo) 6026 { 6027 FIXME("\n"); 6028 return FALSE; 6029 } 6030 6031 /*********************************************************************** 6032 * SetupDiDeleteDevRegKey (SETUPAPI.@) 6033 */ 6034 BOOL WINAPI SetupDiDeleteDevRegKey( 6035 HDEVINFO DeviceInfoSet, 6036 PSP_DEVINFO_DATA DeviceInfoData, 6037 DWORD Scope, 6038 DWORD HwProfile, 6039 DWORD KeyType) 6040 { 6041 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 6042 struct DeviceInfo *devInfo; 6043 BOOL ret = FALSE; 6044 HKEY RootKey; 6045 6046 TRACE("%s(%p %p %d %d %d)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, Scope, HwProfile, 6047 KeyType); 6048 6049 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 6050 { 6051 SetLastError(ERROR_INVALID_HANDLE); 6052 return FALSE; 6053 } 6054 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 6055 { 6056 SetLastError(ERROR_INVALID_HANDLE); 6057 return FALSE; 6058 } 6059 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 6060 || !DeviceInfoData->Reserved) 6061 { 6062 SetLastError(ERROR_INVALID_PARAMETER); 6063 return FALSE; 6064 } 6065 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC) 6066 { 6067 SetLastError(ERROR_INVALID_FLAGS); 6068 return FALSE; 6069 } 6070 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV && KeyType != DIREG_BOTH) 6071 { 6072 SetLastError(ERROR_INVALID_FLAGS); 6073 return FALSE; 6074 } 6075 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 6076 if (devInfo->set != set) 6077 { 6078 SetLastError(ERROR_INVALID_PARAMETER); 6079 return FALSE; 6080 } 6081 if (Scope != DICS_FLAG_GLOBAL) 6082 { 6083 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0); 6084 if (RootKey == INVALID_HANDLE_VALUE) 6085 return FALSE; 6086 } 6087 else 6088 RootKey = set->HKLM; 6089 switch (KeyType) 6090 { 6091 case DIREG_DEV: 6092 ret = SETUPDI_DeleteDevKey(RootKey, devInfo); 6093 break; 6094 case DIREG_DRV: 6095 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo); 6096 break; 6097 case DIREG_BOTH: 6098 ret = SETUPDI_DeleteDevKey(RootKey, devInfo); 6099 if (ret) 6100 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo); 6101 break; 6102 default: 6103 WARN("unknown KeyType %d\n", KeyType); 6104 } 6105 if (RootKey != set->HKLM) 6106 RegCloseKey(RootKey); 6107 return ret; 6108 } 6109 6110 /*********************************************************************** 6111 * SetupDiRestartDevices (SETUPAPI.@) 6112 */ 6113 BOOL 6114 WINAPI 6115 SetupDiRestartDevices( 6116 HDEVINFO DeviceInfoSet, 6117 PSP_DEVINFO_DATA DeviceInfoData) 6118 { 6119 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 6120 struct DeviceInfo *devInfo; 6121 CONFIGRET cr; 6122 6123 TRACE("%s(%p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData); 6124 6125 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 6126 { 6127 SetLastError(ERROR_INVALID_HANDLE); 6128 return FALSE; 6129 } 6130 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 6131 { 6132 SetLastError(ERROR_INVALID_HANDLE); 6133 return FALSE; 6134 } 6135 6136 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 6137 || !DeviceInfoData->Reserved) 6138 { 6139 SetLastError(ERROR_INVALID_PARAMETER); 6140 return FALSE; 6141 } 6142 6143 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 6144 6145 cr = CM_Enable_DevNode_Ex(devInfo->dnDevInst, 0, set->hMachine); 6146 if (cr != CR_SUCCESS) 6147 { 6148 SetLastError(GetErrorCodeFromCrCode(cr)); 6149 return FALSE; 6150 } 6151 6152 return TRUE; 6153 } 6154