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