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