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