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