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