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