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