1 /* 2 * SetupAPI device class-related functions 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 <wingdi.h> 25 #include <shellapi.h> 26 #include <strsafe.h> 27 28 /* Unicode constants */ 29 static const WCHAR BackSlash[] = {'\\',0}; 30 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0}; 31 static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0}; 32 static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0}; 33 static const WCHAR InterfaceInstall32[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0}; 34 static const WCHAR SetupapiDll[] = {'s','e','t','u','p','a','p','i','.','d','l','l',0}; 35 36 typedef BOOL 37 (WINAPI* PROPERTY_PAGE_PROVIDER) ( 38 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest, 39 IN LPFNADDPROPSHEETPAGE fAddFunc, 40 IN LPARAM lParam); 41 typedef BOOL 42 (*UPDATE_CLASS_PARAM_HANDLER) ( 43 IN HDEVINFO DeviceInfoSet, 44 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 45 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, 46 IN DWORD ClassInstallParamsSize); 47 48 static BOOL 49 SETUP_PropertyChangeHandler( 50 IN HDEVINFO DeviceInfoSet, 51 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 52 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, 53 IN DWORD ClassInstallParamsSize); 54 55 static BOOL 56 SETUP_PropertyAddPropertyAdvancedHandler( 57 IN HDEVINFO DeviceInfoSet, 58 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 59 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, 60 IN DWORD ClassInstallParamsSize); 61 62 typedef struct _INSTALL_PARAMS_DATA 63 { 64 DI_FUNCTION Function; 65 UPDATE_CLASS_PARAM_HANDLER UpdateHandler; 66 ULONG ParamsSize; 67 LONG FieldOffset; 68 } INSTALL_PARAMS_DATA; 69 70 #define ADD_PARAM_HANDLER(Function, UpdateHandler, ParamsType, ParamsField) \ 71 { Function, UpdateHandler, sizeof(ParamsType), FIELD_OFFSET(struct ClassInstallParams, ParamsField) }, 72 73 static const INSTALL_PARAMS_DATA InstallParamsData[] = { 74 ADD_PARAM_HANDLER(DIF_PROPERTYCHANGE, SETUP_PropertyChangeHandler, SP_PROPCHANGE_PARAMS, PropChangeParams) 75 ADD_PARAM_HANDLER(DIF_ADDPROPERTYPAGE_ADVANCED, SETUP_PropertyAddPropertyAdvancedHandler, SP_ADDPROPERTYPAGE_DATA, AddPropertyPageData) 76 }; 77 #undef ADD_PARAM_HANDLER 78 79 #define UNKNOWN_ICON_INDEX 18 80 81 /*********************************************************************** 82 * SetupDiDestroyClassImageList(SETUPAPI.@) 83 */ 84 BOOL WINAPI 85 SetupDiDestroyClassImageList( 86 IN PSP_CLASSIMAGELIST_DATA ClassImageListData) 87 { 88 struct ClassImageList *list; 89 BOOL ret = FALSE; 90 91 TRACE("%p\n", ClassImageListData); 92 93 if (!ClassImageListData) 94 SetLastError(ERROR_INVALID_PARAMETER); 95 else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA)) 96 SetLastError(ERROR_INVALID_USER_BUFFER); 97 else if ((list = (struct ClassImageList *)ClassImageListData->Reserved) == NULL) 98 SetLastError(ERROR_INVALID_USER_BUFFER); 99 else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC) 100 SetLastError(ERROR_INVALID_USER_BUFFER); 101 else 102 { 103 /* If Reserved wasn't NULL, then this is valid too */ 104 if (ClassImageListData->ImageList) 105 { 106 ImageList_Destroy(ClassImageListData->ImageList); 107 ClassImageListData->ImageList = NULL; 108 } 109 110 MyFree(list); 111 ClassImageListData->Reserved = 0; 112 113 ret = TRUE; 114 } 115 116 TRACE("Returning %d\n", ret); 117 return ret; 118 } 119 120 LONG 121 SETUP_CreateDevicesList( 122 IN OUT struct DeviceInfoSet *list, 123 IN PCWSTR MachineName OPTIONAL, 124 IN CONST GUID *Class OPTIONAL, 125 IN PCWSTR Enumerator OPTIONAL) 126 { 127 PWCHAR Buffer = NULL; 128 DWORD BufferLength = 4096; 129 PCWSTR InstancePath; 130 struct DeviceInfo *deviceInfo; 131 WCHAR ClassGuidBuffer[MAX_GUID_STRING_LEN]; 132 DWORD ClassGuidBufferSize; 133 GUID ClassGuid; 134 DEVINST dnDevInst; 135 CONFIGRET cr; 136 137 Buffer = HeapAlloc(GetProcessHeap(), 0, BufferLength); 138 if (!Buffer) 139 return ERROR_NOT_ENOUGH_MEMORY; 140 141 do 142 { 143 cr = CM_Get_Device_ID_List_ExW(Enumerator, 144 Buffer, 145 BufferLength / sizeof(WCHAR), 146 Enumerator ? CM_GETIDLIST_FILTER_ENUMERATOR : CM_GETIDLIST_FILTER_NONE, 147 list->hMachine); 148 if (cr == CR_BUFFER_SMALL) 149 { 150 if (Buffer) 151 HeapFree(GetProcessHeap(), 0, Buffer); 152 BufferLength *= 2; 153 Buffer = HeapAlloc(GetProcessHeap(), 0, BufferLength); 154 if (!Buffer) 155 return ERROR_NOT_ENOUGH_MEMORY; 156 } 157 else if (cr != CR_SUCCESS) 158 { 159 TRACE("CM_Get_Device_ID_List_ExW() failed with status 0x%x\n", cr); 160 if (Buffer) 161 HeapFree(GetProcessHeap(), 0, Buffer); 162 return GetErrorCodeFromCrCode(cr); 163 } 164 } 165 while (cr != CR_SUCCESS); 166 167 for (InstancePath = Buffer; *InstancePath != UNICODE_NULL; InstancePath += wcslen(InstancePath) + 1) 168 { 169 /* Check that device really exists */ 170 TRACE("Checking %S\n", InstancePath); 171 cr = CM_Locate_DevNode_Ex(&dnDevInst, 172 (DEVINSTID_W)InstancePath, 173 CM_LOCATE_DEVNODE_NORMAL, 174 list->hMachine); 175 if (cr != CR_SUCCESS) 176 { 177 ERR("CM_Locate_DevNode_ExW('%S') failed with status 0x%x\n", InstancePath, cr); 178 continue; 179 } 180 181 /* Retrieve GUID of this device */ 182 ClassGuidBufferSize = sizeof(ClassGuidBuffer); 183 cr = CM_Get_DevNode_Registry_Property_ExW(dnDevInst, 184 CM_DRP_CLASSGUID, 185 NULL, 186 ClassGuidBuffer, 187 &ClassGuidBufferSize, 188 0, 189 list->hMachine); 190 if (cr == CR_SUCCESS) 191 { 192 ClassGuidBuffer[MAX_GUID_STRING_LEN - 2] = '\0'; /* Replace the } by a NULL character */ 193 if (UuidFromStringW(&ClassGuidBuffer[1], &ClassGuid) != RPC_S_OK) 194 { 195 /* Bad GUID, skip the entry */ 196 ERR("Invalid ClassGUID '%S' for device %S\n", ClassGuidBuffer, InstancePath); 197 continue; 198 } 199 } 200 else 201 { 202 TRACE("Using default class GUID_NULL for device %S\n", InstancePath); 203 memcpy(&ClassGuid, &GUID_NULL, sizeof(GUID)); 204 } 205 206 if (Class && !IsEqualIID(&ClassGuid, Class)) 207 { 208 TRACE("Skipping %S due to wrong class GUID\n", InstancePath); 209 continue; 210 } 211 212 /* Good! Create a device info element */ 213 if (!CreateDeviceInfo(list, InstancePath, &ClassGuid, &deviceInfo)) 214 { 215 ERR("Failed to create info for %S\n", InstancePath); 216 HeapFree(GetProcessHeap(), 0, Buffer); 217 return GetLastError(); 218 } 219 220 TRACE("Adding device %s to list\n", debugstr_w(InstancePath)); 221 InsertTailList(&list->ListHead, &deviceInfo->ListEntry); 222 } 223 224 HeapFree(GetProcessHeap(), 0, Buffer); 225 return ERROR_SUCCESS; 226 } 227 228 static BOOL 229 SETUP_GetIconIndex( 230 IN HKEY hClassKey, 231 OUT PINT ImageIndex) 232 { 233 LPWSTR Buffer = NULL; 234 DWORD dwRegType, dwLength; 235 LONG rc; 236 BOOL ret = FALSE; 237 238 /* Read icon registry key */ 239 rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, &dwRegType, NULL, &dwLength); 240 if (rc != ERROR_SUCCESS) 241 { 242 SetLastError(rc); 243 goto cleanup; 244 } else if (dwRegType != REG_SZ) 245 { 246 SetLastError(ERROR_INVALID_INDEX); 247 goto cleanup; 248 } 249 Buffer = MyMalloc(dwLength + sizeof(WCHAR)); 250 if (!Buffer) 251 { 252 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 253 goto cleanup; 254 } 255 rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, NULL, (LPBYTE)Buffer, &dwLength); 256 if (rc != ERROR_SUCCESS) 257 { 258 SetLastError(rc); 259 goto cleanup; 260 } 261 /* make sure the returned buffer is NULL-terminated */ 262 Buffer[dwLength / sizeof(WCHAR)] = 0; 263 264 /* Transform icon value to a INT */ 265 *ImageIndex = atoiW(Buffer); 266 ret = TRUE; 267 268 cleanup: 269 MyFree(Buffer); 270 return ret; 271 } 272 273 /*********************************************************************** 274 * SetupDiGetClassImageIndex (SETUPAPI.@) 275 */ 276 BOOL WINAPI 277 SetupDiGetClassImageIndex( 278 IN PSP_CLASSIMAGELIST_DATA ClassImageListData, 279 IN CONST GUID *ClassGuid, 280 OUT PINT ImageIndex) 281 { 282 struct ClassImageList *list; 283 BOOL ret = FALSE; 284 285 TRACE("%p %s %p\n", ClassImageListData, debugstr_guid(ClassGuid), ImageIndex); 286 287 if (!ClassImageListData || !ClassGuid || !ImageIndex) 288 SetLastError(ERROR_INVALID_PARAMETER); 289 else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA)) 290 SetLastError(ERROR_INVALID_USER_BUFFER); 291 else if ((list = (struct ClassImageList *)ClassImageListData->Reserved) == NULL) 292 SetLastError(ERROR_INVALID_USER_BUFFER); 293 else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC) 294 SetLastError(ERROR_INVALID_USER_BUFFER); 295 else 296 { 297 DWORD i; 298 299 for (i = 0; i < list->NumberOfGuids; i++) 300 { 301 if (IsEqualIID(ClassGuid, &list->Guids[i])) 302 break; 303 } 304 305 if (i == list->NumberOfGuids || list->IconIndexes[i] < 0) 306 SetLastError(ERROR_FILE_NOT_FOUND); 307 else 308 { 309 *ImageIndex = list->IconIndexes[i]; 310 ret = TRUE; 311 } 312 } 313 314 TRACE("Returning %d\n", ret); 315 return ret; 316 } 317 318 /*********************************************************************** 319 * SetupDiGetClassImageList(SETUPAPI.@) 320 */ 321 BOOL WINAPI 322 SetupDiGetClassImageList( 323 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData) 324 { 325 return SetupDiGetClassImageListExW(ClassImageListData, NULL, NULL); 326 } 327 328 /*********************************************************************** 329 * SetupDiGetClassImageListExA(SETUPAPI.@) 330 */ 331 BOOL WINAPI 332 SetupDiGetClassImageListExA( 333 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData, 334 IN PCSTR MachineName OPTIONAL, 335 IN PVOID Reserved) 336 { 337 PWSTR MachineNameW = NULL; 338 BOOL ret; 339 340 if (MachineName) 341 { 342 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 343 if (MachineNameW == NULL) 344 return FALSE; 345 } 346 347 ret = SetupDiGetClassImageListExW(ClassImageListData, MachineNameW, Reserved); 348 349 MyFree(MachineNameW); 350 351 return ret; 352 } 353 354 static BOOL WINAPI 355 SETUP_GetClassIconInfo(IN CONST GUID *ClassGuid, OUT PINT OutIndex, OUT LPWSTR *OutDllName) 356 { 357 LPWSTR Buffer = NULL; 358 INT iconIndex = -UNKNOWN_ICON_INDEX; 359 HKEY hKey = INVALID_HANDLE_VALUE; 360 BOOL ret = FALSE; 361 362 if (ClassGuid) 363 { 364 hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE); 365 if (hKey != INVALID_HANDLE_VALUE) 366 { 367 SETUP_GetIconIndex(hKey, &iconIndex); 368 } 369 } 370 371 if (iconIndex > 0) 372 { 373 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */ 374 PWCHAR Comma; 375 LONG rc; 376 DWORD dwRegType, dwLength; 377 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength); 378 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ) 379 { 380 Buffer = MyMalloc(dwLength + sizeof(WCHAR)); 381 if (Buffer == NULL) 382 { 383 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 384 goto cleanup; 385 } 386 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)Buffer, &dwLength); 387 if (rc != ERROR_SUCCESS) 388 { 389 SetLastError(rc); 390 goto cleanup; 391 } 392 /* make sure the returned buffer is NULL-terminated */ 393 Buffer[dwLength / sizeof(WCHAR)] = 0; 394 } 395 else if 396 (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength)) 397 && dwRegType == REG_SZ) 398 { 399 Buffer = MyMalloc(dwLength + sizeof(WCHAR)); 400 if (Buffer == NULL) 401 { 402 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 403 goto cleanup; 404 } 405 rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)Buffer, &dwLength); 406 if (rc != ERROR_SUCCESS) 407 { 408 SetLastError(rc); 409 goto cleanup; 410 } 411 /* make sure the returned buffer is NULL-terminated */ 412 Buffer[dwLength / sizeof(WCHAR)] = 0; 413 } 414 else 415 { 416 /* Unable to find where to load the icon */ 417 SetLastError(ERROR_FILE_NOT_FOUND); 418 goto cleanup; 419 } 420 Comma = strchrW(Buffer, ','); 421 if (!Comma) 422 { 423 SetLastError(ERROR_GEN_FAILURE); 424 goto cleanup; 425 } 426 *Comma = '\0'; 427 *OutDllName = Buffer; 428 } 429 else 430 { 431 /* Look up icon in setupapi.dll */ 432 iconIndex = -iconIndex; 433 *OutDllName = NULL; 434 } 435 436 *OutIndex = iconIndex; 437 ret = TRUE; 438 439 TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(*OutDllName ? *OutDllName : SetupapiDll)); 440 441 cleanup: 442 443 if (hKey != INVALID_HANDLE_VALUE) 444 RegCloseKey(hKey); 445 446 if (Buffer && !ret) 447 MyFree(Buffer); 448 449 return ret; 450 } 451 452 453 /*********************************************************************** 454 * SetupDiGetClassImageListExW(SETUPAPI.@) 455 */ 456 BOOL WINAPI 457 SetupDiGetClassImageListExW( 458 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData, 459 IN PCWSTR MachineName OPTIONAL, 460 IN PVOID Reserved) 461 { 462 BOOL ret = FALSE; 463 464 TRACE("%p %p %p\n", ClassImageListData, debugstr_w(MachineName), Reserved); 465 466 if (!ClassImageListData) 467 SetLastError(ERROR_INVALID_PARAMETER); 468 else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA)) 469 SetLastError(ERROR_INVALID_USER_BUFFER); 470 else if (Reserved) 471 SetLastError(ERROR_INVALID_PARAMETER); 472 else 473 { 474 struct ClassImageList *list = NULL; 475 HDC hDC; 476 DWORD RequiredSize; 477 DWORD ilMask, bkColor; 478 HICON hIcon; 479 DWORD size; 480 INT i, bpp; 481 UINT idx; 482 483 /* Get list of all class GUIDs in given computer */ 484 ret = SetupDiBuildClassInfoListExW( 485 0, 486 NULL, 487 0, 488 &RequiredSize, 489 MachineName, 490 NULL); 491 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER) 492 goto cleanup; 493 494 size = sizeof(struct ClassImageList) 495 + (sizeof(GUID) + sizeof(INT)) * RequiredSize; 496 list = HeapAlloc(GetProcessHeap(), 0, size); 497 if (!list) 498 { 499 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 500 goto cleanup; 501 } 502 list->magic = SETUP_CLASS_IMAGE_LIST_MAGIC; 503 list->NumberOfGuids = RequiredSize; 504 list->Guids = (GUID*)(list + 1); 505 list->IconIndexes = (INT*)((ULONG_PTR)(list + 1) + sizeof(GUID) * RequiredSize); 506 507 ret = SetupDiBuildClassInfoListExW( 508 0, 509 list->Guids, 510 list->NumberOfGuids, 511 &RequiredSize, 512 MachineName, 513 NULL); 514 if (!ret) 515 goto cleanup; 516 else if (RequiredSize != list->NumberOfGuids) 517 { 518 /* Hm. Class list changed since last call. Ignore 519 * this case as it should be very rare */ 520 SetLastError(ERROR_GEN_FAILURE); 521 ret = FALSE; 522 goto cleanup; 523 } 524 525 /* Prepare a HIMAGELIST */ 526 InitCommonControls(); 527 528 hDC = GetDC(NULL); 529 if (!hDC) 530 goto cleanup; 531 532 bpp = GetDeviceCaps(hDC, BITSPIXEL); 533 ReleaseDC(NULL, hDC); 534 535 if (bpp <= 4) 536 ilMask = ILC_COLOR4; 537 else if (bpp <= 8) 538 ilMask = ILC_COLOR8; 539 else if (bpp <= 16) 540 ilMask = ILC_COLOR16; 541 else if (bpp <= 24) 542 ilMask = ILC_COLOR24; 543 else if (bpp <= 32) 544 ilMask = ILC_COLOR32; 545 else 546 ilMask = ILC_COLOR; 547 548 ilMask |= ILC_MASK; 549 550 ClassImageListData->ImageList = ImageList_Create(16, 16, ilMask, 100, 10); 551 if (!ClassImageListData->ImageList) 552 goto cleanup; 553 554 ClassImageListData->Reserved = (ULONG_PTR)list; 555 556 /* For some reason, Windows sets the list background to COLOR_WINDOW */ 557 bkColor = GetSysColor(COLOR_WINDOW); 558 ImageList_SetBkColor(ClassImageListData->ImageList, bkColor); 559 560 /* Now, we "simply" need to load icons associated with all class guids, 561 * and put their index in the image list in the IconIndexes array */ 562 for (i = 0; i < list->NumberOfGuids; i++) 563 { 564 INT miniIconIndex; 565 LPWSTR DllName = NULL; 566 567 if (SETUP_GetClassIconInfo(&list->Guids[i], &miniIconIndex, &DllName)) 568 { 569 if (DllName && ExtractIconExW(DllName, -miniIconIndex, NULL, &hIcon, 1) == 1) 570 { 571 list->IconIndexes[i] = ImageList_AddIcon(ClassImageListData->ImageList, hIcon); 572 } 573 else if(!DllName) 574 { 575 hIcon = LoadImage(hInstance, MAKEINTRESOURCE(miniIconIndex), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); 576 list->IconIndexes[i] = ImageList_AddIcon(ClassImageListData->ImageList, hIcon); 577 } 578 579 if(hIcon) 580 DestroyIcon(hIcon); 581 else 582 list->IconIndexes[i] = -1; 583 584 if(DllName) 585 MyFree(DllName); 586 } 587 else 588 { 589 list->IconIndexes[i] = -1; /* Special value to indicate that the icon is unavailable */ 590 } 591 } 592 593 /* Finally, add the overlay icons to the image list */ 594 for (i = 0; i <= 2; i++) 595 { 596 hIcon = LoadImage(hInstance, MAKEINTRESOURCE(500 + i), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); 597 if (hIcon) 598 { 599 idx = ImageList_AddIcon(ClassImageListData->ImageList, hIcon); 600 if (idx != -1) 601 ImageList_SetOverlayImage(ClassImageListData->ImageList, idx, i + 1); 602 DestroyIcon(hIcon); 603 } 604 } 605 606 ret = TRUE; 607 608 cleanup: 609 if (!ret) 610 { 611 if (ClassImageListData->Reserved) 612 SetupDiDestroyClassImageList(ClassImageListData); 613 else if (list) 614 MyFree(list); 615 } 616 } 617 618 TRACE("Returning %d\n", ret); 619 return ret; 620 } 621 622 /*********************************************************************** 623 * SetupDiGetClassInstallParamsA(SETUPAPI.@) 624 */ 625 BOOL WINAPI 626 SetupDiGetClassInstallParamsA( 627 IN HDEVINFO DeviceInfoSet, 628 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 629 OUT PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, 630 IN DWORD ClassInstallParamsSize, 631 OUT PDWORD RequiredSize OPTIONAL) 632 { 633 FIXME("SetupDiGetClassInstallParamsA(%p %p %p %lu %p) Stub\n", 634 DeviceInfoSet, DeviceInfoData, ClassInstallParams, ClassInstallParamsSize, RequiredSize); 635 return FALSE; 636 } 637 638 /*********************************************************************** 639 * SetupDiGetClassInstallParamsW(SETUPAPI.@) 640 */ 641 BOOL WINAPI 642 SetupDiGetClassInstallParamsW( 643 IN HDEVINFO DeviceInfoSet, 644 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 645 OUT PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, 646 IN DWORD ClassInstallParamsSize, 647 OUT PDWORD RequiredSize OPTIONAL) 648 { 649 FIXME("SetupDiGetClassInstallParamsW(%p %p %p %lu %p) Stub\n", 650 DeviceInfoSet, DeviceInfoData, ClassInstallParams, ClassInstallParamsSize, RequiredSize); 651 return FALSE; 652 } 653 654 /*********************************************************************** 655 * SetupDiLoadClassIcon(SETUPAPI.@) 656 */ 657 BOOL WINAPI 658 SetupDiLoadClassIcon( 659 IN CONST GUID *ClassGuid, 660 OUT HICON *LargeIcon OPTIONAL, 661 OUT PINT MiniIconIndex OPTIONAL) 662 { 663 INT iconIndex = 0; 664 LPWSTR DllName = NULL; 665 BOOL ret = FALSE; 666 HICON hIcon = NULL; 667 668 if (LargeIcon) 669 { 670 if(!SETUP_GetClassIconInfo(ClassGuid, &iconIndex, &DllName)) 671 goto cleanup; 672 673 if (!DllName || ExtractIconExW(DllName, -iconIndex, &hIcon, NULL, 1) != 1 || hIcon == NULL) 674 { 675 /* load the default unknown device icon if ExtractIcon failed */ 676 if(DllName) 677 iconIndex = UNKNOWN_ICON_INDEX; 678 679 hIcon = LoadImage(hInstance, MAKEINTRESOURCE(iconIndex), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR); 680 681 if(!hIcon) 682 goto cleanup; 683 } 684 685 *LargeIcon = hIcon; 686 } 687 688 if (MiniIconIndex) 689 *MiniIconIndex = iconIndex; 690 691 ret = TRUE; 692 693 cleanup: 694 695 if(DllName) 696 MyFree(DllName); 697 698 TRACE("Returning %d\n", ret); 699 return ret; 700 } 701 702 /*********************************************************************** 703 * SetupDiInstallClassExW (SETUPAPI.@) 704 */ 705 HKEY 706 SETUP_CreateClassKey(HINF hInf); 707 BOOL WINAPI 708 SetupDiInstallClassExW( 709 IN HWND hwndParent OPTIONAL, 710 IN PCWSTR InfFileName OPTIONAL, 711 IN DWORD Flags, 712 IN HSPFILEQ FileQueue OPTIONAL, 713 IN CONST GUID *InterfaceClassGuid OPTIONAL, 714 IN PVOID Reserved1, 715 IN PVOID Reserved2) 716 { 717 BOOL ret = FALSE; 718 719 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent, debugstr_w(InfFileName), Flags, 720 FileQueue, debugstr_guid(InterfaceClassGuid), Reserved1, Reserved2); 721 722 if (!InfFileName) 723 { 724 FIXME("Case not implemented: InfFileName NULL\n"); 725 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 726 } 727 else if (Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL)) 728 { 729 TRACE("Unknown flags: 0x%08lx\n", Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL)); 730 SetLastError(ERROR_INVALID_FLAGS); 731 } 732 else if ((Flags & DI_NOVCP) && FileQueue == NULL) 733 SetLastError(ERROR_INVALID_PARAMETER); 734 else if (Reserved1 != NULL) 735 SetLastError(ERROR_INVALID_PARAMETER); 736 else if (Reserved2 != NULL) 737 SetLastError(ERROR_INVALID_PARAMETER); 738 else 739 { 740 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE; 741 SP_DEVINSTALL_PARAMS_W InstallParams; 742 WCHAR SectionName[MAX_PATH]; 743 HINF hInf = INVALID_HANDLE_VALUE; 744 HKEY hRootKey = INVALID_HANDLE_VALUE; 745 PVOID callback_context = NULL; 746 747 hDeviceInfo = SetupDiCreateDeviceInfoList(NULL, NULL); 748 if (hDeviceInfo == INVALID_HANDLE_VALUE) 749 goto cleanup; 750 751 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 752 if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo, NULL, &InstallParams)) 753 goto cleanup; 754 755 InstallParams.Flags &= ~(DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL); 756 InstallParams.Flags |= Flags & (DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL); 757 if (Flags & DI_NOVCP) 758 InstallParams.FileQueue = FileQueue; 759 if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo, NULL, &InstallParams)) 760 goto cleanup; 761 762 /* Open the .inf file */ 763 hInf = SetupOpenInfFileW( 764 InfFileName, 765 NULL, 766 INF_STYLE_WIN4, 767 NULL); 768 if (hInf == INVALID_HANDLE_VALUE) 769 goto cleanup; 770 771 /* Try to append a layout file */ 772 SetupOpenAppendInfFileW(NULL, hInf, NULL); 773 774 if (InterfaceClassGuid) 775 { 776 /* Retrieve the actual section name */ 777 ret = SetupDiGetActualSectionToInstallW( 778 hInf, 779 InterfaceInstall32, 780 SectionName, 781 MAX_PATH, 782 NULL, 783 NULL); 784 if (!ret) 785 goto cleanup; 786 787 /* Open registry key related to this interface */ 788 /* FIXME: What happens if the key doesn't exist? */ 789 hRootKey = SetupDiOpenClassRegKeyExW(InterfaceClassGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, NULL, NULL); 790 if (hRootKey == INVALID_HANDLE_VALUE) 791 goto cleanup; 792 793 /* SetupDiCreateDeviceInterface??? */ 794 FIXME("Installing an interface is not implemented\n"); 795 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 796 } 797 else 798 { 799 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */ 800 hRootKey = SETUP_CreateClassKey(hInf); 801 if (hRootKey == INVALID_HANDLE_VALUE) 802 goto cleanup; 803 804 /* Retrieve the actual section name */ 805 ret = SetupDiGetActualSectionToInstallW( 806 hInf, 807 ClassInstall32, 808 SectionName, 809 MAX_PATH - strlenW(DotServices), 810 NULL, 811 NULL); 812 if (!ret) 813 goto cleanup; 814 815 callback_context = SetupInitDefaultQueueCallback(hwndParent); 816 if (!callback_context) 817 goto cleanup; 818 819 ret = SetupInstallFromInfSectionW( 820 hwndParent, 821 hInf, 822 SectionName, 823 SPINST_REGISTRY | SPINST_FILES | SPINST_BITREG | SPINST_INIFILES | SPINST_INI2REG, 824 hRootKey, 825 NULL, /* FIXME: SourceRootPath */ 826 !(Flags & DI_NOVCP) && (Flags & DI_FORCECOPY) ? SP_COPY_FORCE_IN_USE : 0, /* CopyFlags */ 827 SetupDefaultQueueCallbackW, 828 callback_context, 829 hDeviceInfo, 830 NULL); 831 if (!ret) 832 goto cleanup; 833 834 /* OPTIONAL: Install .Services section */ 835 lstrcatW(SectionName, DotServices); 836 SetupInstallServicesFromInfSectionExW( 837 hInf, 838 SectionName, 839 0, 840 hDeviceInfo, 841 NULL, 842 NULL, 843 NULL); 844 ret = TRUE; 845 } 846 847 cleanup: 848 if (hDeviceInfo != INVALID_HANDLE_VALUE) 849 SetupDiDestroyDeviceInfoList(hDeviceInfo); 850 if (hInf != INVALID_HANDLE_VALUE) 851 SetupCloseInfFile(hInf); 852 if (hRootKey != INVALID_HANDLE_VALUE) 853 RegCloseKey(hRootKey); 854 SetupTermDefaultQueueCallback(callback_context); 855 } 856 857 TRACE("Returning %d\n", ret); 858 return ret; 859 } 860 861 /*********************************************************************** 862 * Helper functions for SetupDiSetClassInstallParamsW 863 */ 864 static BOOL 865 SETUP_PropertyChangeHandler( 866 IN HDEVINFO DeviceInfoSet, 867 IN PSP_DEVINFO_DATA DeviceInfoData, 868 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, 869 IN DWORD ClassInstallParamsSize) 870 { 871 PSP_PROPCHANGE_PARAMS PropChangeParams = (PSP_PROPCHANGE_PARAMS)ClassInstallParams; 872 BOOL ret = FALSE; 873 874 if (!DeviceInfoData) 875 SetLastError(ERROR_INVALID_PARAMETER); 876 else if (ClassInstallParamsSize != sizeof(SP_PROPCHANGE_PARAMS)) 877 SetLastError(ERROR_INVALID_PARAMETER); 878 else if (PropChangeParams && PropChangeParams->StateChange != DICS_ENABLE 879 && PropChangeParams->StateChange != DICS_DISABLE && PropChangeParams->StateChange != DICS_PROPCHANGE 880 && PropChangeParams->StateChange != DICS_START && PropChangeParams->StateChange != DICS_STOP) 881 SetLastError(ERROR_INVALID_FLAGS); 882 else if (PropChangeParams && PropChangeParams->Scope != DICS_FLAG_GLOBAL 883 && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC) 884 SetLastError(ERROR_INVALID_FLAGS); 885 else if (PropChangeParams 886 && (PropChangeParams->StateChange == DICS_START || PropChangeParams->StateChange == DICS_STOP) 887 && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC) 888 SetLastError(ERROR_INVALID_USER_BUFFER); 889 else 890 { 891 PSP_PROPCHANGE_PARAMS *CurrentPropChangeParams; 892 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 893 CurrentPropChangeParams = &deviceInfo->ClassInstallParams.PropChangeParams; 894 895 if (*CurrentPropChangeParams) 896 { 897 MyFree(*CurrentPropChangeParams); 898 *CurrentPropChangeParams = NULL; 899 } 900 if (PropChangeParams) 901 { 902 *CurrentPropChangeParams = MyMalloc(ClassInstallParamsSize); 903 if (!*CurrentPropChangeParams) 904 { 905 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 906 goto done; 907 } 908 memcpy(*CurrentPropChangeParams, PropChangeParams, ClassInstallParamsSize); 909 } 910 ret = TRUE; 911 } 912 913 done: 914 return ret; 915 } 916 917 static BOOL 918 SETUP_PropertyAddPropertyAdvancedHandler( 919 IN HDEVINFO DeviceInfoSet, 920 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 921 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, 922 IN DWORD ClassInstallParamsSize) 923 { 924 PSP_ADDPROPERTYPAGE_DATA AddPropertyPageData = (PSP_ADDPROPERTYPAGE_DATA)ClassInstallParams; 925 BOOL ret = FALSE; 926 927 if (ClassInstallParamsSize != sizeof(SP_PROPCHANGE_PARAMS)) 928 SetLastError(ERROR_INVALID_PARAMETER); 929 else if (AddPropertyPageData && AddPropertyPageData->Flags != 0) 930 SetLastError(ERROR_INVALID_FLAGS); 931 else if (AddPropertyPageData && AddPropertyPageData->NumDynamicPages >= MAX_INSTALLWIZARD_DYNAPAGES) 932 SetLastError(ERROR_INVALID_USER_BUFFER); 933 else 934 { 935 PSP_ADDPROPERTYPAGE_DATA *CurrentAddPropertyPageData; 936 if (!DeviceInfoData) 937 { 938 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet; 939 CurrentAddPropertyPageData = &list->ClassInstallParams.AddPropertyPageData; 940 } 941 else 942 { 943 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 944 CurrentAddPropertyPageData = &deviceInfo->ClassInstallParams.AddPropertyPageData; 945 } 946 if (*CurrentAddPropertyPageData) 947 { 948 MyFree(*CurrentAddPropertyPageData); 949 *CurrentAddPropertyPageData = NULL; 950 } 951 if (AddPropertyPageData) 952 { 953 *CurrentAddPropertyPageData = MyMalloc(ClassInstallParamsSize); 954 if (!*CurrentAddPropertyPageData) 955 { 956 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 957 goto done; 958 } 959 memcpy(*CurrentAddPropertyPageData, AddPropertyPageData, ClassInstallParamsSize); 960 } 961 ret = TRUE; 962 } 963 964 done: 965 return ret; 966 } 967 968 /*********************************************************************** 969 * SetupDiSetClassInstallParamsW (SETUPAPI.@) 970 */ 971 BOOL WINAPI 972 SetupDiSetClassInstallParamsW( 973 IN HDEVINFO DeviceInfoSet, 974 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 975 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, 976 IN DWORD ClassInstallParamsSize) 977 { 978 struct DeviceInfoSet *list; 979 BOOL ret = FALSE; 980 981 TRACE("%p %p %p %lu\n", DeviceInfoSet, DeviceInfoData, 982 ClassInstallParams, ClassInstallParamsSize); 983 984 if (!DeviceInfoSet) 985 SetLastError(ERROR_INVALID_PARAMETER); 986 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 987 SetLastError(ERROR_INVALID_HANDLE); 988 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 989 SetLastError(ERROR_INVALID_HANDLE); 990 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 991 SetLastError(ERROR_INVALID_USER_BUFFER); 992 else if (ClassInstallParams && ClassInstallParams->cbSize != sizeof(SP_CLASSINSTALL_HEADER)) 993 SetLastError(ERROR_INVALID_USER_BUFFER); 994 else if (ClassInstallParams && ClassInstallParamsSize < sizeof(SP_CLASSINSTALL_HEADER)) 995 SetLastError(ERROR_INVALID_PARAMETER); 996 else if (!ClassInstallParams && ClassInstallParamsSize != 0) 997 SetLastError(ERROR_INVALID_PARAMETER); 998 else 999 { 1000 SP_DEVINSTALL_PARAMS_W InstallParams; 1001 BOOL Result; 1002 1003 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 1004 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 1005 if (!Result) 1006 goto done; 1007 1008 if (ClassInstallParams) 1009 { 1010 DWORD i; 1011 /* Check parameters in ClassInstallParams */ 1012 for (i = 0; i < sizeof(InstallParamsData) / sizeof(InstallParamsData[0]); i++) 1013 { 1014 if (InstallParamsData[i].Function == ClassInstallParams->InstallFunction) 1015 { 1016 ret = InstallParamsData[i].UpdateHandler( 1017 DeviceInfoSet, 1018 DeviceInfoData, 1019 ClassInstallParams, 1020 ClassInstallParamsSize); 1021 if (ret) 1022 { 1023 InstallParams.Flags |= DI_CLASSINSTALLPARAMS; 1024 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 1025 } 1026 goto done; 1027 } 1028 } 1029 ERR("InstallFunction %u has no associated update handler\n", ClassInstallParams->InstallFunction); 1030 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1031 goto done; 1032 } 1033 else 1034 { 1035 InstallParams.Flags &= ~DI_CLASSINSTALLPARAMS; 1036 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 1037 } 1038 } 1039 1040 done: 1041 TRACE("Returning %d\n", ret); 1042 return ret; 1043 } 1044 1045 /*********************************************************************** 1046 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@) 1047 */ 1048 BOOL WINAPI 1049 SetupDiGetClassDevPropertySheetsA( 1050 IN HDEVINFO DeviceInfoSet, 1051 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 1052 IN LPPROPSHEETHEADERA PropertySheetHeader, 1053 IN DWORD PropertySheetHeaderPageListSize, 1054 OUT PDWORD RequiredSize OPTIONAL, 1055 IN DWORD PropertySheetType) 1056 { 1057 PROPSHEETHEADERW psh; 1058 BOOL ret = FALSE; 1059 1060 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, 1061 PropertySheetHeader, PropertySheetHeaderPageListSize, 1062 RequiredSize, PropertySheetType); 1063 1064 if(PropertySheetHeader) 1065 { 1066 psh.dwFlags = PropertySheetHeader->dwFlags; 1067 psh.phpage = PropertySheetHeader->phpage; 1068 psh.nPages = PropertySheetHeader->nPages; 1069 } 1070 1071 ret = SetupDiGetClassDevPropertySheetsW(DeviceInfoSet, DeviceInfoData, PropertySheetHeader ? &psh : NULL, 1072 PropertySheetHeaderPageListSize, RequiredSize, 1073 PropertySheetType); 1074 if (ret) 1075 { 1076 PropertySheetHeader->nPages = psh.nPages; 1077 } 1078 1079 TRACE("Returning %d\n", ret); 1080 return ret; 1081 } 1082 1083 struct ClassDevPropertySheetsData 1084 { 1085 LPPROPSHEETHEADERW PropertySheetHeader; 1086 DWORD PropertySheetHeaderPageListSize; 1087 DWORD NumberOfPages; 1088 BOOL DontCancel; 1089 }; 1090 1091 static BOOL WINAPI 1092 SETUP_GetClassDevPropertySheetsCallback( 1093 IN HPROPSHEETPAGE hPropSheetPage, 1094 IN OUT LPARAM lParam) 1095 { 1096 struct ClassDevPropertySheetsData *PropPageData; 1097 1098 PropPageData = (struct ClassDevPropertySheetsData *)lParam; 1099 1100 PropPageData->NumberOfPages++; 1101 1102 if (PropPageData->PropertySheetHeader->nPages < PropPageData->PropertySheetHeaderPageListSize) 1103 { 1104 PropPageData->PropertySheetHeader->phpage[PropPageData->PropertySheetHeader->nPages] = hPropSheetPage; 1105 PropPageData->PropertySheetHeader->nPages++; 1106 return TRUE; 1107 } 1108 1109 return PropPageData->DontCancel; 1110 } 1111 1112 static DWORD 1113 SETUP_GetValueString( 1114 IN HKEY hKey, 1115 IN LPWSTR lpValueName, 1116 OUT LPWSTR *lpString) 1117 { 1118 LPWSTR lpBuffer; 1119 DWORD dwLength = 0; 1120 DWORD dwRegType; 1121 DWORD rc; 1122 1123 *lpString = NULL; 1124 1125 RegQueryValueExW(hKey, lpValueName, NULL, &dwRegType, NULL, &dwLength); 1126 1127 if (dwLength == 0 || dwRegType != REG_SZ) 1128 return ERROR_FILE_NOT_FOUND; 1129 1130 lpBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR)); 1131 if (lpBuffer == NULL) 1132 return ERROR_NOT_ENOUGH_MEMORY; 1133 1134 rc = RegQueryValueExW(hKey, lpValueName, NULL, NULL, (LPBYTE)lpBuffer, &dwLength); 1135 if (rc != ERROR_SUCCESS) 1136 { 1137 HeapFree(GetProcessHeap(), 0, lpBuffer); 1138 return rc; 1139 } 1140 1141 lpBuffer[dwLength / sizeof(WCHAR)] = UNICODE_NULL; 1142 1143 *lpString = lpBuffer; 1144 1145 return ERROR_SUCCESS; 1146 } 1147 1148 static 1149 BOOL 1150 SETUP_CallInstaller( 1151 IN DI_FUNCTION InstallFunction, 1152 IN HDEVINFO DeviceInfoSet, 1153 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 1154 IN PSP_ADDPROPERTYPAGE_DATA PageData) 1155 { 1156 PSP_CLASSINSTALL_HEADER pClassInstallParams = NULL; 1157 DWORD dwSize = 0; 1158 DWORD dwError; 1159 BOOL ret = TRUE; 1160 1161 /* Get the size of the old class install parameters */ 1162 if (!SetupDiGetClassInstallParams(DeviceInfoSet, 1163 DeviceInfoData, 1164 NULL, 1165 0, 1166 &dwSize)) 1167 { 1168 dwError = GetLastError(); 1169 if (dwError != ERROR_INSUFFICIENT_BUFFER) 1170 { 1171 ERR("SetupDiGetClassInstallParams failed (Error %lu)\n", dwError); 1172 return FALSE; 1173 } 1174 } 1175 1176 /* Allocate a buffer for the old class install parameters */ 1177 pClassInstallParams = HeapAlloc(GetProcessHeap(), 0, dwSize); 1178 if (pClassInstallParams == NULL) 1179 { 1180 ERR("Failed to allocate the parameters buffer!\n"); 1181 return FALSE; 1182 } 1183 1184 /* Save the old class install parameters */ 1185 if (!SetupDiGetClassInstallParams(DeviceInfoSet, 1186 DeviceInfoData, 1187 pClassInstallParams, 1188 dwSize, 1189 &dwSize)) 1190 { 1191 ERR("SetupDiGetClassInstallParams failed (Error %lu)\n", GetLastError()); 1192 ret = FALSE; 1193 goto done; 1194 } 1195 1196 /* Set the new class install parameters */ 1197 if (!SetupDiSetClassInstallParams(DeviceInfoSet, 1198 DeviceInfoData, 1199 &PageData->ClassInstallHeader, 1200 sizeof(SP_ADDPROPERTYPAGE_DATA))) 1201 { 1202 ERR("SetupDiSetClassInstallParams failed (Error %lu)\n", dwError); 1203 ret = FALSE; 1204 goto done; 1205 } 1206 1207 /* Call the installer */ 1208 ret = SetupDiCallClassInstaller(InstallFunction, 1209 DeviceInfoSet, 1210 DeviceInfoData); 1211 if (ret == FALSE) 1212 { 1213 ERR("SetupDiCallClassInstaller failed\n"); 1214 goto done; 1215 } 1216 1217 /* Read the new class installer parameters */ 1218 if (!SetupDiGetClassInstallParams(DeviceInfoSet, 1219 DeviceInfoData, 1220 &PageData->ClassInstallHeader, 1221 sizeof(SP_ADDPROPERTYPAGE_DATA), 1222 NULL)) 1223 { 1224 ERR("SetupDiGetClassInstallParams failed (Error %lu)\n", GetLastError()); 1225 ret = FALSE; 1226 goto done; 1227 } 1228 1229 done: 1230 /* Restore and free the old class install parameters */ 1231 if (pClassInstallParams != NULL) 1232 { 1233 SetupDiSetClassInstallParams(DeviceInfoSet, 1234 DeviceInfoData, 1235 pClassInstallParams, 1236 dwSize); 1237 1238 HeapFree(GetProcessHeap(), 0, pClassInstallParams); 1239 } 1240 1241 return ret; 1242 } 1243 1244 /*********************************************************************** 1245 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@) 1246 */ 1247 BOOL WINAPI 1248 SetupDiGetClassDevPropertySheetsW( 1249 IN HDEVINFO DeviceInfoSet, 1250 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 1251 IN OUT LPPROPSHEETHEADERW PropertySheetHeader, 1252 IN DWORD PropertySheetHeaderPageListSize, 1253 OUT PDWORD RequiredSize OPTIONAL, 1254 IN DWORD PropertySheetType) 1255 { 1256 struct DeviceInfoSet *devInfoSet = NULL; 1257 struct DeviceInfo *devInfo = NULL; 1258 BOOL ret = FALSE; 1259 1260 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, 1261 PropertySheetHeader, PropertySheetHeaderPageListSize, 1262 RequiredSize, PropertySheetType); 1263 1264 if (!DeviceInfoSet) 1265 SetLastError(ERROR_INVALID_HANDLE); 1266 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1267 SetLastError(ERROR_INVALID_HANDLE); 1268 else if ((devInfoSet = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 1269 SetLastError(ERROR_INVALID_HANDLE); 1270 else if (!PropertySheetHeader) 1271 SetLastError(ERROR_INVALID_PARAMETER); 1272 else if (PropertySheetHeader->dwFlags & PSH_PROPSHEETPAGE) 1273 SetLastError(ERROR_INVALID_FLAGS); 1274 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 1275 SetLastError(ERROR_INVALID_USER_BUFFER); 1276 else if (!DeviceInfoData && IsEqualIID(&devInfoSet->ClassGuid, &GUID_NULL)) 1277 SetLastError(ERROR_INVALID_PARAMETER); 1278 else if (PropertySheetType != DIGCDP_FLAG_ADVANCED 1279 && PropertySheetType != DIGCDP_FLAG_BASIC 1280 && PropertySheetType != DIGCDP_FLAG_REMOTE_ADVANCED 1281 && PropertySheetType != DIGCDP_FLAG_REMOTE_BASIC) 1282 SetLastError(ERROR_INVALID_PARAMETER); 1283 else 1284 { 1285 HKEY hKey = INVALID_HANDLE_VALUE; 1286 SP_PROPSHEETPAGE_REQUEST Request; 1287 LPWSTR PropPageProvider = NULL; 1288 HMODULE hModule = NULL; 1289 PROPERTY_PAGE_PROVIDER pPropPageProvider = NULL; 1290 struct ClassDevPropertySheetsData PropPageData; 1291 SP_ADDPROPERTYPAGE_DATA InstallerPropPageData; 1292 DWORD InitialNumberOfPages, i; 1293 DWORD rc; 1294 1295 if (DeviceInfoData) 1296 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 1297 1298 /* Get the class property page provider */ 1299 if (devInfoSet->hmodClassPropPageProvider == NULL) 1300 { 1301 hKey = SetupDiOpenClassRegKeyExW(devInfo ? &devInfo->ClassGuid : &devInfoSet->ClassGuid, KEY_QUERY_VALUE, 1302 DIOCR_INSTALLER, NULL/*devInfoSet->MachineName + 2*/, NULL); 1303 if (hKey != INVALID_HANDLE_VALUE) 1304 { 1305 rc = SETUP_GetValueString(hKey, REGSTR_VAL_ENUMPROPPAGES_32, &PropPageProvider); 1306 if (rc == ERROR_SUCCESS) 1307 { 1308 rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider); 1309 if (rc != ERROR_SUCCESS) 1310 { 1311 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER); 1312 goto cleanup; 1313 } 1314 1315 devInfoSet->hmodClassPropPageProvider = hModule; 1316 devInfoSet->pClassPropPageProvider = pPropPageProvider; 1317 1318 HeapFree(GetProcessHeap(), 0, PropPageProvider); 1319 PropPageProvider = NULL; 1320 } 1321 1322 RegCloseKey(hKey); 1323 hKey = INVALID_HANDLE_VALUE; 1324 } 1325 } 1326 1327 /* Get the device property page provider */ 1328 if (devInfo != NULL && devInfo->hmodDevicePropPageProvider == NULL) 1329 { 1330 hKey = SETUPDI_OpenDrvKey(devInfoSet->HKLM, devInfo, KEY_QUERY_VALUE); 1331 if (hKey != INVALID_HANDLE_VALUE) 1332 { 1333 rc = SETUP_GetValueString(hKey, REGSTR_VAL_ENUMPROPPAGES_32, &PropPageProvider); 1334 if (rc == ERROR_SUCCESS) 1335 { 1336 rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider); 1337 if (rc != ERROR_SUCCESS) 1338 { 1339 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER); 1340 goto cleanup; 1341 } 1342 1343 devInfo->hmodDevicePropPageProvider = hModule; 1344 devInfo->pDevicePropPageProvider = pPropPageProvider; 1345 1346 HeapFree(GetProcessHeap(), 0, PropPageProvider); 1347 PropPageProvider = NULL; 1348 } 1349 1350 RegCloseKey(hKey); 1351 hKey = INVALID_HANDLE_VALUE; 1352 } 1353 } 1354 1355 InitialNumberOfPages = PropertySheetHeader->nPages; 1356 1357 Request.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST); 1358 Request.PageRequested = SPPSR_ENUM_ADV_DEVICE_PROPERTIES; 1359 Request.DeviceInfoSet = DeviceInfoSet; 1360 Request.DeviceInfoData = DeviceInfoData; 1361 1362 PropPageData.PropertySheetHeader = PropertySheetHeader; 1363 PropPageData.PropertySheetHeaderPageListSize = PropertySheetHeaderPageListSize; 1364 PropPageData.NumberOfPages = 0; 1365 PropPageData.DontCancel = (RequiredSize != NULL) ? TRUE : FALSE; 1366 1367 /* Call the class property page provider */ 1368 if (devInfoSet->pClassPropPageProvider != NULL) 1369 ((PROPERTY_PAGE_PROVIDER)devInfoSet->pClassPropPageProvider)(&Request, SETUP_GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData); 1370 1371 /* Call the device property page provider */ 1372 if (devInfo != NULL && devInfo->pDevicePropPageProvider != NULL) 1373 ((PROPERTY_PAGE_PROVIDER)devInfo->pDevicePropPageProvider)(&Request, SETUP_GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData); 1374 1375 /* Call the class installer and add the returned pages */ 1376 ZeroMemory(&InstallerPropPageData, sizeof(SP_ADDPROPERTYPAGE_DATA)); 1377 InstallerPropPageData.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); 1378 InstallerPropPageData.ClassInstallHeader.InstallFunction = DIF_ADDPROPERTYPAGE_ADVANCED; 1379 InstallerPropPageData.hwndWizardDlg = PropertySheetHeader->hwndParent; 1380 1381 if (SETUP_CallInstaller(DIF_ADDPROPERTYPAGE_ADVANCED, 1382 DeviceInfoSet, 1383 DeviceInfoData, 1384 &InstallerPropPageData)) 1385 { 1386 for (i = 0; i < InstallerPropPageData.NumDynamicPages; i++) 1387 { 1388 if (PropPageData.PropertySheetHeader->nPages < PropertySheetHeaderPageListSize) 1389 { 1390 PropPageData.PropertySheetHeader->phpage[PropPageData.PropertySheetHeader->nPages] = 1391 InstallerPropPageData.DynamicPages[i]; 1392 PropPageData.PropertySheetHeader->nPages++; 1393 } 1394 } 1395 1396 PropPageData.NumberOfPages += InstallerPropPageData.NumDynamicPages; 1397 } 1398 1399 if (RequiredSize) 1400 *RequiredSize = PropPageData.NumberOfPages; 1401 1402 if (InitialNumberOfPages + PropPageData.NumberOfPages <= PropertySheetHeaderPageListSize) 1403 { 1404 ret = TRUE; 1405 } 1406 else 1407 { 1408 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1409 } 1410 1411 cleanup: 1412 if (hKey != INVALID_HANDLE_VALUE) 1413 RegCloseKey(hKey); 1414 1415 if (PropPageProvider != NULL) 1416 HeapFree(GetProcessHeap(), 0, PropPageProvider); 1417 } 1418 1419 TRACE("Returning %d\n", ret); 1420 return ret; 1421 } 1422