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 UNREFERENCED_PARAMETER(hBinding); 3197 UNREFERENCED_PARAMETER(ulFlags); 3198 3199 DPRINT("PNP_GetDeviceStatus(%p %S %p %p 0x%08lx)\n", 3200 hBinding, pDeviceID, pulStatus, pulProblem, ulFlags); 3201 3202 if (!IsValidDeviceInstanceID(pDeviceID)) 3203 return CR_INVALID_DEVINST; 3204 3205 return GetDeviceStatus(pDeviceID, pulStatus, pulProblem); 3206 } 3207 3208 3209 /* Function 31 */ 3210 DWORD 3211 WINAPI 3212 PNP_SetDeviceProblem( 3213 handle_t hBinding, 3214 LPWSTR pDeviceID, 3215 DWORD ulProblem, 3216 DWORD ulFlags) 3217 { 3218 ULONG ulOldStatus, ulOldProblem; 3219 CONFIGRET ret = CR_SUCCESS; 3220 3221 UNREFERENCED_PARAMETER(hBinding); 3222 3223 DPRINT1("PNP_SetDeviceProblem(%p %S %lu 0x%08lx)\n", 3224 hBinding, pDeviceID, ulProblem, ulFlags); 3225 3226 if (ulFlags & ~CM_SET_DEVNODE_PROBLEM_BITS) 3227 return CR_INVALID_FLAG; 3228 3229 if (!IsValidDeviceInstanceID(pDeviceID)) 3230 return CR_INVALID_DEVINST; 3231 3232 ret = GetDeviceStatus(pDeviceID, 3233 &ulOldStatus, 3234 &ulOldProblem); 3235 if (ret != CR_SUCCESS) 3236 return ret; 3237 3238 if (((ulFlags & CM_SET_DEVNODE_PROBLEM_OVERRIDE) == 0) && 3239 (ulOldProblem != 0) && 3240 (ulOldProblem != ulProblem)) 3241 { 3242 return CR_FAILURE; 3243 } 3244 3245 if (ulProblem == 0) 3246 { 3247 ret = ClearDeviceStatus(pDeviceID, 3248 DN_HAS_PROBLEM, 3249 ulOldProblem); 3250 } 3251 else 3252 { 3253 ret = SetDeviceStatus(pDeviceID, 3254 DN_HAS_PROBLEM, 3255 ulProblem); 3256 } 3257 3258 return ret; 3259 } 3260 3261 3262 /* Function 32 */ 3263 DWORD 3264 WINAPI 3265 PNP_DisableDevInst( 3266 handle_t hBinding, 3267 LPWSTR pDeviceID, 3268 PPNP_VETO_TYPE pVetoType, 3269 LPWSTR pszVetoName, 3270 DWORD ulNameLength, 3271 DWORD ulFlags) 3272 { 3273 UNREFERENCED_PARAMETER(hBinding); 3274 3275 DPRINT1("PNP_DisableDevInst(%p %S %p %p %lu 0x%08lx)\n", 3276 hBinding, pDeviceID, pVetoType, pszVetoName, ulNameLength, ulFlags); 3277 3278 if (ulFlags & ~CM_DISABLE_BITS) 3279 return CR_INVALID_FLAG; 3280 3281 if (!IsValidDeviceInstanceID(pDeviceID) || 3282 IsRootDeviceInstanceID(pDeviceID)) 3283 return CR_INVALID_DEVINST; 3284 3285 return DisableDeviceInstance(pDeviceID, 3286 pVetoType, 3287 pszVetoName, 3288 ulNameLength); 3289 } 3290 3291 3292 /* Function 33 */ 3293 DWORD 3294 WINAPI 3295 PNP_UninstallDevInst( 3296 handle_t hBinding, 3297 LPWSTR pDeviceID, 3298 DWORD ulFlags) 3299 { 3300 UNIMPLEMENTED; 3301 return CR_CALL_NOT_IMPLEMENTED; 3302 } 3303 3304 3305 static BOOL 3306 CheckForDeviceId(LPWSTR lpDeviceIdList, 3307 LPWSTR lpDeviceId) 3308 { 3309 LPWSTR lpPtr; 3310 DWORD dwLength; 3311 3312 lpPtr = lpDeviceIdList; 3313 while (*lpPtr != 0) 3314 { 3315 dwLength = wcslen(lpPtr); 3316 if (0 == _wcsicmp(lpPtr, lpDeviceId)) 3317 return TRUE; 3318 3319 lpPtr += (dwLength + 1); 3320 } 3321 3322 return FALSE; 3323 } 3324 3325 3326 static VOID 3327 AppendDeviceId(LPWSTR lpDeviceIdList, 3328 LPDWORD lpDeviceIdListSize, 3329 LPWSTR lpDeviceId) 3330 { 3331 DWORD dwLen; 3332 DWORD dwPos; 3333 3334 dwLen = wcslen(lpDeviceId); 3335 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1; 3336 3337 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId); 3338 3339 dwPos += (dwLen + 1); 3340 3341 lpDeviceIdList[dwPos] = 0; 3342 3343 *lpDeviceIdListSize = dwPos * sizeof(WCHAR); 3344 } 3345 3346 3347 /* Function 34 */ 3348 DWORD 3349 WINAPI 3350 PNP_AddID( 3351 handle_t hBinding, 3352 LPWSTR pszDeviceID, 3353 LPWSTR pszID, 3354 DWORD ulFlags) 3355 { 3356 CONFIGRET ret = CR_SUCCESS; 3357 HKEY hDeviceKey; 3358 LPWSTR pszSubKey; 3359 DWORD dwDeviceIdListSize; 3360 DWORD dwNewDeviceIdSize; 3361 WCHAR * pszDeviceIdList = NULL; 3362 3363 UNREFERENCED_PARAMETER(hBinding); 3364 3365 DPRINT("PNP_AddID(%p %S %S 0x%08lx)\n", 3366 hBinding, pszDeviceID, pszID, ulFlags); 3367 3368 if (RegOpenKeyExW(hEnumKey, 3369 pszDeviceID, 3370 0, 3371 KEY_QUERY_VALUE | KEY_SET_VALUE, 3372 &hDeviceKey) != ERROR_SUCCESS) 3373 { 3374 DPRINT("Failed to open the device key!\n"); 3375 return CR_INVALID_DEVNODE; 3376 } 3377 3378 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID"; 3379 3380 if (RegQueryValueExW(hDeviceKey, 3381 pszSubKey, 3382 NULL, 3383 NULL, 3384 NULL, 3385 &dwDeviceIdListSize) != ERROR_SUCCESS) 3386 { 3387 DPRINT("Failed to query the desired ID string!\n"); 3388 ret = CR_REGISTRY_ERROR; 3389 goto Done; 3390 } 3391 3392 dwNewDeviceIdSize = lstrlenW(pszDeviceID); 3393 if (!dwNewDeviceIdSize) 3394 { 3395 ret = CR_INVALID_POINTER; 3396 goto Done; 3397 } 3398 3399 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR); 3400 3401 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize); 3402 if (!pszDeviceIdList) 3403 { 3404 DPRINT("Failed to allocate memory for the desired ID string!\n"); 3405 ret = CR_OUT_OF_MEMORY; 3406 goto Done; 3407 } 3408 3409 if (RegQueryValueExW(hDeviceKey, 3410 pszSubKey, 3411 NULL, 3412 NULL, 3413 (LPBYTE)pszDeviceIdList, 3414 &dwDeviceIdListSize) != ERROR_SUCCESS) 3415 { 3416 DPRINT("Failed to query the desired ID string!\n"); 3417 ret = CR_REGISTRY_ERROR; 3418 goto Done; 3419 } 3420 3421 /* Check whether the device ID is already in use */ 3422 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID)) 3423 { 3424 DPRINT("Device ID was found in the ID string!\n"); 3425 ret = CR_SUCCESS; 3426 goto Done; 3427 } 3428 3429 /* Append the Device ID */ 3430 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID); 3431 3432 if (RegSetValueExW(hDeviceKey, 3433 pszSubKey, 3434 0, 3435 REG_MULTI_SZ, 3436 (LPBYTE)pszDeviceIdList, 3437 dwDeviceIdListSize) != ERROR_SUCCESS) 3438 { 3439 DPRINT("Failed to set the desired ID string!\n"); 3440 ret = CR_REGISTRY_ERROR; 3441 } 3442 3443 Done: 3444 RegCloseKey(hDeviceKey); 3445 if (pszDeviceIdList) 3446 HeapFree(GetProcessHeap(), 0, pszDeviceIdList); 3447 3448 DPRINT("PNP_AddID() done (returns %lx)\n", ret); 3449 3450 return ret; 3451 } 3452 3453 3454 /* Function 35 */ 3455 DWORD 3456 WINAPI 3457 PNP_RegisterDriver( 3458 handle_t hBinding, 3459 LPWSTR pszDeviceID, 3460 DWORD ulFlags) 3461 { 3462 DPRINT("PNP_RegisterDriver(%p %S 0x%lx)\n", 3463 hBinding, pszDeviceID, ulFlags); 3464 3465 if (ulFlags & ~CM_REGISTER_DEVICE_DRIVER_BITS) 3466 return CR_INVALID_FLAG; 3467 3468 if (!IsValidDeviceInstanceID(pszDeviceID)) 3469 return CR_INVALID_DEVINST; 3470 3471 SetDeviceStatus(pszDeviceID, 0, 0); 3472 3473 return CR_SUCCESS; 3474 } 3475 3476 3477 /* Function 36 */ 3478 DWORD 3479 WINAPI 3480 PNP_QueryRemove( 3481 handle_t hBinding, 3482 LPWSTR pszDeviceID, 3483 PPNP_VETO_TYPE pVetoType, 3484 LPWSTR pszVetoName, 3485 DWORD ulNameLength, 3486 DWORD ulFlags) 3487 { 3488 PLUGPLAY_CONTROL_QUERY_REMOVE_DATA PlugPlayData; 3489 NTSTATUS Status; 3490 DWORD ret = CR_SUCCESS; 3491 3492 DPRINT1("PNP_QueryRemove(%p %S %p %p %lu 0x%lx)\n", 3493 hBinding, pszDeviceID, pVetoType, pszVetoName, 3494 ulNameLength, ulFlags); 3495 3496 if (ulFlags & ~CM_REMOVE_BITS) 3497 return CR_INVALID_FLAG; 3498 3499 if (!IsValidDeviceInstanceID(pszDeviceID) || 3500 IsRootDeviceInstanceID(pszDeviceID)) 3501 return CR_INVALID_DEVINST; 3502 3503 if (pVetoType != NULL) 3504 *pVetoType = PNP_VetoTypeUnknown; 3505 3506 if (pszVetoName != NULL && ulNameLength > 0) 3507 *pszVetoName = UNICODE_NULL; 3508 3509 RtlZeroMemory(&PlugPlayData, sizeof(PlugPlayData)); 3510 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 3511 pszDeviceID); 3512 PlugPlayData.VetoName = pszVetoName; 3513 PlugPlayData.NameLength = ulNameLength; 3514 // PlugPlayData.Flags = 3515 3516 Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice, 3517 &PlugPlayData, 3518 sizeof(PlugPlayData)); 3519 if (!NT_SUCCESS(Status)) 3520 ret = NtStatusToCrError(Status); 3521 3522 return ret; 3523 } 3524 3525 3526 /* Function 37 */ 3527 DWORD 3528 WINAPI 3529 PNP_RequestDeviceEject( 3530 handle_t hBinding, 3531 LPWSTR pszDeviceID, 3532 PPNP_VETO_TYPE pVetoType, 3533 LPWSTR pszVetoName, 3534 DWORD ulNameLength, 3535 DWORD ulFlags) 3536 { 3537 PLUGPLAY_CONTROL_QUERY_REMOVE_DATA PlugPlayData; 3538 NTSTATUS Status; 3539 DWORD ret = CR_SUCCESS; 3540 3541 DPRINT1("PNP_RequestDeviceEject(%p %S %p %p %lu 0x%lx)\n", 3542 hBinding, pszDeviceID, pVetoType, pszVetoName, 3543 ulNameLength, ulFlags); 3544 3545 if (ulFlags != 0) 3546 return CR_INVALID_FLAG; 3547 3548 if (!IsValidDeviceInstanceID(pszDeviceID)) 3549 return CR_INVALID_DEVINST; 3550 3551 if (pVetoType != NULL) 3552 *pVetoType = PNP_VetoTypeUnknown; 3553 3554 if (pszVetoName != NULL && ulNameLength > 0) 3555 *pszVetoName = UNICODE_NULL; 3556 3557 RtlZeroMemory(&PlugPlayData, sizeof(PlugPlayData)); 3558 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 3559 pszDeviceID); 3560 PlugPlayData.VetoName = pszVetoName; 3561 PlugPlayData.NameLength = ulNameLength; 3562 // PlugPlayData.Flags = 3563 3564 Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice, 3565 &PlugPlayData, 3566 sizeof(PlugPlayData)); 3567 if (!NT_SUCCESS(Status)) 3568 ret = NtStatusToCrError(Status); 3569 3570 return ret; 3571 } 3572 3573 3574 /* Function 38 */ 3575 CONFIGRET 3576 WINAPI 3577 PNP_IsDockStationPresent( 3578 handle_t hBinding, 3579 BOOL *Present) 3580 { 3581 HKEY hKey; 3582 DWORD dwType; 3583 DWORD dwValue; 3584 DWORD dwSize; 3585 CONFIGRET ret = CR_SUCCESS; 3586 3587 UNREFERENCED_PARAMETER(hBinding); 3588 3589 DPRINT1("PNP_IsDockStationPresent(%p %p)\n", 3590 hBinding, Present); 3591 3592 *Present = FALSE; 3593 3594 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG, 3595 L"CurrentDockInfo", 3596 0, 3597 KEY_READ, 3598 &hKey) != ERROR_SUCCESS) 3599 return CR_REGISTRY_ERROR; 3600 3601 dwSize = sizeof(DWORD); 3602 if (RegQueryValueExW(hKey, 3603 L"DockingState", 3604 NULL, 3605 &dwType, 3606 (LPBYTE)&dwValue, 3607 &dwSize) != ERROR_SUCCESS) 3608 ret = CR_REGISTRY_ERROR; 3609 3610 RegCloseKey(hKey); 3611 3612 if (ret == CR_SUCCESS) 3613 { 3614 if (dwType != REG_DWORD || dwSize != sizeof(DWORD)) 3615 { 3616 ret = CR_REGISTRY_ERROR; 3617 } 3618 else if (dwValue != 0) 3619 { 3620 *Present = TRUE; 3621 } 3622 } 3623 3624 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret); 3625 3626 return ret; 3627 } 3628 3629 3630 /* Function 39 */ 3631 DWORD 3632 WINAPI 3633 PNP_RequestEjectPC( 3634 handle_t hBinding) 3635 { 3636 WCHAR szDockDeviceInstance[MAX_DEVICE_ID_LEN]; 3637 PLUGPLAY_CONTROL_RETRIEVE_DOCK_DATA DockData; 3638 NTSTATUS Status; 3639 3640 DPRINT("PNP_RequestEjectPC(%p)\n", hBinding); 3641 3642 /* Retrieve the dock device */ 3643 DockData.DeviceInstanceLength = ARRAYSIZE(szDockDeviceInstance); 3644 DockData.DeviceInstance = szDockDeviceInstance; 3645 3646 Status = NtPlugPlayControl(PlugPlayControlRetrieveDock, 3647 &DockData, 3648 sizeof(DockData)); 3649 if (!NT_SUCCESS(Status)) 3650 return NtStatusToCrError(Status); 3651 3652 /* Eject the dock device */ 3653 return PNP_RequestDeviceEject(hBinding, 3654 szDockDeviceInstance, 3655 NULL, 3656 NULL, 3657 0, 3658 0); 3659 } 3660 3661 3662 /* Function 40 */ 3663 DWORD 3664 WINAPI 3665 PNP_HwProfFlags( 3666 handle_t hBinding, 3667 DWORD ulAction, 3668 LPWSTR pDeviceID, 3669 DWORD ulConfig, 3670 DWORD *pulValue, 3671 PPNP_VETO_TYPE pVetoType, 3672 LPWSTR pszVetoName, 3673 DWORD ulNameLength, 3674 DWORD ulFlags) 3675 { 3676 CONFIGRET ret = CR_SUCCESS; 3677 WCHAR szKeyName[MAX_PATH]; 3678 HKEY hKey; 3679 HKEY hDeviceKey; 3680 DWORD dwSize; 3681 3682 UNREFERENCED_PARAMETER(hBinding); 3683 3684 DPRINT("PNP_HwProfFlags() called\n"); 3685 3686 if (!IsValidDeviceInstanceID(pDeviceID)) 3687 return CR_INVALID_DEVINST; 3688 3689 if (ulConfig == 0) 3690 { 3691 wcscpy(szKeyName, 3692 L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum"); 3693 } 3694 else 3695 { 3696 swprintf(szKeyName, 3697 L"System\\CurrentControlSet\\HardwareProfiles\\%04lu\\System\\CurrentControlSet\\Enum", 3698 ulConfig); 3699 } 3700 3701 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 3702 szKeyName, 3703 0, 3704 KEY_QUERY_VALUE, 3705 &hKey) != ERROR_SUCCESS) 3706 return CR_REGISTRY_ERROR; 3707 3708 if (ulAction == PNP_GET_HWPROFFLAGS) 3709 { 3710 if (RegOpenKeyExW(hKey, 3711 pDeviceID, 3712 0, 3713 KEY_QUERY_VALUE, 3714 &hDeviceKey) != ERROR_SUCCESS) 3715 { 3716 *pulValue = 0; 3717 } 3718 else 3719 { 3720 dwSize = sizeof(DWORD); 3721 if (RegQueryValueExW(hDeviceKey, 3722 L"CSConfigFlags", 3723 NULL, 3724 NULL, 3725 (LPBYTE)pulValue, 3726 &dwSize) != ERROR_SUCCESS) 3727 { 3728 *pulValue = 0; 3729 } 3730 3731 RegCloseKey(hDeviceKey); 3732 } 3733 } 3734 else if (ulAction == PNP_SET_HWPROFFLAGS) 3735 { 3736 /* FIXME: not implemented yet */ 3737 ret = CR_CALL_NOT_IMPLEMENTED; 3738 } 3739 3740 RegCloseKey(hKey); 3741 3742 return ret; 3743 } 3744 3745 3746 /* Function 41 */ 3747 DWORD 3748 WINAPI 3749 PNP_GetHwProfInfo( 3750 handle_t hBinding, 3751 DWORD ulIndex, 3752 HWPROFILEINFO *pHWProfileInfo, 3753 DWORD ulProfileInfoSize, 3754 DWORD ulFlags) 3755 { 3756 WCHAR szProfileName[5]; 3757 HKEY hKeyConfig = NULL; 3758 HKEY hKeyProfiles = NULL; 3759 HKEY hKeyProfile = NULL; 3760 DWORD dwDisposition; 3761 DWORD dwSize; 3762 LONG lError; 3763 CONFIGRET ret = CR_SUCCESS; 3764 3765 UNREFERENCED_PARAMETER(hBinding); 3766 3767 DPRINT("PNP_GetHwProfInfo() called\n"); 3768 3769 if (ulProfileInfoSize == 0) 3770 { 3771 ret = CR_INVALID_DATA; 3772 goto done; 3773 } 3774 3775 if (ulFlags != 0) 3776 { 3777 ret = CR_INVALID_FLAG; 3778 goto done; 3779 } 3780 3781 /* Initialize the profile information */ 3782 pHWProfileInfo->HWPI_ulHWProfile = 0; 3783 pHWProfileInfo->HWPI_szFriendlyName[0] = 0; 3784 pHWProfileInfo->HWPI_dwFlags = 0; 3785 3786 /* Open the 'IDConfigDB' key */ 3787 lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE, 3788 L"System\\CurrentControlSet\\Control\\IDConfigDB", 3789 0, 3790 NULL, 3791 REG_OPTION_NON_VOLATILE, 3792 KEY_QUERY_VALUE, 3793 NULL, 3794 &hKeyConfig, 3795 &dwDisposition); 3796 if (lError != ERROR_SUCCESS) 3797 { 3798 ret = CR_REGISTRY_ERROR; 3799 goto done; 3800 } 3801 3802 /* Open the 'Hardware Profiles' subkey */ 3803 lError = RegCreateKeyExW(hKeyConfig, 3804 L"Hardware Profiles", 3805 0, 3806 NULL, 3807 REG_OPTION_NON_VOLATILE, 3808 KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, 3809 NULL, 3810 &hKeyProfiles, 3811 &dwDisposition); 3812 if (lError != ERROR_SUCCESS) 3813 { 3814 ret = CR_REGISTRY_ERROR; 3815 goto done; 3816 } 3817 3818 if (ulIndex == (ULONG)-1) 3819 { 3820 dwSize = sizeof(ULONG); 3821 lError = RegQueryValueExW(hKeyConfig, 3822 L"CurrentConfig", 3823 NULL, 3824 NULL, 3825 (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile, 3826 &dwSize); 3827 if (lError != ERROR_SUCCESS) 3828 { 3829 pHWProfileInfo->HWPI_ulHWProfile = 0; 3830 ret = CR_REGISTRY_ERROR; 3831 goto done; 3832 } 3833 } 3834 else 3835 { 3836 /* FIXME: not implemented yet */ 3837 ret = CR_CALL_NOT_IMPLEMENTED; 3838 goto done; 3839 } 3840 3841 swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile); 3842 3843 lError = RegOpenKeyExW(hKeyProfiles, 3844 szProfileName, 3845 0, 3846 KEY_QUERY_VALUE, 3847 &hKeyProfile); 3848 if (lError != ERROR_SUCCESS) 3849 { 3850 ret = CR_REGISTRY_ERROR; 3851 goto done; 3852 } 3853 3854 dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName); 3855 lError = RegQueryValueExW(hKeyProfile, 3856 L"FriendlyName", 3857 NULL, 3858 NULL, 3859 (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName, 3860 &dwSize); 3861 if (lError != ERROR_SUCCESS) 3862 { 3863 ret = CR_REGISTRY_ERROR; 3864 goto done; 3865 } 3866 3867 done: 3868 if (hKeyProfile != NULL) 3869 RegCloseKey(hKeyProfile); 3870 3871 if (hKeyProfiles != NULL) 3872 RegCloseKey(hKeyProfiles); 3873 3874 if (hKeyConfig != NULL) 3875 RegCloseKey(hKeyConfig); 3876 3877 return ret; 3878 } 3879 3880 3881 /* Function 42 */ 3882 DWORD 3883 WINAPI 3884 PNP_AddEmptyLogConf( 3885 handle_t hBinding, 3886 LPWSTR pDeviceID, 3887 DWORD ulPriority, 3888 DWORD *pulLogConfTag, 3889 DWORD ulFlags) 3890 { 3891 UNIMPLEMENTED; 3892 return CR_CALL_NOT_IMPLEMENTED; 3893 } 3894 3895 3896 /* Function 43 */ 3897 DWORD 3898 WINAPI 3899 PNP_FreeLogConf( 3900 handle_t hBinding, 3901 LPWSTR pDeviceID, 3902 DWORD ulLogConfType, 3903 DWORD ulLogConfTag, 3904 DWORD ulFlags) 3905 { 3906 UNIMPLEMENTED; 3907 return CR_CALL_NOT_IMPLEMENTED; 3908 } 3909 3910 3911 /* Function 44 */ 3912 DWORD 3913 WINAPI 3914 PNP_GetFirstLogConf( 3915 handle_t hBinding, 3916 LPWSTR pDeviceID, 3917 DWORD ulLogConfType, 3918 DWORD *pulLogConfTag, 3919 DWORD ulFlags) 3920 { 3921 HKEY hConfigKey = NULL; 3922 DWORD RegDataType = 0; 3923 ULONG ulDataSize = 0; 3924 LPBYTE lpData = NULL; 3925 CONFIGRET ret = CR_SUCCESS; 3926 3927 DPRINT("PNP_GetFirstLogConf(%p %S %lu %p 0x%08lx)\n", 3928 hBinding, pDeviceID, ulLogConfType, pulLogConfTag, ulFlags); 3929 3930 if (pulLogConfTag == NULL) 3931 return CR_INVALID_POINTER; 3932 3933 *pulLogConfTag = (DWORD)0; 3934 3935 if (ulFlags & ~LOG_CONF_BITS) 3936 return CR_INVALID_FLAG; 3937 3938 if (!IsValidDeviceInstanceID(pDeviceID)) 3939 return CR_INVALID_DEVINST; 3940 3941 ret = OpenConfigurationKey(pDeviceID, 3942 &hConfigKey); 3943 if (ret != CR_SUCCESS) 3944 { 3945 DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret); 3946 ret = CR_NO_MORE_LOG_CONF; 3947 goto done; 3948 } 3949 3950 ret = GetConfigurationData(hConfigKey, 3951 ulLogConfType, 3952 &RegDataType, 3953 &ulDataSize, 3954 &lpData); 3955 if (ret != CR_SUCCESS) 3956 { 3957 DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret); 3958 ret = CR_NO_MORE_LOG_CONF; 3959 goto done; 3960 } 3961 3962 DPRINT("Data size %lu\n", ulDataSize); 3963 if (ulDataSize == 0 || lpData == NULL) 3964 { 3965 DPRINT1("No config data available!\n"); 3966 ret = CR_NO_MORE_LOG_CONF; 3967 goto done; 3968 } 3969 3970 /* Get the first tag */ 3971 if (RegDataType == REG_RESOURCE_LIST) 3972 { 3973 DPRINT("REG_RESOURCE_LIST\n"); 3974 3975 DPRINT("ResourceList->Count %lu\n", ((PCM_RESOURCE_LIST)lpData)->Count); 3976 if (((PCM_RESOURCE_LIST)lpData)->Count == 0) 3977 { 3978 DPRINT1("No resource descriptors!\n"); 3979 ret = CR_NO_MORE_LOG_CONF; 3980 goto done; 3981 } 3982 3983 DPRINT("lpData %p\n", lpData); 3984 DPRINT("&List[0] %p\n", &(((PCM_RESOURCE_LIST)lpData)->List[0])); 3985 3986 *pulLogConfTag = (DWORD)((DWORD_PTR)&(((PCM_RESOURCE_LIST)lpData)->List[0]) - (DWORD_PTR)lpData); 3987 DPRINT("Offset (Tag): 0x%08lx\n", *pulLogConfTag); 3988 } 3989 else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) 3990 { 3991 DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n"); 3992 /* FIXME */ 3993 ret = CR_NO_MORE_LOG_CONF; 3994 goto done; 3995 } 3996 3997 done: 3998 if (lpData != NULL) 3999 HeapFree(GetProcessHeap(), 0, lpData); 4000 4001 if (hConfigKey != NULL) 4002 RegCloseKey(hConfigKey); 4003 4004 DPRINT("PNP_GetFirstLogConf() returns %lu\n", ret); 4005 4006 return ret; 4007 } 4008 4009 4010 /* Function 45 */ 4011 DWORD 4012 WINAPI 4013 PNP_GetNextLogConf( 4014 handle_t hBinding, 4015 LPWSTR pDeviceID, 4016 DWORD ulLogConfType, 4017 DWORD ulCurrentTag, 4018 DWORD *pulNextTag, 4019 DWORD ulFlags) 4020 { 4021 HKEY hConfigKey = NULL; 4022 DWORD RegDataType = 0; 4023 ULONG ulDataSize = 0; 4024 LPBYTE lpData = NULL; 4025 CONFIGRET ret = CR_SUCCESS; 4026 4027 DPRINT("PNP_GetNextLogConf(%p %S %lu %ul %p 0x%08lx)\n", 4028 hBinding, pDeviceID, ulLogConfType, ulCurrentTag, pulNextTag, ulFlags); 4029 4030 if (pulNextTag == NULL) 4031 return CR_INVALID_POINTER; 4032 4033 *pulNextTag = (DWORD)0; 4034 4035 if (ulFlags != 0) 4036 return CR_INVALID_FLAG; 4037 4038 if (!IsValidDeviceInstanceID(pDeviceID)) 4039 return CR_INVALID_DEVINST; 4040 4041 ret = OpenConfigurationKey(pDeviceID, 4042 &hConfigKey); 4043 if (ret != CR_SUCCESS) 4044 { 4045 DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret); 4046 ret = CR_NO_MORE_LOG_CONF; 4047 goto done; 4048 } 4049 4050 ret = GetConfigurationData(hConfigKey, 4051 ulLogConfType, 4052 &RegDataType, 4053 &ulDataSize, 4054 &lpData); 4055 if (ret != CR_SUCCESS) 4056 { 4057 DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret); 4058 ret = CR_NO_MORE_LOG_CONF; 4059 goto done; 4060 } 4061 4062 DPRINT("Data size %lu\n", ulDataSize); 4063 4064 if (ulDataSize == 0 || lpData == NULL) 4065 { 4066 DPRINT1("No config data available!\n"); 4067 ret = CR_NO_MORE_LOG_CONF; 4068 goto done; 4069 } 4070 4071 /* FIXME: Get the next tag */ 4072 if (RegDataType == REG_RESOURCE_LIST) 4073 { 4074 DPRINT1("FIXME: REG_RESOURCE_LIST\n"); 4075 /* FIXME */ 4076 ret = CR_NO_MORE_LOG_CONF; 4077 goto done; 4078 } 4079 else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) 4080 { 4081 DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n"); 4082 /* FIXME */ 4083 ret = CR_NO_MORE_LOG_CONF; 4084 goto done; 4085 } 4086 4087 done: 4088 if (lpData != NULL) 4089 HeapFree(GetProcessHeap(), 0, lpData); 4090 4091 if (hConfigKey != NULL) 4092 RegCloseKey(hConfigKey); 4093 4094 DPRINT("PNP_GetNextLogConf() returns %lu\n", ret); 4095 4096 return ret; 4097 } 4098 4099 4100 /* Function 46 */ 4101 DWORD 4102 WINAPI 4103 PNP_GetLogConfPriority( 4104 handle_t hBinding, 4105 LPWSTR pDeviceID, 4106 DWORD ulType, 4107 DWORD ulTag, 4108 DWORD *pPriority, 4109 DWORD ulFlags) 4110 { 4111 UNIMPLEMENTED; 4112 return CR_CALL_NOT_IMPLEMENTED; 4113 } 4114 4115 4116 /* Function 47 */ 4117 DWORD 4118 WINAPI 4119 PNP_AddResDes( 4120 handle_t hBinding, 4121 LPWSTR pDeviceID, 4122 DWORD ulLogConfTag, 4123 DWORD ulLogConfType, 4124 RESOURCEID ResourceID, 4125 DWORD *pulResourceTag, 4126 BYTE *ResourceData, 4127 PNP_RPC_BUFFER_SIZE ResourceLen, 4128 DWORD ulFlags) 4129 { 4130 UNIMPLEMENTED; 4131 return CR_CALL_NOT_IMPLEMENTED; 4132 } 4133 4134 4135 /* Function 48 */ 4136 DWORD 4137 WINAPI 4138 PNP_FreeResDes( 4139 handle_t hBinding, 4140 LPWSTR pDeviceID, 4141 DWORD ulLogConfTag, 4142 DWORD ulLogConfType, 4143 RESOURCEID ResourceID, 4144 DWORD ulResourceTag, 4145 DWORD *pulPreviousResType, 4146 DWORD *pulPreviousResTag, 4147 DWORD ulFlags) 4148 { 4149 UNIMPLEMENTED; 4150 return CR_CALL_NOT_IMPLEMENTED; 4151 } 4152 4153 4154 /* Function 49 */ 4155 DWORD 4156 WINAPI 4157 PNP_GetNextResDes( 4158 handle_t hBinding, 4159 LPWSTR pDeviceID, 4160 DWORD ulLogConfTag, 4161 DWORD ulLogConfType, 4162 RESOURCEID ResourceID, 4163 DWORD ulResourceTag, 4164 DWORD *pulNextResType, 4165 DWORD *pulNextResTag, 4166 DWORD ulFlags) 4167 { 4168 HKEY hConfigKey = NULL; 4169 DWORD RegDataType = 0; 4170 ULONG ulDataSize = 0; 4171 LPBYTE lpData = NULL; 4172 CONFIGRET ret = CR_SUCCESS; 4173 4174 DPRINT1("PNP_GetNextResDes(%p %S 0x%lx %lu %lu %ul %p %p 0x%08lx)\n", 4175 hBinding, pDeviceID, ulLogConfTag, ulLogConfType, ResourceID, 4176 ulResourceTag, pulNextResType, pulNextResTag, ulFlags); 4177 4178 if (pulNextResType == NULL) 4179 return CR_INVALID_POINTER; 4180 4181 *pulNextResType = 0; 4182 4183 if (ulFlags != 0) 4184 return CR_INVALID_FLAG; 4185 4186 if (!IsValidDeviceInstanceID(pDeviceID)) 4187 return CR_INVALID_DEVINST; 4188 4189 ret = OpenConfigurationKey(pDeviceID, 4190 &hConfigKey); 4191 if (ret != CR_SUCCESS) 4192 { 4193 DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret); 4194 ret = CR_NO_MORE_LOG_CONF; 4195 goto done; 4196 } 4197 4198 ret = GetConfigurationData(hConfigKey, 4199 ulLogConfType, 4200 &RegDataType, 4201 &ulDataSize, 4202 &lpData); 4203 if (ret != CR_SUCCESS) 4204 { 4205 DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret); 4206 ret = CR_NO_MORE_LOG_CONF; 4207 goto done; 4208 } 4209 4210 DPRINT1("Data size %lu\n", ulDataSize); 4211 4212 if (ulDataSize == 0 || lpData == NULL) 4213 { 4214 DPRINT1("No config data available!\n"); 4215 ret = CR_NO_MORE_LOG_CONF; 4216 goto done; 4217 } 4218 4219 /* Get the next resource descriptor */ 4220 if (RegDataType == REG_RESOURCE_LIST) 4221 { 4222 DPRINT1("FIXME: REG_RESOURCE_LIST\n"); 4223 /* FIXME */ 4224 ret = CR_NO_MORE_LOG_CONF; 4225 goto done; 4226 } 4227 else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) 4228 { 4229 DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n"); 4230 /* FIXME */ 4231 ret = CR_NO_MORE_LOG_CONF; 4232 goto done; 4233 } 4234 4235 done: 4236 if (lpData != NULL) 4237 HeapFree(GetProcessHeap(), 0, lpData); 4238 4239 if (hConfigKey != NULL) 4240 RegCloseKey(hConfigKey); 4241 4242 DPRINT1("PNP_GetNextResDes() returns %lu\n", ret); 4243 4244 return ret; 4245 } 4246 4247 4248 /* Function 50 */ 4249 DWORD 4250 WINAPI 4251 PNP_GetResDesData( 4252 handle_t hBinding, 4253 LPWSTR pDeviceID, 4254 DWORD ulLogConfTag, 4255 DWORD ulLogConfType, 4256 RESOURCEID ResourceID, 4257 DWORD ulResourceTag, 4258 BYTE *Buffer, 4259 PNP_RPC_BUFFER_SIZE BufferLen, 4260 DWORD ulFlags) 4261 { 4262 UNIMPLEMENTED; 4263 return CR_CALL_NOT_IMPLEMENTED; 4264 } 4265 4266 4267 /* Function 51 */ 4268 DWORD 4269 WINAPI 4270 PNP_GetResDesDataSize( 4271 handle_t hBinding, 4272 LPWSTR pDeviceID, 4273 DWORD ulLogConfTag, 4274 DWORD ulLogConfType, 4275 RESOURCEID ResourceID, 4276 DWORD ulResourceTag, 4277 DWORD *pulSize, 4278 DWORD ulFlags) 4279 { 4280 UNIMPLEMENTED; 4281 return CR_CALL_NOT_IMPLEMENTED; 4282 } 4283 4284 4285 /* Function 52 */ 4286 DWORD 4287 WINAPI 4288 PNP_ModifyResDes( 4289 handle_t hBinding, 4290 LPWSTR pDeviceID, 4291 DWORD ulLogConfTag, 4292 DWORD ulLogConfType, 4293 RESOURCEID CurrentResourceID, 4294 RESOURCEID NewResourceID, 4295 DWORD ulResourceTag, 4296 BYTE *ResourceData, 4297 PNP_RPC_BUFFER_SIZE ResourceLen, 4298 DWORD ulFlags) 4299 { 4300 UNIMPLEMENTED; 4301 return CR_CALL_NOT_IMPLEMENTED; 4302 } 4303 4304 4305 /* Function 53 */ 4306 DWORD 4307 WINAPI 4308 PNP_DetectResourceConflict( 4309 handle_t hBinding, 4310 LPWSTR pDeviceID, 4311 RESOURCEID ResourceID, 4312 BYTE *ResourceData, 4313 PNP_RPC_BUFFER_SIZE ResourceLen, 4314 BOOL *pbConflictDetected, 4315 DWORD ulFlags) 4316 { 4317 DPRINT("PNP_DetectResourceConflict()\n"); 4318 4319 if (pbConflictDetected != NULL) 4320 *pbConflictDetected = FALSE; 4321 4322 return CR_CALL_NOT_IMPLEMENTED; 4323 } 4324 4325 4326 /* Function 54 */ 4327 DWORD 4328 WINAPI 4329 PNP_QueryResConfList( 4330 handle_t hBinding, 4331 LPWSTR pDeviceID, 4332 RESOURCEID ResourceID, 4333 BYTE *ResourceData, 4334 PNP_RPC_BUFFER_SIZE ResourceLen, 4335 BYTE *Buffer, 4336 PNP_RPC_BUFFER_SIZE BufferLen, 4337 DWORD ulFlags) 4338 { 4339 UNIMPLEMENTED; 4340 return CR_CALL_NOT_IMPLEMENTED; 4341 } 4342 4343 4344 /* Function 55 */ 4345 DWORD 4346 WINAPI 4347 PNP_SetHwProf( 4348 handle_t hBinding, 4349 DWORD ulHardwareProfile, 4350 DWORD ulFlags) 4351 { 4352 return CR_CALL_NOT_IMPLEMENTED; 4353 } 4354 4355 4356 /* Function 56 */ 4357 DWORD 4358 WINAPI 4359 PNP_QueryArbitratorFreeData( 4360 handle_t hBinding, 4361 BYTE *pData, 4362 DWORD DataLen, 4363 LPWSTR pDeviceID, 4364 RESOURCEID ResourceID, 4365 DWORD ulFlags) 4366 { 4367 return CR_CALL_NOT_IMPLEMENTED; 4368 } 4369 4370 4371 /* Function 57 */ 4372 DWORD 4373 WINAPI 4374 PNP_QueryArbitratorFreeSize( 4375 handle_t hBinding, 4376 DWORD *pulSize, 4377 LPWSTR pDeviceID, 4378 RESOURCEID ResourceID, 4379 DWORD ulFlags) 4380 { 4381 if (pulSize != NULL) 4382 *pulSize = 0; 4383 4384 return CR_CALL_NOT_IMPLEMENTED; 4385 } 4386 4387 4388 /* Function 58 */ 4389 CONFIGRET 4390 WINAPI 4391 PNP_RunDetection( 4392 handle_t hBinding, 4393 DWORD ulFlags) 4394 { 4395 return CR_CALL_NOT_IMPLEMENTED; 4396 } 4397 4398 4399 /* Function 59 */ 4400 DWORD 4401 WINAPI 4402 PNP_RegisterNotification( 4403 handle_t hBinding, 4404 DWORD ulUnknown2, 4405 LPWSTR pszName, 4406 BYTE *pNotificationFilter, 4407 DWORD ulNotificationFilterSize, 4408 DWORD ulFlags, 4409 DWORD *pulNotify, 4410 DWORD ulUnknown8, 4411 DWORD *pulUnknown9) 4412 { 4413 PDEV_BROADCAST_DEVICEINTERFACE_W pBroadcastDeviceInterface; 4414 PDEV_BROADCAST_HANDLE pBroadcastDeviceHandle; 4415 #if 0 4416 PNOTIFY_DATA pNotifyData; 4417 #endif 4418 4419 DPRINT1("PNP_RegisterNotification(%p %lx '%S' %p %lu 0x%lx %p %lx %p)\n", 4420 hBinding, ulUnknown2, pszName, pNotificationFilter, 4421 ulNotificationFilterSize, ulFlags, pulNotify, ulUnknown8, pulUnknown9); 4422 4423 if (pNotificationFilter == NULL || 4424 pulNotify == NULL || 4425 pulUnknown9 == NULL) 4426 return CR_INVALID_POINTER; 4427 4428 if (ulFlags & ~0x7) 4429 return CR_INVALID_FLAG; 4430 4431 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_HDR)) || 4432 (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_size < sizeof(DEV_BROADCAST_HDR))) 4433 return CR_INVALID_DATA; 4434 4435 if (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) 4436 { 4437 DPRINT1("DBT_DEVTYP_DEVICEINTERFACE\n"); 4438 pBroadcastDeviceInterface = (PDEV_BROADCAST_DEVICEINTERFACE_W)pNotificationFilter; 4439 4440 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_DEVICEINTERFACE_W)) || 4441 (pBroadcastDeviceInterface->dbcc_size < sizeof(DEV_BROADCAST_DEVICEINTERFACE_W))) 4442 return CR_INVALID_DATA; 4443 } 4444 else if (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype == DBT_DEVTYP_HANDLE) 4445 { 4446 DPRINT1("DBT_DEVTYP_HANDLE\n"); 4447 pBroadcastDeviceHandle = (PDEV_BROADCAST_HANDLE)pNotificationFilter; 4448 4449 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_HANDLE)) || 4450 (pBroadcastDeviceHandle->dbch_size < sizeof(DEV_BROADCAST_HANDLE))) 4451 return CR_INVALID_DATA; 4452 4453 if (ulFlags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES) 4454 return CR_INVALID_FLAG; 4455 } 4456 else 4457 { 4458 DPRINT1("Invalid device type %lu\n", ((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype); 4459 return CR_INVALID_DATA; 4460 } 4461 4462 4463 #if 0 4464 pNotifyData = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NOTIFY_DATA)); 4465 if (pNotifyData == NULL) 4466 return CR_OUT_OF_MEMORY; 4467 4468 *pulNotify = (DWORD)pNotifyData; 4469 #endif 4470 4471 *pulNotify = 1; 4472 4473 return CR_SUCCESS; 4474 } 4475 4476 4477 /* Function 60 */ 4478 DWORD 4479 WINAPI 4480 PNP_UnregisterNotification( 4481 handle_t hBinding, 4482 DWORD ulNotify) 4483 { 4484 DPRINT1("PNP_UnregisterNotification(%p 0x%lx)\n", 4485 hBinding, ulNotify); 4486 4487 #if 0 4488 UNIMPLEMENTED; 4489 return CR_CALL_NOT_IMPLEMENTED; 4490 #endif 4491 4492 return CR_SUCCESS; 4493 } 4494 4495 4496 /* Function 61 */ 4497 DWORD 4498 WINAPI 4499 PNP_GetCustomDevProp( 4500 handle_t hBinding, 4501 LPWSTR pDeviceID, 4502 LPWSTR CustomPropName, 4503 DWORD *pulRegDataType, 4504 BYTE *Buffer, 4505 PNP_RPC_STRING_LEN *pulTransferLen, 4506 PNP_RPC_STRING_LEN *pulLength, 4507 DWORD ulFlags) 4508 { 4509 HKEY hDeviceKey = NULL; 4510 HKEY hParamKey = NULL; 4511 LONG lError; 4512 CONFIGRET ret = CR_SUCCESS; 4513 4514 UNREFERENCED_PARAMETER(hBinding); 4515 4516 DPRINT("PNP_GetCustomDevProp() called\n"); 4517 4518 if (pulTransferLen == NULL || pulLength == NULL) 4519 { 4520 ret = CR_INVALID_POINTER; 4521 goto done; 4522 } 4523 4524 if (ulFlags & ~CM_CUSTOMDEVPROP_BITS) 4525 { 4526 ret = CR_INVALID_FLAG; 4527 goto done; 4528 } 4529 4530 if (!IsValidDeviceInstanceID(pDeviceID)) 4531 return CR_INVALID_DEVINST; 4532 4533 if (*pulLength < *pulTransferLen) 4534 *pulLength = *pulTransferLen; 4535 4536 *pulTransferLen = 0; 4537 4538 lError = RegOpenKeyExW(hEnumKey, 4539 pDeviceID, 4540 0, 4541 KEY_READ, 4542 &hDeviceKey); 4543 if (lError != ERROR_SUCCESS) 4544 { 4545 ret = CR_REGISTRY_ERROR; 4546 goto done; 4547 } 4548 4549 lError = RegOpenKeyExW(hDeviceKey, 4550 L"Device Parameters", 4551 0, 4552 KEY_READ, 4553 &hParamKey); 4554 if (lError != ERROR_SUCCESS) 4555 { 4556 ret = CR_REGISTRY_ERROR; 4557 goto done; 4558 } 4559 4560 lError = RegQueryValueExW(hParamKey, 4561 CustomPropName, 4562 NULL, 4563 pulRegDataType, 4564 Buffer, 4565 pulLength); 4566 if (lError != ERROR_SUCCESS) 4567 { 4568 if (lError == ERROR_MORE_DATA) 4569 { 4570 ret = CR_BUFFER_SMALL; 4571 } 4572 else 4573 { 4574 *pulLength = 0; 4575 ret = CR_NO_SUCH_VALUE; 4576 } 4577 } 4578 4579 done: 4580 if (ret == CR_SUCCESS) 4581 *pulTransferLen = *pulLength; 4582 4583 if (hParamKey != NULL) 4584 RegCloseKey(hParamKey); 4585 4586 if (hDeviceKey != NULL) 4587 RegCloseKey(hDeviceKey); 4588 4589 DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret); 4590 4591 return ret; 4592 } 4593 4594 4595 /* Function 62 */ 4596 DWORD 4597 WINAPI 4598 PNP_GetVersionInternal( 4599 handle_t hBinding, 4600 WORD *pwVersion) 4601 { 4602 UNREFERENCED_PARAMETER(hBinding); 4603 4604 *pwVersion = 0x501; 4605 return CR_SUCCESS; 4606 } 4607 4608 4609 /* Function 63 */ 4610 DWORD 4611 WINAPI 4612 PNP_GetBlockedDriverInfo( 4613 handle_t hBinding, 4614 BYTE *Buffer, 4615 PNP_RPC_BUFFER_SIZE *pulTransferLen, 4616 PNP_RPC_BUFFER_SIZE *pulLength, 4617 DWORD ulFlags) 4618 { 4619 UNIMPLEMENTED; 4620 return CR_CALL_NOT_IMPLEMENTED; 4621 } 4622 4623 4624 /* Function 64 */ 4625 DWORD 4626 WINAPI 4627 PNP_GetServerSideDeviceInstallFlags( 4628 handle_t hBinding, 4629 DWORD *pulSSDIFlags, 4630 DWORD ulFlags) 4631 { 4632 UNREFERENCED_PARAMETER(hBinding); 4633 4634 DPRINT1("PNP_GetServerSideDeviceInstallFlags(%p %p %lu)\n", 4635 hBinding, pulSSDIFlags, ulFlags); 4636 4637 if (pulSSDIFlags == NULL) 4638 return CR_INVALID_POINTER; 4639 4640 if (ulFlags != 0) 4641 return CR_INVALID_FLAG; 4642 4643 /* FIXME */ 4644 *pulSSDIFlags = 0; 4645 4646 return CR_SUCCESS; 4647 } 4648 4649 4650 /* Function 65 */ 4651 DWORD 4652 WINAPI 4653 PNP_GetObjectPropKeys( 4654 handle_t hBinding, 4655 LPWSTR ObjectName, 4656 DWORD ObjectType, 4657 LPWSTR PropertyCultureName, 4658 PNP_PROP_COUNT *PropertyCount, 4659 PNP_PROP_COUNT *TransferLen, 4660 DEVPROPKEY *PropertyKeys, 4661 DWORD Flags) 4662 { 4663 UNIMPLEMENTED; 4664 return CR_CALL_NOT_IMPLEMENTED; 4665 } 4666 4667 4668 /* Function 66 */ 4669 DWORD 4670 WINAPI 4671 PNP_GetObjectProp( 4672 handle_t hBinding, 4673 LPWSTR ObjectName, 4674 DWORD ObjectType, 4675 LPWSTR PropertyCultureName, 4676 const DEVPROPKEY *PropertyKey, 4677 DEVPROPTYPE *PropertyType, 4678 PNP_PROP_SIZE *PropertySize, 4679 PNP_PROP_SIZE *TransferLen, 4680 BYTE *PropertyBuffer, 4681 DWORD Flags) 4682 { 4683 UNIMPLEMENTED; 4684 return CR_CALL_NOT_IMPLEMENTED; 4685 } 4686 4687 4688 /* Function 67 */ 4689 DWORD 4690 WINAPI 4691 PNP_SetObjectProp( 4692 handle_t hBinding, 4693 LPWSTR ObjectName, 4694 DWORD ObjectType, 4695 LPWSTR PropertyCultureName, 4696 const DEVPROPKEY *PropertyKey, 4697 DEVPROPTYPE PropertyType, 4698 PNP_PROP_SIZE PropertySize, 4699 BYTE *PropertyBuffer, 4700 DWORD Flags) 4701 { 4702 UNIMPLEMENTED; 4703 return CR_CALL_NOT_IMPLEMENTED; 4704 } 4705 4706 4707 /* Function 68 */ 4708 DWORD 4709 WINAPI 4710 PNP_InstallDevInst( 4711 handle_t hBinding) 4712 { 4713 UNIMPLEMENTED; 4714 return CR_CALL_NOT_IMPLEMENTED; 4715 } 4716 4717 4718 /* Function 69 */ 4719 DWORD 4720 WINAPI 4721 PNP_ApplyPowerSettings( 4722 handle_t hBinding) 4723 { 4724 UNIMPLEMENTED; 4725 return CR_CALL_NOT_IMPLEMENTED; 4726 } 4727 4728 4729 /* Function 70 */ 4730 DWORD 4731 WINAPI 4732 PNP_DriverStoreAddDriverPackage( 4733 handle_t hBinding) 4734 { 4735 UNIMPLEMENTED; 4736 return CR_CALL_NOT_IMPLEMENTED; 4737 } 4738 4739 4740 /* Function 71 */ 4741 DWORD 4742 WINAPI 4743 PNP_DriverStoreDeleteDriverPackage( 4744 handle_t hBinding) 4745 { 4746 UNIMPLEMENTED; 4747 return CR_CALL_NOT_IMPLEMENTED; 4748 } 4749 4750 4751 /* Function 72 */ 4752 DWORD 4753 WINAPI 4754 PNP_RegisterServiceNotification( 4755 handle_t hBinding) 4756 { 4757 UNIMPLEMENTED; 4758 return CR_CALL_NOT_IMPLEMENTED; 4759 } 4760 4761 4762 /* Function 73 */ 4763 DWORD 4764 WINAPI 4765 PNP_SetActiveService( 4766 handle_t hBinding, 4767 LPWSTR pszFilter, 4768 DWORD ulFlags) 4769 { 4770 UNIMPLEMENTED; 4771 return CR_CALL_NOT_IMPLEMENTED; 4772 } 4773 4774 4775 /* Function 74 */ 4776 DWORD 4777 WINAPI 4778 PNP_DeleteServiceDevices( 4779 handle_t hBinding) 4780 { 4781 UNIMPLEMENTED; 4782 return CR_CALL_NOT_IMPLEMENTED; 4783 } 4784