1 /* 2 * ReactOS kernel 3 * Copyright (C) 2005 ReactOS Team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 /* 20 * COPYRIGHT: See COPYING in the top level directory 21 * PROJECT: ReactOS kernel 22 * FILE: base/services/umpnpmgr/rpcserver.c 23 * PURPOSE: RPC server 24 * PROGRAMMER: Eric Kohl (eric.kohl@reactos.org) 25 * Herv� Poussineau (hpoussin@reactos.org) 26 * Colin Finck (colin@reactos.org) 27 */ 28 29 /* INCLUDES *****************************************************************/ 30 31 #include "precomp.h" 32 33 #define NDEBUG 34 #include <debug.h> 35 36 37 /* GLOBALS ******************************************************************/ 38 39 static WCHAR szRootDeviceInstanceID[] = L"HTREE\\ROOT\\0"; 40 41 42 /* FUNCTIONS *****************************************************************/ 43 44 DWORD WINAPI 45 RpcServerThread(LPVOID lpParameter) 46 { 47 RPC_STATUS Status; 48 BOOLEAN RegisteredProtSeq = FALSE; 49 50 UNREFERENCED_PARAMETER(lpParameter); 51 52 DPRINT("RpcServerThread() called\n"); 53 54 #if 0 55 /* 2k/XP/2k3-compatible protocol sequence/endpoint */ 56 Status = RpcServerUseProtseqEpW(L"ncacn_np", 57 20, 58 L"\\pipe\\ntsvcs", 59 NULL); // Security descriptor 60 if (Status == RPC_S_OK) 61 RegisteredProtSeq = TRUE; 62 else 63 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); 64 #endif 65 66 /* Vista/7-compatible protocol sequence/endpoint */ 67 Status = RpcServerUseProtseqEpW(L"ncacn_np", 68 20, 69 L"\\pipe\\plugplay", 70 NULL); // Security descriptor 71 if (Status == RPC_S_OK) 72 RegisteredProtSeq = TRUE; 73 else 74 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); 75 76 /* Make sure there's a usable endpoint */ 77 if (RegisteredProtSeq == FALSE) 78 return 0; 79 80 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec, 81 NULL, 82 NULL); 83 if (Status != RPC_S_OK) 84 { 85 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status); 86 return 0; 87 } 88 89 Status = RpcServerListen(1, 90 20, 91 FALSE); 92 if (Status != RPC_S_OK) 93 { 94 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status); 95 return 0; 96 } 97 98 /* ROS HACK (this should never happen...) */ 99 DPRINT1("*** Other devices won't be installed correctly. If something\n"); 100 DPRINT1("*** doesn't work, try to reboot to get a new chance.\n"); 101 102 DPRINT("RpcServerThread() done\n"); 103 104 return 0; 105 } 106 107 108 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len) 109 { 110 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); 111 } 112 113 114 void __RPC_USER midl_user_free(void __RPC_FAR * ptr) 115 { 116 HeapFree(GetProcessHeap(), 0, ptr); 117 } 118 119 120 static CONFIGRET WINAPI 121 NtStatusToCrError(NTSTATUS Status) 122 { 123 switch (Status) 124 { 125 case STATUS_NOT_IMPLEMENTED: 126 return CR_CALL_NOT_IMPLEMENTED; 127 128 case STATUS_INVALID_PARAMETER: 129 return CR_INVALID_DATA; 130 131 case STATUS_NO_SUCH_DEVICE: 132 return CR_NO_SUCH_DEVINST; 133 134 case STATUS_ACCESS_DENIED: 135 return CR_ACCESS_DENIED; 136 137 case STATUS_BUFFER_TOO_SMALL: 138 return CR_BUFFER_SMALL; 139 140 case STATUS_OBJECT_NAME_NOT_FOUND: 141 return CR_NO_SUCH_VALUE; 142 143 default: 144 return CR_FAILURE; 145 } 146 } 147 148 149 static VOID 150 SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID, 151 OUT LPWSTR pszEnumerator, 152 OUT LPWSTR pszDevice, 153 OUT LPWSTR pszInstance) 154 { 155 WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN]; 156 LPWSTR lpEnumerator = NULL; 157 LPWSTR lpDevice = NULL; 158 LPWSTR lpInstance = NULL; 159 LPWSTR ptr; 160 161 wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID); 162 163 *pszEnumerator = 0; 164 *pszDevice = 0; 165 *pszInstance = 0; 166 167 lpEnumerator = szLocalDeviceInstanceID; 168 169 ptr = wcschr(lpEnumerator, L'\\'); 170 if (ptr != NULL) 171 { 172 *ptr = 0; 173 lpDevice = ++ptr; 174 175 ptr = wcschr(lpDevice, L'\\'); 176 if (ptr != NULL) 177 { 178 *ptr = 0; 179 lpInstance = ++ptr; 180 } 181 } 182 183 if (lpEnumerator != NULL) 184 wcscpy(pszEnumerator, lpEnumerator); 185 186 if (lpDevice != NULL) 187 wcscpy(pszDevice, lpDevice); 188 189 if (lpInstance != NULL) 190 wcscpy(pszInstance, lpInstance); 191 } 192 193 194 static 195 CONFIGRET 196 ClearDeviceStatus( 197 _In_ LPWSTR pszDeviceID, 198 _In_ DWORD ulStatus, 199 _In_ DWORD ulProblem) 200 { 201 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData; 202 CONFIGRET ret = CR_SUCCESS; 203 NTSTATUS Status; 204 205 DPRINT1("ClearDeviceStatus(%S 0x%lx 0x%lx)\n", 206 pszDeviceID, ulStatus, ulProblem); 207 208 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 209 pszDeviceID); 210 PlugPlayData.Operation = PNP_CLEAR_DEVICE_STATUS; 211 PlugPlayData.DeviceStatus = ulStatus; 212 PlugPlayData.DeviceProblem = ulProblem; 213 214 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus, 215 (PVOID)&PlugPlayData, 216 sizeof(PLUGPLAY_CONTROL_STATUS_DATA)); 217 if (!NT_SUCCESS(Status)) 218 ret = NtStatusToCrError(Status); 219 220 return ret; 221 } 222 223 224 static 225 CONFIGRET 226 GetDeviceStatus( 227 _In_ LPWSTR pszDeviceID, 228 _Out_ DWORD *pulStatus, 229 _Out_ DWORD *pulProblem) 230 { 231 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData; 232 CONFIGRET ret = CR_SUCCESS; 233 NTSTATUS Status; 234 235 DPRINT("GetDeviceStatus(%S %p %p)\n", 236 pszDeviceID, pulStatus, pulProblem); 237 238 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 239 pszDeviceID); 240 PlugPlayData.Operation = PNP_GET_DEVICE_STATUS; 241 242 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus, 243 (PVOID)&PlugPlayData, 244 sizeof(PLUGPLAY_CONTROL_STATUS_DATA)); 245 if (NT_SUCCESS(Status)) 246 { 247 *pulStatus = PlugPlayData.DeviceStatus; 248 *pulProblem = PlugPlayData.DeviceProblem; 249 } 250 else 251 { 252 ret = NtStatusToCrError(Status); 253 } 254 255 return ret; 256 } 257 258 259 static 260 CONFIGRET 261 SetDeviceStatus( 262 _In_ LPWSTR pszDeviceID, 263 _In_ DWORD ulStatus, 264 _In_ DWORD ulProblem) 265 { 266 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData; 267 CONFIGRET ret = CR_SUCCESS; 268 NTSTATUS Status; 269 270 DPRINT1("SetDeviceStatus(%S 0x%lx 0x%lx)\n", 271 pszDeviceID, ulStatus, ulProblem); 272 273 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 274 pszDeviceID); 275 PlugPlayData.Operation = PNP_SET_DEVICE_STATUS; 276 PlugPlayData.DeviceStatus = ulStatus; 277 PlugPlayData.DeviceProblem = ulProblem; 278 279 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus, 280 (PVOID)&PlugPlayData, 281 sizeof(PLUGPLAY_CONTROL_STATUS_DATA)); 282 if (!NT_SUCCESS(Status)) 283 ret = NtStatusToCrError(Status); 284 285 return ret; 286 } 287 288 289 static 290 CONFIGRET 291 DisableDeviceInstance( 292 _In_ LPWSTR pszDeviceInstance, 293 _Inout_opt_ PPNP_VETO_TYPE pVetoType, 294 _Inout_opt_ LPWSTR pszVetoName, 295 _In_ DWORD ulNameLength) 296 { 297 PLUGPLAY_CONTROL_QUERY_REMOVE_DATA QueryRemoveData; 298 CONFIGRET ret = CR_SUCCESS; 299 NTSTATUS Status; 300 301 DPRINT1("DisableDeviceInstance(%S %p %p %lu)\n", 302 pszDeviceInstance, pVetoType, pszVetoName, ulNameLength); 303 304 RtlInitUnicodeString(&QueryRemoveData.DeviceInstance, 305 pszDeviceInstance); 306 307 QueryRemoveData.Flags = 0; 308 QueryRemoveData.VetoType = 0; 309 QueryRemoveData.VetoName = pszVetoName; 310 QueryRemoveData.NameLength = ulNameLength; 311 312 Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice, 313 &QueryRemoveData, 314 sizeof(PLUGPLAY_CONTROL_QUERY_REMOVE_DATA)); 315 if (Status == STATUS_NO_SUCH_DEVICE) 316 { 317 ret = CR_INVALID_DEVNODE; 318 } 319 else if (Status == STATUS_PLUGPLAY_QUERY_VETOED) 320 { 321 if (pVetoType != NULL) 322 *pVetoType = QueryRemoveData.VetoType; 323 324 ret = CR_REMOVE_VETOED; 325 } 326 else if (!NT_SUCCESS(Status)) 327 { 328 ret = NtStatusToCrError(Status); 329 } 330 331 return ret; 332 } 333 334 335 static 336 BOOL 337 IsValidDeviceInstanceID( 338 _In_ PWSTR pszDeviceInstanceID) 339 { 340 INT nPartLength[3] = {0, 0, 0}; 341 INT nLength = 0, nParts = 0; 342 PWCHAR p; 343 344 DPRINT("IsValidDeviceInstanceID(%S)\n", 345 pszDeviceInstanceID); 346 347 if (pszDeviceInstanceID == NULL) 348 { 349 DPRINT("Device instance ID is NULL!\n"); 350 return FALSE; 351 } 352 353 p = pszDeviceInstanceID; 354 while (*p != UNICODE_NULL) 355 { 356 if (*p == L'\\') 357 { 358 nParts++; 359 if (nParts >= 3) 360 { 361 DPRINT("Too many separators: %d\n", nParts); 362 return FALSE; 363 } 364 } 365 else 366 { 367 nPartLength[nParts]++; 368 } 369 370 nLength++; 371 if (nLength >= MAX_DEVICE_ID_LEN) 372 { 373 DPRINT("Too long: %d\n", nLength); 374 return FALSE; 375 } 376 377 p++; 378 } 379 380 if (nParts != 2) 381 { 382 DPRINT("Invalid number of separtors: %d\n", nParts); 383 return FALSE; 384 } 385 386 if ((nPartLength[0] == 0) || 387 (nPartLength[1] == 0) || 388 (nPartLength[2] == 0)) 389 { 390 DPRINT("Invalid part lengths: %d %d %d\n", 391 nPartLength[0], nPartLength[1], nPartLength[2]); 392 return FALSE; 393 } 394 395 DPRINT("Valid device instance ID!\n"); 396 397 return TRUE; 398 } 399 400 401 static 402 BOOL 403 IsRootDeviceInstanceID( 404 _In_ PWSTR pszDeviceInstanceID) 405 { 406 if (_wcsicmp(pszDeviceInstanceID, szRootDeviceInstanceID) == 0) 407 return TRUE; 408 409 return FALSE; 410 } 411 412 413 static 414 CONFIGRET 415 OpenConfigurationKey( 416 _In_ LPCWSTR pszDeviceID, 417 _Out_ PHKEY phKey) 418 { 419 WCHAR szKeyName[MAX_PATH]; 420 HKEY hInstanceKey; 421 DWORD dwError; 422 423 /* Build the full device instance key name */ 424 wcscpy(szKeyName, L"System\\CurrentControlSet\\Enum\\"); 425 wcscat(szKeyName, pszDeviceID); 426 427 /* Open the device instance key */ 428 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 429 szKeyName, 430 0, 431 KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY, 432 &hInstanceKey); 433 if (dwError != ERROR_SUCCESS) 434 return CR_INVALID_DEVINST; 435 436 /* Create or open the LogConf key */ 437 dwError = RegCreateKeyExW(hInstanceKey, 438 L"LogConf", 439 0, 440 NULL, 441 REG_OPTION_NON_VOLATILE, 442 KEY_ALL_ACCESS, 443 NULL, 444 phKey, 445 NULL); 446 447 /* Close the device instance key */ 448 RegCloseKey(hInstanceKey); 449 450 if (dwError != ERROR_SUCCESS) 451 return CR_REGISTRY_ERROR; 452 453 return CR_SUCCESS; 454 } 455 456 457 static 458 CONFIGRET 459 GetConfigurationData( 460 _In_ HKEY hKey, 461 _In_ ULONG ulLogConfType, 462 _Out_ PULONG pulRegDataType, 463 _Out_ PULONG pulDataSize, 464 _Out_ LPBYTE *ppBuffer) 465 { 466 LPCWSTR pszValueName; 467 468 switch (ulLogConfType) 469 { 470 case BOOT_LOG_CONF: 471 pszValueName = L"BootConfig"; 472 *pulRegDataType = REG_RESOURCE_LIST; 473 break; 474 475 case ALLOC_LOG_CONF: 476 pszValueName = L"AllocConfig"; 477 *pulRegDataType = REG_RESOURCE_LIST; 478 break; 479 480 case FORCED_LOG_CONF: 481 pszValueName = L"ForcedConfig"; 482 *pulRegDataType = REG_RESOURCE_LIST; 483 break; 484 485 case FILTERED_LOG_CONF: 486 pszValueName = L"FilteredConfigVector"; 487 *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST; 488 break; 489 490 case BASIC_LOG_CONF: 491 pszValueName = L"BasicConfigVector"; 492 *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST; 493 break; 494 495 case OVERRIDE_LOG_CONF: 496 pszValueName = L"OverrideConfigVector"; 497 *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST; 498 break; 499 500 default: 501 DPRINT1("Unsupported configuration type!\n"); 502 return CR_FAILURE; 503 } 504 505 /* Get the configuration data size */ 506 if (RegQueryValueExW(hKey, 507 pszValueName, 508 NULL, 509 NULL, 510 NULL, 511 pulDataSize) != ERROR_SUCCESS) 512 { 513 return CR_INVALID_LOG_CONF; 514 } 515 516 /* Allocate the buffer */ 517 *ppBuffer = HeapAlloc(GetProcessHeap(), 0, *pulDataSize); 518 if (*ppBuffer == NULL) 519 { 520 return CR_OUT_OF_MEMORY; 521 } 522 523 /* Retrieve the configuration data */ 524 if (RegQueryValueExW(hKey, 525 pszValueName, 526 NULL, 527 NULL, 528 (LPBYTE)*ppBuffer, 529 pulDataSize) != ERROR_SUCCESS) 530 { 531 return CR_INVALID_LOG_CONF; 532 } 533 534 return CR_SUCCESS; 535 } 536 537 538 /* PUBLIC FUNCTIONS **********************************************************/ 539 540 /* Function 0 */ 541 DWORD 542 WINAPI 543 PNP_Disconnect( 544 handle_t hBinding) 545 { 546 UNREFERENCED_PARAMETER(hBinding); 547 return CR_SUCCESS; 548 } 549 550 551 /* Function 1 */ 552 DWORD 553 WINAPI 554 PNP_Connect( 555 handle_t hBinding) 556 { 557 UNREFERENCED_PARAMETER(hBinding); 558 return CR_SUCCESS; 559 } 560 561 562 /* Function 2 */ 563 DWORD 564 WINAPI 565 PNP_GetVersion( 566 handle_t hBinding, 567 WORD *pVersion) 568 { 569 UNREFERENCED_PARAMETER(hBinding); 570 571 DPRINT("PNP_GetVersion(%p %p)\n", 572 hBinding, pVersion); 573 574 *pVersion = 0x0400; 575 576 return CR_SUCCESS; 577 } 578 579 580 /* Function 3 */ 581 DWORD 582 WINAPI 583 PNP_GetGlobalState( 584 handle_t hBinding, 585 DWORD *pulState, 586 DWORD ulFlags) 587 { 588 UNREFERENCED_PARAMETER(hBinding); 589 UNREFERENCED_PARAMETER(ulFlags); 590 591 DPRINT("PNP_GetGlobalState(%p %p 0x%08lx)\n", 592 hBinding, pulState, ulFlags); 593 594 *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE; 595 596 return CR_SUCCESS; 597 } 598 599 600 /* Function 4 */ 601 DWORD 602 WINAPI 603 PNP_InitDetection( 604 handle_t hBinding) 605 { 606 UNREFERENCED_PARAMETER(hBinding); 607 608 DPRINT("PNP_InitDetection(%p)\n", 609 hBinding); 610 611 return CR_SUCCESS; 612 } 613 614 615 /* Function 5 */ 616 DWORD 617 WINAPI 618 PNP_ReportLogOn( 619 handle_t hBinding, 620 BOOL Admin, 621 DWORD ProcessId) 622 { 623 DWORD ReturnValue = CR_FAILURE; 624 HANDLE hProcess; 625 626 UNREFERENCED_PARAMETER(hBinding); 627 UNREFERENCED_PARAMETER(Admin); 628 629 DPRINT("PNP_ReportLogOn(%p %u, %u)\n", 630 hBinding, Admin, ProcessId); 631 632 /* Get the users token */ 633 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId); 634 635 if (!hProcess) 636 { 637 DPRINT1("OpenProcess failed with error %u\n", GetLastError()); 638 goto cleanup; 639 } 640 641 if (hUserToken) 642 { 643 CloseHandle(hUserToken); 644 hUserToken = NULL; 645 } 646 647 if (!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken)) 648 { 649 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError()); 650 goto cleanup; 651 } 652 653 /* Trigger the installer thread */ 654 if (hInstallEvent) 655 SetEvent(hInstallEvent); 656 657 ReturnValue = CR_SUCCESS; 658 659 cleanup: 660 if (hProcess) 661 CloseHandle(hProcess); 662 663 return ReturnValue; 664 } 665 666 667 /* Function 6 */ 668 DWORD 669 WINAPI 670 PNP_ValidateDeviceInstance( 671 handle_t hBinding, 672 LPWSTR pDeviceID, 673 DWORD ulFlags) 674 { 675 CONFIGRET ret = CR_SUCCESS; 676 HKEY hDeviceKey = NULL; 677 678 UNREFERENCED_PARAMETER(hBinding); 679 UNREFERENCED_PARAMETER(ulFlags); 680 681 DPRINT("PNP_ValidateDeviceInstance(%p %S 0x%08lx)\n", 682 hBinding, pDeviceID, ulFlags); 683 684 if (!IsValidDeviceInstanceID(pDeviceID)) 685 return CR_INVALID_DEVINST; 686 687 if (RegOpenKeyExW(hEnumKey, 688 pDeviceID, 689 0, 690 KEY_READ, 691 &hDeviceKey)) 692 { 693 DPRINT("Could not open the Device Key!\n"); 694 ret = CR_NO_SUCH_DEVNODE; 695 goto Done; 696 } 697 698 /* FIXME: add more tests */ 699 700 Done: 701 if (hDeviceKey != NULL) 702 RegCloseKey(hDeviceKey); 703 704 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret); 705 706 return ret; 707 } 708 709 710 /* Function 7 */ 711 DWORD 712 WINAPI 713 PNP_GetRootDeviceInstance( 714 handle_t hBinding, 715 LPWSTR pDeviceID, 716 PNP_RPC_STRING_LEN ulLength) 717 { 718 CONFIGRET ret = CR_SUCCESS; 719 720 UNREFERENCED_PARAMETER(hBinding); 721 722 DPRINT("PNP_GetRootDeviceInstance(%p %S %lu)\n", 723 hBinding, pDeviceID, ulLength); 724 725 if (!pDeviceID) 726 { 727 ret = CR_INVALID_POINTER; 728 goto Done; 729 } 730 731 if (ulLength < lstrlenW(szRootDeviceInstanceID) + 1) 732 { 733 ret = CR_BUFFER_SMALL; 734 goto Done; 735 } 736 737 lstrcpyW(pDeviceID, 738 szRootDeviceInstanceID); 739 740 Done: 741 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret); 742 743 return ret; 744 } 745 746 747 /* Function 8 */ 748 DWORD 749 WINAPI 750 PNP_GetRelatedDeviceInstance( 751 handle_t hBinding, 752 DWORD ulRelationship, 753 LPWSTR pDeviceID, 754 LPWSTR pRelatedDeviceId, 755 PNP_RPC_STRING_LEN *pulLength, 756 DWORD ulFlags) 757 { 758 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData; 759 CONFIGRET ret = CR_SUCCESS; 760 NTSTATUS Status; 761 762 UNREFERENCED_PARAMETER(hBinding); 763 UNREFERENCED_PARAMETER(ulFlags); 764 765 DPRINT("PNP_GetRelatedDeviceInstance(%p %lu %S %p %p 0x%lx)\n", 766 hBinding, ulRelationship, pDeviceID, pRelatedDeviceId, 767 pulLength, ulFlags); 768 769 if (!IsValidDeviceInstanceID(pDeviceID)) 770 return CR_INVALID_DEVINST; 771 772 RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance, 773 pDeviceID); 774 775 PlugPlayData.Relation = ulRelationship; 776 777 PlugPlayData.RelatedDeviceInstanceLength = *pulLength; 778 PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId; 779 780 Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice, 781 (PVOID)&PlugPlayData, 782 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA)); 783 if (!NT_SUCCESS(Status)) 784 { 785 ret = NtStatusToCrError(Status); 786 } 787 788 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret); 789 if (ret == CR_SUCCESS) 790 { 791 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance); 792 } 793 794 return ret; 795 } 796 797 798 /* Function 9 */ 799 DWORD 800 WINAPI 801 PNP_EnumerateSubKeys( 802 handle_t hBinding, 803 DWORD ulBranch, 804 DWORD ulIndex, 805 LPWSTR Buffer, 806 PNP_RPC_STRING_LEN ulLength, 807 PNP_RPC_STRING_LEN *pulRequiredLen, 808 DWORD ulFlags) 809 { 810 CONFIGRET ret = CR_SUCCESS; 811 HKEY hKey; 812 DWORD dwError; 813 814 UNREFERENCED_PARAMETER(hBinding); 815 UNREFERENCED_PARAMETER(ulFlags); 816 817 DPRINT("PNP_EnumerateSubKeys(%p %lu %lu %p %lu %p 0x%08lx)\n", 818 hBinding, ulBranch, ulIndex, Buffer, ulLength, 819 pulRequiredLen, ulFlags); 820 821 switch (ulBranch) 822 { 823 case PNP_ENUMERATOR_SUBKEYS: 824 hKey = hEnumKey; 825 break; 826 827 case PNP_CLASS_SUBKEYS: 828 hKey = hClassKey; 829 break; 830 831 default: 832 return CR_FAILURE; 833 } 834 835 *pulRequiredLen = ulLength; 836 dwError = RegEnumKeyExW(hKey, 837 ulIndex, 838 Buffer, 839 pulRequiredLen, 840 NULL, 841 NULL, 842 NULL, 843 NULL); 844 if (dwError != ERROR_SUCCESS) 845 { 846 ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE; 847 } 848 else 849 { 850 (*pulRequiredLen)++; 851 } 852 853 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret); 854 855 return ret; 856 } 857 858 859 static 860 CONFIGRET 861 GetRelationsInstanceList( 862 _In_ PWSTR pszDevice, 863 _In_ DWORD ulFlags, 864 _Inout_ PWSTR pszBuffer, 865 _Inout_ PDWORD pulLength) 866 { 867 PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData; 868 NTSTATUS Status; 869 CONFIGRET ret = CR_SUCCESS; 870 871 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 872 pszDevice); 873 874 if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS) 875 { 876 PlugPlayData.Relations = 3; 877 } 878 else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS) 879 { 880 PlugPlayData.Relations = 2; 881 } 882 else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS) 883 { 884 PlugPlayData.Relations = 1; 885 } 886 else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS) 887 { 888 PlugPlayData.Relations = 0; 889 } 890 891 PlugPlayData.BufferSize = *pulLength * sizeof(WCHAR); 892 PlugPlayData.Buffer = pszBuffer; 893 894 Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations, 895 (PVOID)&PlugPlayData, 896 sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA)); 897 if (NT_SUCCESS(Status)) 898 { 899 *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR); 900 } 901 else 902 { 903 ret = NtStatusToCrError(Status); 904 } 905 906 return ret; 907 } 908 909 910 static 911 CONFIGRET 912 GetServiceInstanceList( 913 _In_ PWSTR pszService, 914 _Inout_ PWSTR pszBuffer, 915 _Inout_ PDWORD pulLength) 916 { 917 WCHAR szPathBuffer[512]; 918 WCHAR szName[16]; 919 HKEY hServicesKey = NULL, hServiceKey = NULL, hEnumKey = NULL; 920 DWORD dwValues, dwSize, dwIndex, dwUsedLength, dwPathLength; 921 DWORD dwError; 922 PWSTR pPtr; 923 CONFIGRET ret = CR_SUCCESS; 924 925 /* Open the device key */ 926 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 927 L"System\\CurrentControlSet\\Services", 928 0, 929 KEY_READ, 930 &hServicesKey); 931 if (dwError != ERROR_SUCCESS) 932 { 933 DPRINT("Failed to open the services key (Error %lu)\n", dwError); 934 return CR_REGISTRY_ERROR; 935 } 936 937 dwError = RegOpenKeyExW(hServicesKey, 938 pszService, 939 0, 940 KEY_READ, 941 &hServiceKey); 942 if (dwError != ERROR_SUCCESS) 943 { 944 DPRINT("Failed to open the service key (Error %lu)\n", dwError); 945 ret = CR_REGISTRY_ERROR; 946 goto Done; 947 } 948 949 dwError = RegOpenKeyExW(hServiceKey, 950 L"Enum", 951 0, 952 KEY_READ, 953 &hEnumKey); 954 if (dwError != ERROR_SUCCESS) 955 { 956 DPRINT("Failed to open the service enum key (Error %lu)\n", dwError); 957 ret = CR_REGISTRY_ERROR; 958 goto Done; 959 } 960 961 /* Retrieve the number of device instances */ 962 dwSize = sizeof(DWORD); 963 dwError = RegQueryValueExW(hEnumKey, 964 L"Count", 965 NULL, 966 NULL, 967 (LPBYTE)&dwValues, 968 &dwSize); 969 if (dwError != ERROR_SUCCESS) 970 { 971 DPRINT("RegQueryValueExW failed (Error %lu)\n", dwError); 972 dwValues = 1; 973 } 974 975 DPRINT("dwValues %lu\n", dwValues); 976 977 dwUsedLength = 0; 978 pPtr = pszBuffer; 979 980 for (dwIndex = 0; dwIndex < dwValues; dwIndex++) 981 { 982 wsprintf(szName, L"%lu", dwIndex); 983 984 dwSize = sizeof(szPathBuffer); 985 dwError = RegQueryValueExW(hEnumKey, 986 szName, 987 NULL, 988 NULL, 989 (LPBYTE)szPathBuffer, 990 &dwSize); 991 if (dwError != ERROR_SUCCESS) 992 break; 993 994 DPRINT("Path: %S\n", szPathBuffer); 995 996 dwPathLength = wcslen(szPathBuffer) + 1; 997 if (dwUsedLength + dwPathLength + 1 > *pulLength) 998 { 999 ret = CR_BUFFER_SMALL; 1000 break; 1001 } 1002 1003 wcscpy(pPtr, szPathBuffer); 1004 dwUsedLength += dwPathLength; 1005 pPtr += dwPathLength; 1006 1007 *pPtr = UNICODE_NULL; 1008 } 1009 1010 Done: 1011 if (hEnumKey != NULL) 1012 RegCloseKey(hEnumKey); 1013 1014 if (hServiceKey != NULL) 1015 RegCloseKey(hServiceKey); 1016 1017 if (hServicesKey != NULL) 1018 RegCloseKey(hServicesKey); 1019 1020 if (ret == CR_SUCCESS) 1021 *pulLength = dwUsedLength + 1; 1022 else 1023 *pulLength = 0; 1024 1025 return ret; 1026 } 1027 1028 1029 static 1030 CONFIGRET 1031 GetDeviceInstanceList( 1032 _In_ PWSTR pszDevice, 1033 _Inout_ PWSTR pszBuffer, 1034 _Inout_ PDWORD pulLength) 1035 { 1036 WCHAR szInstanceBuffer[MAX_DEVICE_ID_LEN]; 1037 WCHAR szPathBuffer[512]; 1038 HKEY hDeviceKey; 1039 DWORD dwInstanceLength, dwPathLength, dwUsedLength; 1040 DWORD dwIndex, dwError; 1041 PWSTR pPtr; 1042 CONFIGRET ret = CR_SUCCESS; 1043 1044 /* Open the device key */ 1045 dwError = RegOpenKeyExW(hEnumKey, 1046 pszDevice, 1047 0, 1048 KEY_ENUMERATE_SUB_KEYS, 1049 &hDeviceKey); 1050 if (dwError != ERROR_SUCCESS) 1051 { 1052 DPRINT("Failed to open the device key (Error %lu)\n", dwError); 1053 return CR_REGISTRY_ERROR; 1054 } 1055 1056 dwUsedLength = 0; 1057 pPtr = pszBuffer; 1058 1059 for (dwIndex = 0; ; dwIndex++) 1060 { 1061 dwInstanceLength = MAX_DEVICE_ID_LEN; 1062 dwError = RegEnumKeyExW(hDeviceKey, 1063 dwIndex, 1064 szInstanceBuffer, 1065 &dwInstanceLength, 1066 NULL, 1067 NULL, 1068 NULL, 1069 NULL); 1070 if (dwError != ERROR_SUCCESS) 1071 break; 1072 1073 wsprintf(szPathBuffer, L"%s\\%s", pszDevice, szInstanceBuffer); 1074 DPRINT("Path: %S\n", szPathBuffer); 1075 1076 dwPathLength = wcslen(szPathBuffer) + 1; 1077 if (dwUsedLength + dwPathLength + 1 > *pulLength) 1078 { 1079 ret = CR_BUFFER_SMALL; 1080 break; 1081 } 1082 1083 wcscpy(pPtr, szPathBuffer); 1084 dwUsedLength += dwPathLength; 1085 pPtr += dwPathLength; 1086 1087 *pPtr = UNICODE_NULL; 1088 } 1089 1090 RegCloseKey(hDeviceKey); 1091 1092 if (ret == CR_SUCCESS) 1093 *pulLength = dwUsedLength + 1; 1094 else 1095 *pulLength = 0; 1096 1097 return ret; 1098 } 1099 1100 1101 CONFIGRET 1102 GetEnumeratorInstanceList( 1103 _In_ PWSTR pszEnumerator, 1104 _Inout_ PWSTR pszBuffer, 1105 _Inout_ PDWORD pulLength) 1106 { 1107 WCHAR szDeviceBuffer[MAX_DEVICE_ID_LEN]; 1108 WCHAR szPathBuffer[512]; 1109 HKEY hEnumeratorKey; 1110 PWSTR pPtr; 1111 DWORD dwIndex, dwDeviceLength, dwUsedLength, dwRemainingLength, dwPathLength; 1112 DWORD dwError; 1113 CONFIGRET ret = CR_SUCCESS; 1114 1115 /* Open the enumerator key */ 1116 dwError = RegOpenKeyExW(hEnumKey, 1117 pszEnumerator, 1118 0, 1119 KEY_ENUMERATE_SUB_KEYS, 1120 &hEnumeratorKey); 1121 if (dwError != ERROR_SUCCESS) 1122 { 1123 DPRINT("Failed to open the enumerator key (Error %lu)\n", dwError); 1124 return CR_REGISTRY_ERROR; 1125 } 1126 1127 dwUsedLength = 0; 1128 dwRemainingLength = *pulLength; 1129 pPtr = pszBuffer; 1130 1131 for (dwIndex = 0; ; dwIndex++) 1132 { 1133 dwDeviceLength = MAX_DEVICE_ID_LEN; 1134 dwError = RegEnumKeyExW(hEnumeratorKey, 1135 dwIndex, 1136 szDeviceBuffer, 1137 &dwDeviceLength, 1138 NULL, 1139 NULL, 1140 NULL, 1141 NULL); 1142 if (dwError != ERROR_SUCCESS) 1143 break; 1144 1145 wsprintf(szPathBuffer, L"%s\\%s", pszEnumerator, szDeviceBuffer); 1146 DPRINT("Path: %S\n", szPathBuffer); 1147 1148 dwPathLength = dwRemainingLength; 1149 ret = GetDeviceInstanceList(szPathBuffer, 1150 pPtr, 1151 &dwPathLength); 1152 if (ret != CR_SUCCESS) 1153 break; 1154 1155 dwUsedLength += dwPathLength - 1; 1156 dwRemainingLength += dwPathLength - 1; 1157 pPtr += dwPathLength - 1; 1158 } 1159 1160 RegCloseKey(hEnumeratorKey); 1161 1162 if (ret == CR_SUCCESS) 1163 *pulLength = dwUsedLength + 1; 1164 else 1165 *pulLength = 0; 1166 1167 return ret; 1168 } 1169 1170 1171 static 1172 CONFIGRET 1173 GetAllInstanceList( 1174 _Inout_ PWSTR pszBuffer, 1175 _Inout_ PDWORD pulLength) 1176 { 1177 WCHAR szEnumeratorBuffer[MAX_DEVICE_ID_LEN]; 1178 PWSTR pPtr; 1179 DWORD dwIndex, dwEnumeratorLength, dwUsedLength, dwRemainingLength, dwPathLength; 1180 DWORD dwError; 1181 CONFIGRET ret = CR_SUCCESS; 1182 1183 dwUsedLength = 0; 1184 dwRemainingLength = *pulLength; 1185 pPtr = pszBuffer; 1186 1187 for (dwIndex = 0; ; dwIndex++) 1188 { 1189 dwEnumeratorLength = MAX_DEVICE_ID_LEN; 1190 dwError = RegEnumKeyExW(hEnumKey, 1191 dwIndex, 1192 szEnumeratorBuffer, 1193 &dwEnumeratorLength, 1194 NULL, NULL, NULL, NULL); 1195 if (dwError != ERROR_SUCCESS) 1196 break; 1197 1198 dwPathLength = dwRemainingLength; 1199 ret = GetEnumeratorInstanceList(szEnumeratorBuffer, 1200 pPtr, 1201 &dwPathLength); 1202 if (ret != CR_SUCCESS) 1203 break; 1204 1205 dwUsedLength += dwPathLength - 1; 1206 dwRemainingLength += dwPathLength - 1; 1207 pPtr += dwPathLength - 1; 1208 } 1209 1210 if (ret == CR_SUCCESS) 1211 *pulLength = dwUsedLength + 1; 1212 else 1213 *pulLength = 0; 1214 1215 return ret; 1216 } 1217 1218 1219 /* Function 10 */ 1220 DWORD 1221 WINAPI 1222 PNP_GetDeviceList( 1223 handle_t hBinding, 1224 LPWSTR pszFilter, 1225 LPWSTR Buffer, 1226 PNP_RPC_STRING_LEN *pulLength, 1227 DWORD ulFlags) 1228 { 1229 WCHAR szEnumerator[MAX_DEVICE_ID_LEN]; 1230 WCHAR szDevice[MAX_DEVICE_ID_LEN]; 1231 WCHAR szInstance[MAX_DEVICE_ID_LEN]; 1232 CONFIGRET ret = CR_SUCCESS; 1233 1234 DPRINT("PNP_GetDeviceList(%p %S %p %p 0x%08lx)\n", 1235 hBinding, pszFilter, Buffer, pulLength, ulFlags); 1236 1237 if (ulFlags & ~CM_GETIDLIST_FILTER_BITS) 1238 return CR_INVALID_FLAG; 1239 1240 if (pulLength == NULL) 1241 return CR_INVALID_POINTER; 1242 1243 if ((ulFlags != CM_GETIDLIST_FILTER_NONE) && 1244 (pszFilter == NULL)) 1245 return CR_INVALID_POINTER; 1246 1247 if (ulFlags & 1248 (CM_GETIDLIST_FILTER_BUSRELATIONS | 1249 CM_GETIDLIST_FILTER_POWERRELATIONS | 1250 CM_GETIDLIST_FILTER_REMOVALRELATIONS | 1251 CM_GETIDLIST_FILTER_EJECTRELATIONS)) 1252 { 1253 ret = GetRelationsInstanceList(pszFilter, 1254 ulFlags, 1255 Buffer, 1256 pulLength); 1257 } 1258 else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE) 1259 { 1260 ret = GetServiceInstanceList(pszFilter, 1261 Buffer, 1262 pulLength); 1263 } 1264 else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR) 1265 { 1266 SplitDeviceInstanceID(pszFilter, 1267 szEnumerator, 1268 szDevice, 1269 szInstance); 1270 1271 if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL) 1272 { 1273 ret = GetDeviceInstanceList(pszFilter, 1274 Buffer, 1275 pulLength); 1276 } 1277 else 1278 { 1279 ret = GetEnumeratorInstanceList(pszFilter, 1280 Buffer, 1281 pulLength); 1282 } 1283 } 1284 else /* CM_GETIDLIST_FILTER_NONE */ 1285 { 1286 ret = GetAllInstanceList(Buffer, 1287 pulLength); 1288 } 1289 1290 return ret; 1291 } 1292 1293 1294 static 1295 CONFIGRET 1296 GetRelationsInstanceListSize( 1297 _In_ PWSTR pszDevice, 1298 _In_ DWORD ulFlags, 1299 _Inout_ PDWORD pulLength) 1300 { 1301 PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData; 1302 NTSTATUS Status; 1303 CONFIGRET ret = CR_SUCCESS; 1304 1305 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 1306 pszDevice); 1307 1308 if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS) 1309 { 1310 PlugPlayData.Relations = 3; 1311 } 1312 else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS) 1313 { 1314 PlugPlayData.Relations = 2; 1315 } 1316 else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS) 1317 { 1318 PlugPlayData.Relations = 1; 1319 } 1320 else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS) 1321 { 1322 PlugPlayData.Relations = 0; 1323 } 1324 1325 PlugPlayData.BufferSize = 0; 1326 PlugPlayData.Buffer = NULL; 1327 1328 Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations, 1329 (PVOID)&PlugPlayData, 1330 sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA)); 1331 if (NT_SUCCESS(Status)) 1332 { 1333 *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR); 1334 } 1335 else 1336 { 1337 ret = NtStatusToCrError(Status); 1338 } 1339 1340 return ret; 1341 } 1342 1343 1344 static 1345 CONFIGRET 1346 GetServiceInstanceListSize( 1347 _In_ PWSTR pszService, 1348 _Out_ PDWORD pulLength) 1349 { 1350 HKEY hServicesKey = NULL, hServiceKey = NULL, hEnumKey = NULL; 1351 DWORD dwValues, dwMaxValueLength, dwSize; 1352 DWORD dwError; 1353 CONFIGRET ret = CR_SUCCESS; 1354 1355 /* Open the device key */ 1356 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1357 L"System\\CurrentControlSet\\Services", 1358 0, 1359 KEY_READ, 1360 &hServicesKey); 1361 if (dwError != ERROR_SUCCESS) 1362 { 1363 DPRINT("Failed to open the services key (Error %lu)\n", dwError); 1364 return CR_REGISTRY_ERROR; 1365 } 1366 1367 dwError = RegOpenKeyExW(hServicesKey, 1368 pszService, 1369 0, 1370 KEY_READ, 1371 &hServiceKey); 1372 if (dwError != ERROR_SUCCESS) 1373 { 1374 DPRINT("Failed to open the service key (Error %lu)\n", dwError); 1375 ret = CR_REGISTRY_ERROR; 1376 goto Done; 1377 } 1378 1379 dwError = RegOpenKeyExW(hServiceKey, 1380 L"Enum", 1381 0, 1382 KEY_READ, 1383 &hEnumKey); 1384 if (dwError != ERROR_SUCCESS) 1385 { 1386 DPRINT("Failed to open the service enum key (Error %lu)\n", dwError); 1387 ret = CR_REGISTRY_ERROR; 1388 goto Done; 1389 } 1390 1391 /* Retrieve the number of device instances */ 1392 dwSize = sizeof(DWORD); 1393 dwError = RegQueryValueExW(hEnumKey, 1394 L"Count", 1395 NULL, 1396 NULL, 1397 (LPBYTE)&dwValues, 1398 &dwSize); 1399 if (dwError != ERROR_SUCCESS) 1400 { 1401 DPRINT("RegQueryValueExW failed (Error %lu)\n", dwError); 1402 dwValues = 1; 1403 } 1404 1405 /* Retrieve the maximum instance name length */ 1406 dwError = RegQueryInfoKeyW(hEnumKey, 1407 NULL, 1408 NULL, 1409 NULL, 1410 NULL, 1411 NULL, 1412 NULL, 1413 NULL, 1414 NULL, 1415 &dwMaxValueLength, 1416 NULL, 1417 NULL); 1418 if (dwError != ERROR_SUCCESS) 1419 { 1420 DPRINT("RegQueryInfoKeyW failed (Error %lu)\n", dwError); 1421 dwMaxValueLength = MAX_DEVICE_ID_LEN; 1422 } 1423 1424 DPRINT("dwValues %lu dwMaxValueLength %lu\n", dwValues, dwMaxValueLength / sizeof(WCHAR)); 1425 1426 /* Return the largest possible buffer size */ 1427 *pulLength = dwValues * dwMaxValueLength / sizeof(WCHAR) + 2; 1428 1429 Done: 1430 if (hEnumKey != NULL) 1431 RegCloseKey(hEnumKey); 1432 1433 if (hServiceKey != NULL) 1434 RegCloseKey(hServiceKey); 1435 1436 if (hServicesKey != NULL) 1437 RegCloseKey(hServicesKey); 1438 1439 return ret; 1440 } 1441 1442 1443 static 1444 CONFIGRET 1445 GetDeviceInstanceListSize( 1446 _In_ LPCWSTR pszDevice, 1447 _Out_ PULONG pulLength) 1448 { 1449 HKEY hDeviceKey; 1450 DWORD dwSubKeys, dwMaxSubKeyLength; 1451 DWORD dwError; 1452 1453 /* Open the device key */ 1454 dwError = RegOpenKeyExW(hEnumKey, 1455 pszDevice, 1456 0, 1457 KEY_READ, 1458 &hDeviceKey); 1459 if (dwError != ERROR_SUCCESS) 1460 { 1461 DPRINT("Failed to open the device key (Error %lu)\n", dwError); 1462 return CR_REGISTRY_ERROR; 1463 } 1464 1465 /* Retrieve the number of device instances and the maximum name length */ 1466 dwError = RegQueryInfoKeyW(hDeviceKey, 1467 NULL, 1468 NULL, 1469 NULL, 1470 &dwSubKeys, 1471 &dwMaxSubKeyLength, 1472 NULL, 1473 NULL, 1474 NULL, 1475 NULL, 1476 NULL, 1477 NULL); 1478 if (dwError != ERROR_SUCCESS) 1479 { 1480 DPRINT("RegQueryInfoKeyW failed (Error %lu)\n", dwError); 1481 dwSubKeys = 0; 1482 dwMaxSubKeyLength = 0; 1483 } 1484 1485 /* Close the device key */ 1486 RegCloseKey(hDeviceKey); 1487 1488 /* Return the largest possible buffer size */ 1489 *pulLength = dwSubKeys * (wcslen(pszDevice) + 1 + dwMaxSubKeyLength + 1); 1490 1491 return CR_SUCCESS; 1492 } 1493 1494 1495 static 1496 CONFIGRET 1497 GetEnumeratorInstanceListSize( 1498 _In_ LPCWSTR pszEnumerator, 1499 _Out_ PULONG pulLength) 1500 { 1501 WCHAR szDeviceBuffer[MAX_DEVICE_ID_LEN]; 1502 WCHAR szPathBuffer[512]; 1503 HKEY hEnumeratorKey; 1504 DWORD dwIndex, dwDeviceLength, dwBufferLength; 1505 DWORD dwError; 1506 CONFIGRET ret = CR_SUCCESS; 1507 1508 *pulLength = 0; 1509 1510 /* Open the enumerator key */ 1511 dwError = RegOpenKeyExW(hEnumKey, 1512 pszEnumerator, 1513 0, 1514 KEY_ENUMERATE_SUB_KEYS, 1515 &hEnumeratorKey); 1516 if (dwError != ERROR_SUCCESS) 1517 { 1518 DPRINT("Failed to open the enumerator key (Error %lu)\n", dwError); 1519 return CR_REGISTRY_ERROR; 1520 } 1521 1522 for (dwIndex = 0; ; dwIndex++) 1523 { 1524 dwDeviceLength = MAX_DEVICE_ID_LEN; 1525 dwError = RegEnumKeyExW(hEnumeratorKey, 1526 dwIndex, 1527 szDeviceBuffer, 1528 &dwDeviceLength, 1529 NULL, 1530 NULL, 1531 NULL, 1532 NULL); 1533 if (dwError != ERROR_SUCCESS) 1534 break; 1535 1536 wsprintf(szPathBuffer, L"%s\\%s", pszEnumerator, szDeviceBuffer); 1537 DPRINT("Path: %S\n", szPathBuffer); 1538 1539 ret = GetDeviceInstanceListSize(szPathBuffer, &dwBufferLength); 1540 if (ret != CR_SUCCESS) 1541 { 1542 *pulLength = 0; 1543 break; 1544 } 1545 1546 *pulLength += dwBufferLength; 1547 } 1548 1549 /* Close the enumerator key */ 1550 RegCloseKey(hEnumeratorKey); 1551 1552 return ret; 1553 } 1554 1555 1556 static 1557 CONFIGRET 1558 GetAllInstanceListSize( 1559 _Out_ PULONG pulLength) 1560 { 1561 WCHAR szEnumeratorBuffer[MAX_DEVICE_ID_LEN]; 1562 DWORD dwIndex, dwEnumeratorLength, dwBufferLength; 1563 DWORD dwError; 1564 CONFIGRET ret = CR_SUCCESS; 1565 1566 for (dwIndex = 0; ; dwIndex++) 1567 { 1568 dwEnumeratorLength = MAX_DEVICE_ID_LEN; 1569 dwError = RegEnumKeyExW(hEnumKey, 1570 dwIndex, 1571 szEnumeratorBuffer, 1572 &dwEnumeratorLength, 1573 NULL, NULL, NULL, NULL); 1574 if (dwError != ERROR_SUCCESS) 1575 break; 1576 1577 /* Get the size of all device instances for the enumerator */ 1578 ret = GetEnumeratorInstanceListSize(szEnumeratorBuffer, 1579 &dwBufferLength); 1580 if (ret != CR_SUCCESS) 1581 break; 1582 1583 *pulLength += dwBufferLength; 1584 } 1585 1586 return ret; 1587 } 1588 1589 1590 /* Function 11 */ 1591 DWORD 1592 WINAPI 1593 PNP_GetDeviceListSize( 1594 handle_t hBinding, 1595 LPWSTR pszFilter, 1596 PNP_RPC_BUFFER_SIZE *pulLength, 1597 DWORD ulFlags) 1598 { 1599 WCHAR szEnumerator[MAX_DEVICE_ID_LEN]; 1600 WCHAR szDevice[MAX_DEVICE_ID_LEN]; 1601 WCHAR szInstance[MAX_DEVICE_ID_LEN]; 1602 CONFIGRET ret = CR_SUCCESS; 1603 1604 DPRINT("PNP_GetDeviceListSize(%p %S %p 0x%08lx)\n", 1605 hBinding, pszFilter, pulLength, ulFlags); 1606 1607 if (ulFlags & ~CM_GETIDLIST_FILTER_BITS) 1608 return CR_INVALID_FLAG; 1609 1610 if (pulLength == NULL) 1611 return CR_INVALID_POINTER; 1612 1613 if ((ulFlags != CM_GETIDLIST_FILTER_NONE) && 1614 (pszFilter == NULL)) 1615 return CR_INVALID_POINTER; 1616 1617 *pulLength = 0; 1618 1619 if (ulFlags & 1620 (CM_GETIDLIST_FILTER_BUSRELATIONS | 1621 CM_GETIDLIST_FILTER_POWERRELATIONS | 1622 CM_GETIDLIST_FILTER_REMOVALRELATIONS | 1623 CM_GETIDLIST_FILTER_EJECTRELATIONS)) 1624 { 1625 ret = GetRelationsInstanceListSize(pszFilter, 1626 ulFlags, 1627 pulLength); 1628 } 1629 else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE) 1630 { 1631 ret = GetServiceInstanceListSize(pszFilter, 1632 pulLength); 1633 } 1634 else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR) 1635 { 1636 SplitDeviceInstanceID(pszFilter, 1637 szEnumerator, 1638 szDevice, 1639 szInstance); 1640 1641 if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL) 1642 { 1643 ret = GetDeviceInstanceListSize(pszFilter, 1644 pulLength); 1645 } 1646 else 1647 { 1648 ret = GetEnumeratorInstanceListSize(pszFilter, 1649 pulLength); 1650 } 1651 } 1652 else /* CM_GETIDLIST_FILTER_NONE */ 1653 { 1654 ret = GetAllInstanceListSize(pulLength); 1655 } 1656 1657 /* Add one character for the terminating double UNICODE_NULL */ 1658 if (ret == CR_SUCCESS) 1659 (*pulLength) += 1; 1660 1661 return ret; 1662 } 1663 1664 1665 /* Function 12 */ 1666 DWORD 1667 WINAPI 1668 PNP_GetDepth( 1669 handle_t hBinding, 1670 LPWSTR pszDeviceID, 1671 DWORD *pulDepth, 1672 DWORD ulFlags) 1673 { 1674 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData; 1675 CONFIGRET ret = CR_SUCCESS; 1676 NTSTATUS Status; 1677 1678 UNREFERENCED_PARAMETER(hBinding); 1679 UNREFERENCED_PARAMETER(ulFlags); 1680 1681 DPRINT("PNP_GetDepth(%p %S %p 0x%08lx)\n", 1682 hBinding, pszDeviceID, pulDepth, ulFlags); 1683 1684 if (!IsValidDeviceInstanceID(pszDeviceID)) 1685 return CR_INVALID_DEVINST; 1686 1687 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 1688 pszDeviceID); 1689 1690 Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth, 1691 (PVOID)&PlugPlayData, 1692 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA)); 1693 if (NT_SUCCESS(Status)) 1694 { 1695 *pulDepth = PlugPlayData.Depth; 1696 } 1697 else 1698 { 1699 ret = NtStatusToCrError(Status); 1700 } 1701 1702 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret); 1703 1704 return ret; 1705 } 1706 1707 1708 /* Function 13 */ 1709 DWORD 1710 WINAPI 1711 PNP_GetDeviceRegProp( 1712 handle_t hBinding, 1713 LPWSTR pDeviceID, 1714 DWORD ulProperty, 1715 DWORD *pulRegDataType, 1716 BYTE *Buffer, 1717 PNP_PROP_SIZE *pulTransferLen, 1718 PNP_PROP_SIZE *pulLength, 1719 DWORD ulFlags) 1720 { 1721 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData; 1722 CONFIGRET ret = CR_SUCCESS; 1723 LPWSTR lpValueName = NULL; 1724 HKEY hKey = NULL; 1725 LONG lError; 1726 NTSTATUS Status; 1727 1728 UNREFERENCED_PARAMETER(hBinding); 1729 1730 DPRINT("PNP_GetDeviceRegProp(%p %S %lu %p %p %p %p 0x%08lx)\n", 1731 hBinding, pDeviceID, ulProperty, pulRegDataType, Buffer, 1732 pulTransferLen, pulLength, ulFlags); 1733 1734 if (pulTransferLen == NULL || pulLength == NULL) 1735 { 1736 ret = CR_INVALID_POINTER; 1737 goto done; 1738 } 1739 1740 if (ulFlags != 0) 1741 { 1742 ret = CR_INVALID_FLAG; 1743 goto done; 1744 } 1745 1746 /* Check pDeviceID */ 1747 if (!IsValidDeviceInstanceID(pDeviceID)) 1748 { 1749 ret = CR_INVALID_DEVINST; 1750 goto done; 1751 } 1752 1753 if (*pulLength < *pulTransferLen) 1754 *pulLength = *pulTransferLen; 1755 1756 *pulTransferLen = 0; 1757 1758 switch (ulProperty) 1759 { 1760 case CM_DRP_DEVICEDESC: 1761 lpValueName = L"DeviceDesc"; 1762 break; 1763 1764 case CM_DRP_HARDWAREID: 1765 lpValueName = L"HardwareID"; 1766 break; 1767 1768 case CM_DRP_COMPATIBLEIDS: 1769 lpValueName = L"CompatibleIDs"; 1770 break; 1771 1772 case CM_DRP_SERVICE: 1773 lpValueName = L"Service"; 1774 break; 1775 1776 case CM_DRP_CLASS: 1777 lpValueName = L"Class"; 1778 break; 1779 1780 case CM_DRP_CLASSGUID: 1781 lpValueName = L"ClassGUID"; 1782 break; 1783 1784 case CM_DRP_DRIVER: 1785 lpValueName = L"Driver"; 1786 break; 1787 1788 case CM_DRP_CONFIGFLAGS: 1789 lpValueName = L"ConfigFlags"; 1790 break; 1791 1792 case CM_DRP_MFG: 1793 lpValueName = L"Mfg"; 1794 break; 1795 1796 case CM_DRP_FRIENDLYNAME: 1797 lpValueName = L"FriendlyName"; 1798 break; 1799 1800 case CM_DRP_LOCATION_INFORMATION: 1801 lpValueName = L"LocationInformation"; 1802 break; 1803 1804 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME: 1805 PlugPlayData.Property = PNP_PROPERTY_PHYSICAL_DEVICE_OBJECT_NAME; 1806 break; 1807 1808 case CM_DRP_CAPABILITIES: 1809 lpValueName = L"Capabilities"; 1810 break; 1811 1812 case CM_DRP_UI_NUMBER: 1813 PlugPlayData.Property = PNP_PROPERTY_UI_NUMBER; 1814 break; 1815 1816 case CM_DRP_UPPERFILTERS: 1817 lpValueName = L"UpperFilters"; 1818 break; 1819 1820 case CM_DRP_LOWERFILTERS: 1821 lpValueName = L"LowerFilters"; 1822 break; 1823 1824 case CM_DRP_BUSTYPEGUID: 1825 PlugPlayData.Property = PNP_PROPERTY_BUSTYPEGUID; 1826 break; 1827 1828 case CM_DRP_LEGACYBUSTYPE: 1829 PlugPlayData.Property = PNP_PROPERTY_LEGACYBUSTYPE; 1830 break; 1831 1832 case CM_DRP_BUSNUMBER: 1833 PlugPlayData.Property = PNP_PROPERTY_BUSNUMBER; 1834 break; 1835 1836 case CM_DRP_ENUMERATOR_NAME: 1837 PlugPlayData.Property = PNP_PROPERTY_ENUMERATOR_NAME; 1838 break; 1839 1840 case CM_DRP_SECURITY: 1841 lpValueName = L"Security"; 1842 break; 1843 1844 case CM_DRP_DEVTYPE: 1845 lpValueName = L"DeviceType"; 1846 break; 1847 1848 case CM_DRP_EXCLUSIVE: 1849 lpValueName = L"Exclusive"; 1850 break; 1851 1852 case CM_DRP_CHARACTERISTICS: 1853 lpValueName = L"DeviceCharacteristics"; 1854 break; 1855 1856 case CM_DRP_ADDRESS: 1857 PlugPlayData.Property = PNP_PROPERTY_ADDRESS; 1858 break; 1859 1860 case CM_DRP_UI_NUMBER_DESC_FORMAT: 1861 lpValueName = L"UINumberDescFormat"; 1862 break; 1863 1864 case CM_DRP_DEVICE_POWER_DATA: 1865 PlugPlayData.Property = PNP_PROPERTY_POWER_DATA; 1866 break; 1867 1868 case CM_DRP_REMOVAL_POLICY: 1869 PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY; 1870 break; 1871 1872 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT: 1873 PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY_HARDWARE_DEFAULT; 1874 break; 1875 1876 case CM_DRP_REMOVAL_POLICY_OVERRIDE: 1877 lpValueName = L"RemovalPolicy"; 1878 break; 1879 1880 case CM_DRP_INSTALL_STATE: 1881 PlugPlayData.Property = PNP_PROPERTY_INSTALL_STATE; 1882 break; 1883 1884 #if (WINVER >= _WIN32_WINNT_WS03) 1885 case CM_DRP_LOCATION_PATHS: 1886 PlugPlayData.Property = PNP_PROPERTY_LOCATION_PATHS; 1887 break; 1888 #endif 1889 1890 #if (WINVER >= _WIN32_WINNT_WIN7) 1891 case CM_DRP_BASE_CONTAINERID: 1892 PlugPlayData.Property = PNP_PROPERTY_CONTAINERID; 1893 break; 1894 #endif 1895 1896 default: 1897 ret = CR_INVALID_PROPERTY; 1898 goto done; 1899 } 1900 1901 DPRINT("Value name: %S\n", lpValueName); 1902 1903 if (lpValueName) 1904 { 1905 /* Retrieve information from the Registry */ 1906 lError = RegOpenKeyExW(hEnumKey, 1907 pDeviceID, 1908 0, 1909 KEY_QUERY_VALUE, 1910 &hKey); 1911 if (lError != ERROR_SUCCESS) 1912 { 1913 hKey = NULL; 1914 *pulLength = 0; 1915 ret = CR_INVALID_DEVNODE; 1916 goto done; 1917 } 1918 1919 lError = RegQueryValueExW(hKey, 1920 lpValueName, 1921 NULL, 1922 pulRegDataType, 1923 Buffer, 1924 pulLength); 1925 if (lError != ERROR_SUCCESS) 1926 { 1927 if (lError == ERROR_MORE_DATA) 1928 { 1929 ret = CR_BUFFER_SMALL; 1930 } 1931 else 1932 { 1933 *pulLength = 0; 1934 ret = CR_NO_SUCH_VALUE; 1935 } 1936 } 1937 } 1938 else 1939 { 1940 /* Retrieve information from the Device Node */ 1941 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 1942 pDeviceID); 1943 PlugPlayData.Buffer = Buffer; 1944 PlugPlayData.BufferSize = *pulLength; 1945 1946 Status = NtPlugPlayControl(PlugPlayControlProperty, 1947 (PVOID)&PlugPlayData, 1948 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA)); 1949 if (NT_SUCCESS(Status)) 1950 { 1951 *pulLength = PlugPlayData.BufferSize; 1952 } 1953 else 1954 { 1955 ret = NtStatusToCrError(Status); 1956 } 1957 } 1958 1959 done: 1960 if (pulTransferLen) 1961 *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0; 1962 1963 if (hKey != NULL) 1964 RegCloseKey(hKey); 1965 1966 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret); 1967 1968 return ret; 1969 } 1970 1971 1972 /* Function 14 */ 1973 DWORD 1974 WINAPI 1975 PNP_SetDeviceRegProp( 1976 handle_t hBinding, 1977 LPWSTR pDeviceId, 1978 DWORD ulProperty, 1979 DWORD ulDataType, 1980 BYTE *Buffer, 1981 PNP_PROP_SIZE ulLength, 1982 DWORD ulFlags) 1983 { 1984 CONFIGRET ret = CR_SUCCESS; 1985 LPWSTR lpValueName = NULL; 1986 HKEY hKey = 0; 1987 1988 UNREFERENCED_PARAMETER(hBinding); 1989 UNREFERENCED_PARAMETER(ulFlags); 1990 1991 DPRINT("PNP_SetDeviceRegProp(%p %S %lu %lu %p %lu 0x%08lx)\n", 1992 hBinding, pDeviceId, ulProperty, ulDataType, Buffer, 1993 ulLength, ulFlags); 1994 1995 if (!IsValidDeviceInstanceID(pDeviceId)) 1996 return CR_INVALID_DEVINST; 1997 1998 switch (ulProperty) 1999 { 2000 case CM_DRP_DEVICEDESC: 2001 lpValueName = L"DeviceDesc"; 2002 break; 2003 2004 case CM_DRP_HARDWAREID: 2005 lpValueName = L"HardwareID"; 2006 break; 2007 2008 case CM_DRP_COMPATIBLEIDS: 2009 lpValueName = L"CompatibleIDs"; 2010 break; 2011 2012 case CM_DRP_SERVICE: 2013 lpValueName = L"Service"; 2014 break; 2015 2016 case CM_DRP_CLASS: 2017 lpValueName = L"Class"; 2018 break; 2019 2020 case CM_DRP_CLASSGUID: 2021 lpValueName = L"ClassGUID"; 2022 break; 2023 2024 case CM_DRP_DRIVER: 2025 lpValueName = L"Driver"; 2026 break; 2027 2028 case CM_DRP_CONFIGFLAGS: 2029 lpValueName = L"ConfigFlags"; 2030 break; 2031 2032 case CM_DRP_MFG: 2033 lpValueName = L"Mfg"; 2034 break; 2035 2036 case CM_DRP_FRIENDLYNAME: 2037 lpValueName = L"FriendlyName"; 2038 break; 2039 2040 case CM_DRP_LOCATION_INFORMATION: 2041 lpValueName = L"LocationInformation"; 2042 break; 2043 2044 case CM_DRP_UPPERFILTERS: 2045 lpValueName = L"UpperFilters"; 2046 break; 2047 2048 case CM_DRP_LOWERFILTERS: 2049 lpValueName = L"LowerFilters"; 2050 break; 2051 2052 case CM_DRP_SECURITY: 2053 lpValueName = L"Security"; 2054 break; 2055 2056 case CM_DRP_DEVTYPE: 2057 lpValueName = L"DeviceType"; 2058 break; 2059 2060 case CM_DRP_EXCLUSIVE: 2061 lpValueName = L"Exclusive"; 2062 break; 2063 2064 case CM_DRP_CHARACTERISTICS: 2065 lpValueName = L"DeviceCharacteristics"; 2066 break; 2067 2068 case CM_DRP_UI_NUMBER_DESC_FORMAT: 2069 lpValueName = L"UINumberDescFormat"; 2070 break; 2071 2072 case CM_DRP_REMOVAL_POLICY_OVERRIDE: 2073 lpValueName = L"RemovalPolicy"; 2074 break; 2075 2076 default: 2077 return CR_INVALID_PROPERTY; 2078 } 2079 2080 DPRINT("Value name: %S\n", lpValueName); 2081 2082 if (RegOpenKeyExW(hEnumKey, 2083 pDeviceId, 2084 0, 2085 KEY_SET_VALUE, 2086 &hKey)) 2087 return CR_INVALID_DEVNODE; 2088 2089 if (ulLength == 0) 2090 { 2091 if (RegDeleteValueW(hKey, 2092 lpValueName)) 2093 ret = CR_REGISTRY_ERROR; 2094 } 2095 else 2096 { 2097 if (RegSetValueExW(hKey, 2098 lpValueName, 2099 0, 2100 ulDataType, 2101 Buffer, 2102 ulLength)) 2103 ret = CR_REGISTRY_ERROR; 2104 } 2105 2106 RegCloseKey(hKey); 2107 2108 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret); 2109 2110 return ret; 2111 } 2112 2113 2114 /* Function 15 */ 2115 DWORD 2116 WINAPI 2117 PNP_GetClassInstance( 2118 handle_t hBinding, 2119 LPWSTR pDeviceId, 2120 LPWSTR pszClassInstance, 2121 PNP_RPC_STRING_LEN ulLength) 2122 { 2123 WCHAR szClassGuid[40]; 2124 WCHAR szClassInstance[5]; 2125 HKEY hDeviceClassKey = NULL; 2126 HKEY hClassInstanceKey; 2127 ULONG ulTransferLength, ulDataLength; 2128 DWORD dwDataType, dwDisposition, i; 2129 DWORD dwError; 2130 CONFIGRET ret = CR_SUCCESS; 2131 2132 DPRINT("PNP_GetClassInstance(%p %S %p %lu)\n", 2133 hBinding, pDeviceId, pszClassInstance, ulLength); 2134 2135 if (!IsValidDeviceInstanceID(pDeviceId)) 2136 return CR_INVALID_DEVINST; 2137 2138 ulTransferLength = ulLength; 2139 ret = PNP_GetDeviceRegProp(hBinding, 2140 pDeviceId, 2141 CM_DRP_DRIVER, 2142 &dwDataType, 2143 (BYTE *)pszClassInstance, 2144 &ulTransferLength, 2145 &ulLength, 2146 0); 2147 if (ret == CR_SUCCESS) 2148 return ret; 2149 2150 ulTransferLength = sizeof(szClassGuid); 2151 ulDataLength = sizeof(szClassGuid); 2152 ret = PNP_GetDeviceRegProp(hBinding, 2153 pDeviceId, 2154 CM_DRP_CLASSGUID, 2155 &dwDataType, 2156 (BYTE *)szClassGuid, 2157 &ulTransferLength, 2158 &ulDataLength, 2159 0); 2160 if (ret != CR_SUCCESS) 2161 { 2162 DPRINT1("PNP_GetDeviceRegProp() failed (Error %lu)\n", ret); 2163 goto done; 2164 } 2165 2166 dwError = RegOpenKeyExW(hClassKey, 2167 szClassGuid, 2168 0, 2169 KEY_READ, 2170 &hDeviceClassKey); 2171 if (dwError != ERROR_SUCCESS) 2172 { 2173 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError); 2174 ret = CR_FAILURE; 2175 goto done; 2176 } 2177 2178 for (i = 0; i < 10000; i++) 2179 { 2180 wsprintf(szClassInstance, L"%04lu", i); 2181 2182 dwError = RegCreateKeyExW(hDeviceClassKey, 2183 szClassInstance, 2184 0, 2185 NULL, 2186 REG_OPTION_NON_VOLATILE, 2187 KEY_ALL_ACCESS, 2188 NULL, 2189 &hClassInstanceKey, 2190 &dwDisposition); 2191 if (dwError == ERROR_SUCCESS) 2192 { 2193 RegCloseKey(hClassInstanceKey); 2194 2195 if (dwDisposition == REG_CREATED_NEW_KEY) 2196 { 2197 wsprintf(pszClassInstance, 2198 L"%s\\%s", 2199 szClassGuid, 2200 szClassInstance); 2201 2202 ulDataLength = (wcslen(pszClassInstance) + 1) * sizeof(WCHAR); 2203 ret = PNP_SetDeviceRegProp(hBinding, 2204 pDeviceId, 2205 CM_DRP_DRIVER, 2206 REG_SZ, 2207 (BYTE *)pszClassInstance, 2208 ulDataLength, 2209 0); 2210 if (ret != CR_SUCCESS) 2211 { 2212 DPRINT1("PNP_SetDeviceRegProp() failed (Error %lu)\n", ret); 2213 RegDeleteKeyW(hDeviceClassKey, 2214 szClassInstance); 2215 } 2216 2217 break; 2218 } 2219 } 2220 } 2221 2222 done: 2223 if (hDeviceClassKey != NULL) 2224 RegCloseKey(hDeviceClassKey); 2225 2226 return ret; 2227 } 2228 2229 2230 /* Function 16 */ 2231 DWORD 2232 WINAPI 2233 PNP_CreateKey( 2234 handle_t hBinding, 2235 LPWSTR pszSubKey, 2236 DWORD samDesired, 2237 DWORD ulFlags) 2238 { 2239 HKEY hDeviceKey = NULL, hParametersKey = NULL; 2240 DWORD dwError; 2241 CONFIGRET ret = CR_SUCCESS; 2242 2243 UNREFERENCED_PARAMETER(hBinding); 2244 UNREFERENCED_PARAMETER(samDesired); 2245 2246 DPRINT("PNP_CreateKey(%p %S 0x%lx 0x%08lx)\n", 2247 hBinding, pszSubKey, samDesired, ulFlags); 2248 2249 if (ulFlags != 0) 2250 return CR_INVALID_FLAG; 2251 2252 if (!IsValidDeviceInstanceID(pszSubKey)) 2253 return CR_INVALID_DEVINST; 2254 2255 dwError = RegOpenKeyExW(hEnumKey, 2256 pszSubKey, 2257 0, 2258 KEY_WRITE, 2259 &hDeviceKey); 2260 if (dwError != ERROR_SUCCESS) 2261 { 2262 ret = CR_INVALID_DEVNODE; 2263 goto done; 2264 } 2265 2266 dwError = RegCreateKeyExW(hDeviceKey, 2267 L"Device Parameters", 2268 0, 2269 NULL, 2270 REG_OPTION_NON_VOLATILE, 2271 KEY_ALL_ACCESS, 2272 NULL, 2273 &hParametersKey, 2274 NULL); 2275 if (dwError != ERROR_SUCCESS) 2276 { 2277 ret = CR_REGISTRY_ERROR; 2278 goto done; 2279 } 2280 2281 /* FIXME: Set key security */ 2282 2283 done: 2284 if (hParametersKey != NULL) 2285 RegCloseKey(hParametersKey); 2286 2287 if (hDeviceKey != NULL) 2288 RegCloseKey(hDeviceKey); 2289 2290 return ret; 2291 } 2292 2293 2294 /* Function 17 */ 2295 DWORD 2296 WINAPI 2297 PNP_DeleteRegistryKey( 2298 handle_t hBinding, 2299 LPWSTR pszDeviceID, 2300 LPWSTR pszParentKey, 2301 LPWSTR pszChildKey, 2302 DWORD ulFlags) 2303 { 2304 UNIMPLEMENTED; 2305 return CR_CALL_NOT_IMPLEMENTED; 2306 } 2307 2308 2309 /* Function 18 */ 2310 DWORD 2311 WINAPI 2312 PNP_GetClassCount( 2313 handle_t hBinding, 2314 DWORD *pulClassCount, 2315 DWORD ulFlags) 2316 { 2317 HKEY hKey; 2318 DWORD dwError; 2319 2320 UNREFERENCED_PARAMETER(hBinding); 2321 UNREFERENCED_PARAMETER(ulFlags); 2322 2323 DPRINT("PNP_GetClassCount(%p %p 0x%08lx)\n", 2324 hBinding, pulClassCount, ulFlags); 2325 2326 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 2327 REGSTR_PATH_CLASS, 2328 0, 2329 KEY_QUERY_VALUE, 2330 &hKey); 2331 if (dwError != ERROR_SUCCESS) 2332 return CR_INVALID_DATA; 2333 2334 dwError = RegQueryInfoKeyW(hKey, 2335 NULL, 2336 NULL, 2337 NULL, 2338 pulClassCount, 2339 NULL, 2340 NULL, 2341 NULL, 2342 NULL, 2343 NULL, 2344 NULL, 2345 NULL); 2346 RegCloseKey(hKey); 2347 if (dwError != ERROR_SUCCESS) 2348 return CR_INVALID_DATA; 2349 2350 return CR_SUCCESS; 2351 } 2352 2353 2354 /* Function 19 */ 2355 DWORD 2356 WINAPI 2357 PNP_GetClassName( 2358 handle_t hBinding, 2359 LPWSTR pszClassGuid, 2360 LPWSTR Buffer, 2361 PNP_RPC_STRING_LEN *pulLength, 2362 DWORD ulFlags) 2363 { 2364 WCHAR szKeyName[MAX_PATH]; 2365 CONFIGRET ret = CR_SUCCESS; 2366 HKEY hKey; 2367 DWORD dwSize; 2368 2369 UNREFERENCED_PARAMETER(hBinding); 2370 UNREFERENCED_PARAMETER(ulFlags); 2371 2372 DPRINT("PNP_GetClassName(%p %S %p %p 0x%08lx)\n", 2373 hBinding, pszClassGuid, Buffer, pulLength, ulFlags); 2374 2375 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\"); 2376 if (lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR))) 2377 lstrcatW(szKeyName, pszClassGuid); 2378 else 2379 return CR_INVALID_DATA; 2380 2381 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 2382 szKeyName, 2383 0, 2384 KEY_QUERY_VALUE, 2385 &hKey)) 2386 return CR_REGISTRY_ERROR; 2387 2388 dwSize = *pulLength * sizeof(WCHAR); 2389 if (RegQueryValueExW(hKey, 2390 L"Class", 2391 NULL, 2392 NULL, 2393 (LPBYTE)Buffer, 2394 &dwSize)) 2395 { 2396 *pulLength = 0; 2397 ret = CR_REGISTRY_ERROR; 2398 } 2399 else 2400 { 2401 *pulLength = dwSize / sizeof(WCHAR); 2402 } 2403 2404 RegCloseKey(hKey); 2405 2406 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret); 2407 2408 return ret; 2409 } 2410 2411 2412 /* Function 20 */ 2413 DWORD 2414 WINAPI 2415 PNP_DeleteClassKey( 2416 handle_t hBinding, 2417 LPWSTR pszClassGuid, 2418 DWORD ulFlags) 2419 { 2420 CONFIGRET ret = CR_SUCCESS; 2421 2422 UNREFERENCED_PARAMETER(hBinding); 2423 2424 DPRINT("PNP_DeleteClassKey(%p %S 0x%08lx)\n", 2425 hBinding, pszClassGuid, ulFlags); 2426 2427 if (ulFlags & CM_DELETE_CLASS_SUBKEYS) 2428 { 2429 if (SHDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS) 2430 ret = CR_REGISTRY_ERROR; 2431 } 2432 else 2433 { 2434 if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS) 2435 ret = CR_REGISTRY_ERROR; 2436 } 2437 2438 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret); 2439 2440 return ret; 2441 } 2442 2443 2444 /* Function 21 */ 2445 DWORD 2446 WINAPI 2447 PNP_GetInterfaceDeviceAlias( 2448 handle_t hBinding, 2449 LPWSTR pszInterfaceDevice, 2450 GUID *AliasInterfaceGuid, 2451 LPWSTR pszAliasInterfaceDevice, 2452 PNP_RPC_STRING_LEN *pulLength, 2453 PNP_RPC_STRING_LEN *pulTransferLen, 2454 DWORD ulFlags) 2455 { 2456 UNIMPLEMENTED; 2457 return CR_CALL_NOT_IMPLEMENTED; 2458 } 2459 2460 2461 /* Function 22 */ 2462 DWORD 2463 WINAPI 2464 PNP_GetInterfaceDeviceList( 2465 handle_t hBinding, 2466 GUID *InterfaceGuid, 2467 LPWSTR pszDeviceID, 2468 BYTE *Buffer, 2469 PNP_RPC_BUFFER_SIZE *pulLength, 2470 DWORD ulFlags) 2471 { 2472 NTSTATUS Status; 2473 PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData; 2474 DWORD ret = CR_SUCCESS; 2475 2476 UNREFERENCED_PARAMETER(hBinding); 2477 2478 DPRINT("PNP_GetInterfaceDeviceList(%p %p %S %p %p 0x%08lx)\n", 2479 hBinding, InterfaceGuid, pszDeviceID, Buffer, pulLength, ulFlags); 2480 2481 if (!IsValidDeviceInstanceID(pszDeviceID)) 2482 return CR_INVALID_DEVINST; 2483 2484 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 2485 pszDeviceID); 2486 2487 PlugPlayData.Flags = ulFlags; 2488 PlugPlayData.FilterGuid = InterfaceGuid; 2489 PlugPlayData.Buffer = Buffer; 2490 PlugPlayData.BufferSize = *pulLength; 2491 2492 Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList, 2493 (PVOID)&PlugPlayData, 2494 sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA)); 2495 if (NT_SUCCESS(Status)) 2496 { 2497 *pulLength = PlugPlayData.BufferSize; 2498 } 2499 else 2500 { 2501 ret = NtStatusToCrError(Status); 2502 } 2503 2504 DPRINT("PNP_GetInterfaceDeviceList() done (returns %lx)\n", ret); 2505 return ret; 2506 } 2507 2508 2509 /* Function 23 */ 2510 DWORD 2511 WINAPI 2512 PNP_GetInterfaceDeviceListSize( 2513 handle_t hBinding, 2514 PNP_RPC_BUFFER_SIZE *pulLen, 2515 GUID *InterfaceGuid, 2516 LPWSTR pszDeviceID, 2517 DWORD ulFlags) 2518 { 2519 NTSTATUS Status; 2520 PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData; 2521 DWORD ret = CR_SUCCESS; 2522 2523 UNREFERENCED_PARAMETER(hBinding); 2524 2525 DPRINT("PNP_GetInterfaceDeviceListSize(%p %p %p %S 0x%08lx)\n", 2526 hBinding, pulLen, InterfaceGuid, pszDeviceID, ulFlags); 2527 2528 if (!IsValidDeviceInstanceID(pszDeviceID)) 2529 return CR_INVALID_DEVINST; 2530 2531 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 2532 pszDeviceID); 2533 2534 PlugPlayData.FilterGuid = InterfaceGuid; 2535 PlugPlayData.Buffer = NULL; 2536 PlugPlayData.BufferSize = 0; 2537 PlugPlayData.Flags = ulFlags; 2538 2539 Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList, 2540 (PVOID)&PlugPlayData, 2541 sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA)); 2542 if (NT_SUCCESS(Status)) 2543 { 2544 *pulLen = PlugPlayData.BufferSize; 2545 } 2546 else 2547 { 2548 ret = NtStatusToCrError(Status); 2549 } 2550 2551 DPRINT("PNP_GetInterfaceDeviceListSize() done (returns %lx)\n", ret); 2552 return ret; 2553 } 2554 2555 2556 /* Function 24 */ 2557 DWORD 2558 WINAPI 2559 PNP_RegisterDeviceClassAssociation( 2560 handle_t hBinding, 2561 LPWSTR pszDeviceID, 2562 GUID *InterfaceGuid, 2563 LPWSTR pszReference, 2564 LPWSTR pszSymLink, 2565 PNP_RPC_STRING_LEN *pulLength, 2566 PNP_RPC_STRING_LEN *pulTransferLen, 2567 DWORD ulFlags) 2568 { 2569 UNIMPLEMENTED; 2570 return CR_CALL_NOT_IMPLEMENTED; 2571 } 2572 2573 2574 /* Function 25 */ 2575 DWORD 2576 WINAPI 2577 PNP_UnregisterDeviceClassAssociation( 2578 handle_t hBinding, 2579 LPWSTR pszInterfaceDevice, 2580 DWORD ulFlags) 2581 { 2582 UNIMPLEMENTED; 2583 return CR_CALL_NOT_IMPLEMENTED; 2584 } 2585 2586 2587 /* Function 26 */ 2588 DWORD 2589 WINAPI 2590 PNP_GetClassRegProp( 2591 handle_t hBinding, 2592 LPWSTR pszClassGuid, 2593 DWORD ulProperty, 2594 DWORD *pulRegDataType, 2595 BYTE *Buffer, 2596 PNP_RPC_STRING_LEN *pulTransferLen, 2597 PNP_RPC_STRING_LEN *pulLength, 2598 DWORD ulFlags) 2599 { 2600 CONFIGRET ret = CR_SUCCESS; 2601 LPWSTR lpValueName = NULL; 2602 HKEY hInstKey = NULL; 2603 HKEY hPropKey = NULL; 2604 LONG lError; 2605 2606 UNREFERENCED_PARAMETER(hBinding); 2607 2608 DPRINT("PNP_GetClassRegProp(%p %S %lu %p %p %p %p 0x%08lx)\n", 2609 hBinding, pszClassGuid, ulProperty, pulRegDataType, 2610 Buffer, pulTransferLen, pulLength, ulFlags); 2611 2612 if (pulTransferLen == NULL || pulLength == NULL) 2613 { 2614 ret = CR_INVALID_POINTER; 2615 goto done; 2616 } 2617 2618 if (ulFlags != 0) 2619 { 2620 ret = CR_INVALID_FLAG; 2621 goto done; 2622 } 2623 2624 if (*pulLength < *pulTransferLen) 2625 *pulLength = *pulTransferLen; 2626 2627 *pulTransferLen = 0; 2628 2629 switch (ulProperty) 2630 { 2631 case CM_CRP_SECURITY: 2632 lpValueName = L"Security"; 2633 break; 2634 2635 case CM_CRP_DEVTYPE: 2636 lpValueName = L"DeviceType"; 2637 break; 2638 2639 case CM_CRP_EXCLUSIVE: 2640 lpValueName = L"Exclusive"; 2641 break; 2642 2643 case CM_CRP_CHARACTERISTICS: 2644 lpValueName = L"DeviceCharacteristics"; 2645 break; 2646 2647 default: 2648 ret = CR_INVALID_PROPERTY; 2649 goto done; 2650 } 2651 2652 DPRINT("Value name: %S\n", lpValueName); 2653 2654 lError = RegOpenKeyExW(hClassKey, 2655 pszClassGuid, 2656 0, 2657 KEY_READ, 2658 &hInstKey); 2659 if (lError != ERROR_SUCCESS) 2660 { 2661 *pulLength = 0; 2662 ret = CR_NO_SUCH_REGISTRY_KEY; 2663 goto done; 2664 } 2665 2666 lError = RegOpenKeyExW(hInstKey, 2667 L"Properties", 2668 0, 2669 KEY_READ, 2670 &hPropKey); 2671 if (lError != ERROR_SUCCESS) 2672 { 2673 *pulLength = 0; 2674 ret = CR_NO_SUCH_REGISTRY_KEY; 2675 goto done; 2676 } 2677 2678 lError = RegQueryValueExW(hPropKey, 2679 lpValueName, 2680 NULL, 2681 pulRegDataType, 2682 Buffer, 2683 pulLength); 2684 if (lError != ERROR_SUCCESS) 2685 { 2686 if (lError == ERROR_MORE_DATA) 2687 { 2688 ret = CR_BUFFER_SMALL; 2689 } 2690 else 2691 { 2692 *pulLength = 0; 2693 ret = CR_NO_SUCH_VALUE; 2694 } 2695 } 2696 2697 done: 2698 if (ret == CR_SUCCESS) 2699 *pulTransferLen = *pulLength; 2700 2701 if (hPropKey != NULL) 2702 RegCloseKey(hPropKey); 2703 2704 if (hInstKey != NULL) 2705 RegCloseKey(hInstKey); 2706 2707 DPRINT("PNP_GetClassRegProp() done (returns %lx)\n", ret); 2708 2709 return ret; 2710 } 2711 2712 2713 /* Function 27 */ 2714 DWORD 2715 WINAPI 2716 PNP_SetClassRegProp( 2717 handle_t hBinding, 2718 LPWSTR pszClassGuid, 2719 DWORD ulProperty, 2720 DWORD ulDataType, 2721 BYTE *Buffer, 2722 PNP_PROP_SIZE ulLength, 2723 DWORD ulFlags) 2724 { 2725 CONFIGRET ret = CR_SUCCESS; 2726 LPWSTR lpValueName = NULL; 2727 HKEY hInstKey = 0; 2728 HKEY hPropKey = 0; 2729 LONG lError; 2730 2731 UNREFERENCED_PARAMETER(hBinding); 2732 2733 DPRINT("PNP_SetClassRegProp(%p %S %lu %lu %p %lu 0x%08lx)\n", 2734 hBinding, pszClassGuid, ulProperty, ulDataType, 2735 Buffer, ulLength, ulFlags); 2736 2737 if (ulFlags != 0) 2738 return CR_INVALID_FLAG; 2739 2740 switch (ulProperty) 2741 { 2742 case CM_CRP_SECURITY: 2743 lpValueName = L"Security"; 2744 break; 2745 2746 case CM_CRP_DEVTYPE: 2747 lpValueName = L"DeviceType"; 2748 break; 2749 2750 case CM_CRP_EXCLUSIVE: 2751 lpValueName = L"Exclusive"; 2752 break; 2753 2754 case CM_CRP_CHARACTERISTICS: 2755 lpValueName = L"DeviceCharacteristics"; 2756 break; 2757 2758 default: 2759 return CR_INVALID_PROPERTY; 2760 } 2761 2762 lError = RegOpenKeyExW(hClassKey, 2763 pszClassGuid, 2764 0, 2765 KEY_WRITE, 2766 &hInstKey); 2767 if (lError != ERROR_SUCCESS) 2768 { 2769 ret = CR_NO_SUCH_REGISTRY_KEY; 2770 goto done; 2771 } 2772 2773 /* FIXME: Set security descriptor */ 2774 lError = RegCreateKeyExW(hInstKey, 2775 L"Properties", 2776 0, 2777 NULL, 2778 REG_OPTION_NON_VOLATILE, 2779 KEY_ALL_ACCESS, 2780 NULL, 2781 &hPropKey, 2782 NULL); 2783 if (lError != ERROR_SUCCESS) 2784 { 2785 ret = CR_REGISTRY_ERROR; 2786 goto done; 2787 } 2788 2789 if (ulLength == 0) 2790 { 2791 if (RegDeleteValueW(hPropKey, 2792 lpValueName)) 2793 ret = CR_REGISTRY_ERROR; 2794 } 2795 else 2796 { 2797 if (RegSetValueExW(hPropKey, 2798 lpValueName, 2799 0, 2800 ulDataType, 2801 Buffer, 2802 ulLength)) 2803 ret = CR_REGISTRY_ERROR; 2804 } 2805 2806 done: 2807 if (hPropKey != NULL) 2808 RegCloseKey(hPropKey); 2809 2810 if (hInstKey != NULL) 2811 RegCloseKey(hInstKey); 2812 2813 return ret; 2814 } 2815 2816 2817 static CONFIGRET 2818 CreateDeviceInstance(LPWSTR pszDeviceID) 2819 { 2820 WCHAR szEnumerator[MAX_DEVICE_ID_LEN]; 2821 WCHAR szDevice[MAX_DEVICE_ID_LEN]; 2822 WCHAR szInstance[MAX_DEVICE_ID_LEN]; 2823 HKEY hKeyEnumerator; 2824 HKEY hKeyDevice; 2825 HKEY hKeyInstance; 2826 HKEY hKeyControl; 2827 LONG lError; 2828 2829 /* Split the instance ID */ 2830 SplitDeviceInstanceID(pszDeviceID, 2831 szEnumerator, 2832 szDevice, 2833 szInstance); 2834 2835 /* Open or create the enumerator key */ 2836 lError = RegCreateKeyExW(hEnumKey, 2837 szEnumerator, 2838 0, 2839 NULL, 2840 REG_OPTION_NON_VOLATILE, 2841 KEY_ALL_ACCESS, 2842 NULL, 2843 &hKeyEnumerator, 2844 NULL); 2845 if (lError != ERROR_SUCCESS) 2846 { 2847 return CR_REGISTRY_ERROR; 2848 } 2849 2850 /* Open or create the device key */ 2851 lError = RegCreateKeyExW(hKeyEnumerator, 2852 szDevice, 2853 0, 2854 NULL, 2855 REG_OPTION_NON_VOLATILE, 2856 KEY_ALL_ACCESS, 2857 NULL, 2858 &hKeyDevice, 2859 NULL); 2860 2861 /* Close the enumerator key */ 2862 RegCloseKey(hKeyEnumerator); 2863 2864 if (lError != ERROR_SUCCESS) 2865 { 2866 return CR_REGISTRY_ERROR; 2867 } 2868 2869 /* Try to open the instance key and fail if it exists */ 2870 lError = RegOpenKeyExW(hKeyDevice, 2871 szInstance, 2872 0, 2873 KEY_SET_VALUE, 2874 &hKeyInstance); 2875 if (lError == ERROR_SUCCESS) 2876 { 2877 DPRINT1("Instance %S already exists!\n", szInstance); 2878 RegCloseKey(hKeyInstance); 2879 RegCloseKey(hKeyDevice); 2880 return CR_ALREADY_SUCH_DEVINST; 2881 } 2882 2883 /* Create a new instance key */ 2884 lError = RegCreateKeyExW(hKeyDevice, 2885 szInstance, 2886 0, 2887 NULL, 2888 REG_OPTION_NON_VOLATILE, 2889 KEY_ALL_ACCESS, 2890 NULL, 2891 &hKeyInstance, 2892 NULL); 2893 2894 /* Close the device key */ 2895 RegCloseKey(hKeyDevice); 2896 2897 if (lError != ERROR_SUCCESS) 2898 { 2899 return CR_REGISTRY_ERROR; 2900 } 2901 2902 /* Create the 'Control' sub key */ 2903 lError = RegCreateKeyExW(hKeyInstance, 2904 L"Control", 2905 0, 2906 NULL, 2907 REG_OPTION_NON_VOLATILE, 2908 KEY_ALL_ACCESS, 2909 NULL, 2910 &hKeyControl, 2911 NULL); 2912 if (lError == ERROR_SUCCESS) 2913 { 2914 RegCloseKey(hKeyControl); 2915 } 2916 2917 RegCloseKey(hKeyInstance); 2918 2919 return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR; 2920 } 2921 2922 2923 /* Function 28 */ 2924 DWORD 2925 WINAPI 2926 PNP_CreateDevInst( 2927 handle_t hBinding, 2928 LPWSTR pszDeviceID, 2929 LPWSTR pszParentDeviceID, 2930 PNP_RPC_STRING_LEN ulLength, 2931 DWORD ulFlags) 2932 { 2933 CONFIGRET ret = CR_SUCCESS; 2934 2935 DPRINT("PNP_CreateDevInst(%p %S %S %lu 0x%08lx)\n", 2936 hBinding, pszParentDeviceID, pszDeviceID, ulLength, ulFlags); 2937 2938 if (ulFlags & ~CM_CREATE_DEVNODE_BITS) 2939 return CR_INVALID_FLAG; 2940 2941 if (pszDeviceID == NULL || pszParentDeviceID == NULL) 2942 return CR_INVALID_POINTER; 2943 2944 /* Fail, if the parent device is not the root device */ 2945 if (!IsRootDeviceInstanceID(pszParentDeviceID)) 2946 return CR_INVALID_DEVINST; 2947 2948 if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID) 2949 { 2950 WCHAR szGeneratedInstance[MAX_DEVICE_ID_LEN]; 2951 DWORD dwInstanceNumber; 2952 2953 /* Generated ID is: Root\<Device ID>\<Instance number> */ 2954 dwInstanceNumber = 0; 2955 do 2956 { 2957 swprintf(szGeneratedInstance, L"Root\\%ls\\%04lu", 2958 pszDeviceID, dwInstanceNumber); 2959 2960 /* Try to create a device instance with this ID */ 2961 ret = CreateDeviceInstance(szGeneratedInstance); 2962 2963 dwInstanceNumber++; 2964 } 2965 while (ret == CR_ALREADY_SUCH_DEVINST); 2966 2967 if (ret == CR_SUCCESS) 2968 { 2969 /* pszDeviceID is an out parameter too for generated IDs */ 2970 if (wcslen(szGeneratedInstance) > ulLength) 2971 { 2972 ret = CR_BUFFER_SMALL; 2973 } 2974 else 2975 { 2976 wcscpy(pszDeviceID, szGeneratedInstance); 2977 } 2978 } 2979 } 2980 else 2981 { 2982 /* Create the device instance */ 2983 ret = CreateDeviceInstance(pszDeviceID); 2984 } 2985 2986 DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret); 2987 2988 return ret; 2989 } 2990 2991 2992 static CONFIGRET 2993 SetupDeviceInstance( 2994 _In_ LPWSTR pszDeviceInstance, 2995 _In_ DWORD ulMinorAction) 2996 { 2997 HKEY hDeviceKey = NULL; 2998 DWORD dwDisableCount, dwSize; 2999 DWORD ulStatus, ulProblem; 3000 DWORD dwError; 3001 CONFIGRET ret = CR_SUCCESS; 3002 3003 DPRINT1("SetupDeviceInstance(%S 0x%08lx)\n", 3004 pszDeviceInstance, ulMinorAction); 3005 3006 if (IsRootDeviceInstanceID(pszDeviceInstance)) 3007 return CR_INVALID_DEVINST; 3008 3009 if (ulMinorAction & ~CM_SETUP_BITS) 3010 return CR_INVALID_FLAG; 3011 3012 if ((ulMinorAction == CM_SETUP_DOWNLOAD) || 3013 (ulMinorAction == CM_SETUP_WRITE_LOG_CONFS)) 3014 return CR_SUCCESS; 3015 3016 dwError = RegOpenKeyExW(hEnumKey, 3017 pszDeviceInstance, 3018 0, 3019 KEY_READ, 3020 &hDeviceKey); 3021 if (dwError != ERROR_SUCCESS) 3022 return CR_INVALID_DEVNODE; 3023 3024 dwSize = sizeof(dwDisableCount); 3025 dwError = RegQueryValueExW(hDeviceKey, 3026 L"DisableCount", 3027 NULL, 3028 NULL, 3029 (LPBYTE)&dwDisableCount, 3030 &dwSize); 3031 if ((dwError == ERROR_SUCCESS) && 3032 (dwDisableCount > 0)) 3033 { 3034 goto done; 3035 } 3036 3037 GetDeviceStatus(pszDeviceInstance, 3038 &ulStatus, 3039 &ulProblem); 3040 3041 if (ulStatus & DN_STARTED) 3042 { 3043 goto done; 3044 } 3045 3046 if (ulStatus & DN_HAS_PROBLEM) 3047 { 3048 ret = ClearDeviceStatus(pszDeviceInstance, 3049 DN_HAS_PROBLEM, 3050 ulProblem); 3051 } 3052 3053 if (ret != CR_SUCCESS) 3054 goto done; 3055 3056 3057 /* FIXME: Start the device */ 3058 3059 done: 3060 if (hDeviceKey != NULL) 3061 RegCloseKey(hDeviceKey); 3062 3063 return ret; 3064 } 3065 3066 3067 static CONFIGRET 3068 EnableDeviceInstance( 3069 _In_ LPWSTR pszDeviceInstance) 3070 { 3071 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData; 3072 CONFIGRET ret = CR_SUCCESS; 3073 NTSTATUS Status; 3074 3075 DPRINT("Enable device instance %S\n", pszDeviceInstance); 3076 3077 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, 3078 pszDeviceInstance); 3079 Status = NtPlugPlayControl(PlugPlayControlResetDevice, 3080 &ResetDeviceData, 3081 sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA)); 3082 if (!NT_SUCCESS(Status)) 3083 ret = NtStatusToCrError(Status); 3084 3085 return ret; 3086 } 3087 3088 3089 static CONFIGRET 3090 ReenumerateDeviceInstance( 3091 _In_ LPWSTR pszDeviceInstance, 3092 _In_ ULONG ulMinorAction) 3093 { 3094 PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA EnumerateDeviceData; 3095 CONFIGRET ret = CR_SUCCESS; 3096 NTSTATUS Status; 3097 3098 DPRINT1("ReenumerateDeviceInstance(%S 0x%08lx)\n", 3099 pszDeviceInstance, ulMinorAction); 3100 3101 if (ulMinorAction & ~CM_REENUMERATE_BITS) 3102 return CR_INVALID_FLAG; 3103 3104 if (ulMinorAction & CM_REENUMERATE_RETRY_INSTALLATION) 3105 { 3106 DPRINT1("CM_REENUMERATE_RETRY_INSTALLATION not implemented!\n"); 3107 } 3108 3109 RtlInitUnicodeString(&EnumerateDeviceData.DeviceInstance, 3110 pszDeviceInstance); 3111 EnumerateDeviceData.Flags = 0; 3112 3113 Status = NtPlugPlayControl(PlugPlayControlEnumerateDevice, 3114 &EnumerateDeviceData, 3115 sizeof(PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA)); 3116 if (!NT_SUCCESS(Status)) 3117 ret = NtStatusToCrError(Status); 3118 3119 return ret; 3120 } 3121 3122 3123 /* Function 29 */ 3124 DWORD 3125 WINAPI 3126 PNP_DeviceInstanceAction( 3127 handle_t hBinding, 3128 DWORD ulMajorAction, 3129 DWORD ulMinorAction, 3130 LPWSTR pszDeviceInstance1, 3131 LPWSTR pszDeviceInstance2) 3132 { 3133 CONFIGRET ret = CR_SUCCESS; 3134 3135 UNREFERENCED_PARAMETER(hBinding); 3136 3137 DPRINT("PNP_DeviceInstanceAction(%p %lu 0x%08lx %S %S)\n", 3138 hBinding, ulMajorAction, ulMinorAction, 3139 pszDeviceInstance1, pszDeviceInstance2); 3140 3141 switch (ulMajorAction) 3142 { 3143 case PNP_DEVINST_SETUP: 3144 ret = SetupDeviceInstance(pszDeviceInstance1, 3145 ulMinorAction); 3146 break; 3147 3148 case PNP_DEVINST_ENABLE: 3149 ret = EnableDeviceInstance(pszDeviceInstance1); 3150 break; 3151 3152 case PNP_DEVINST_REENUMERATE: 3153 ret = ReenumerateDeviceInstance(pszDeviceInstance1, 3154 ulMinorAction); 3155 break; 3156 3157 default: 3158 DPRINT1("Unknown device action %lu: not implemented\n", ulMajorAction); 3159 ret = CR_CALL_NOT_IMPLEMENTED; 3160 } 3161 3162 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret); 3163 3164 return ret; 3165 } 3166 3167 3168 /* Function 30 */ 3169 DWORD 3170 WINAPI 3171 PNP_GetDeviceStatus( 3172 handle_t hBinding, 3173 LPWSTR pDeviceID, 3174 DWORD *pulStatus, 3175 DWORD *pulProblem, 3176 DWORD ulFlags) 3177 { 3178 UNREFERENCED_PARAMETER(hBinding); 3179 UNREFERENCED_PARAMETER(ulFlags); 3180 3181 DPRINT("PNP_GetDeviceStatus(%p %S %p %p)\n", 3182 hBinding, pDeviceID, pulStatus, pulProblem, ulFlags); 3183 3184 if (!IsValidDeviceInstanceID(pDeviceID)) 3185 return CR_INVALID_DEVINST; 3186 3187 return GetDeviceStatus(pDeviceID, pulStatus, pulProblem); 3188 } 3189 3190 3191 /* Function 31 */ 3192 DWORD 3193 WINAPI 3194 PNP_SetDeviceProblem( 3195 handle_t hBinding, 3196 LPWSTR pDeviceID, 3197 DWORD ulProblem, 3198 DWORD ulFlags) 3199 { 3200 UNIMPLEMENTED; 3201 return CR_CALL_NOT_IMPLEMENTED; 3202 } 3203 3204 3205 /* Function 32 */ 3206 DWORD 3207 WINAPI 3208 PNP_DisableDevInst( 3209 handle_t hBinding, 3210 LPWSTR pDeviceID, 3211 PPNP_VETO_TYPE pVetoType, 3212 LPWSTR pszVetoName, 3213 DWORD ulNameLength, 3214 DWORD ulFlags) 3215 { 3216 UNREFERENCED_PARAMETER(hBinding); 3217 3218 DPRINT1("PNP_DisableDevInst(%p %S %p %p %lu 0x%08lx)\n", 3219 hBinding, pDeviceID, pVetoType, pszVetoName, ulNameLength, ulFlags); 3220 3221 if (ulFlags & ~CM_DISABLE_BITS) 3222 return CR_INVALID_FLAG; 3223 3224 if (!IsValidDeviceInstanceID(pDeviceID) || 3225 IsRootDeviceInstanceID(pDeviceID)) 3226 return CR_INVALID_DEVINST; 3227 3228 return DisableDeviceInstance(pDeviceID, 3229 pVetoType, 3230 pszVetoName, 3231 ulNameLength); 3232 } 3233 3234 3235 /* Function 33 */ 3236 DWORD 3237 WINAPI 3238 PNP_UninstallDevInst( 3239 handle_t hBinding, 3240 LPWSTR pDeviceID, 3241 DWORD ulFlags) 3242 { 3243 UNIMPLEMENTED; 3244 return CR_CALL_NOT_IMPLEMENTED; 3245 } 3246 3247 3248 static BOOL 3249 CheckForDeviceId(LPWSTR lpDeviceIdList, 3250 LPWSTR lpDeviceId) 3251 { 3252 LPWSTR lpPtr; 3253 DWORD dwLength; 3254 3255 lpPtr = lpDeviceIdList; 3256 while (*lpPtr != 0) 3257 { 3258 dwLength = wcslen(lpPtr); 3259 if (0 == _wcsicmp(lpPtr, lpDeviceId)) 3260 return TRUE; 3261 3262 lpPtr += (dwLength + 1); 3263 } 3264 3265 return FALSE; 3266 } 3267 3268 3269 static VOID 3270 AppendDeviceId(LPWSTR lpDeviceIdList, 3271 LPDWORD lpDeviceIdListSize, 3272 LPWSTR lpDeviceId) 3273 { 3274 DWORD dwLen; 3275 DWORD dwPos; 3276 3277 dwLen = wcslen(lpDeviceId); 3278 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1; 3279 3280 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId); 3281 3282 dwPos += (dwLen + 1); 3283 3284 lpDeviceIdList[dwPos] = 0; 3285 3286 *lpDeviceIdListSize = dwPos * sizeof(WCHAR); 3287 } 3288 3289 3290 /* Function 34 */ 3291 DWORD 3292 WINAPI 3293 PNP_AddID( 3294 handle_t hBinding, 3295 LPWSTR pszDeviceID, 3296 LPWSTR pszID, 3297 DWORD ulFlags) 3298 { 3299 CONFIGRET ret = CR_SUCCESS; 3300 HKEY hDeviceKey; 3301 LPWSTR pszSubKey; 3302 DWORD dwDeviceIdListSize; 3303 DWORD dwNewDeviceIdSize; 3304 WCHAR * pszDeviceIdList = NULL; 3305 3306 UNREFERENCED_PARAMETER(hBinding); 3307 3308 DPRINT("PNP_AddID(%p %S %S 0x%08lx)\n", 3309 hBinding, pszDeviceID, pszID, ulFlags); 3310 3311 if (RegOpenKeyExW(hEnumKey, 3312 pszDeviceID, 3313 0, 3314 KEY_QUERY_VALUE | KEY_SET_VALUE, 3315 &hDeviceKey) != ERROR_SUCCESS) 3316 { 3317 DPRINT("Failed to open the device key!\n"); 3318 return CR_INVALID_DEVNODE; 3319 } 3320 3321 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID"; 3322 3323 if (RegQueryValueExW(hDeviceKey, 3324 pszSubKey, 3325 NULL, 3326 NULL, 3327 NULL, 3328 &dwDeviceIdListSize) != ERROR_SUCCESS) 3329 { 3330 DPRINT("Failed to query the desired ID string!\n"); 3331 ret = CR_REGISTRY_ERROR; 3332 goto Done; 3333 } 3334 3335 dwNewDeviceIdSize = lstrlenW(pszDeviceID); 3336 if (!dwNewDeviceIdSize) 3337 { 3338 ret = CR_INVALID_POINTER; 3339 goto Done; 3340 } 3341 3342 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR); 3343 3344 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize); 3345 if (!pszDeviceIdList) 3346 { 3347 DPRINT("Failed to allocate memory for the desired ID string!\n"); 3348 ret = CR_OUT_OF_MEMORY; 3349 goto Done; 3350 } 3351 3352 if (RegQueryValueExW(hDeviceKey, 3353 pszSubKey, 3354 NULL, 3355 NULL, 3356 (LPBYTE)pszDeviceIdList, 3357 &dwDeviceIdListSize) != ERROR_SUCCESS) 3358 { 3359 DPRINT("Failed to query the desired ID string!\n"); 3360 ret = CR_REGISTRY_ERROR; 3361 goto Done; 3362 } 3363 3364 /* Check whether the device ID is already in use */ 3365 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID)) 3366 { 3367 DPRINT("Device ID was found in the ID string!\n"); 3368 ret = CR_SUCCESS; 3369 goto Done; 3370 } 3371 3372 /* Append the Device ID */ 3373 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID); 3374 3375 if (RegSetValueExW(hDeviceKey, 3376 pszSubKey, 3377 0, 3378 REG_MULTI_SZ, 3379 (LPBYTE)pszDeviceIdList, 3380 dwDeviceIdListSize) != ERROR_SUCCESS) 3381 { 3382 DPRINT("Failed to set the desired ID string!\n"); 3383 ret = CR_REGISTRY_ERROR; 3384 } 3385 3386 Done: 3387 RegCloseKey(hDeviceKey); 3388 if (pszDeviceIdList) 3389 HeapFree(GetProcessHeap(), 0, pszDeviceIdList); 3390 3391 DPRINT("PNP_AddID() done (returns %lx)\n", ret); 3392 3393 return ret; 3394 } 3395 3396 3397 /* Function 35 */ 3398 DWORD 3399 WINAPI 3400 PNP_RegisterDriver( 3401 handle_t hBinding, 3402 LPWSTR pszDeviceID, 3403 DWORD ulFlags) 3404 { 3405 DPRINT("PNP_RegisterDriver(%p %S 0x%lx)\n", 3406 hBinding, pszDeviceID, ulFlags); 3407 3408 if (ulFlags & ~CM_REGISTER_DEVICE_DRIVER_BITS) 3409 return CR_INVALID_FLAG; 3410 3411 if (!IsValidDeviceInstanceID(pszDeviceID)) 3412 return CR_INVALID_DEVINST; 3413 3414 SetDeviceStatus(pszDeviceID, 0, 0); 3415 3416 return CR_SUCCESS; 3417 } 3418 3419 3420 /* Function 36 */ 3421 DWORD 3422 WINAPI 3423 PNP_QueryRemove( 3424 handle_t hBinding, 3425 LPWSTR pszDeviceID, 3426 PPNP_VETO_TYPE pVetoType, 3427 LPWSTR pszVetoName, 3428 DWORD ulNameLength, 3429 DWORD ulFlags) 3430 { 3431 PLUGPLAY_CONTROL_QUERY_REMOVE_DATA PlugPlayData; 3432 NTSTATUS Status; 3433 DWORD ret = CR_SUCCESS; 3434 3435 DPRINT1("PNP_QueryRemove(%p %S %p %p %lu 0x%lx)\n", 3436 hBinding, pszDeviceID, pVetoType, pszVetoName, 3437 ulNameLength, ulFlags); 3438 3439 if (ulFlags & ~CM_REMOVE_BITS) 3440 return CR_INVALID_FLAG; 3441 3442 if (!IsValidDeviceInstanceID(pszDeviceID) || 3443 IsRootDeviceInstanceID(pszDeviceID)) 3444 return CR_INVALID_DEVINST; 3445 3446 if (pVetoType != NULL) 3447 *pVetoType = PNP_VetoTypeUnknown; 3448 3449 if (pszVetoName != NULL && ulNameLength > 0) 3450 *pszVetoName = UNICODE_NULL; 3451 3452 RtlZeroMemory(&PlugPlayData, sizeof(PlugPlayData)); 3453 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 3454 pszDeviceID); 3455 PlugPlayData.VetoName = pszVetoName; 3456 PlugPlayData.NameLength = ulNameLength; 3457 // PlugPlayData.Flags = 3458 3459 Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice, 3460 &PlugPlayData, 3461 sizeof(PlugPlayData)); 3462 if (!NT_SUCCESS(Status)) 3463 ret = NtStatusToCrError(Status); 3464 3465 return ret; 3466 } 3467 3468 3469 /* Function 37 */ 3470 DWORD 3471 WINAPI 3472 PNP_RequestDeviceEject( 3473 handle_t hBinding, 3474 LPWSTR pszDeviceID, 3475 PPNP_VETO_TYPE pVetoType, 3476 LPWSTR pszVetoName, 3477 DWORD ulNameLength, 3478 DWORD ulFlags) 3479 { 3480 PLUGPLAY_CONTROL_QUERY_REMOVE_DATA PlugPlayData; 3481 NTSTATUS Status; 3482 DWORD ret = CR_SUCCESS; 3483 3484 DPRINT1("PNP_RequestDeviceEject(%p %S %p %p %lu 0x%lx)\n", 3485 hBinding, pszDeviceID, pVetoType, pszVetoName, 3486 ulNameLength, ulFlags); 3487 3488 if (ulFlags != 0) 3489 return CR_INVALID_FLAG; 3490 3491 if (!IsValidDeviceInstanceID(pszDeviceID)) 3492 return CR_INVALID_DEVINST; 3493 3494 if (pVetoType != NULL) 3495 *pVetoType = PNP_VetoTypeUnknown; 3496 3497 if (pszVetoName != NULL && ulNameLength > 0) 3498 *pszVetoName = UNICODE_NULL; 3499 3500 RtlZeroMemory(&PlugPlayData, sizeof(PlugPlayData)); 3501 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 3502 pszDeviceID); 3503 PlugPlayData.VetoName = pszVetoName; 3504 PlugPlayData.NameLength = ulNameLength; 3505 // PlugPlayData.Flags = 3506 3507 Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice, 3508 &PlugPlayData, 3509 sizeof(PlugPlayData)); 3510 if (!NT_SUCCESS(Status)) 3511 ret = NtStatusToCrError(Status); 3512 3513 return ret; 3514 } 3515 3516 3517 /* Function 38 */ 3518 CONFIGRET 3519 WINAPI 3520 PNP_IsDockStationPresent( 3521 handle_t hBinding, 3522 BOOL *Present) 3523 { 3524 HKEY hKey; 3525 DWORD dwType; 3526 DWORD dwValue; 3527 DWORD dwSize; 3528 CONFIGRET ret = CR_SUCCESS; 3529 3530 UNREFERENCED_PARAMETER(hBinding); 3531 3532 DPRINT1("PNP_IsDockStationPresent(%p %p)\n", 3533 hBinding, Present); 3534 3535 *Present = FALSE; 3536 3537 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG, 3538 L"CurrentDockInfo", 3539 0, 3540 KEY_READ, 3541 &hKey) != ERROR_SUCCESS) 3542 return CR_REGISTRY_ERROR; 3543 3544 dwSize = sizeof(DWORD); 3545 if (RegQueryValueExW(hKey, 3546 L"DockingState", 3547 NULL, 3548 &dwType, 3549 (LPBYTE)&dwValue, 3550 &dwSize) != ERROR_SUCCESS) 3551 ret = CR_REGISTRY_ERROR; 3552 3553 RegCloseKey(hKey); 3554 3555 if (ret == CR_SUCCESS) 3556 { 3557 if (dwType != REG_DWORD || dwSize != sizeof(DWORD)) 3558 { 3559 ret = CR_REGISTRY_ERROR; 3560 } 3561 else if (dwValue != 0) 3562 { 3563 *Present = TRUE; 3564 } 3565 } 3566 3567 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret); 3568 3569 return ret; 3570 } 3571 3572 3573 /* Function 39 */ 3574 DWORD 3575 WINAPI 3576 PNP_RequestEjectPC( 3577 handle_t hBinding) 3578 { 3579 WCHAR szDockDeviceInstance[MAX_DEVICE_ID_LEN]; 3580 PLUGPLAY_CONTROL_RETRIEVE_DOCK_DATA DockData; 3581 NTSTATUS Status; 3582 3583 DPRINT("PNP_RequestEjectPC(%p)\n", hBinding); 3584 3585 /* Retrieve the dock device */ 3586 DockData.DeviceInstanceLength = ARRAYSIZE(szDockDeviceInstance); 3587 DockData.DeviceInstance = szDockDeviceInstance; 3588 3589 Status = NtPlugPlayControl(PlugPlayControlRetrieveDock, 3590 &DockData, 3591 sizeof(DockData)); 3592 if (!NT_SUCCESS(Status)) 3593 return NtStatusToCrError(Status); 3594 3595 /* Eject the dock device */ 3596 return PNP_RequestDeviceEject(hBinding, 3597 szDockDeviceInstance, 3598 NULL, 3599 NULL, 3600 0, 3601 0); 3602 } 3603 3604 3605 /* Function 40 */ 3606 DWORD 3607 WINAPI 3608 PNP_HwProfFlags( 3609 handle_t hBinding, 3610 DWORD ulAction, 3611 LPWSTR pDeviceID, 3612 DWORD ulConfig, 3613 DWORD *pulValue, 3614 PPNP_VETO_TYPE pVetoType, 3615 LPWSTR pszVetoName, 3616 DWORD ulNameLength, 3617 DWORD ulFlags) 3618 { 3619 CONFIGRET ret = CR_SUCCESS; 3620 WCHAR szKeyName[MAX_PATH]; 3621 HKEY hKey; 3622 HKEY hDeviceKey; 3623 DWORD dwSize; 3624 3625 UNREFERENCED_PARAMETER(hBinding); 3626 3627 DPRINT("PNP_HwProfFlags() called\n"); 3628 3629 if (!IsValidDeviceInstanceID(pDeviceID)) 3630 return CR_INVALID_DEVINST; 3631 3632 if (ulConfig == 0) 3633 { 3634 wcscpy(szKeyName, 3635 L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum"); 3636 } 3637 else 3638 { 3639 swprintf(szKeyName, 3640 L"System\\CurrentControlSet\\HardwareProfiles\\%04lu\\System\\CurrentControlSet\\Enum", 3641 ulConfig); 3642 } 3643 3644 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 3645 szKeyName, 3646 0, 3647 KEY_QUERY_VALUE, 3648 &hKey) != ERROR_SUCCESS) 3649 return CR_REGISTRY_ERROR; 3650 3651 if (ulAction == PNP_GET_HWPROFFLAGS) 3652 { 3653 if (RegOpenKeyExW(hKey, 3654 pDeviceID, 3655 0, 3656 KEY_QUERY_VALUE, 3657 &hDeviceKey) != ERROR_SUCCESS) 3658 { 3659 *pulValue = 0; 3660 } 3661 else 3662 { 3663 dwSize = sizeof(DWORD); 3664 if (RegQueryValueExW(hDeviceKey, 3665 L"CSConfigFlags", 3666 NULL, 3667 NULL, 3668 (LPBYTE)pulValue, 3669 &dwSize) != ERROR_SUCCESS) 3670 { 3671 *pulValue = 0; 3672 } 3673 3674 RegCloseKey(hDeviceKey); 3675 } 3676 } 3677 else if (ulAction == PNP_SET_HWPROFFLAGS) 3678 { 3679 /* FIXME: not implemented yet */ 3680 ret = CR_CALL_NOT_IMPLEMENTED; 3681 } 3682 3683 RegCloseKey(hKey); 3684 3685 return ret; 3686 } 3687 3688 3689 /* Function 41 */ 3690 DWORD 3691 WINAPI 3692 PNP_GetHwProfInfo( 3693 handle_t hBinding, 3694 DWORD ulIndex, 3695 HWPROFILEINFO *pHWProfileInfo, 3696 DWORD ulProfileInfoSize, 3697 DWORD ulFlags) 3698 { 3699 WCHAR szProfileName[5]; 3700 HKEY hKeyConfig = NULL; 3701 HKEY hKeyProfiles = NULL; 3702 HKEY hKeyProfile = NULL; 3703 DWORD dwDisposition; 3704 DWORD dwSize; 3705 LONG lError; 3706 CONFIGRET ret = CR_SUCCESS; 3707 3708 UNREFERENCED_PARAMETER(hBinding); 3709 3710 DPRINT("PNP_GetHwProfInfo() called\n"); 3711 3712 if (ulProfileInfoSize == 0) 3713 { 3714 ret = CR_INVALID_DATA; 3715 goto done; 3716 } 3717 3718 if (ulFlags != 0) 3719 { 3720 ret = CR_INVALID_FLAG; 3721 goto done; 3722 } 3723 3724 /* Initialize the profile information */ 3725 pHWProfileInfo->HWPI_ulHWProfile = 0; 3726 pHWProfileInfo->HWPI_szFriendlyName[0] = 0; 3727 pHWProfileInfo->HWPI_dwFlags = 0; 3728 3729 /* Open the 'IDConfigDB' key */ 3730 lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE, 3731 L"System\\CurrentControlSet\\Control\\IDConfigDB", 3732 0, 3733 NULL, 3734 REG_OPTION_NON_VOLATILE, 3735 KEY_QUERY_VALUE, 3736 NULL, 3737 &hKeyConfig, 3738 &dwDisposition); 3739 if (lError != ERROR_SUCCESS) 3740 { 3741 ret = CR_REGISTRY_ERROR; 3742 goto done; 3743 } 3744 3745 /* Open the 'Hardware Profiles' subkey */ 3746 lError = RegCreateKeyExW(hKeyConfig, 3747 L"Hardware Profiles", 3748 0, 3749 NULL, 3750 REG_OPTION_NON_VOLATILE, 3751 KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, 3752 NULL, 3753 &hKeyProfiles, 3754 &dwDisposition); 3755 if (lError != ERROR_SUCCESS) 3756 { 3757 ret = CR_REGISTRY_ERROR; 3758 goto done; 3759 } 3760 3761 if (ulIndex == (ULONG)-1) 3762 { 3763 dwSize = sizeof(ULONG); 3764 lError = RegQueryValueExW(hKeyConfig, 3765 L"CurrentConfig", 3766 NULL, 3767 NULL, 3768 (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile, 3769 &dwSize); 3770 if (lError != ERROR_SUCCESS) 3771 { 3772 pHWProfileInfo->HWPI_ulHWProfile = 0; 3773 ret = CR_REGISTRY_ERROR; 3774 goto done; 3775 } 3776 } 3777 else 3778 { 3779 /* FIXME: not implemented yet */ 3780 ret = CR_CALL_NOT_IMPLEMENTED; 3781 goto done; 3782 } 3783 3784 swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile); 3785 3786 lError = RegOpenKeyExW(hKeyProfiles, 3787 szProfileName, 3788 0, 3789 KEY_QUERY_VALUE, 3790 &hKeyProfile); 3791 if (lError != ERROR_SUCCESS) 3792 { 3793 ret = CR_REGISTRY_ERROR; 3794 goto done; 3795 } 3796 3797 dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName); 3798 lError = RegQueryValueExW(hKeyProfile, 3799 L"FriendlyName", 3800 NULL, 3801 NULL, 3802 (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName, 3803 &dwSize); 3804 if (lError != ERROR_SUCCESS) 3805 { 3806 ret = CR_REGISTRY_ERROR; 3807 goto done; 3808 } 3809 3810 done: 3811 if (hKeyProfile != NULL) 3812 RegCloseKey(hKeyProfile); 3813 3814 if (hKeyProfiles != NULL) 3815 RegCloseKey(hKeyProfiles); 3816 3817 if (hKeyConfig != NULL) 3818 RegCloseKey(hKeyConfig); 3819 3820 return ret; 3821 } 3822 3823 3824 /* Function 42 */ 3825 DWORD 3826 WINAPI 3827 PNP_AddEmptyLogConf( 3828 handle_t hBinding, 3829 LPWSTR pDeviceID, 3830 DWORD ulPriority, 3831 DWORD *pulLogConfTag, 3832 DWORD ulFlags) 3833 { 3834 UNIMPLEMENTED; 3835 return CR_CALL_NOT_IMPLEMENTED; 3836 } 3837 3838 3839 /* Function 43 */ 3840 DWORD 3841 WINAPI 3842 PNP_FreeLogConf( 3843 handle_t hBinding, 3844 LPWSTR pDeviceID, 3845 DWORD ulLogConfType, 3846 DWORD ulLogConfTag, 3847 DWORD ulFlags) 3848 { 3849 UNIMPLEMENTED; 3850 return CR_CALL_NOT_IMPLEMENTED; 3851 } 3852 3853 3854 /* Function 44 */ 3855 DWORD 3856 WINAPI 3857 PNP_GetFirstLogConf( 3858 handle_t hBinding, 3859 LPWSTR pDeviceID, 3860 DWORD ulLogConfType, 3861 DWORD *pulLogConfTag, 3862 DWORD ulFlags) 3863 { 3864 HKEY hConfigKey = NULL; 3865 DWORD RegDataType = 0; 3866 ULONG ulDataSize = 0; 3867 LPBYTE lpData = NULL; 3868 CONFIGRET ret = CR_SUCCESS; 3869 3870 DPRINT("PNP_GetFirstLogConf(%p %S %lu %p 0x%08lx)\n", 3871 hBinding, pDeviceID, ulLogConfType, pulLogConfTag, ulFlags); 3872 3873 if (pulLogConfTag == NULL) 3874 return CR_INVALID_POINTER; 3875 3876 *pulLogConfTag = (DWORD)0; 3877 3878 if (ulFlags & ~LOG_CONF_BITS) 3879 return CR_INVALID_FLAG; 3880 3881 if (!IsValidDeviceInstanceID(pDeviceID)) 3882 return CR_INVALID_DEVINST; 3883 3884 ret = OpenConfigurationKey(pDeviceID, 3885 &hConfigKey); 3886 if (ret != CR_SUCCESS) 3887 { 3888 DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret); 3889 ret = CR_NO_MORE_LOG_CONF; 3890 goto done; 3891 } 3892 3893 ret = GetConfigurationData(hConfigKey, 3894 ulLogConfType, 3895 &RegDataType, 3896 &ulDataSize, 3897 &lpData); 3898 if (ret != CR_SUCCESS) 3899 { 3900 DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret); 3901 ret = CR_NO_MORE_LOG_CONF; 3902 goto done; 3903 } 3904 3905 DPRINT("Data size %lu\n", ulDataSize); 3906 if (ulDataSize == 0 || lpData == NULL) 3907 { 3908 DPRINT1("No config data available!\n"); 3909 ret = CR_NO_MORE_LOG_CONF; 3910 goto done; 3911 } 3912 3913 /* Get the first tag */ 3914 if (RegDataType == REG_RESOURCE_LIST) 3915 { 3916 DPRINT("REG_RESOURCE_LIST\n"); 3917 3918 DPRINT("ResourceList->Count %lu\n", ((PCM_RESOURCE_LIST)lpData)->Count); 3919 if (((PCM_RESOURCE_LIST)lpData)->Count == 0) 3920 { 3921 DPRINT1("No resource descriptors!\n"); 3922 ret = CR_NO_MORE_LOG_CONF; 3923 goto done; 3924 } 3925 3926 DPRINT("lpData %p\n", lpData); 3927 DPRINT("&List[0] %p\n", &(((PCM_RESOURCE_LIST)lpData)->List[0])); 3928 3929 *pulLogConfTag = (DWORD)((DWORD_PTR)&(((PCM_RESOURCE_LIST)lpData)->List[0]) - (DWORD_PTR)lpData); 3930 DPRINT("Offset (Tag): 0x%08lx\n", *pulLogConfTag); 3931 } 3932 else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) 3933 { 3934 DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n"); 3935 /* FIXME */ 3936 ret = CR_NO_MORE_LOG_CONF; 3937 goto done; 3938 } 3939 3940 done: 3941 if (lpData != NULL) 3942 HeapFree(GetProcessHeap(), 0, lpData); 3943 3944 if (hConfigKey != NULL) 3945 RegCloseKey(hConfigKey); 3946 3947 DPRINT("PNP_GetFirstLogConf() returns %lu\n", ret); 3948 3949 return ret; 3950 } 3951 3952 3953 /* Function 45 */ 3954 DWORD 3955 WINAPI 3956 PNP_GetNextLogConf( 3957 handle_t hBinding, 3958 LPWSTR pDeviceID, 3959 DWORD ulLogConfType, 3960 DWORD ulCurrentTag, 3961 DWORD *pulNextTag, 3962 DWORD ulFlags) 3963 { 3964 HKEY hConfigKey = NULL; 3965 DWORD RegDataType = 0; 3966 ULONG ulDataSize = 0; 3967 LPBYTE lpData = NULL; 3968 CONFIGRET ret = CR_SUCCESS; 3969 3970 DPRINT("PNP_GetNextLogConf(%p %S %lu %ul %p 0x%08lx)\n", 3971 hBinding, pDeviceID, ulLogConfType, ulCurrentTag, pulNextTag, ulFlags); 3972 3973 if (pulNextTag == NULL) 3974 return CR_INVALID_POINTER; 3975 3976 *pulNextTag = (DWORD)0; 3977 3978 if (ulFlags != 0) 3979 return CR_INVALID_FLAG; 3980 3981 if (!IsValidDeviceInstanceID(pDeviceID)) 3982 return CR_INVALID_DEVINST; 3983 3984 ret = OpenConfigurationKey(pDeviceID, 3985 &hConfigKey); 3986 if (ret != CR_SUCCESS) 3987 { 3988 DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret); 3989 ret = CR_NO_MORE_LOG_CONF; 3990 goto done; 3991 } 3992 3993 ret = GetConfigurationData(hConfigKey, 3994 ulLogConfType, 3995 &RegDataType, 3996 &ulDataSize, 3997 &lpData); 3998 if (ret != CR_SUCCESS) 3999 { 4000 DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret); 4001 ret = CR_NO_MORE_LOG_CONF; 4002 goto done; 4003 } 4004 4005 DPRINT("Data size %lu\n", ulDataSize); 4006 4007 if (ulDataSize == 0 || lpData == NULL) 4008 { 4009 DPRINT1("No config data available!\n"); 4010 ret = CR_NO_MORE_LOG_CONF; 4011 goto done; 4012 } 4013 4014 /* FIXME: Get the next tag */ 4015 if (RegDataType == REG_RESOURCE_LIST) 4016 { 4017 DPRINT1("FIXME: REG_RESOURCE_LIST\n"); 4018 /* FIXME */ 4019 ret = CR_NO_MORE_LOG_CONF; 4020 goto done; 4021 } 4022 else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) 4023 { 4024 DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n"); 4025 /* FIXME */ 4026 ret = CR_NO_MORE_LOG_CONF; 4027 goto done; 4028 } 4029 4030 done: 4031 if (lpData != NULL) 4032 HeapFree(GetProcessHeap(), 0, lpData); 4033 4034 if (hConfigKey != NULL) 4035 RegCloseKey(hConfigKey); 4036 4037 DPRINT("PNP_GetNextLogConf() returns %lu\n", ret); 4038 4039 return ret; 4040 } 4041 4042 4043 /* Function 46 */ 4044 DWORD 4045 WINAPI 4046 PNP_GetLogConfPriority( 4047 handle_t hBinding, 4048 LPWSTR pDeviceID, 4049 DWORD ulType, 4050 DWORD ulTag, 4051 DWORD *pPriority, 4052 DWORD ulFlags) 4053 { 4054 UNIMPLEMENTED; 4055 return CR_CALL_NOT_IMPLEMENTED; 4056 } 4057 4058 4059 /* Function 47 */ 4060 DWORD 4061 WINAPI 4062 PNP_AddResDes( 4063 handle_t hBinding, 4064 LPWSTR pDeviceID, 4065 DWORD ulLogConfTag, 4066 DWORD ulLogConfType, 4067 RESOURCEID ResourceID, 4068 DWORD *pulResourceTag, 4069 BYTE *ResourceData, 4070 PNP_RPC_BUFFER_SIZE ResourceLen, 4071 DWORD ulFlags) 4072 { 4073 UNIMPLEMENTED; 4074 return CR_CALL_NOT_IMPLEMENTED; 4075 } 4076 4077 4078 /* Function 48 */ 4079 DWORD 4080 WINAPI 4081 PNP_FreeResDes( 4082 handle_t hBinding, 4083 LPWSTR pDeviceID, 4084 DWORD ulLogConfTag, 4085 DWORD ulLogConfType, 4086 RESOURCEID ResourceID, 4087 DWORD ulResourceTag, 4088 DWORD *pulPreviousResType, 4089 DWORD *pulPreviousResTag, 4090 DWORD ulFlags) 4091 { 4092 UNIMPLEMENTED; 4093 return CR_CALL_NOT_IMPLEMENTED; 4094 } 4095 4096 4097 /* Function 49 */ 4098 DWORD 4099 WINAPI 4100 PNP_GetNextResDes( 4101 handle_t hBinding, 4102 LPWSTR pDeviceID, 4103 DWORD ulLogConfTag, 4104 DWORD ulLogConfType, 4105 RESOURCEID ResourceID, 4106 DWORD ulResourceTag, 4107 DWORD *pulNextResType, 4108 DWORD *pulNextResTag, 4109 DWORD ulFlags) 4110 { 4111 HKEY hConfigKey = NULL; 4112 DWORD RegDataType = 0; 4113 ULONG ulDataSize = 0; 4114 LPBYTE lpData = NULL; 4115 CONFIGRET ret = CR_SUCCESS; 4116 4117 DPRINT1("PNP_GetNextResDes(%p %S 0x%lx %lu %lu %ul %p %p 0x%08lx)\n", 4118 hBinding, pDeviceID, ulLogConfTag, ulLogConfType, ResourceID, 4119 ulResourceTag, pulNextResType, pulNextResTag, ulFlags); 4120 4121 if (pulNextResType == NULL) 4122 return CR_INVALID_POINTER; 4123 4124 *pulNextResType = 0; 4125 4126 if (ulFlags != 0) 4127 return CR_INVALID_FLAG; 4128 4129 if (!IsValidDeviceInstanceID(pDeviceID)) 4130 return CR_INVALID_DEVINST; 4131 4132 ret = OpenConfigurationKey(pDeviceID, 4133 &hConfigKey); 4134 if (ret != CR_SUCCESS) 4135 { 4136 DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret); 4137 ret = CR_NO_MORE_LOG_CONF; 4138 goto done; 4139 } 4140 4141 ret = GetConfigurationData(hConfigKey, 4142 ulLogConfType, 4143 &RegDataType, 4144 &ulDataSize, 4145 &lpData); 4146 if (ret != CR_SUCCESS) 4147 { 4148 DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret); 4149 ret = CR_NO_MORE_LOG_CONF; 4150 goto done; 4151 } 4152 4153 DPRINT1("Data size %lu\n", ulDataSize); 4154 4155 if (ulDataSize == 0 || lpData == NULL) 4156 { 4157 DPRINT1("No config data available!\n"); 4158 ret = CR_NO_MORE_LOG_CONF; 4159 goto done; 4160 } 4161 4162 /* Get the next resource descriptor */ 4163 if (RegDataType == REG_RESOURCE_LIST) 4164 { 4165 DPRINT1("FIXME: REG_RESOURCE_LIST\n"); 4166 /* FIXME */ 4167 ret = CR_NO_MORE_LOG_CONF; 4168 goto done; 4169 } 4170 else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) 4171 { 4172 DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n"); 4173 /* FIXME */ 4174 ret = CR_NO_MORE_LOG_CONF; 4175 goto done; 4176 } 4177 4178 done: 4179 if (lpData != NULL) 4180 HeapFree(GetProcessHeap(), 0, lpData); 4181 4182 if (hConfigKey != NULL) 4183 RegCloseKey(hConfigKey); 4184 4185 DPRINT1("PNP_GetNextResDes() returns %lu\n", ret); 4186 4187 return ret; 4188 } 4189 4190 4191 /* Function 50 */ 4192 DWORD 4193 WINAPI 4194 PNP_GetResDesData( 4195 handle_t hBinding, 4196 LPWSTR pDeviceID, 4197 DWORD ulLogConfTag, 4198 DWORD ulLogConfType, 4199 RESOURCEID ResourceID, 4200 DWORD ulResourceTag, 4201 BYTE *Buffer, 4202 PNP_RPC_BUFFER_SIZE BufferLen, 4203 DWORD ulFlags) 4204 { 4205 UNIMPLEMENTED; 4206 return CR_CALL_NOT_IMPLEMENTED; 4207 } 4208 4209 4210 /* Function 51 */ 4211 DWORD 4212 WINAPI 4213 PNP_GetResDesDataSize( 4214 handle_t hBinding, 4215 LPWSTR pDeviceID, 4216 DWORD ulLogConfTag, 4217 DWORD ulLogConfType, 4218 RESOURCEID ResourceID, 4219 DWORD ulResourceTag, 4220 DWORD *pulSize, 4221 DWORD ulFlags) 4222 { 4223 UNIMPLEMENTED; 4224 return CR_CALL_NOT_IMPLEMENTED; 4225 } 4226 4227 4228 /* Function 52 */ 4229 DWORD 4230 WINAPI 4231 PNP_ModifyResDes( 4232 handle_t hBinding, 4233 LPWSTR pDeviceID, 4234 DWORD ulLogConfTag, 4235 DWORD ulLogConfType, 4236 RESOURCEID CurrentResourceID, 4237 RESOURCEID NewResourceID, 4238 DWORD ulResourceTag, 4239 BYTE *ResourceData, 4240 PNP_RPC_BUFFER_SIZE ResourceLen, 4241 DWORD ulFlags) 4242 { 4243 UNIMPLEMENTED; 4244 return CR_CALL_NOT_IMPLEMENTED; 4245 } 4246 4247 4248 /* Function 53 */ 4249 DWORD 4250 WINAPI 4251 PNP_DetectResourceConflict( 4252 handle_t hBinding, 4253 LPWSTR pDeviceID, 4254 RESOURCEID ResourceID, 4255 BYTE *ResourceData, 4256 PNP_RPC_BUFFER_SIZE ResourceLen, 4257 BOOL *pbConflictDetected, 4258 DWORD ulFlags) 4259 { 4260 DPRINT("PNP_DetectResourceConflict()\n"); 4261 4262 if (pbConflictDetected != NULL) 4263 *pbConflictDetected = FALSE; 4264 4265 return CR_CALL_NOT_IMPLEMENTED; 4266 } 4267 4268 4269 /* Function 54 */ 4270 DWORD 4271 WINAPI 4272 PNP_QueryResConfList( 4273 handle_t hBinding, 4274 LPWSTR pDeviceID, 4275 RESOURCEID ResourceID, 4276 BYTE *ResourceData, 4277 PNP_RPC_BUFFER_SIZE ResourceLen, 4278 BYTE *Buffer, 4279 PNP_RPC_BUFFER_SIZE BufferLen, 4280 DWORD ulFlags) 4281 { 4282 UNIMPLEMENTED; 4283 return CR_CALL_NOT_IMPLEMENTED; 4284 } 4285 4286 4287 /* Function 55 */ 4288 DWORD 4289 WINAPI 4290 PNP_SetHwProf( 4291 handle_t hBinding, 4292 DWORD ulHardwareProfile, 4293 DWORD ulFlags) 4294 { 4295 return CR_CALL_NOT_IMPLEMENTED; 4296 } 4297 4298 4299 /* Function 56 */ 4300 DWORD 4301 WINAPI 4302 PNP_QueryArbitratorFreeData( 4303 handle_t hBinding, 4304 BYTE *pData, 4305 DWORD DataLen, 4306 LPWSTR pDeviceID, 4307 RESOURCEID ResourceID, 4308 DWORD ulFlags) 4309 { 4310 return CR_CALL_NOT_IMPLEMENTED; 4311 } 4312 4313 4314 /* Function 57 */ 4315 DWORD 4316 WINAPI 4317 PNP_QueryArbitratorFreeSize( 4318 handle_t hBinding, 4319 DWORD *pulSize, 4320 LPWSTR pDeviceID, 4321 RESOURCEID ResourceID, 4322 DWORD ulFlags) 4323 { 4324 if (pulSize != NULL) 4325 *pulSize = 0; 4326 4327 return CR_CALL_NOT_IMPLEMENTED; 4328 } 4329 4330 4331 /* Function 58 */ 4332 CONFIGRET 4333 WINAPI 4334 PNP_RunDetection( 4335 handle_t hBinding, 4336 DWORD ulFlags) 4337 { 4338 return CR_CALL_NOT_IMPLEMENTED; 4339 } 4340 4341 4342 /* Function 59 */ 4343 DWORD 4344 WINAPI 4345 PNP_RegisterNotification( 4346 handle_t hBinding, 4347 DWORD ulUnknown2, 4348 LPWSTR pszName, 4349 BYTE *pNotificationFilter, 4350 DWORD ulNotificationFilterSize, 4351 DWORD ulFlags, 4352 DWORD *pulNotify, 4353 DWORD ulUnknown8, 4354 DWORD *pulUnknown9) 4355 { 4356 PDEV_BROADCAST_DEVICEINTERFACE_W pBroadcastDeviceInterface; 4357 PDEV_BROADCAST_HANDLE pBroadcastDeviceHandle; 4358 #if 0 4359 PNOTIFY_DATA pNotifyData; 4360 #endif 4361 4362 DPRINT1("PNP_RegisterNotification(%p %lx '%S' %p %lu 0x%lx %p %lx %p)\n", 4363 hBinding, ulUnknown2, pszName, pNotificationFilter, 4364 ulNotificationFilterSize, ulFlags, pulNotify, ulUnknown8, pulUnknown9); 4365 4366 if (pNotificationFilter == NULL || 4367 pulNotify == NULL || 4368 pulUnknown9 == NULL) 4369 return CR_INVALID_POINTER; 4370 4371 if (ulFlags & ~0x7) 4372 return CR_INVALID_FLAG; 4373 4374 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_HDR)) || 4375 (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_size < sizeof(DEV_BROADCAST_HDR))) 4376 return CR_INVALID_DATA; 4377 4378 if (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) 4379 { 4380 DPRINT1("DBT_DEVTYP_DEVICEINTERFACE\n"); 4381 pBroadcastDeviceInterface = (PDEV_BROADCAST_DEVICEINTERFACE_W)pNotificationFilter; 4382 4383 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_DEVICEINTERFACE_W)) || 4384 (pBroadcastDeviceInterface->dbcc_size < sizeof(DEV_BROADCAST_DEVICEINTERFACE_W))) 4385 return CR_INVALID_DATA; 4386 } 4387 else if (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype == DBT_DEVTYP_HANDLE) 4388 { 4389 DPRINT1("DBT_DEVTYP_HANDLE\n"); 4390 pBroadcastDeviceHandle = (PDEV_BROADCAST_HANDLE)pNotificationFilter; 4391 4392 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_HANDLE)) || 4393 (pBroadcastDeviceHandle->dbch_size < sizeof(DEV_BROADCAST_HANDLE))) 4394 return CR_INVALID_DATA; 4395 4396 if (ulFlags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES) 4397 return CR_INVALID_FLAG; 4398 } 4399 else 4400 { 4401 DPRINT1("Invalid device type %lu\n", ((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype); 4402 return CR_INVALID_DATA; 4403 } 4404 4405 4406 #if 0 4407 pNotifyData = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NOTIFY_DATA)); 4408 if (pNotifyData == NULL) 4409 return CR_OUT_OF_MEMORY; 4410 4411 *pulNotify = (DWORD)pNotifyData; 4412 #endif 4413 4414 *pulNotify = 1; 4415 4416 return CR_SUCCESS; 4417 } 4418 4419 4420 /* Function 60 */ 4421 DWORD 4422 WINAPI 4423 PNP_UnregisterNotification( 4424 handle_t hBinding, 4425 DWORD ulNotify) 4426 { 4427 DPRINT1("PNP_UnregisterNotification(%p 0x%lx)\n", 4428 hBinding, ulNotify); 4429 4430 #if 0 4431 UNIMPLEMENTED; 4432 return CR_CALL_NOT_IMPLEMENTED; 4433 #endif 4434 4435 return CR_SUCCESS; 4436 } 4437 4438 4439 /* Function 61 */ 4440 DWORD 4441 WINAPI 4442 PNP_GetCustomDevProp( 4443 handle_t hBinding, 4444 LPWSTR pDeviceID, 4445 LPWSTR CustomPropName, 4446 DWORD *pulRegDataType, 4447 BYTE *Buffer, 4448 PNP_RPC_STRING_LEN *pulTransferLen, 4449 PNP_RPC_STRING_LEN *pulLength, 4450 DWORD ulFlags) 4451 { 4452 HKEY hDeviceKey = NULL; 4453 HKEY hParamKey = NULL; 4454 LONG lError; 4455 CONFIGRET ret = CR_SUCCESS; 4456 4457 UNREFERENCED_PARAMETER(hBinding); 4458 4459 DPRINT("PNP_GetCustomDevProp() called\n"); 4460 4461 if (pulTransferLen == NULL || pulLength == NULL) 4462 { 4463 ret = CR_INVALID_POINTER; 4464 goto done; 4465 } 4466 4467 if (ulFlags & ~CM_CUSTOMDEVPROP_BITS) 4468 { 4469 ret = CR_INVALID_FLAG; 4470 goto done; 4471 } 4472 4473 if (!IsValidDeviceInstanceID(pDeviceID)) 4474 return CR_INVALID_DEVINST; 4475 4476 if (*pulLength < *pulTransferLen) 4477 *pulLength = *pulTransferLen; 4478 4479 *pulTransferLen = 0; 4480 4481 lError = RegOpenKeyExW(hEnumKey, 4482 pDeviceID, 4483 0, 4484 KEY_READ, 4485 &hDeviceKey); 4486 if (lError != ERROR_SUCCESS) 4487 { 4488 ret = CR_REGISTRY_ERROR; 4489 goto done; 4490 } 4491 4492 lError = RegOpenKeyExW(hDeviceKey, 4493 L"Device Parameters", 4494 0, 4495 KEY_READ, 4496 &hParamKey); 4497 if (lError != ERROR_SUCCESS) 4498 { 4499 ret = CR_REGISTRY_ERROR; 4500 goto done; 4501 } 4502 4503 lError = RegQueryValueExW(hParamKey, 4504 CustomPropName, 4505 NULL, 4506 pulRegDataType, 4507 Buffer, 4508 pulLength); 4509 if (lError != ERROR_SUCCESS) 4510 { 4511 if (lError == ERROR_MORE_DATA) 4512 { 4513 ret = CR_BUFFER_SMALL; 4514 } 4515 else 4516 { 4517 *pulLength = 0; 4518 ret = CR_NO_SUCH_VALUE; 4519 } 4520 } 4521 4522 done: 4523 if (ret == CR_SUCCESS) 4524 *pulTransferLen = *pulLength; 4525 4526 if (hParamKey != NULL) 4527 RegCloseKey(hParamKey); 4528 4529 if (hDeviceKey != NULL) 4530 RegCloseKey(hDeviceKey); 4531 4532 DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret); 4533 4534 return ret; 4535 } 4536 4537 4538 /* Function 62 */ 4539 DWORD 4540 WINAPI 4541 PNP_GetVersionInternal( 4542 handle_t hBinding, 4543 WORD *pwVersion) 4544 { 4545 UNREFERENCED_PARAMETER(hBinding); 4546 4547 *pwVersion = 0x501; 4548 return CR_SUCCESS; 4549 } 4550 4551 4552 /* Function 63 */ 4553 DWORD 4554 WINAPI 4555 PNP_GetBlockedDriverInfo( 4556 handle_t hBinding, 4557 BYTE *Buffer, 4558 PNP_RPC_BUFFER_SIZE *pulTransferLen, 4559 PNP_RPC_BUFFER_SIZE *pulLength, 4560 DWORD ulFlags) 4561 { 4562 UNIMPLEMENTED; 4563 return CR_CALL_NOT_IMPLEMENTED; 4564 } 4565 4566 4567 /* Function 64 */ 4568 DWORD 4569 WINAPI 4570 PNP_GetServerSideDeviceInstallFlags( 4571 handle_t hBinding, 4572 DWORD *pulSSDIFlags, 4573 DWORD ulFlags) 4574 { 4575 UNREFERENCED_PARAMETER(hBinding); 4576 4577 DPRINT1("PNP_GetServerSideDeviceInstallFlags(%p %p %lu)\n", 4578 hBinding, pulSSDIFlags, ulFlags); 4579 4580 if (pulSSDIFlags == NULL) 4581 return CR_INVALID_POINTER; 4582 4583 if (ulFlags != 0) 4584 return CR_INVALID_FLAG; 4585 4586 /* FIXME */ 4587 *pulSSDIFlags = 0; 4588 4589 return CR_SUCCESS; 4590 } 4591 4592 4593 /* Function 65 */ 4594 DWORD 4595 WINAPI 4596 PNP_GetObjectPropKeys( 4597 handle_t hBinding, 4598 LPWSTR ObjectName, 4599 DWORD ObjectType, 4600 LPWSTR PropertyCultureName, 4601 PNP_PROP_COUNT *PropertyCount, 4602 PNP_PROP_COUNT *TransferLen, 4603 DEVPROPKEY *PropertyKeys, 4604 DWORD Flags) 4605 { 4606 UNIMPLEMENTED; 4607 return CR_CALL_NOT_IMPLEMENTED; 4608 } 4609 4610 4611 /* Function 66 */ 4612 DWORD 4613 WINAPI 4614 PNP_GetObjectProp( 4615 handle_t hBinding, 4616 LPWSTR ObjectName, 4617 DWORD ObjectType, 4618 LPWSTR PropertyCultureName, 4619 const DEVPROPKEY *PropertyKey, 4620 DEVPROPTYPE *PropertyType, 4621 PNP_PROP_SIZE *PropertySize, 4622 PNP_PROP_SIZE *TransferLen, 4623 BYTE *PropertyBuffer, 4624 DWORD Flags) 4625 { 4626 UNIMPLEMENTED; 4627 return CR_CALL_NOT_IMPLEMENTED; 4628 } 4629 4630 4631 /* Function 67 */ 4632 DWORD 4633 WINAPI 4634 PNP_SetObjectProp( 4635 handle_t hBinding, 4636 LPWSTR ObjectName, 4637 DWORD ObjectType, 4638 LPWSTR PropertyCultureName, 4639 const DEVPROPKEY *PropertyKey, 4640 DEVPROPTYPE PropertyType, 4641 PNP_PROP_SIZE PropertySize, 4642 BYTE *PropertyBuffer, 4643 DWORD Flags) 4644 { 4645 UNIMPLEMENTED; 4646 return CR_CALL_NOT_IMPLEMENTED; 4647 } 4648 4649 4650 /* Function 68 */ 4651 DWORD 4652 WINAPI 4653 PNP_InstallDevInst( 4654 handle_t hBinding) 4655 { 4656 UNIMPLEMENTED; 4657 return CR_CALL_NOT_IMPLEMENTED; 4658 } 4659 4660 4661 /* Function 69 */ 4662 DWORD 4663 WINAPI 4664 PNP_ApplyPowerSettings( 4665 handle_t hBinding) 4666 { 4667 UNIMPLEMENTED; 4668 return CR_CALL_NOT_IMPLEMENTED; 4669 } 4670 4671 4672 /* Function 70 */ 4673 DWORD 4674 WINAPI 4675 PNP_DriverStoreAddDriverPackage( 4676 handle_t hBinding) 4677 { 4678 UNIMPLEMENTED; 4679 return CR_CALL_NOT_IMPLEMENTED; 4680 } 4681 4682 4683 /* Function 71 */ 4684 DWORD 4685 WINAPI 4686 PNP_DriverStoreDeleteDriverPackage( 4687 handle_t hBinding) 4688 { 4689 UNIMPLEMENTED; 4690 return CR_CALL_NOT_IMPLEMENTED; 4691 } 4692 4693 4694 /* Function 72 */ 4695 DWORD 4696 WINAPI 4697 PNP_RegisterServiceNotification( 4698 handle_t hBinding) 4699 { 4700 UNIMPLEMENTED; 4701 return CR_CALL_NOT_IMPLEMENTED; 4702 } 4703 4704 4705 /* Function 73 */ 4706 DWORD 4707 WINAPI 4708 PNP_SetActiveService( 4709 handle_t hBinding, 4710 LPWSTR pszFilter, 4711 DWORD ulFlags) 4712 { 4713 UNIMPLEMENTED; 4714 return CR_CALL_NOT_IMPLEMENTED; 4715 } 4716 4717 4718 /* Function 74 */ 4719 DWORD 4720 WINAPI 4721 PNP_DeleteServiceDevices( 4722 handle_t hBinding) 4723 { 4724 UNIMPLEMENTED; 4725 return CR_CALL_NOT_IMPLEMENTED; 4726 } 4727