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