Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenumpnpmgr.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS kernel 00003 * Copyright (C) 2005 ReactOS Team 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along 00016 * with this program; if not, write to the Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00018 */ 00019 /* 00020 * COPYRIGHT: See COPYING in the top level directory 00021 * PROJECT: ReactOS kernel 00022 * FILE: services/umpnpmgr/umpnpmgr.c 00023 * PURPOSE: User-mode Plug and Play manager 00024 * PROGRAMMER: Eric Kohl 00025 * Hervé Poussineau (hpoussin@reactos.org) 00026 * Colin Finck (colin@reactos.org) 00027 */ 00028 00029 /* INCLUDES *****************************************************************/ 00030 //#define HAVE_SLIST_ENTRY_IMPLEMENTED 00031 #define WIN32_NO_STATUS 00032 #include <windows.h> 00033 #include <stdio.h> 00034 #include <cmtypes.h> 00035 #include <cmfuncs.h> 00036 #include <rtlfuncs.h> 00037 #include <setypes.h> 00038 #include <umpnpmgr/sysguid.h> 00039 #include <wdmguid.h> 00040 #include <cfgmgr32.h> 00041 #include <regstr.h> 00042 #include <userenv.h> 00043 00044 #include <rpc.h> 00045 #include <rpcdce.h> 00046 00047 #include "pnp_s.h" 00048 00049 #define NDEBUG 00050 #include <debug.h> 00051 00052 /* GLOBALS ******************************************************************/ 00053 00054 static VOID CALLBACK ServiceMain(DWORD argc, LPWSTR *argv); 00055 static WCHAR ServiceName[] = L"PlugPlay"; 00056 static SERVICE_TABLE_ENTRYW ServiceTable[] = 00057 { 00058 {ServiceName, ServiceMain}, 00059 {NULL, NULL} 00060 }; 00061 00062 static SERVICE_STATUS_HANDLE ServiceStatusHandle; 00063 static SERVICE_STATUS ServiceStatus; 00064 00065 static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0"; 00066 00067 static HKEY hEnumKey = NULL; 00068 static HKEY hClassKey = NULL; 00069 00070 static HANDLE hUserToken = NULL; 00071 static HANDLE hInstallEvent = NULL; 00072 static HANDLE hNoPendingInstalls = NULL; 00073 00074 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED 00075 static SLIST_HEADER DeviceInstallListHead; 00076 #else 00077 static LIST_ENTRY DeviceInstallListHead; 00078 #endif 00079 static HANDLE hDeviceInstallListNotEmpty; 00080 00081 typedef struct 00082 { 00083 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED 00084 SLIST_ENTRY ListEntry; 00085 #else 00086 LIST_ENTRY ListEntry; 00087 #endif 00088 WCHAR DeviceIds[1]; 00089 } DeviceInstallParams; 00090 00091 /* FUNCTIONS *****************************************************************/ 00092 00093 static DWORD WINAPI 00094 RpcServerThread(LPVOID lpParameter) 00095 { 00096 RPC_STATUS Status; 00097 BOOLEAN RegisteredProtSeq = FALSE; 00098 00099 UNREFERENCED_PARAMETER(lpParameter); 00100 00101 DPRINT("RpcServerThread() called\n"); 00102 00103 #if 0 00104 /* XP-compatible protocol sequence/endpoint */ 00105 Status = RpcServerUseProtseqEpW(L"ncacn_np", 00106 20, 00107 L"\\pipe\\ntsvcs", 00108 NULL); // Security descriptor 00109 if (Status == RPC_S_OK) 00110 RegisteredProtSeq = TRUE; 00111 else 00112 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); 00113 #endif 00114 00115 /* Vista-compatible protocol sequence/endpoint */ 00116 Status = RpcServerUseProtseqEpW(L"ncacn_np", 00117 20, 00118 L"\\pipe\\plugplay", 00119 NULL); // Security descriptor 00120 if (Status == RPC_S_OK) 00121 RegisteredProtSeq = TRUE; 00122 else 00123 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); 00124 00125 /* Make sure there's a usable endpoint */ 00126 if (RegisteredProtSeq == FALSE) 00127 return 0; 00128 00129 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec, 00130 NULL, 00131 NULL); 00132 if (Status != RPC_S_OK) 00133 { 00134 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status); 00135 return 0; 00136 } 00137 00138 Status = RpcServerListen(1, 00139 20, 00140 FALSE); 00141 if (Status != RPC_S_OK) 00142 { 00143 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status); 00144 return 0; 00145 } 00146 00147 /* ROS HACK (this should never happen...) */ 00148 DPRINT1("*** Other devices won't be installed correctly. If something\n"); 00149 DPRINT1("*** doesn't work, try to reboot to get a new chance.\n"); 00150 00151 DPRINT("RpcServerThread() done\n"); 00152 00153 return 0; 00154 } 00155 00156 00157 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len) 00158 { 00159 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); 00160 } 00161 00162 00163 void __RPC_USER midl_user_free(void __RPC_FAR * ptr) 00164 { 00165 HeapFree(GetProcessHeap(), 0, ptr); 00166 } 00167 00168 00169 static CONFIGRET WINAPI 00170 NtStatusToCrError(NTSTATUS Status) 00171 { 00172 switch (Status) 00173 { 00174 case STATUS_NO_SUCH_DEVICE: 00175 return CR_NO_SUCH_DEVINST; 00176 00177 default: 00178 /* FIXME: add more mappings */ 00179 DPRINT1("Unable to map status 0x%08lx\n", Status); 00180 return CR_FAILURE; 00181 } 00182 } 00183 00184 00185 /* Function 0 */ 00186 DWORD PNP_Disconnect( 00187 handle_t hBinding) 00188 { 00189 UNREFERENCED_PARAMETER(hBinding); 00190 return CR_SUCCESS; 00191 } 00192 00193 00194 /* Function 1 */ 00195 DWORD PNP_Connect( 00196 handle_t hBinding) 00197 { 00198 UNREFERENCED_PARAMETER(hBinding); 00199 return CR_SUCCESS; 00200 } 00201 00202 00203 /* Function 2 */ 00204 DWORD PNP_GetVersion( 00205 handle_t hBinding, 00206 WORD *pVersion) 00207 { 00208 UNREFERENCED_PARAMETER(hBinding); 00209 00210 *pVersion = 0x0400; 00211 return CR_SUCCESS; 00212 } 00213 00214 00215 /* Function 3 */ 00216 DWORD PNP_GetGlobalState( 00217 handle_t hBinding, 00218 DWORD *pulState, 00219 DWORD ulFlags) 00220 { 00221 UNREFERENCED_PARAMETER(hBinding); 00222 UNREFERENCED_PARAMETER(ulFlags); 00223 00224 *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE; 00225 return CR_SUCCESS; 00226 } 00227 00228 00229 /* Function 4 */ 00230 DWORD PNP_InitDetection( 00231 handle_t hBinding) 00232 { 00233 UNREFERENCED_PARAMETER(hBinding); 00234 00235 DPRINT("PNP_InitDetection() called\n"); 00236 return CR_SUCCESS; 00237 } 00238 00239 00240 /* Function 5 */ 00241 DWORD PNP_ReportLogOn( 00242 handle_t hBinding, 00243 BOOL Admin, 00244 DWORD ProcessId) 00245 { 00246 DWORD ReturnValue = CR_FAILURE; 00247 HANDLE hProcess; 00248 00249 UNREFERENCED_PARAMETER(hBinding); 00250 UNREFERENCED_PARAMETER(Admin); 00251 00252 DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin, ProcessId); 00253 00254 /* Get the users token */ 00255 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId); 00256 00257 if(!hProcess) 00258 { 00259 DPRINT1("OpenProcess failed with error %u\n", GetLastError()); 00260 goto cleanup; 00261 } 00262 00263 if (hUserToken) 00264 { 00265 CloseHandle(hUserToken); 00266 hUserToken = NULL; 00267 } 00268 00269 if(!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken)) 00270 { 00271 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError()); 00272 goto cleanup; 00273 } 00274 00275 /* Trigger the installer thread */ 00276 if (hInstallEvent) 00277 SetEvent(hInstallEvent); 00278 00279 ReturnValue = CR_SUCCESS; 00280 00281 cleanup: 00282 if(hProcess) 00283 CloseHandle(hProcess); 00284 00285 return ReturnValue; 00286 } 00287 00288 00289 /* Function 6 */ 00290 DWORD PNP_ValidateDeviceInstance( 00291 handle_t hBinding, 00292 LPWSTR pDeviceID, 00293 DWORD ulFlags) 00294 { 00295 CONFIGRET ret = CR_SUCCESS; 00296 HKEY hDeviceKey = NULL; 00297 00298 UNREFERENCED_PARAMETER(hBinding); 00299 UNREFERENCED_PARAMETER(ulFlags); 00300 00301 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n", 00302 pDeviceID, ulFlags); 00303 00304 if (RegOpenKeyExW(hEnumKey, 00305 pDeviceID, 00306 0, 00307 KEY_READ, 00308 &hDeviceKey)) 00309 { 00310 DPRINT("Could not open the Device Key!\n"); 00311 ret = CR_NO_SUCH_DEVNODE; 00312 goto Done; 00313 } 00314 00315 /* FIXME: add more tests */ 00316 00317 Done: 00318 if (hDeviceKey != NULL) 00319 RegCloseKey(hDeviceKey); 00320 00321 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret); 00322 00323 return ret; 00324 } 00325 00326 00327 /* Function 7 */ 00328 DWORD PNP_GetRootDeviceInstance( 00329 handle_t hBinding, 00330 LPWSTR pDeviceID, 00331 PNP_RPC_STRING_LEN ulLength) 00332 { 00333 CONFIGRET ret = CR_SUCCESS; 00334 00335 UNREFERENCED_PARAMETER(hBinding); 00336 00337 DPRINT("PNP_GetRootDeviceInstance() called\n"); 00338 00339 if (!pDeviceID) 00340 { 00341 ret = CR_INVALID_POINTER; 00342 goto Done; 00343 } 00344 if (ulLength < lstrlenW(szRootDeviceId) + 1) 00345 { 00346 ret = CR_BUFFER_SMALL; 00347 goto Done; 00348 } 00349 00350 lstrcpyW(pDeviceID, 00351 szRootDeviceId); 00352 00353 Done: 00354 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret); 00355 00356 return ret; 00357 } 00358 00359 00360 /* Function 8 */ 00361 DWORD PNP_GetRelatedDeviceInstance( 00362 handle_t hBinding, 00363 DWORD ulRelationship, 00364 LPWSTR pDeviceID, 00365 LPWSTR pRelatedDeviceId, 00366 PNP_RPC_STRING_LEN *pulLength, 00367 DWORD ulFlags) 00368 { 00369 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData; 00370 CONFIGRET ret = CR_SUCCESS; 00371 NTSTATUS Status; 00372 00373 UNREFERENCED_PARAMETER(hBinding); 00374 UNREFERENCED_PARAMETER(ulFlags); 00375 00376 DPRINT("PNP_GetRelatedDeviceInstance() called\n"); 00377 DPRINT(" Relationship %ld\n", ulRelationship); 00378 DPRINT(" DeviceId %S\n", pDeviceID); 00379 00380 RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance, 00381 pDeviceID); 00382 00383 PlugPlayData.Relation = ulRelationship; 00384 00385 PlugPlayData.RelatedDeviceInstanceLength = *pulLength; 00386 PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId; 00387 00388 Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice, 00389 (PVOID)&PlugPlayData, 00390 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA)); 00391 if (!NT_SUCCESS(Status)) 00392 { 00393 ret = NtStatusToCrError(Status); 00394 } 00395 00396 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret); 00397 if (ret == CR_SUCCESS) 00398 { 00399 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance); 00400 } 00401 00402 return ret; 00403 } 00404 00405 00406 /* Function 9 */ 00407 DWORD PNP_EnumerateSubKeys( 00408 handle_t hBinding, 00409 DWORD ulBranch, 00410 DWORD ulIndex, 00411 LPWSTR Buffer, 00412 PNP_RPC_STRING_LEN ulLength, 00413 PNP_RPC_STRING_LEN *pulRequiredLen, 00414 DWORD ulFlags) 00415 { 00416 CONFIGRET ret = CR_SUCCESS; 00417 HKEY hKey; 00418 DWORD dwError; 00419 00420 UNREFERENCED_PARAMETER(hBinding); 00421 UNREFERENCED_PARAMETER(ulFlags); 00422 00423 DPRINT("PNP_EnumerateSubKeys() called\n"); 00424 00425 switch (ulBranch) 00426 { 00427 case PNP_ENUMERATOR_SUBKEYS: 00428 hKey = hEnumKey; 00429 break; 00430 00431 case PNP_CLASS_SUBKEYS: 00432 hKey = hClassKey; 00433 break; 00434 00435 default: 00436 return CR_FAILURE; 00437 } 00438 00439 *pulRequiredLen = ulLength; 00440 dwError = RegEnumKeyExW(hKey, 00441 ulIndex, 00442 Buffer, 00443 pulRequiredLen, 00444 NULL, 00445 NULL, 00446 NULL, 00447 NULL); 00448 if (dwError != ERROR_SUCCESS) 00449 { 00450 ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE; 00451 } 00452 else 00453 { 00454 (*pulRequiredLen)++; 00455 } 00456 00457 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret); 00458 00459 return ret; 00460 } 00461 00462 00463 /* Function 10 */ 00464 DWORD PNP_GetDeviceList( 00465 handle_t hBinding, 00466 LPWSTR pszFilter, 00467 LPWSTR Buffer, 00468 PNP_RPC_STRING_LEN *pulLength, 00469 DWORD ulFlags) 00470 { 00471 UNIMPLEMENTED; 00472 return CR_CALL_NOT_IMPLEMENTED; 00473 } 00474 00475 00476 /* Function 11 */ 00477 DWORD PNP_GetDeviceListSize( 00478 handle_t hBinding, 00479 LPWSTR pszFilter, 00480 PNP_RPC_BUFFER_SIZE *pulLen, 00481 DWORD ulFlags) 00482 { 00483 UNIMPLEMENTED; 00484 return CR_CALL_NOT_IMPLEMENTED; 00485 } 00486 00487 00488 /* Function 12 */ 00489 DWORD PNP_GetDepth( 00490 handle_t hBinding, 00491 LPWSTR pszDeviceID, 00492 DWORD *pulDepth, 00493 DWORD ulFlags) 00494 { 00495 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData; 00496 CONFIGRET ret = CR_SUCCESS; 00497 NTSTATUS Status; 00498 00499 UNREFERENCED_PARAMETER(hBinding); 00500 UNREFERENCED_PARAMETER(ulFlags); 00501 00502 DPRINT("PNP_GetDepth() called\n"); 00503 00504 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 00505 pszDeviceID); 00506 00507 Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth, 00508 (PVOID)&PlugPlayData, 00509 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA)); 00510 if (NT_SUCCESS(Status)) 00511 { 00512 *pulDepth = PlugPlayData.Depth; 00513 } 00514 else 00515 { 00516 ret = NtStatusToCrError(Status); 00517 } 00518 00519 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret); 00520 00521 return ret; 00522 } 00523 00524 00525 /* Function 13 */ 00526 DWORD PNP_GetDeviceRegProp( 00527 handle_t hBinding, 00528 LPWSTR pDeviceID, 00529 DWORD ulProperty, 00530 DWORD *pulRegDataType, 00531 BYTE *Buffer, 00532 PNP_PROP_SIZE *pulTransferLen, 00533 PNP_PROP_SIZE *pulLength, 00534 DWORD ulFlags) 00535 { 00536 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData; 00537 CONFIGRET ret = CR_SUCCESS; 00538 LPWSTR lpValueName = NULL; 00539 HKEY hKey = NULL; 00540 LONG lError; 00541 NTSTATUS Status; 00542 00543 UNREFERENCED_PARAMETER(hBinding); 00544 00545 DPRINT("PNP_GetDeviceRegProp() called\n"); 00546 00547 if (pulTransferLen == NULL || pulLength == NULL) 00548 { 00549 ret = CR_INVALID_POINTER; 00550 goto done; 00551 } 00552 00553 if (ulFlags != 0) 00554 { 00555 ret = CR_INVALID_FLAG; 00556 goto done; 00557 } 00558 00559 /* FIXME: Check pDeviceID */ 00560 00561 if (*pulLength < *pulTransferLen) 00562 *pulLength = *pulTransferLen; 00563 00564 *pulTransferLen = 0; 00565 00566 switch (ulProperty) 00567 { 00568 case CM_DRP_DEVICEDESC: 00569 lpValueName = L"DeviceDesc"; 00570 break; 00571 00572 case CM_DRP_HARDWAREID: 00573 lpValueName = L"HardwareID"; 00574 break; 00575 00576 case CM_DRP_COMPATIBLEIDS: 00577 lpValueName = L"CompatibleIDs"; 00578 break; 00579 00580 case CM_DRP_SERVICE: 00581 lpValueName = L"Service"; 00582 break; 00583 00584 case CM_DRP_CLASS: 00585 lpValueName = L"Class"; 00586 break; 00587 00588 case CM_DRP_CLASSGUID: 00589 lpValueName = L"ClassGUID"; 00590 break; 00591 00592 case CM_DRP_DRIVER: 00593 lpValueName = L"Driver"; 00594 break; 00595 00596 case CM_DRP_CONFIGFLAGS: 00597 lpValueName = L"ConfigFlags"; 00598 break; 00599 00600 case CM_DRP_MFG: 00601 lpValueName = L"Mfg"; 00602 break; 00603 00604 case CM_DRP_FRIENDLYNAME: 00605 lpValueName = L"FriendlyName"; 00606 break; 00607 00608 case CM_DRP_LOCATION_INFORMATION: 00609 lpValueName = L"LocationInformation"; 00610 break; 00611 00612 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME: 00613 lpValueName = NULL; 00614 break; 00615 00616 case CM_DRP_CAPABILITIES: 00617 lpValueName = L"Capabilities"; 00618 break; 00619 00620 case CM_DRP_UI_NUMBER: 00621 lpValueName = NULL; 00622 break; 00623 00624 case CM_DRP_UPPERFILTERS: 00625 lpValueName = L"UpperFilters"; 00626 break; 00627 00628 case CM_DRP_LOWERFILTERS: 00629 lpValueName = L"LowerFilters"; 00630 break; 00631 00632 case CM_DRP_BUSTYPEGUID: 00633 lpValueName = NULL; 00634 break; 00635 00636 case CM_DRP_LEGACYBUSTYPE: 00637 lpValueName = NULL; 00638 break; 00639 00640 case CM_DRP_BUSNUMBER: 00641 lpValueName = NULL; 00642 break; 00643 00644 case CM_DRP_ENUMERATOR_NAME: 00645 lpValueName = NULL; 00646 break; 00647 00648 case CM_DRP_SECURITY: 00649 lpValueName = L"Security"; 00650 break; 00651 00652 case CM_DRP_DEVTYPE: 00653 lpValueName = L"DeviceType"; 00654 break; 00655 00656 case CM_DRP_EXCLUSIVE: 00657 lpValueName = L"Exclusive"; 00658 break; 00659 00660 case CM_DRP_CHARACTERISTICS: 00661 lpValueName = L"DeviceCharacteristics"; 00662 break; 00663 00664 case CM_DRP_ADDRESS: 00665 lpValueName = NULL; 00666 break; 00667 00668 case CM_DRP_UI_NUMBER_DESC_FORMAT: 00669 lpValueName = L"UINumberDescFormat"; 00670 break; 00671 00672 case CM_DRP_DEVICE_POWER_DATA: 00673 lpValueName = NULL; 00674 break; 00675 00676 case CM_DRP_REMOVAL_POLICY: 00677 lpValueName = NULL; 00678 break; 00679 00680 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT: 00681 lpValueName = NULL; 00682 break; 00683 00684 case CM_DRP_REMOVAL_POLICY_OVERRIDE: 00685 lpValueName = L"RemovalPolicy"; 00686 break; 00687 00688 case CM_DRP_INSTALL_STATE: 00689 lpValueName = NULL; 00690 break; 00691 00692 #if (WINVER >= _WIN32_WINNT_WS03) 00693 case CM_DRP_LOCATION_PATHS: 00694 lpValueName = NULL; 00695 break; 00696 #endif 00697 00698 #if (WINVER >= _WIN32_WINNT_WIN7) 00699 case CM_DRP_BASE_CONTAINERID: 00700 lpValueName = NULL; 00701 break; 00702 #endif 00703 00704 default: 00705 ret = CR_INVALID_PROPERTY; 00706 goto done; 00707 } 00708 00709 DPRINT("Value name: %S\n", lpValueName); 00710 00711 if (lpValueName) 00712 { 00713 /* Retrieve information from the Registry */ 00714 lError = RegOpenKeyExW(hEnumKey, 00715 pDeviceID, 00716 0, 00717 KEY_QUERY_VALUE, 00718 &hKey); 00719 if (lError != ERROR_SUCCESS) 00720 { 00721 hKey = NULL; 00722 *pulLength = 0; 00723 ret = CR_INVALID_DEVNODE; 00724 goto done; 00725 } 00726 00727 lError = RegQueryValueExW(hKey, 00728 lpValueName, 00729 NULL, 00730 pulRegDataType, 00731 Buffer, 00732 pulLength); 00733 if (lError != ERROR_SUCCESS) 00734 { 00735 if (lError == ERROR_MORE_DATA) 00736 { 00737 ret = CR_BUFFER_SMALL; 00738 } 00739 else 00740 { 00741 *pulLength = 0; 00742 ret = CR_NO_SUCH_VALUE; 00743 } 00744 } 00745 } 00746 else 00747 { 00748 /* Retrieve information from the Device Node */ 00749 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 00750 pDeviceID); 00751 PlugPlayData.Buffer = Buffer; 00752 PlugPlayData.BufferSize = *pulLength; 00753 00754 switch (ulProperty) 00755 { 00756 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME: 00757 PlugPlayData.Property = 0xb; // DevicePropertyPhysicalDeviceObjectName; 00758 break; 00759 00760 case CM_DRP_UI_NUMBER: 00761 PlugPlayData.Property = 0x11; // DevicePropertyUINumber; 00762 break; 00763 00764 case CM_DRP_BUSTYPEGUID: 00765 PlugPlayData.Property = 0xc; // DevicePropertyBusTypeGuid; 00766 break; 00767 00768 case CM_DRP_LEGACYBUSTYPE: 00769 PlugPlayData.Property = 0xd; // DevicePropertyLegacyBusType; 00770 break; 00771 00772 case CM_DRP_BUSNUMBER: 00773 PlugPlayData.Property = 0xe; // DevicePropertyBusNumber; 00774 break; 00775 00776 case CM_DRP_ENUMERATOR_NAME: 00777 PlugPlayData.Property = 0xf; // DevicePropertyEnumeratorName; 00778 break; 00779 00780 case CM_DRP_ADDRESS: 00781 PlugPlayData.Property = 0x10; // DevicePropertyAddress; 00782 break; 00783 00784 #if 0 00785 /* FIXME: This property is not supported by IoGetDeviceProperty */ 00786 case CM_DRP_DEVICE_POWER_DATA: 00787 #endif 00788 00789 case CM_DRP_REMOVAL_POLICY: 00790 PlugPlayData.Property = 0x12; // DevicePropertyRemovalPolicy 00791 break; 00792 00793 #if 0 00794 /* FIXME: This property is not supported by IoGetDeviceProperty */ 00795 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT: 00796 #endif 00797 00798 case CM_DRP_INSTALL_STATE: 00799 PlugPlayData.Property = 0x12; // DevicePropertyInstallState; 00800 break; 00801 00802 #if 0 00803 /* FIXME: This property is not supported by IoGetDeviceProperty */ 00804 #if (WINVER >= _WIN32_WINNT_WS03) 00805 case CM_DRP_LOCATION_PATHS: 00806 #endif 00807 #endif 00808 00809 #if (WINVER >= _WIN32_WINNT_WIN7) 00810 case CM_DRP_BASE_CONTAINERID: 00811 PlugPlayData.Property = 0x16; // DevicePropertyContainerID; 00812 break; 00813 #endif 00814 00815 default: 00816 return CR_INVALID_PROPERTY; 00817 } 00818 00819 Status = NtPlugPlayControl(PlugPlayControlProperty, 00820 (PVOID)&PlugPlayData, 00821 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA)); 00822 if (NT_SUCCESS(Status)) 00823 { 00824 *pulLength = PlugPlayData.BufferSize; 00825 } 00826 else 00827 { 00828 ret = NtStatusToCrError(Status); 00829 } 00830 } 00831 00832 done: 00833 *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0; 00834 00835 if (hKey != NULL) 00836 RegCloseKey(hKey); 00837 00838 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret); 00839 00840 return ret; 00841 } 00842 00843 00844 /* Function 14 */ 00845 DWORD PNP_SetDeviceRegProp( 00846 handle_t hBinding, 00847 LPWSTR pDeviceId, 00848 DWORD ulProperty, 00849 DWORD ulDataType, 00850 BYTE *Buffer, 00851 PNP_PROP_SIZE ulLength, 00852 DWORD ulFlags) 00853 { 00854 CONFIGRET ret = CR_SUCCESS; 00855 LPWSTR lpValueName = NULL; 00856 HKEY hKey = 0; 00857 00858 UNREFERENCED_PARAMETER(hBinding); 00859 UNREFERENCED_PARAMETER(ulFlags); 00860 00861 DPRINT("PNP_SetDeviceRegProp() called\n"); 00862 00863 DPRINT("DeviceId: %S\n", pDeviceId); 00864 DPRINT("Property: %lu\n", ulProperty); 00865 DPRINT("DataType: %lu\n", ulDataType); 00866 DPRINT("Length: %lu\n", ulLength); 00867 00868 switch (ulProperty) 00869 { 00870 case CM_DRP_DEVICEDESC: 00871 lpValueName = L"DeviceDesc"; 00872 break; 00873 00874 case CM_DRP_HARDWAREID: 00875 lpValueName = L"HardwareID"; 00876 break; 00877 00878 case CM_DRP_COMPATIBLEIDS: 00879 lpValueName = L"CompatibleIDs"; 00880 break; 00881 00882 case CM_DRP_SERVICE: 00883 lpValueName = L"Service"; 00884 break; 00885 00886 case CM_DRP_CLASS: 00887 lpValueName = L"Class"; 00888 break; 00889 00890 case CM_DRP_CLASSGUID: 00891 lpValueName = L"ClassGUID"; 00892 break; 00893 00894 case CM_DRP_DRIVER: 00895 lpValueName = L"Driver"; 00896 break; 00897 00898 case CM_DRP_CONFIGFLAGS: 00899 lpValueName = L"ConfigFlags"; 00900 break; 00901 00902 case CM_DRP_MFG: 00903 lpValueName = L"Mfg"; 00904 break; 00905 00906 case CM_DRP_FRIENDLYNAME: 00907 lpValueName = L"FriendlyName"; 00908 break; 00909 00910 case CM_DRP_LOCATION_INFORMATION: 00911 lpValueName = L"LocationInformation"; 00912 break; 00913 00914 case CM_DRP_UPPERFILTERS: 00915 lpValueName = L"UpperFilters"; 00916 break; 00917 00918 case CM_DRP_LOWERFILTERS: 00919 lpValueName = L"LowerFilters"; 00920 break; 00921 00922 case CM_DRP_SECURITY: 00923 lpValueName = L"Security"; 00924 break; 00925 00926 case CM_DRP_DEVTYPE: 00927 lpValueName = L"DeviceType"; 00928 break; 00929 00930 case CM_DRP_EXCLUSIVE: 00931 lpValueName = L"Exclusive"; 00932 break; 00933 00934 case CM_DRP_CHARACTERISTICS: 00935 lpValueName = L"DeviceCharacteristics"; 00936 break; 00937 00938 case CM_DRP_UI_NUMBER_DESC_FORMAT: 00939 lpValueName = L"UINumberDescFormat"; 00940 break; 00941 00942 case CM_DRP_REMOVAL_POLICY_OVERRIDE: 00943 lpValueName = L"RemovalPolicy"; 00944 break; 00945 00946 default: 00947 return CR_INVALID_PROPERTY; 00948 } 00949 00950 DPRINT("Value name: %S\n", lpValueName); 00951 00952 if (RegOpenKeyExW(hEnumKey, 00953 pDeviceId, 00954 0, 00955 KEY_SET_VALUE, 00956 &hKey)) 00957 return CR_INVALID_DEVNODE; 00958 00959 if (ulLength == 0) 00960 { 00961 if (RegDeleteValueW(hKey, 00962 lpValueName)) 00963 ret = CR_REGISTRY_ERROR; 00964 } 00965 else 00966 { 00967 if (RegSetValueExW(hKey, 00968 lpValueName, 00969 0, 00970 ulDataType, 00971 Buffer, 00972 ulLength)) 00973 ret = CR_REGISTRY_ERROR; 00974 } 00975 00976 RegCloseKey(hKey); 00977 00978 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret); 00979 00980 return ret; 00981 } 00982 00983 00984 /* Function 15 */ 00985 DWORD PNP_GetClassInstance( 00986 handle_t hBinding, 00987 LPWSTR pDeviceId, 00988 LPWSTR pszClassInstance, 00989 PNP_RPC_STRING_LEN ulLength) 00990 { 00991 UNIMPLEMENTED; 00992 return CR_CALL_NOT_IMPLEMENTED; 00993 } 00994 00995 00996 /* Function 16 */ 00997 DWORD PNP_CreateKey( 00998 handle_t hBinding, 00999 LPWSTR pszSubKey, 01000 DWORD samDesired, 01001 DWORD ulFlags) 01002 { 01003 HKEY hKey = 0; 01004 01005 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, 01006 pszSubKey, 01007 0, 01008 NULL, 01009 0, 01010 KEY_ALL_ACCESS, 01011 NULL, 01012 &hKey, 01013 NULL)) 01014 return CR_REGISTRY_ERROR; 01015 01016 /* FIXME: Set security key */ 01017 01018 RegCloseKey(hKey); 01019 01020 return CR_SUCCESS; 01021 } 01022 01023 01024 /* Function 17 */ 01025 DWORD PNP_DeleteRegistryKey( 01026 handle_t hBinding, 01027 LPWSTR pszDeviceID, 01028 LPWSTR pszParentKey, 01029 LPWSTR pszChildKey, 01030 DWORD ulFlags) 01031 { 01032 UNIMPLEMENTED; 01033 return CR_CALL_NOT_IMPLEMENTED; 01034 } 01035 01036 01037 /* Function 18 */ 01038 DWORD PNP_GetClassCount( 01039 handle_t hBinding, 01040 DWORD *pulClassCount, 01041 DWORD ulFlags) 01042 { 01043 HKEY hKey; 01044 DWORD dwError; 01045 01046 UNREFERENCED_PARAMETER(hBinding); 01047 UNREFERENCED_PARAMETER(ulFlags); 01048 01049 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 01050 REGSTR_PATH_CLASS, 01051 0, 01052 KEY_QUERY_VALUE, 01053 &hKey); 01054 if (dwError != ERROR_SUCCESS) 01055 return CR_INVALID_DATA; 01056 01057 dwError = RegQueryInfoKeyW(hKey, 01058 NULL, 01059 NULL, 01060 NULL, 01061 pulClassCount, 01062 NULL, 01063 NULL, 01064 NULL, 01065 NULL, 01066 NULL, 01067 NULL, 01068 NULL); 01069 RegCloseKey(hKey); 01070 if (dwError != ERROR_SUCCESS) 01071 return CR_INVALID_DATA; 01072 01073 return CR_SUCCESS; 01074 } 01075 01076 01077 /* Function 19 */ 01078 DWORD PNP_GetClassName( 01079 handle_t hBinding, 01080 LPWSTR pszClassGuid, 01081 LPWSTR Buffer, 01082 PNP_RPC_STRING_LEN *pulLength, 01083 DWORD ulFlags) 01084 { 01085 WCHAR szKeyName[MAX_PATH]; 01086 CONFIGRET ret = CR_SUCCESS; 01087 HKEY hKey; 01088 DWORD dwSize; 01089 01090 UNREFERENCED_PARAMETER(hBinding); 01091 UNREFERENCED_PARAMETER(ulFlags); 01092 01093 DPRINT("PNP_GetClassName() called\n"); 01094 01095 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\"); 01096 if(lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR))) 01097 lstrcatW(szKeyName, pszClassGuid); 01098 else return CR_INVALID_DATA; 01099 01100 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 01101 szKeyName, 01102 0, 01103 KEY_QUERY_VALUE, 01104 &hKey)) 01105 return CR_REGISTRY_ERROR; 01106 01107 dwSize = *pulLength * sizeof(WCHAR); 01108 if (RegQueryValueExW(hKey, 01109 L"Class", 01110 NULL, 01111 NULL, 01112 (LPBYTE)Buffer, 01113 &dwSize)) 01114 { 01115 *pulLength = 0; 01116 ret = CR_REGISTRY_ERROR; 01117 } 01118 else 01119 { 01120 *pulLength = dwSize / sizeof(WCHAR); 01121 } 01122 01123 RegCloseKey(hKey); 01124 01125 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret); 01126 01127 return ret; 01128 } 01129 01130 01131 /* Function 20 */ 01132 DWORD PNP_DeleteClassKey( 01133 handle_t hBinding, 01134 LPWSTR pszClassGuid, 01135 DWORD ulFlags) 01136 { 01137 CONFIGRET ret = CR_SUCCESS; 01138 01139 UNREFERENCED_PARAMETER(hBinding); 01140 01141 DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid, ulFlags); 01142 01143 if (ulFlags & CM_DELETE_CLASS_SUBKEYS) 01144 { 01145 if (RegDeleteTreeW(hClassKey, pszClassGuid) != ERROR_SUCCESS) 01146 ret = CR_REGISTRY_ERROR; 01147 } 01148 else 01149 { 01150 if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS) 01151 ret = CR_REGISTRY_ERROR; 01152 } 01153 01154 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret); 01155 01156 return ret; 01157 } 01158 01159 01160 /* Function 21 */ 01161 DWORD PNP_GetInterfaceDeviceAlias( 01162 handle_t hBinding, 01163 LPWSTR pszInterfaceDevice, 01164 GUID *AliasInterfaceGuid, 01165 LPWSTR pszAliasInterfaceDevice, 01166 PNP_RPC_STRING_LEN *pulLength, 01167 PNP_RPC_STRING_LEN *pulTransferLen, 01168 DWORD ulFlags) 01169 { 01170 UNIMPLEMENTED; 01171 return CR_CALL_NOT_IMPLEMENTED; 01172 } 01173 01174 01175 /* Function 22 */ 01176 DWORD PNP_GetInterfaceDeviceList( 01177 handle_t hBinding, 01178 GUID *InterfaceGuid, 01179 LPWSTR pszDeviceID, 01180 BYTE *Buffer, 01181 PNP_RPC_BUFFER_SIZE *pulLength, 01182 DWORD ulFlags) 01183 { 01184 UNIMPLEMENTED; 01185 return CR_CALL_NOT_IMPLEMENTED; 01186 } 01187 01188 01189 /* Function 23 */ 01190 DWORD PNP_GetInterfaceDeviceListSize( 01191 handle_t hBinding, 01192 PNP_RPC_BUFFER_SIZE *pulLen, 01193 GUID *InterfaceGuid, 01194 LPWSTR pszDeviceID, 01195 DWORD ulFlags) 01196 { 01197 UNIMPLEMENTED; 01198 return CR_CALL_NOT_IMPLEMENTED; 01199 } 01200 01201 01202 /* Function 24 */ 01203 DWORD PNP_RegisterDeviceClassAssociation( 01204 handle_t hBinding, 01205 LPWSTR pszDeviceID, 01206 GUID *InterfaceGuid, 01207 LPWSTR pszReference, 01208 LPWSTR pszSymLink, 01209 PNP_RPC_STRING_LEN *pulLength, 01210 PNP_RPC_STRING_LEN *pulTransferLen, 01211 DWORD ulFlags) 01212 { 01213 UNIMPLEMENTED; 01214 return CR_CALL_NOT_IMPLEMENTED; 01215 } 01216 01217 01218 /* Function 25 */ 01219 DWORD PNP_UnregisterDeviceClassAssociation( 01220 handle_t hBinding, 01221 LPWSTR pszInterfaceDevice, 01222 DWORD ulFlags) 01223 { 01224 UNIMPLEMENTED; 01225 return CR_CALL_NOT_IMPLEMENTED; 01226 } 01227 01228 01229 /* Function 26 */ 01230 DWORD PNP_GetClassRegProp( 01231 handle_t hBinding, 01232 LPWSTR pszClassGuid, 01233 DWORD ulProperty, 01234 DWORD *pulRegDataType, 01235 BYTE *Buffer, 01236 PNP_RPC_STRING_LEN *pulTransferLen, 01237 PNP_RPC_STRING_LEN *pulLength, 01238 DWORD ulFlags) 01239 { 01240 CONFIGRET ret = CR_SUCCESS; 01241 LPWSTR lpValueName = NULL; 01242 HKEY hInstKey = NULL; 01243 HKEY hPropKey = NULL; 01244 LONG lError; 01245 01246 UNREFERENCED_PARAMETER(hBinding); 01247 01248 DPRINT("PNP_GetClassRegProp() called\n"); 01249 01250 if (pulTransferLen == NULL || pulLength == NULL) 01251 { 01252 ret = CR_INVALID_POINTER; 01253 goto done; 01254 } 01255 01256 if (ulFlags != 0) 01257 { 01258 ret = CR_INVALID_FLAG; 01259 goto done; 01260 } 01261 01262 if (*pulLength < *pulTransferLen) 01263 *pulLength = *pulTransferLen; 01264 01265 *pulTransferLen = 0; 01266 01267 switch (ulProperty) 01268 { 01269 case CM_CRP_SECURITY: 01270 lpValueName = L"Security"; 01271 break; 01272 01273 case CM_CRP_DEVTYPE: 01274 lpValueName = L"DeviceType"; 01275 break; 01276 01277 case CM_CRP_EXCLUSIVE: 01278 lpValueName = L"Exclusive"; 01279 break; 01280 01281 case CM_CRP_CHARACTERISTICS: 01282 lpValueName = L"DeviceCharacteristics"; 01283 break; 01284 01285 default: 01286 ret = CR_INVALID_PROPERTY; 01287 goto done; 01288 } 01289 01290 DPRINT("Value name: %S\n", lpValueName); 01291 01292 lError = RegOpenKeyExW(hClassKey, 01293 pszClassGuid, 01294 0, 01295 KEY_READ, 01296 &hInstKey); 01297 if (lError != ERROR_SUCCESS) 01298 { 01299 *pulLength = 0; 01300 ret = CR_NO_SUCH_REGISTRY_KEY; 01301 goto done; 01302 } 01303 01304 lError = RegOpenKeyExW(hInstKey, 01305 L"Properties", 01306 0, 01307 KEY_READ, 01308 &hPropKey); 01309 if (lError != ERROR_SUCCESS) 01310 { 01311 *pulLength = 0; 01312 ret = CR_NO_SUCH_REGISTRY_KEY; 01313 goto done; 01314 } 01315 01316 lError = RegQueryValueExW(hPropKey, 01317 lpValueName, 01318 NULL, 01319 pulRegDataType, 01320 Buffer, 01321 pulLength); 01322 if (lError != ERROR_SUCCESS) 01323 { 01324 if (lError == ERROR_MORE_DATA) 01325 { 01326 ret = CR_BUFFER_SMALL; 01327 } 01328 else 01329 { 01330 *pulLength = 0; 01331 ret = CR_NO_SUCH_VALUE; 01332 } 01333 } 01334 01335 done:; 01336 if (ret == CR_SUCCESS) 01337 *pulTransferLen = *pulLength; 01338 01339 if (hPropKey != NULL) 01340 RegCloseKey(hPropKey); 01341 01342 if (hInstKey != NULL) 01343 RegCloseKey(hInstKey); 01344 01345 DPRINT("PNP_GetClassRegProp() done (returns %lx)\n", ret); 01346 01347 return ret; 01348 } 01349 01350 01351 /* Function 27 */ 01352 DWORD PNP_SetClassRegProp( 01353 handle_t hBinding, 01354 LPWSTR pszClassGuid, 01355 DWORD ulProperty, 01356 DWORD ulDataType, 01357 BYTE *Buffer, 01358 PNP_PROP_SIZE ulLength, 01359 DWORD ulFlags) 01360 { 01361 CONFIGRET ret = CR_SUCCESS; 01362 LPWSTR lpValueName = NULL; 01363 HKEY hInstKey = 0; 01364 HKEY hPropKey = 0; 01365 LONG lError; 01366 01367 UNREFERENCED_PARAMETER(hBinding); 01368 01369 DPRINT("PNP_SetClassRegProp() called\n"); 01370 01371 if (ulFlags != 0) 01372 return CR_INVALID_FLAG; 01373 01374 switch (ulProperty) 01375 { 01376 case CM_CRP_SECURITY: 01377 lpValueName = L"Security"; 01378 break; 01379 01380 case CM_CRP_DEVTYPE: 01381 lpValueName = L"DeviceType"; 01382 break; 01383 01384 case CM_CRP_EXCLUSIVE: 01385 lpValueName = L"Exclusive"; 01386 break; 01387 01388 case CM_CRP_CHARACTERISTICS: 01389 lpValueName = L"DeviceCharacteristics"; 01390 break; 01391 01392 default: 01393 return CR_INVALID_PROPERTY; 01394 } 01395 01396 lError = RegOpenKeyExW(hClassKey, 01397 pszClassGuid, 01398 0, 01399 KEY_WRITE, 01400 &hInstKey); 01401 if (lError != ERROR_SUCCESS) 01402 { 01403 ret = CR_NO_SUCH_REGISTRY_KEY; 01404 goto done; 01405 } 01406 01407 /* FIXME: Set security descriptor */ 01408 lError = RegCreateKeyExW(hInstKey, 01409 L"Properties", 01410 0, 01411 NULL, 01412 REG_OPTION_NON_VOLATILE, 01413 KEY_ALL_ACCESS, 01414 NULL, 01415 &hPropKey, 01416 NULL); 01417 if (lError != ERROR_SUCCESS) 01418 { 01419 ret = CR_REGISTRY_ERROR; 01420 goto done; 01421 } 01422 01423 if (ulLength == 0) 01424 { 01425 if (RegDeleteValueW(hPropKey, 01426 lpValueName)) 01427 ret = CR_REGISTRY_ERROR; 01428 } 01429 else 01430 { 01431 if (RegSetValueExW(hPropKey, 01432 lpValueName, 01433 0, 01434 ulDataType, 01435 Buffer, 01436 ulLength)) 01437 ret = CR_REGISTRY_ERROR; 01438 } 01439 01440 done:; 01441 if (hPropKey != NULL) 01442 RegCloseKey(hPropKey); 01443 01444 if (hInstKey != NULL) 01445 RegCloseKey(hInstKey); 01446 01447 return ret; 01448 } 01449 01450 01451 static VOID 01452 SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID, 01453 OUT LPWSTR pszEnumerator, 01454 OUT LPWSTR pszDevice, 01455 OUT LPWSTR pszInstance) 01456 { 01457 WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN]; 01458 LPWSTR lpEnumerator = NULL; 01459 LPWSTR lpDevice = NULL; 01460 LPWSTR lpInstance = NULL; 01461 LPWSTR ptr; 01462 01463 wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID); 01464 01465 *pszEnumerator = 0; 01466 *pszDevice = 0; 01467 *pszInstance = 0; 01468 01469 lpEnumerator = szLocalDeviceInstanceID; 01470 01471 ptr = wcschr(lpEnumerator, L'\\'); 01472 if (ptr != NULL) 01473 { 01474 *ptr = 0; 01475 lpDevice = ++ptr; 01476 01477 ptr = wcschr(lpDevice, L'\\'); 01478 if (ptr != NULL) 01479 { 01480 *ptr = 0; 01481 lpInstance = ++ptr; 01482 } 01483 } 01484 01485 if (lpEnumerator != NULL) 01486 wcscpy(pszEnumerator, lpEnumerator); 01487 01488 if (lpDevice != NULL) 01489 wcscpy(pszDevice, lpDevice); 01490 01491 if (lpInstance != NULL) 01492 wcscpy(pszInstance, lpInstance); 01493 } 01494 01495 01496 static CONFIGRET 01497 CreateDeviceInstance(LPWSTR pszDeviceID) 01498 { 01499 WCHAR szEnumerator[MAX_DEVICE_ID_LEN]; 01500 WCHAR szDevice[MAX_DEVICE_ID_LEN]; 01501 WCHAR szInstance[MAX_DEVICE_ID_LEN]; 01502 HKEY hKeyEnumerator; 01503 HKEY hKeyDevice; 01504 HKEY hKeyInstance; 01505 HKEY hKeyControl; 01506 LONG lError; 01507 01508 /* Split the instance ID */ 01509 SplitDeviceInstanceID(pszDeviceID, 01510 szEnumerator, 01511 szDevice, 01512 szInstance); 01513 01514 /* Open or create the enumerator key */ 01515 lError = RegCreateKeyExW(hEnumKey, 01516 szEnumerator, 01517 0, 01518 NULL, 01519 REG_OPTION_NON_VOLATILE, 01520 KEY_ALL_ACCESS, 01521 NULL, 01522 &hKeyEnumerator, 01523 NULL); 01524 if (lError != ERROR_SUCCESS) 01525 { 01526 return CR_REGISTRY_ERROR; 01527 } 01528 01529 /* Open or create the device key */ 01530 lError = RegCreateKeyExW(hKeyEnumerator, 01531 szDevice, 01532 0, 01533 NULL, 01534 REG_OPTION_NON_VOLATILE, 01535 KEY_ALL_ACCESS, 01536 NULL, 01537 &hKeyDevice, 01538 NULL); 01539 01540 /* Close the enumerator key */ 01541 RegCloseKey(hKeyEnumerator); 01542 01543 if (lError != ERROR_SUCCESS) 01544 { 01545 return CR_REGISTRY_ERROR; 01546 } 01547 01548 /* Try to open the instance key and fail if it exists */ 01549 lError = RegOpenKeyExW(hKeyDevice, 01550 szInstance, 01551 0, 01552 KEY_SET_VALUE, 01553 &hKeyInstance); 01554 if (lError == ERROR_SUCCESS) 01555 { 01556 DPRINT1("Instance %S already exists!\n", szInstance); 01557 RegCloseKey(hKeyInstance); 01558 RegCloseKey(hKeyDevice); 01559 return CR_ALREADY_SUCH_DEVINST; 01560 } 01561 01562 /* Create a new instance key */ 01563 lError = RegCreateKeyExW(hKeyDevice, 01564 szInstance, 01565 0, 01566 NULL, 01567 REG_OPTION_NON_VOLATILE, 01568 KEY_ALL_ACCESS, 01569 NULL, 01570 &hKeyInstance, 01571 NULL); 01572 01573 /* Close the device key */ 01574 RegCloseKey(hKeyDevice); 01575 01576 if (lError != ERROR_SUCCESS) 01577 { 01578 return CR_REGISTRY_ERROR; 01579 } 01580 01581 /* Create the 'Control' sub key */ 01582 lError = RegCreateKeyExW(hKeyInstance, 01583 L"Control", 01584 0, 01585 NULL, 01586 REG_OPTION_NON_VOLATILE, 01587 KEY_ALL_ACCESS, 01588 NULL, 01589 &hKeyControl, 01590 NULL); 01591 if (lError == ERROR_SUCCESS) 01592 { 01593 RegCloseKey(hKeyControl); 01594 } 01595 01596 RegCloseKey(hKeyInstance); 01597 01598 return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR; 01599 } 01600 01601 01602 /* Function 28 */ 01603 DWORD PNP_CreateDevInst( 01604 handle_t hBinding, 01605 LPWSTR pszDeviceID, 01606 LPWSTR pszParentDeviceID, 01607 PNP_RPC_STRING_LEN ulLength, 01608 DWORD ulFlags) 01609 { 01610 CONFIGRET ret = CR_SUCCESS; 01611 01612 DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID); 01613 01614 if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID) 01615 { 01616 /* FIXME */ 01617 DPRINT1("CM_CREATE_DEVNODE_GENERATE_ID support not implemented yet!\n", ret); 01618 ret = CR_CALL_NOT_IMPLEMENTED; 01619 goto done; 01620 } 01621 01622 /* Create the device instance */ 01623 ret = CreateDeviceInstance(pszDeviceID); 01624 01625 done:; 01626 DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret); 01627 01628 return ret; 01629 } 01630 01631 01632 static CONFIGRET 01633 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination, 01634 LPWSTR pszDeviceInstanceSource) 01635 { 01636 DPRINT("MoveDeviceInstance: not implemented\n"); 01637 /* FIXME */ 01638 return CR_CALL_NOT_IMPLEMENTED; 01639 } 01640 01641 01642 static CONFIGRET 01643 SetupDeviceInstance(LPWSTR pszDeviceInstance, 01644 DWORD ulFlags) 01645 { 01646 DPRINT("SetupDeviceInstance: not implemented\n"); 01647 /* FIXME */ 01648 return CR_CALL_NOT_IMPLEMENTED; 01649 } 01650 01651 01652 static CONFIGRET 01653 EnableDeviceInstance(LPWSTR pszDeviceInstance) 01654 { 01655 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData; 01656 CONFIGRET ret = CR_SUCCESS; 01657 NTSTATUS Status; 01658 01659 DPRINT("Enable device instance\n"); 01660 01661 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance); 01662 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA)); 01663 if (!NT_SUCCESS(Status)) 01664 ret = NtStatusToCrError(Status); 01665 01666 return ret; 01667 } 01668 01669 01670 static CONFIGRET 01671 DisableDeviceInstance(LPWSTR pszDeviceInstance) 01672 { 01673 DPRINT("DisableDeviceInstance: not implemented\n"); 01674 /* FIXME */ 01675 return CR_CALL_NOT_IMPLEMENTED; 01676 } 01677 01678 01679 static CONFIGRET 01680 ReenumerateDeviceInstance(LPWSTR pszDeviceInstance) 01681 { 01682 DPRINT("ReenumerateDeviceInstance: not implemented\n"); 01683 /* FIXME */ 01684 return CR_CALL_NOT_IMPLEMENTED; 01685 } 01686 01687 01688 /* Function 29 */ 01689 DWORD PNP_DeviceInstanceAction( 01690 handle_t hBinding, 01691 DWORD ulAction, 01692 DWORD ulFlags, 01693 LPWSTR pszDeviceInstance1, 01694 LPWSTR pszDeviceInstance2) 01695 { 01696 CONFIGRET ret = CR_SUCCESS; 01697 01698 UNREFERENCED_PARAMETER(hBinding); 01699 01700 DPRINT("PNP_DeviceInstanceAction() called\n"); 01701 01702 switch (ulAction) 01703 { 01704 case PNP_DEVINST_MOVE: 01705 ret = MoveDeviceInstance(pszDeviceInstance1, 01706 pszDeviceInstance2); 01707 break; 01708 01709 case PNP_DEVINST_SETUP: 01710 ret = SetupDeviceInstance(pszDeviceInstance1, 01711 ulFlags); 01712 break; 01713 01714 case PNP_DEVINST_ENABLE: 01715 ret = EnableDeviceInstance(pszDeviceInstance1); 01716 break; 01717 01718 case PNP_DEVINST_DISABLE: 01719 ret = DisableDeviceInstance(pszDeviceInstance1); 01720 break; 01721 01722 case PNP_DEVINST_REENUMERATE: 01723 ret = ReenumerateDeviceInstance(pszDeviceInstance1); 01724 break; 01725 01726 default: 01727 DPRINT1("Unknown device action %lu: not implemented\n", ulAction); 01728 ret = CR_CALL_NOT_IMPLEMENTED; 01729 } 01730 01731 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret); 01732 01733 return ret; 01734 } 01735 01736 01737 /* Function 30 */ 01738 DWORD PNP_GetDeviceStatus( 01739 handle_t hBinding, 01740 LPWSTR pDeviceID, 01741 DWORD *pulStatus, 01742 DWORD *pulProblem, 01743 DWORD ulFlags) 01744 { 01745 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData; 01746 CONFIGRET ret = CR_SUCCESS; 01747 NTSTATUS Status; 01748 01749 UNREFERENCED_PARAMETER(hBinding); 01750 UNREFERENCED_PARAMETER(ulFlags); 01751 01752 DPRINT("PNP_GetDeviceStatus() called\n"); 01753 01754 RtlInitUnicodeString(&PlugPlayData.DeviceInstance, 01755 pDeviceID); 01756 PlugPlayData.Operation = 0; /* Get status */ 01757 01758 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus, 01759 (PVOID)&PlugPlayData, 01760 sizeof(PLUGPLAY_CONTROL_STATUS_DATA)); 01761 if (NT_SUCCESS(Status)) 01762 { 01763 *pulStatus = PlugPlayData.DeviceStatus; 01764 *pulProblem = PlugPlayData.DeviceProblem; 01765 } 01766 else 01767 { 01768 ret = NtStatusToCrError(Status); 01769 } 01770 01771 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret); 01772 01773 return ret; 01774 } 01775 01776 01777 /* Function 31 */ 01778 DWORD PNP_SetDeviceProblem( 01779 handle_t hBinding, 01780 LPWSTR pDeviceID, 01781 DWORD ulProblem, 01782 DWORD ulFlags) 01783 { 01784 UNIMPLEMENTED; 01785 return CR_CALL_NOT_IMPLEMENTED; 01786 } 01787 01788 01789 /* Function 32 */ 01790 DWORD PNP_DisableDevInst( 01791 handle_t hBinding, 01792 LPWSTR pDeviceID, 01793 PPNP_VETO_TYPE pVetoType, 01794 LPWSTR pszVetoName, 01795 DWORD ulNameLength, 01796 DWORD ulFlags) 01797 { 01798 UNIMPLEMENTED; 01799 return CR_CALL_NOT_IMPLEMENTED; 01800 } 01801 01802 /* Function 33 */ 01803 DWORD PNP_UninstallDevInst( 01804 handle_t hBinding, 01805 LPWSTR pDeviceID, 01806 DWORD ulFlags) 01807 { 01808 UNIMPLEMENTED; 01809 return CR_CALL_NOT_IMPLEMENTED; 01810 } 01811 01812 01813 static BOOL 01814 CheckForDeviceId(LPWSTR lpDeviceIdList, 01815 LPWSTR lpDeviceId) 01816 { 01817 LPWSTR lpPtr; 01818 DWORD dwLength; 01819 01820 lpPtr = lpDeviceIdList; 01821 while (*lpPtr != 0) 01822 { 01823 dwLength = wcslen(lpPtr); 01824 if (0 == _wcsicmp(lpPtr, lpDeviceId)) 01825 return TRUE; 01826 01827 lpPtr += (dwLength + 1); 01828 } 01829 01830 return FALSE; 01831 } 01832 01833 01834 static VOID 01835 AppendDeviceId(LPWSTR lpDeviceIdList, 01836 LPDWORD lpDeviceIdListSize, 01837 LPWSTR lpDeviceId) 01838 { 01839 DWORD dwLen; 01840 DWORD dwPos; 01841 01842 dwLen = wcslen(lpDeviceId); 01843 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1; 01844 01845 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId); 01846 01847 dwPos += (dwLen + 1); 01848 01849 lpDeviceIdList[dwPos] = 0; 01850 01851 *lpDeviceIdListSize = dwPos * sizeof(WCHAR); 01852 } 01853 01854 01855 /* Function 34 */ 01856 DWORD PNP_AddID( 01857 handle_t hBinding, 01858 LPWSTR pszDeviceID, 01859 LPWSTR pszID, 01860 DWORD ulFlags) 01861 { 01862 CONFIGRET ret = CR_SUCCESS; 01863 HKEY hDeviceKey; 01864 LPWSTR pszSubKey; 01865 DWORD dwDeviceIdListSize; 01866 DWORD dwNewDeviceIdSize; 01867 WCHAR * pszDeviceIdList = NULL; 01868 01869 UNREFERENCED_PARAMETER(hBinding); 01870 01871 DPRINT("PNP_AddID() called\n"); 01872 DPRINT(" DeviceInstance: %S\n", pszDeviceID); 01873 DPRINT(" DeviceId: %S\n", pszID); 01874 DPRINT(" Flags: %lx\n", ulFlags); 01875 01876 if (RegOpenKeyExW(hEnumKey, 01877 pszDeviceID, 01878 0, 01879 KEY_QUERY_VALUE | KEY_SET_VALUE, 01880 &hDeviceKey) != ERROR_SUCCESS) 01881 { 01882 DPRINT("Failed to open the device key!\n"); 01883 return CR_INVALID_DEVNODE; 01884 } 01885 01886 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID"; 01887 01888 if (RegQueryValueExW(hDeviceKey, 01889 pszSubKey, 01890 NULL, 01891 NULL, 01892 NULL, 01893 &dwDeviceIdListSize) != ERROR_SUCCESS) 01894 { 01895 DPRINT("Failed to query the desired ID string!\n"); 01896 ret = CR_REGISTRY_ERROR; 01897 goto Done; 01898 } 01899 01900 dwNewDeviceIdSize = lstrlenW(pszDeviceID); 01901 if (!dwNewDeviceIdSize) 01902 { 01903 ret = CR_INVALID_POINTER; 01904 goto Done; 01905 } 01906 01907 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR); 01908 01909 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize); 01910 if (!pszDeviceIdList) 01911 { 01912 DPRINT("Failed to allocate memory for the desired ID string!\n"); 01913 ret = CR_OUT_OF_MEMORY; 01914 goto Done; 01915 } 01916 01917 if (RegQueryValueExW(hDeviceKey, 01918 pszSubKey, 01919 NULL, 01920 NULL, 01921 (LPBYTE)pszDeviceIdList, 01922 &dwDeviceIdListSize) != ERROR_SUCCESS) 01923 { 01924 DPRINT("Failed to query the desired ID string!\n"); 01925 ret = CR_REGISTRY_ERROR; 01926 goto Done; 01927 } 01928 01929 /* Check whether the device ID is already in use */ 01930 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID)) 01931 { 01932 DPRINT("Device ID was found in the ID string!\n"); 01933 ret = CR_SUCCESS; 01934 goto Done; 01935 } 01936 01937 /* Append the Device ID */ 01938 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID); 01939 01940 if (RegSetValueExW(hDeviceKey, 01941 pszSubKey, 01942 0, 01943 REG_MULTI_SZ, 01944 (LPBYTE)pszDeviceIdList, 01945 dwDeviceIdListSize) != ERROR_SUCCESS) 01946 { 01947 DPRINT("Failed to set the desired ID string!\n"); 01948 ret = CR_REGISTRY_ERROR; 01949 } 01950 01951 Done: 01952 RegCloseKey(hDeviceKey); 01953 if (pszDeviceIdList) 01954 HeapFree(GetProcessHeap(), 0, pszDeviceIdList); 01955 01956 DPRINT("PNP_AddID() done (returns %lx)\n", ret); 01957 01958 return ret; 01959 } 01960 01961 01962 /* Function 35 */ 01963 DWORD PNP_RegisterDriver( 01964 handle_t hBinding, 01965 LPWSTR pszDeviceID, 01966 DWORD ulFlags) 01967 { 01968 UNIMPLEMENTED; 01969 return CR_CALL_NOT_IMPLEMENTED; 01970 } 01971 01972 01973 /* Function 36 */ 01974 DWORD PNP_QueryRemove( 01975 handle_t hBinding, 01976 LPWSTR pszDeviceID, 01977 PPNP_VETO_TYPE pVetoType, 01978 LPWSTR pszVetoName, 01979 DWORD ulNameLength, 01980 DWORD ulFlags) 01981 { 01982 UNIMPLEMENTED; 01983 return CR_CALL_NOT_IMPLEMENTED; 01984 } 01985 01986 01987 /* Function 37 */ 01988 DWORD PNP_RequestDeviceEject( 01989 handle_t hBinding, 01990 LPWSTR pszDeviceID, 01991 PPNP_VETO_TYPE pVetoType, 01992 LPWSTR pszVetoName, 01993 DWORD ulNameLength, 01994 DWORD ulFlags) 01995 { 01996 UNIMPLEMENTED; 01997 return CR_CALL_NOT_IMPLEMENTED; 01998 } 01999 02000 /* Function 38 */ 02001 CONFIGRET 02002 PNP_IsDockStationPresent(handle_t hBinding, 02003 BOOL *Present) 02004 { 02005 HKEY hKey; 02006 DWORD dwType; 02007 DWORD dwValue; 02008 DWORD dwSize; 02009 CONFIGRET ret = CR_SUCCESS; 02010 02011 UNREFERENCED_PARAMETER(hBinding); 02012 02013 DPRINT1("PNP_IsDockStationPresent() called\n"); 02014 02015 *Present = FALSE; 02016 02017 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG, 02018 L"CurrentDockInfo", 02019 0, 02020 KEY_READ, 02021 &hKey) != ERROR_SUCCESS) 02022 return CR_REGISTRY_ERROR; 02023 02024 dwSize = sizeof(DWORD); 02025 if (RegQueryValueExW(hKey, 02026 L"DockingState", 02027 NULL, 02028 &dwType, 02029 (LPBYTE)&dwValue, 02030 &dwSize) != ERROR_SUCCESS) 02031 ret = CR_REGISTRY_ERROR; 02032 02033 RegCloseKey(hKey); 02034 02035 if (ret == CR_SUCCESS) 02036 { 02037 if (dwType != REG_DWORD || dwSize != sizeof(DWORD)) 02038 { 02039 ret = CR_REGISTRY_ERROR; 02040 } 02041 else if (dwValue != 0) 02042 { 02043 *Present = TRUE; 02044 } 02045 } 02046 02047 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret); 02048 02049 return ret; 02050 } 02051 02052 02053 /* Function 39 */ 02054 DWORD PNP_RequestEjectPC( 02055 handle_t hBinding) 02056 { 02057 UNIMPLEMENTED; 02058 return CR_CALL_NOT_IMPLEMENTED; 02059 } 02060 02061 02062 /* Function 40 */ 02063 DWORD PNP_HwProfFlags( 02064 handle_t hBinding, 02065 DWORD ulAction, 02066 LPWSTR pDeviceID, 02067 DWORD ulConfig, 02068 DWORD *pulValue, 02069 PPNP_VETO_TYPE pVetoType, 02070 LPWSTR pszVetoName, 02071 DWORD ulNameLength, 02072 DWORD ulFlags) 02073 { 02074 CONFIGRET ret = CR_SUCCESS; 02075 WCHAR szKeyName[MAX_PATH]; 02076 HKEY hKey; 02077 HKEY hDeviceKey; 02078 DWORD dwSize; 02079 02080 UNREFERENCED_PARAMETER(hBinding); 02081 02082 DPRINT("PNP_HwProfFlags() called\n"); 02083 02084 if (ulConfig == 0) 02085 { 02086 wcscpy(szKeyName, 02087 L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum"); 02088 } 02089 else 02090 { 02091 swprintf(szKeyName, 02092 L"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum", 02093 ulConfig); 02094 } 02095 02096 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 02097 szKeyName, 02098 0, 02099 KEY_QUERY_VALUE, 02100 &hKey) != ERROR_SUCCESS) 02101 return CR_REGISTRY_ERROR; 02102 02103 if (ulAction == PNP_GET_HWPROFFLAGS) 02104 { 02105 if (RegOpenKeyExW(hKey, 02106 pDeviceID, 02107 0, 02108 KEY_QUERY_VALUE, 02109 &hDeviceKey) != ERROR_SUCCESS) 02110 { 02111 *pulValue = 0; 02112 } 02113 else 02114 { 02115 dwSize = sizeof(DWORD); 02116 if (!RegQueryValueExW(hDeviceKey, 02117 L"CSConfigFlags", 02118 NULL, 02119 NULL, 02120 (LPBYTE)pulValue, 02121 &dwSize) != ERROR_SUCCESS) 02122 { 02123 *pulValue = 0; 02124 } 02125 02126 RegCloseKey(hDeviceKey); 02127 } 02128 } 02129 else if (ulAction == PNP_SET_HWPROFFLAGS) 02130 { 02131 /* FIXME: not implemented yet */ 02132 ret = CR_CALL_NOT_IMPLEMENTED; 02133 } 02134 02135 RegCloseKey(hKey); 02136 02137 return ret; 02138 } 02139 02140 02141 /* Function 41 */ 02142 DWORD PNP_GetHwProfInfo( 02143 handle_t hBinding, 02144 DWORD ulIndex, 02145 HWPROFILEINFO *pHWProfileInfo, 02146 DWORD ulProfileInfoSize, 02147 DWORD ulFlags) 02148 { 02149 WCHAR szProfileName[5]; 02150 HKEY hKeyConfig = NULL; 02151 HKEY hKeyProfiles = NULL; 02152 HKEY hKeyProfile = NULL; 02153 DWORD dwDisposition; 02154 DWORD dwSize; 02155 LONG lError; 02156 CONFIGRET ret = CR_SUCCESS; 02157 02158 UNREFERENCED_PARAMETER(hBinding); 02159 02160 DPRINT("PNP_GetHwProfInfo() called\n"); 02161 02162 if (ulProfileInfoSize == 0) 02163 { 02164 ret = CR_INVALID_DATA; 02165 goto done; 02166 } 02167 02168 if (ulFlags != 0) 02169 { 02170 ret = CR_INVALID_FLAG; 02171 goto done; 02172 } 02173 02174 /* Initialize the profile information */ 02175 pHWProfileInfo->HWPI_ulHWProfile = 0; 02176 pHWProfileInfo->HWPI_szFriendlyName[0] = 0; 02177 pHWProfileInfo->HWPI_dwFlags = 0; 02178 02179 /* Open the 'IDConfigDB' key */ 02180 lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE, 02181 L"System\\CurrentControlSet\\Control\\IDConfigDB", 02182 0, 02183 NULL, 02184 REG_OPTION_NON_VOLATILE, 02185 KEY_QUERY_VALUE, 02186 NULL, 02187 &hKeyConfig, 02188 &dwDisposition); 02189 if (lError != ERROR_SUCCESS) 02190 { 02191 ret = CR_REGISTRY_ERROR; 02192 goto done; 02193 } 02194 02195 /* Open the 'Hardware Profiles' subkey */ 02196 lError = RegCreateKeyExW(hKeyConfig, 02197 L"Hardware Profiles", 02198 0, 02199 NULL, 02200 REG_OPTION_NON_VOLATILE, 02201 KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, 02202 NULL, 02203 &hKeyProfiles, 02204 &dwDisposition); 02205 if (lError != ERROR_SUCCESS) 02206 { 02207 ret = CR_REGISTRY_ERROR; 02208 goto done; 02209 } 02210 02211 if (ulIndex == (ULONG)-1) 02212 { 02213 dwSize = sizeof(ULONG); 02214 lError = RegQueryValueExW(hKeyConfig, 02215 L"CurrentConfig", 02216 NULL, 02217 NULL, 02218 (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile, 02219 &dwSize); 02220 if (lError != ERROR_SUCCESS) 02221 { 02222 pHWProfileInfo->HWPI_ulHWProfile = 0; 02223 ret = CR_REGISTRY_ERROR; 02224 goto done; 02225 } 02226 } 02227 else 02228 { 02229 /* FIXME: not implemented yet */ 02230 ret = CR_CALL_NOT_IMPLEMENTED; 02231 goto done; 02232 } 02233 02234 swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile); 02235 02236 lError = RegOpenKeyExW(hKeyProfiles, 02237 szProfileName, 02238 0, 02239 KEY_QUERY_VALUE, 02240 &hKeyProfile); 02241 if (lError != ERROR_SUCCESS) 02242 { 02243 ret = CR_REGISTRY_ERROR; 02244 goto done; 02245 } 02246 02247 dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName); 02248 lError = RegQueryValueExW(hKeyProfile, 02249 L"FriendlyName", 02250 NULL, 02251 NULL, 02252 (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName, 02253 &dwSize); 02254 if (lError != ERROR_SUCCESS) 02255 { 02256 ret = CR_REGISTRY_ERROR; 02257 goto done; 02258 } 02259 02260 done: 02261 if (hKeyProfile != NULL) 02262 RegCloseKey(hKeyProfile); 02263 02264 if (hKeyProfiles != NULL) 02265 RegCloseKey(hKeyProfiles); 02266 02267 if (hKeyConfig != NULL) 02268 RegCloseKey(hKeyConfig); 02269 02270 return ret; 02271 } 02272 02273 02274 /* Function 42 */ 02275 DWORD PNP_AddEmptyLogConf( 02276 handle_t hBinding, 02277 LPWSTR pDeviceID, 02278 DWORD ulPriority, 02279 DWORD *pulLogConfTag, 02280 DWORD ulFlags) 02281 { 02282 UNIMPLEMENTED; 02283 return CR_CALL_NOT_IMPLEMENTED; 02284 } 02285 02286 02287 /* Function 43 */ 02288 DWORD PNP_FreeLogConf( 02289 handle_t hBinding, 02290 LPWSTR pDeviceID, 02291 DWORD ulLogConfType, 02292 DWORD ulLogConfTag, 02293 DWORD ulFlags) 02294 { 02295 UNIMPLEMENTED; 02296 return CR_CALL_NOT_IMPLEMENTED; 02297 } 02298 02299 02300 /* Function 44 */ 02301 DWORD PNP_GetFirstLogConf( 02302 handle_t hBinding, 02303 LPWSTR pDeviceID, 02304 DWORD ulLogConfType, 02305 DWORD *pulLogConfTag, 02306 DWORD ulFlags) 02307 { 02308 UNIMPLEMENTED; 02309 return CR_CALL_NOT_IMPLEMENTED; 02310 } 02311 02312 02313 /* Function 45 */ 02314 DWORD PNP_GetNextLogConf( 02315 handle_t hBinding, 02316 LPWSTR pDeviceID, 02317 DWORD ulLogConfType, 02318 DWORD ulCurrentTag, 02319 DWORD *pulNextTag, 02320 DWORD ulFlags) 02321 { 02322 UNIMPLEMENTED; 02323 return CR_CALL_NOT_IMPLEMENTED; 02324 } 02325 02326 02327 /* Function 46 */ 02328 DWORD PNP_GetLogConfPriority( 02329 handle_t hBinding, 02330 LPWSTR pDeviceID, 02331 DWORD ulType, 02332 DWORD ulTag, 02333 DWORD *pPriority, 02334 DWORD ulFlags) 02335 { 02336 UNIMPLEMENTED; 02337 return CR_CALL_NOT_IMPLEMENTED; 02338 } 02339 02340 02341 /* Function 47 */ 02342 DWORD PNP_AddResDes( 02343 handle_t hBinding, 02344 LPWSTR pDeviceID, 02345 DWORD ulLogConfTag, 02346 DWORD ulLogConfType, 02347 RESOURCEID ResourceID, 02348 DWORD *pulResourceTag, 02349 BYTE *ResourceData, 02350 PNP_RPC_BUFFER_SIZE ResourceLen, 02351 DWORD ulFlags) 02352 { 02353 UNIMPLEMENTED; 02354 return CR_CALL_NOT_IMPLEMENTED; 02355 } 02356 02357 02358 /* Function 48 */ 02359 DWORD PNP_FreeResDes( 02360 handle_t hBinding, 02361 LPWSTR pDeviceID, 02362 DWORD ulLogConfTag, 02363 DWORD ulLogConfType, 02364 RESOURCEID ResourceID, 02365 DWORD ulResourceTag, 02366 DWORD *pulPreviousResType, 02367 DWORD *pulPreviousResTag, 02368 DWORD ulFlags) 02369 { 02370 UNIMPLEMENTED; 02371 return CR_CALL_NOT_IMPLEMENTED; 02372 } 02373 02374 02375 /* Function 49 */ 02376 DWORD PNP_GetNextResDes( 02377 handle_t hBinding, 02378 LPWSTR pDeviceID, 02379 DWORD ulLogConfTag, 02380 DWORD ulLogConfType, 02381 RESOURCEID ResourceID, 02382 DWORD ulResourceTag, 02383 DWORD *pulNextResType, 02384 DWORD *pulNextResTag, 02385 DWORD ulFlags) 02386 { 02387 UNIMPLEMENTED; 02388 return CR_CALL_NOT_IMPLEMENTED; 02389 } 02390 02391 02392 /* Function 50 */ 02393 DWORD PNP_GetResDesData( 02394 handle_t hBinding, 02395 LPWSTR pDeviceID, 02396 DWORD ulLogConfTag, 02397 DWORD ulLogConfType, 02398 RESOURCEID ResourceID, 02399 DWORD ulResourceTag, 02400 BYTE *Buffer, 02401 PNP_RPC_BUFFER_SIZE BufferLen, 02402 DWORD ulFlags) 02403 { 02404 UNIMPLEMENTED; 02405 return CR_CALL_NOT_IMPLEMENTED; 02406 } 02407 02408 02409 /* Function 51 */ 02410 DWORD PNP_GetResDesDataSize( 02411 handle_t hBinding, 02412 LPWSTR pDeviceID, 02413 DWORD ulLogConfTag, 02414 DWORD ulLogConfType, 02415 RESOURCEID ResourceID, 02416 DWORD ulResourceTag, 02417 DWORD *pulSize, 02418 DWORD ulFlags) 02419 { 02420 UNIMPLEMENTED; 02421 return CR_CALL_NOT_IMPLEMENTED; 02422 } 02423 02424 02425 /* Function 52 */ 02426 DWORD PNP_ModifyResDes( 02427 handle_t hBinding, 02428 LPWSTR pDeviceID, 02429 DWORD ulLogConfTag, 02430 DWORD ulLogConfType, 02431 RESOURCEID CurrentResourceID, 02432 RESOURCEID NewResourceID, 02433 DWORD ulResourceTag, 02434 BYTE *ResourceData, 02435 PNP_RPC_BUFFER_SIZE ResourceLen, 02436 DWORD ulFlags) 02437 { 02438 UNIMPLEMENTED; 02439 return CR_CALL_NOT_IMPLEMENTED; 02440 } 02441 02442 02443 /* Function 53 */ 02444 DWORD PNP_DetectResourceConflict( 02445 handle_t hBinding, 02446 LPWSTR pDeviceID, 02447 RESOURCEID ResourceID, 02448 BYTE *ResourceData, 02449 PNP_RPC_BUFFER_SIZE ResourceLen, 02450 BOOL *pbConflictDetected, 02451 DWORD ulFlags) 02452 { 02453 UNIMPLEMENTED; 02454 return CR_CALL_NOT_IMPLEMENTED; 02455 } 02456 02457 02458 /* Function 54 */ 02459 DWORD PNP_QueryResConfList( 02460 handle_t hBinding, 02461 LPWSTR pDeviceID, 02462 RESOURCEID ResourceID, 02463 BYTE *ResourceData, 02464 PNP_RPC_BUFFER_SIZE ResourceLen, 02465 BYTE *Buffer, 02466 PNP_RPC_BUFFER_SIZE BufferLen, 02467 DWORD ulFlags) 02468 { 02469 UNIMPLEMENTED; 02470 return CR_CALL_NOT_IMPLEMENTED; 02471 } 02472 02473 02474 /* Function 55 */ 02475 DWORD PNP_SetHwProf( 02476 handle_t hBinding, 02477 DWORD ulHardwareProfile, 02478 DWORD ulFlags) 02479 { 02480 UNIMPLEMENTED; 02481 return CR_CALL_NOT_IMPLEMENTED; 02482 } 02483 02484 02485 /* Function 56 */ 02486 DWORD PNP_QueryArbitratorFreeData( 02487 handle_t hBinding, 02488 BYTE *pData, 02489 DWORD DataLen, 02490 LPWSTR pDeviceID, 02491 RESOURCEID ResourceID, 02492 DWORD ulFlags) 02493 { 02494 UNIMPLEMENTED; 02495 return CR_CALL_NOT_IMPLEMENTED; 02496 } 02497 02498 02499 /* Function 57 */ 02500 DWORD PNP_QueryArbitratorFreeSize( 02501 handle_t hBinding, 02502 DWORD *pulSize, 02503 LPWSTR pDeviceID, 02504 RESOURCEID ResourceID, 02505 DWORD ulFlags) 02506 { 02507 UNIMPLEMENTED; 02508 return CR_CALL_NOT_IMPLEMENTED; 02509 } 02510 02511 02512 /* Function 58 */ 02513 CONFIGRET 02514 PNP_RunDetection( 02515 handle_t hBinding, 02516 DWORD ulFlags) 02517 { 02518 return CR_CALL_NOT_IMPLEMENTED; 02519 } 02520 02521 02522 /* Function 59 */ 02523 DWORD PNP_RegisterNotification( 02524 handle_t hBinding) 02525 { 02526 UNIMPLEMENTED; 02527 return CR_CALL_NOT_IMPLEMENTED; 02528 } 02529 02530 02531 /* Function 60 */ 02532 DWORD PNP_UnregisterNotification( 02533 handle_t hBinding) 02534 { 02535 UNIMPLEMENTED; 02536 return CR_CALL_NOT_IMPLEMENTED; 02537 } 02538 02539 02540 /* Function 61 */ 02541 DWORD PNP_GetCustomDevProp( 02542 handle_t hBinding, 02543 LPWSTR pDeviceID, 02544 LPWSTR CustomPropName, 02545 DWORD *pulRegDataType, 02546 BYTE *Buffer, 02547 PNP_RPC_STRING_LEN *pulTransferLen, 02548 PNP_RPC_STRING_LEN *pulLength, 02549 DWORD ulFlags) 02550 { 02551 HKEY hDeviceKey = NULL; 02552 HKEY hParamKey = NULL; 02553 LONG lError; 02554 CONFIGRET ret = CR_SUCCESS; 02555 02556 UNREFERENCED_PARAMETER(hBinding); 02557 02558 DPRINT("PNP_GetCustomDevProp() called\n"); 02559 02560 if (pulTransferLen == NULL || pulLength == NULL) 02561 { 02562 ret = CR_INVALID_POINTER; 02563 goto done; 02564 } 02565 02566 if (ulFlags & ~CM_CUSTOMDEVPROP_BITS) 02567 { 02568 ret = CR_INVALID_FLAG; 02569 goto done; 02570 } 02571 02572 if (*pulLength < *pulTransferLen) 02573 *pulLength = *pulTransferLen; 02574 02575 *pulTransferLen = 0; 02576 02577 lError = RegOpenKeyExW(hEnumKey, 02578 pDeviceID, 02579 0, 02580 KEY_READ, 02581 &hDeviceKey); 02582 if (lError != ERROR_SUCCESS) 02583 { 02584 ret = CR_REGISTRY_ERROR; 02585 goto done; 02586 } 02587 02588 lError = RegOpenKeyExW(hDeviceKey, 02589 L"Device Parameters", 02590 0, 02591 KEY_READ, 02592 &hParamKey); 02593 if (lError != ERROR_SUCCESS) 02594 { 02595 ret = CR_REGISTRY_ERROR; 02596 goto done; 02597 } 02598 02599 lError = RegQueryValueExW(hParamKey, 02600 CustomPropName, 02601 NULL, 02602 pulRegDataType, 02603 Buffer, 02604 pulLength); 02605 if (lError != ERROR_SUCCESS) 02606 { 02607 if (lError == ERROR_MORE_DATA) 02608 { 02609 ret = CR_BUFFER_SMALL; 02610 } 02611 else 02612 { 02613 *pulLength = 0; 02614 ret = CR_NO_SUCH_VALUE; 02615 } 02616 } 02617 02618 done:; 02619 if (ret == CR_SUCCESS) 02620 *pulTransferLen = *pulLength; 02621 02622 if (hParamKey != NULL) 02623 RegCloseKey(hParamKey); 02624 02625 if (hDeviceKey != NULL) 02626 RegCloseKey(hDeviceKey); 02627 02628 DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret); 02629 02630 return ret; 02631 } 02632 02633 02634 /* Function 62 */ 02635 DWORD PNP_GetVersionInternal( 02636 handle_t hBinding, 02637 WORD *pwVersion) 02638 { 02639 *pwVersion = 0x501; 02640 return CR_SUCCESS; 02641 UNIMPLEMENTED; 02642 return CR_CALL_NOT_IMPLEMENTED; 02643 } 02644 02645 02646 /* Function 63 */ 02647 DWORD PNP_GetBlockedDriverInfo( 02648 handle_t hBinding, 02649 BYTE *Buffer, 02650 PNP_RPC_BUFFER_SIZE *pulTransferLen, 02651 PNP_RPC_BUFFER_SIZE *pulLength, 02652 DWORD ulFlags) 02653 { 02654 UNIMPLEMENTED; 02655 return CR_CALL_NOT_IMPLEMENTED; 02656 } 02657 02658 02659 /* Function 64 */ 02660 DWORD PNP_GetServerSideDeviceInstallFlags( 02661 handle_t hBinding, 02662 DWORD *pulSSDIFlags, 02663 DWORD ulFlags) 02664 { 02665 UNIMPLEMENTED; 02666 return CR_CALL_NOT_IMPLEMENTED; 02667 } 02668 02669 02670 /* Function 65 */ 02671 DWORD PNP_GetObjectPropKeys( 02672 handle_t hBinding, 02673 LPWSTR ObjectName, 02674 DWORD ObjectType, 02675 LPWSTR PropertyCultureName, 02676 PNP_PROP_COUNT *PropertyCount, 02677 PNP_PROP_COUNT *TransferLen, 02678 DEVPROPKEY *PropertyKeys, 02679 DWORD Flags) 02680 { 02681 UNIMPLEMENTED; 02682 return CR_CALL_NOT_IMPLEMENTED; 02683 } 02684 02685 02686 /* Function 66 */ 02687 DWORD PNP_GetObjectProp( 02688 handle_t hBinding, 02689 LPWSTR ObjectName, 02690 DWORD ObjectType, 02691 LPWSTR PropertyCultureName, 02692 const DEVPROPKEY *PropertyKey, 02693 DEVPROPTYPE *PropertyType, 02694 PNP_PROP_SIZE *PropertySize, 02695 PNP_PROP_SIZE *TransferLen, 02696 BYTE *PropertyBuffer, 02697 DWORD Flags) 02698 { 02699 UNIMPLEMENTED; 02700 return CR_CALL_NOT_IMPLEMENTED; 02701 } 02702 02703 02704 /* Function 67 */ 02705 DWORD PNP_SetObjectProp( 02706 handle_t hBinding, 02707 LPWSTR ObjectName, 02708 DWORD ObjectType, 02709 LPWSTR PropertyCultureName, 02710 const DEVPROPKEY *PropertyKey, 02711 DEVPROPTYPE PropertyType, 02712 PNP_PROP_SIZE PropertySize, 02713 BYTE *PropertyBuffer, 02714 DWORD Flags) 02715 { 02716 UNIMPLEMENTED; 02717 return CR_CALL_NOT_IMPLEMENTED; 02718 } 02719 02720 02721 /* Function 68 */ 02722 DWORD PNP_InstallDevInst( 02723 handle_t hBinding) 02724 { 02725 UNIMPLEMENTED; 02726 return CR_CALL_NOT_IMPLEMENTED; 02727 } 02728 02729 02730 /* Function 69 */ 02731 DWORD PNP_ApplyPowerSettings( 02732 handle_t hBinding) 02733 { 02734 UNIMPLEMENTED; 02735 return CR_CALL_NOT_IMPLEMENTED; 02736 } 02737 02738 02739 /* Function 70 */ 02740 DWORD PNP_DriverStoreAddDriverPackage( 02741 handle_t hBinding) 02742 { 02743 UNIMPLEMENTED; 02744 return CR_CALL_NOT_IMPLEMENTED; 02745 } 02746 02747 02748 /* Function 71 */ 02749 DWORD PNP_DriverStoreDeleteDriverPackage( 02750 handle_t hBinding) 02751 { 02752 UNIMPLEMENTED; 02753 return CR_CALL_NOT_IMPLEMENTED; 02754 } 02755 02756 02757 /* Function 72 */ 02758 DWORD PNP_RegisterServiceNotification( 02759 handle_t hBinding) 02760 { 02761 UNIMPLEMENTED; 02762 return CR_CALL_NOT_IMPLEMENTED; 02763 } 02764 02765 02766 /* Function 73 */ 02767 DWORD PNP_SetActiveService( 02768 handle_t hBinding) 02769 { 02770 UNIMPLEMENTED; 02771 return CR_CALL_NOT_IMPLEMENTED; 02772 } 02773 02774 02775 /* Function 74 */ 02776 DWORD PNP_DeleteServiceDevices( 02777 handle_t hBinding) 02778 { 02779 UNIMPLEMENTED; 02780 return CR_CALL_NOT_IMPLEMENTED; 02781 } 02782 02783 02784 static BOOL 02785 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard) 02786 { 02787 BOOL DeviceInstalled = FALSE; 02788 DWORD BytesWritten; 02789 DWORD Value; 02790 HANDLE hPipe = INVALID_HANDLE_VALUE; 02791 LPVOID Environment = NULL; 02792 PROCESS_INFORMATION ProcessInfo; 02793 STARTUPINFOW StartupInfo; 02794 UUID RandomUuid; 02795 HKEY DeviceKey; 02796 02797 /* The following lengths are constant (see below), they cannot overflow */ 02798 WCHAR CommandLine[116]; 02799 WCHAR InstallEventName[73]; 02800 WCHAR PipeName[74]; 02801 WCHAR UuidString[39]; 02802 02803 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard); 02804 02805 ZeroMemory(&ProcessInfo, sizeof(ProcessInfo)); 02806 02807 if (RegOpenKeyExW(hEnumKey, 02808 DeviceInstance, 02809 0, 02810 KEY_QUERY_VALUE, 02811 &DeviceKey) == ERROR_SUCCESS) 02812 { 02813 if (RegQueryValueExW(DeviceKey, 02814 L"Class", 02815 NULL, 02816 NULL, 02817 NULL, 02818 NULL) == ERROR_SUCCESS) 02819 { 02820 DPRINT("No need to install: %S\n", DeviceInstance); 02821 RegCloseKey(DeviceKey); 02822 return TRUE; 02823 } 02824 02825 RegCloseKey(DeviceKey); 02826 } 02827 02828 DPRINT1("Installing: %S\n", DeviceInstance); 02829 02830 /* Create a random UUID for the named pipe */ 02831 UuidCreate(&RandomUuid); 02832 swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", 02833 RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3, 02834 RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2], 02835 RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5], 02836 RandomUuid.Data4[6], RandomUuid.Data4[7]); 02837 02838 /* Create the named pipe */ 02839 wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0."); 02840 wcscat(PipeName, UuidString); 02841 hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL); 02842 02843 if(hPipe == INVALID_HANDLE_VALUE) 02844 { 02845 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError()); 02846 goto cleanup; 02847 } 02848 02849 /* Launch rundll32 to call ClientSideInstallW */ 02850 wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall "); 02851 wcscat(CommandLine, PipeName); 02852 02853 ZeroMemory(&StartupInfo, sizeof(StartupInfo)); 02854 StartupInfo.cb = sizeof(StartupInfo); 02855 02856 if(hUserToken) 02857 { 02858 /* newdev has to run under the environment of the current user */ 02859 if(!CreateEnvironmentBlock(&Environment, hUserToken, FALSE)) 02860 { 02861 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError()); 02862 goto cleanup; 02863 } 02864 02865 if(!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo)) 02866 { 02867 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError()); 02868 goto cleanup; 02869 } 02870 } 02871 else 02872 { 02873 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges. 02874 02875 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here. 02876 (ShowWizard is only set to FALSE for these two modes) */ 02877 ASSERT(!ShowWizard); 02878 02879 if(!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo)) 02880 { 02881 DPRINT1("CreateProcessW failed with error %u\n", GetLastError()); 02882 goto cleanup; 02883 } 02884 } 02885 02886 /* Wait for the function to connect to our pipe */ 02887 if(!ConnectNamedPipe(hPipe, NULL)) 02888 { 02889 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError()); 02890 goto cleanup; 02891 } 02892 02893 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */ 02894 wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0."); 02895 wcscat(InstallEventName, UuidString); 02896 02897 Value = sizeof(InstallEventName); 02898 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL); 02899 WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL); 02900 02901 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once. 02902 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */ 02903 WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL); 02904 02905 Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR); 02906 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL); 02907 WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL); 02908 02909 /* Wait for newdev.dll to finish processing */ 02910 WaitForSingleObject(ProcessInfo.hProcess, INFINITE); 02911 02912 /* The following check for success is probably not compatible to Windows, but should do its job */ 02913 if(!GetExitCodeProcess(ProcessInfo.hProcess, &Value)) 02914 { 02915 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError()); 02916 goto cleanup; 02917 } 02918 02919 DeviceInstalled = Value; 02920 02921 cleanup: 02922 if(hPipe != INVALID_HANDLE_VALUE) 02923 CloseHandle(hPipe); 02924 02925 if(Environment) 02926 DestroyEnvironmentBlock(Environment); 02927 02928 if(ProcessInfo.hProcess) 02929 CloseHandle(ProcessInfo.hProcess); 02930 02931 if(ProcessInfo.hThread) 02932 CloseHandle(ProcessInfo.hThread); 02933 02934 DPRINT1("Success? %d\n", DeviceInstalled); 02935 02936 return DeviceInstalled; 02937 } 02938 02939 02940 static LONG 02941 ReadRegSzKey( 02942 IN HKEY hKey, 02943 IN LPCWSTR pszKey, 02944 OUT LPWSTR* pValue) 02945 { 02946 LONG rc; 02947 DWORD dwType; 02948 DWORD cbData = 0; 02949 LPWSTR Value; 02950 02951 if (!pValue) 02952 return ERROR_INVALID_PARAMETER; 02953 02954 *pValue = NULL; 02955 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData); 02956 if (rc != ERROR_SUCCESS) 02957 return rc; 02958 if (dwType != REG_SZ) 02959 return ERROR_FILE_NOT_FOUND; 02960 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR)); 02961 if (!Value) 02962 return ERROR_NOT_ENOUGH_MEMORY; 02963 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData); 02964 if (rc != ERROR_SUCCESS) 02965 { 02966 HeapFree(GetProcessHeap(), 0, Value); 02967 return rc; 02968 } 02969 /* NULL-terminate the string */ 02970 Value[cbData / sizeof(WCHAR)] = '\0'; 02971 02972 *pValue = Value; 02973 return ERROR_SUCCESS; 02974 } 02975 02976 02977 static BOOL 02978 SetupIsActive(VOID) 02979 { 02980 HKEY hKey = NULL; 02981 DWORD regType, active, size; 02982 LONG rc; 02983 BOOL ret = FALSE; 02984 02985 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey); 02986 if (rc != ERROR_SUCCESS) 02987 goto cleanup; 02988 02989 size = sizeof(DWORD); 02990 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, ®Type, (LPBYTE)&active, &size); 02991 if (rc != ERROR_SUCCESS) 02992 goto cleanup; 02993 if (regType != REG_DWORD || size != sizeof(DWORD)) 02994 goto cleanup; 02995 02996 ret = (active != 0); 02997 02998 cleanup: 02999 if (hKey != NULL) 03000 RegCloseKey(hKey); 03001 03002 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO"); 03003 03004 return ret; 03005 } 03006 03007 03008 static BOOL 03009 IsConsoleBoot(VOID) 03010 { 03011 HKEY ControlKey = NULL; 03012 LPWSTR SystemStartOptions = NULL; 03013 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */ 03014 BOOL ConsoleBoot = FALSE; 03015 LONG rc; 03016 03017 rc = RegOpenKeyExW( 03018 HKEY_LOCAL_MACHINE, 03019 L"SYSTEM\\CurrentControlSet\\Control", 03020 0, 03021 KEY_QUERY_VALUE, 03022 &ControlKey); 03023 03024 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions); 03025 if (rc != ERROR_SUCCESS) 03026 goto cleanup; 03027 03028 /* Check for CMDCONS in SystemStartOptions */ 03029 CurrentOption = SystemStartOptions; 03030 while (CurrentOption) 03031 { 03032 NextOption = wcschr(CurrentOption, L' '); 03033 if (NextOption) 03034 *NextOption = L'\0'; 03035 if (_wcsicmp(CurrentOption, L"CONSOLE") == 0) 03036 { 03037 DPRINT("Found %S. Switching to console boot\n", CurrentOption); 03038 ConsoleBoot = TRUE; 03039 goto cleanup; 03040 } 03041 CurrentOption = NextOption ? NextOption + 1 : NULL; 03042 } 03043 03044 cleanup: 03045 if (ControlKey != NULL) 03046 RegCloseKey(ControlKey); 03047 HeapFree(GetProcessHeap(), 0, SystemStartOptions); 03048 return ConsoleBoot; 03049 } 03050 03051 03052 /* Loop to install all queued devices installations */ 03053 static DWORD WINAPI 03054 DeviceInstallThread(LPVOID lpParameter) 03055 { 03056 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED 03057 PSLIST_ENTRY ListEntry; 03058 #else 03059 PLIST_ENTRY ListEntry; 03060 #endif 03061 DeviceInstallParams* Params; 03062 BOOL showWizard; 03063 03064 UNREFERENCED_PARAMETER(lpParameter); 03065 03066 WaitForSingleObject(hInstallEvent, INFINITE); 03067 03068 showWizard = !SetupIsActive() && !IsConsoleBoot(); 03069 03070 while (TRUE) 03071 { 03072 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED 03073 ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead); 03074 #else 03075 if ((BOOL)IsListEmpty(&DeviceInstallListHead)) 03076 ListEntry = NULL; 03077 else 03078 ListEntry = RemoveHeadList(&DeviceInstallListHead); 03079 #endif 03080 if (ListEntry == NULL) 03081 { 03082 SetEvent(hNoPendingInstalls); 03083 WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE); 03084 } 03085 else 03086 { 03087 ResetEvent(hNoPendingInstalls); 03088 Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry); 03089 InstallDevice(Params->DeviceIds, showWizard); 03090 } 03091 } 03092 03093 return 0; 03094 } 03095 03096 03097 static DWORD WINAPI 03098 PnpEventThread(LPVOID lpParameter) 03099 { 03100 PPLUGPLAY_EVENT_BLOCK PnpEvent; 03101 ULONG PnpEventSize; 03102 NTSTATUS Status; 03103 RPC_STATUS RpcStatus; 03104 03105 UNREFERENCED_PARAMETER(lpParameter); 03106 03107 PnpEventSize = 0x1000; 03108 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize); 03109 if (PnpEvent == NULL) 03110 return ERROR_OUTOFMEMORY; 03111 03112 for (;;) 03113 { 03114 DPRINT("Calling NtGetPlugPlayEvent()\n"); 03115 03116 /* Wait for the next pnp event */ 03117 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize); 03118 03119 /* Resize the buffer for the PnP event if it's too small. */ 03120 if (Status == STATUS_BUFFER_TOO_SMALL) 03121 { 03122 PnpEventSize += 0x400; 03123 HeapFree(GetProcessHeap(), 0, PnpEvent); 03124 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize); 03125 if (PnpEvent == NULL) 03126 return ERROR_OUTOFMEMORY; 03127 continue; 03128 } 03129 03130 if (!NT_SUCCESS(Status)) 03131 { 03132 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status); 03133 break; 03134 } 03135 03136 /* Process the pnp event */ 03137 DPRINT("Received PnP Event\n"); 03138 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus)) 03139 { 03140 DeviceInstallParams* Params; 03141 DWORD len; 03142 DWORD DeviceIdLength; 03143 03144 DPRINT("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds); 03145 03146 DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds); 03147 if (DeviceIdLength) 03148 { 03149 /* Queue device install (will be dequeued by DeviceInstallThread */ 03150 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR); 03151 Params = HeapAlloc(GetProcessHeap(), 0, len); 03152 if (Params) 03153 { 03154 wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds); 03155 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED 03156 InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry); 03157 #else 03158 InsertTailList(&DeviceInstallListHead, &Params->ListEntry); 03159 #endif 03160 SetEvent(hDeviceInstallListNotEmpty); 03161 } 03162 } 03163 } 03164 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus)) 03165 { 03166 DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds); 03167 /* FIXME: ? */ 03168 } 03169 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_EJECT_VETOED, &RpcStatus)) 03170 { 03171 DPRINT1("Eject vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds); 03172 } 03173 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_KERNEL_INITIATED_EJECT, &RpcStatus)) 03174 { 03175 DPRINT1("Kernel initiated eject: %S\n", PnpEvent->TargetDevice.DeviceIds); 03176 } 03177 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SAFE_REMOVAL, &RpcStatus)) 03178 { 03179 DPRINT1("Safe removal: %S\n", PnpEvent->TargetDevice.DeviceIds); 03180 } 03181 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SURPRISE_REMOVAL, &RpcStatus)) 03182 { 03183 DPRINT1("Surprise removal: %S\n", PnpEvent->TargetDevice.DeviceIds); 03184 } 03185 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVAL_VETOED, &RpcStatus)) 03186 { 03187 DPRINT1("Removal vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds); 03188 } 03189 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVE_PENDING, &RpcStatus)) 03190 { 03191 DPRINT1("Removal pending: %S\n", PnpEvent->TargetDevice.DeviceIds); 03192 } 03193 else 03194 { 03195 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n", 03196 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3, 03197 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2], 03198 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5], 03199 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]); 03200 } 03201 03202 /* Dequeue the current pnp event and signal the next one */ 03203 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0); 03204 } 03205 03206 HeapFree(GetProcessHeap(), 0, PnpEvent); 03207 03208 return ERROR_SUCCESS; 03209 } 03210 03211 03212 static VOID 03213 UpdateServiceStatus(DWORD dwState) 03214 { 03215 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 03216 ServiceStatus.dwCurrentState = dwState; 03217 ServiceStatus.dwControlsAccepted = 0; 03218 ServiceStatus.dwWin32ExitCode = 0; 03219 ServiceStatus.dwServiceSpecificExitCode = 0; 03220 ServiceStatus.dwCheckPoint = 0; 03221 03222 if (dwState == SERVICE_START_PENDING || 03223 dwState == SERVICE_STOP_PENDING || 03224 dwState == SERVICE_PAUSE_PENDING || 03225 dwState == SERVICE_CONTINUE_PENDING) 03226 ServiceStatus.dwWaitHint = 10000; 03227 else 03228 ServiceStatus.dwWaitHint = 0; 03229 03230 SetServiceStatus(ServiceStatusHandle, 03231 &ServiceStatus); 03232 } 03233 03234 03235 static DWORD WINAPI 03236 ServiceControlHandler(DWORD dwControl, 03237 DWORD dwEventType, 03238 LPVOID lpEventData, 03239 LPVOID lpContext) 03240 { 03241 DPRINT1("ServiceControlHandler() called\n"); 03242 03243 switch (dwControl) 03244 { 03245 case SERVICE_CONTROL_STOP: 03246 DPRINT1(" SERVICE_CONTROL_STOP received\n"); 03247 /* Stop listening to RPC Messages */ 03248 RpcMgmtStopServerListening(NULL); 03249 UpdateServiceStatus(SERVICE_STOPPED); 03250 return ERROR_SUCCESS; 03251 03252 case SERVICE_CONTROL_PAUSE: 03253 DPRINT1(" SERVICE_CONTROL_PAUSE received\n"); 03254 UpdateServiceStatus(SERVICE_PAUSED); 03255 return ERROR_SUCCESS; 03256 03257 case SERVICE_CONTROL_CONTINUE: 03258 DPRINT1(" SERVICE_CONTROL_CONTINUE received\n"); 03259 UpdateServiceStatus(SERVICE_RUNNING); 03260 return ERROR_SUCCESS; 03261 03262 case SERVICE_CONTROL_INTERROGATE: 03263 DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n"); 03264 SetServiceStatus(ServiceStatusHandle, 03265 &ServiceStatus); 03266 return ERROR_SUCCESS; 03267 03268 case SERVICE_CONTROL_SHUTDOWN: 03269 DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n"); 03270 /* Stop listening to RPC Messages */ 03271 RpcMgmtStopServerListening(NULL); 03272 UpdateServiceStatus(SERVICE_STOPPED); 03273 return ERROR_SUCCESS; 03274 03275 default : 03276 DPRINT1(" Control %lu received\n"); 03277 return ERROR_CALL_NOT_IMPLEMENTED; 03278 } 03279 } 03280 03281 03282 static VOID CALLBACK 03283 ServiceMain(DWORD argc, LPTSTR *argv) 03284 { 03285 HANDLE hThread; 03286 DWORD dwThreadId; 03287 03288 UNREFERENCED_PARAMETER(argc); 03289 UNREFERENCED_PARAMETER(argv); 03290 03291 DPRINT("ServiceMain() called\n"); 03292 03293 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName, 03294 ServiceControlHandler, 03295 NULL); 03296 if (!ServiceStatusHandle) 03297 { 03298 DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError()); 03299 return; 03300 } 03301 03302 UpdateServiceStatus(SERVICE_START_PENDING); 03303 03304 hThread = CreateThread(NULL, 03305 0, 03306 PnpEventThread, 03307 NULL, 03308 0, 03309 &dwThreadId); 03310 if (hThread != NULL) 03311 CloseHandle(hThread); 03312 03313 hThread = CreateThread(NULL, 03314 0, 03315 RpcServerThread, 03316 NULL, 03317 0, 03318 &dwThreadId); 03319 if (hThread != NULL) 03320 CloseHandle(hThread); 03321 03322 hThread = CreateThread(NULL, 03323 0, 03324 DeviceInstallThread, 03325 NULL, 03326 0, 03327 &dwThreadId); 03328 if (hThread != NULL) 03329 CloseHandle(hThread); 03330 03331 UpdateServiceStatus(SERVICE_RUNNING); 03332 03333 DPRINT("ServiceMain() done\n"); 03334 } 03335 03336 03337 int 03338 wmain(int argc, WCHAR *argv[]) 03339 { 03340 BOOLEAN OldValue; 03341 DWORD dwError; 03342 03343 UNREFERENCED_PARAMETER(argc); 03344 UNREFERENCED_PARAMETER(argv); 03345 03346 DPRINT("Umpnpmgr: main() started\n"); 03347 03348 /* We need this privilege for using CreateProcessAsUserW */ 03349 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue); 03350 03351 hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL); 03352 if (hInstallEvent == NULL) 03353 { 03354 dwError = GetLastError(); 03355 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError); 03356 return dwError; 03357 } 03358 03359 hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL); 03360 if (hDeviceInstallListNotEmpty == NULL) 03361 { 03362 dwError = GetLastError(); 03363 DPRINT1("Could not create the Event! (Error %lu)\n", dwError); 03364 return dwError; 03365 } 03366 03367 hNoPendingInstalls = CreateEventW(NULL, 03368 TRUE, 03369 FALSE, 03370 L"Global\\PnP_No_Pending_Install_Events"); 03371 if (hNoPendingInstalls == NULL) 03372 { 03373 dwError = GetLastError(); 03374 DPRINT1("Could not create the Event! (Error %lu)\n", dwError); 03375 return dwError; 03376 } 03377 03378 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED 03379 InitializeSListHead(&DeviceInstallListHead); 03380 #else 03381 InitializeListHead(&DeviceInstallListHead); 03382 #endif 03383 03384 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 03385 L"System\\CurrentControlSet\\Enum", 03386 0, 03387 KEY_ALL_ACCESS, 03388 &hEnumKey); 03389 if (dwError != ERROR_SUCCESS) 03390 { 03391 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError); 03392 return dwError; 03393 } 03394 03395 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 03396 L"System\\CurrentControlSet\\Control\\Class", 03397 0, 03398 KEY_ALL_ACCESS, 03399 &hClassKey); 03400 if (dwError != ERROR_SUCCESS) 03401 { 03402 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError); 03403 return dwError; 03404 } 03405 03406 StartServiceCtrlDispatcher(ServiceTable); 03407 03408 DPRINT("Umpnpmgr: main() done\n"); 03409 03410 ExitThread(0); 03411 03412 return 0; 03413 } 03414 03415 /* EOF */ Generated on Sat May 26 2012 04:16:40 for ReactOS by
1.7.6.1
|