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