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