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