From fe3ae243695b3d2d9a641789a959c33d596573b0 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Thu, 30 May 2019 11:48:29 +0200 Subject: [PATCH] [UMPNPMGR] Split the monolithic monster: service, rpc and installer. --- base/services/umpnpmgr/CMakeLists.txt | 2 + base/services/umpnpmgr/install.c | 377 +++ base/services/umpnpmgr/precomp.h | 75 + base/services/umpnpmgr/rpcserver.c | 3762 +++++++++++++++++++++++ base/services/umpnpmgr/umpnpmgr.c | 4091 +------------------------ 5 files changed, 4220 insertions(+), 4087 deletions(-) create mode 100644 base/services/umpnpmgr/install.c create mode 100644 base/services/umpnpmgr/precomp.h create mode 100644 base/services/umpnpmgr/rpcserver.c diff --git a/base/services/umpnpmgr/CMakeLists.txt b/base/services/umpnpmgr/CMakeLists.txt index 4248d0e9d81..7c344f9914c 100644 --- a/base/services/umpnpmgr/CMakeLists.txt +++ b/base/services/umpnpmgr/CMakeLists.txt @@ -4,6 +4,8 @@ add_rpc_files(server ${REACTOS_SOURCE_DIR}/sdk/include/reactos/idl/pnp.idl) spec2def(umpnpmgr.dll umpnpmgr.spec ADD_IMPORTLIB) add_library(umpnpmgr MODULE + install.c + rpcserver.c umpnpmgr.c umpnpmgr.rc ${CMAKE_CURRENT_BINARY_DIR}/pnp_s.c diff --git a/base/services/umpnpmgr/install.c b/base/services/umpnpmgr/install.c new file mode 100644 index 00000000000..2f3bdfd1050 --- /dev/null +++ b/base/services/umpnpmgr/install.c @@ -0,0 +1,377 @@ +/* + * ReactOS kernel + * Copyright (C) 2005 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: base/services/umpnpmgr/install.c + * PURPOSE: Device installer + * PROGRAMMER: Eric Kohl (eric.kohl@reactos.org) + * Hervé Poussineau (hpoussin@reactos.org) + * Colin Finck (colin@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include "precomp.h" + +#define NDEBUG +#include + + +/* GLOBALS ******************************************************************/ + +HANDLE hUserToken = NULL; +HANDLE hInstallEvent = NULL; +HANDLE hNoPendingInstalls = NULL; + +SLIST_HEADER DeviceInstallListHead; +HANDLE hDeviceInstallListNotEmpty; + + +/* FUNCTIONS *****************************************************************/ + +static BOOL +InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard) +{ + BOOL DeviceInstalled = FALSE; + DWORD BytesWritten; + DWORD Value; + HANDLE hInstallEvent; + HANDLE hPipe = INVALID_HANDLE_VALUE; + LPVOID Environment = NULL; + PROCESS_INFORMATION ProcessInfo; + STARTUPINFOW StartupInfo; + UUID RandomUuid; + HKEY DeviceKey; + + /* The following lengths are constant (see below), they cannot overflow */ + WCHAR CommandLine[116]; + WCHAR InstallEventName[73]; + WCHAR PipeName[74]; + WCHAR UuidString[39]; + + DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard); + + ZeroMemory(&ProcessInfo, sizeof(ProcessInfo)); + + if (RegOpenKeyExW(hEnumKey, + DeviceInstance, + 0, + KEY_QUERY_VALUE, + &DeviceKey) == ERROR_SUCCESS) + { + if (RegQueryValueExW(DeviceKey, + L"Class", + NULL, + NULL, + NULL, + NULL) == ERROR_SUCCESS) + { + DPRINT("No need to install: %S\n", DeviceInstance); + RegCloseKey(DeviceKey); + return TRUE; + } + + BytesWritten = sizeof(DWORD); + if (RegQueryValueExW(DeviceKey, + L"ConfigFlags", + NULL, + NULL, + (PBYTE)&Value, + &BytesWritten) == ERROR_SUCCESS) + { + if (Value & CONFIGFLAG_FAILEDINSTALL) + { + DPRINT("No need to install: %S\n", DeviceInstance); + RegCloseKey(DeviceKey); + return TRUE; + } + } + + RegCloseKey(DeviceKey); + } + + DPRINT1("Installing: %S\n", DeviceInstance); + + /* Create a random UUID for the named pipe & event*/ + UuidCreate(&RandomUuid); + swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3, + RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2], + RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5], + RandomUuid.Data4[6], RandomUuid.Data4[7]); + + /* Create the event */ + wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0."); + wcscat(InstallEventName, UuidString); + hInstallEvent = CreateEventW(NULL, TRUE, FALSE, InstallEventName); + if (!hInstallEvent) + { + DPRINT1("CreateEventW('%ls') failed with error %lu\n", InstallEventName, GetLastError()); + goto cleanup; + } + + /* Create the named pipe */ + wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0."); + wcscat(PipeName, UuidString); + hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL); + if (hPipe == INVALID_HANDLE_VALUE) + { + DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError()); + goto cleanup; + } + + /* Launch rundll32 to call ClientSideInstallW */ + wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall "); + wcscat(CommandLine, PipeName); + + ZeroMemory(&StartupInfo, sizeof(StartupInfo)); + StartupInfo.cb = sizeof(StartupInfo); + + if (hUserToken) + { + /* newdev has to run under the environment of the current user */ + if (!CreateEnvironmentBlock(&Environment, hUserToken, FALSE)) + { + DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError()); + goto cleanup; + } + + if (!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo)) + { + DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError()); + goto cleanup; + } + } + else + { + /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges. + + Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here. + (ShowWizard is only set to FALSE for these two modes) */ + ASSERT(!ShowWizard); + + if (!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo)) + { + DPRINT1("CreateProcessW failed with error %u\n", GetLastError()); + goto cleanup; + } + } + + /* Wait for the function to connect to our pipe */ + if (!ConnectNamedPipe(hPipe, NULL)) + { + if (GetLastError() != ERROR_PIPE_CONNECTED) + { + DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError()); + goto cleanup; + } + } + + /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */ + Value = sizeof(InstallEventName); + WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL); + WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL); + + /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once. + Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */ + WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL); + + Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR); + WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL); + WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL); + + /* Wait for newdev.dll to finish processing */ + WaitForSingleObject(ProcessInfo.hProcess, INFINITE); + + /* If the event got signalled, this is success */ + DeviceInstalled = WaitForSingleObject(hInstallEvent, 0) == WAIT_OBJECT_0; + +cleanup: + if (hInstallEvent) + CloseHandle(hInstallEvent); + + if (hPipe != INVALID_HANDLE_VALUE) + CloseHandle(hPipe); + + if (Environment) + DestroyEnvironmentBlock(Environment); + + if (ProcessInfo.hProcess) + CloseHandle(ProcessInfo.hProcess); + + if (ProcessInfo.hThread) + CloseHandle(ProcessInfo.hThread); + + if (!DeviceInstalled) + { + DPRINT1("InstallDevice failed for DeviceInstance '%ws'\n", DeviceInstance); + } + + return DeviceInstalled; +} + + +static LONG +ReadRegSzKey( + IN HKEY hKey, + IN LPCWSTR pszKey, + OUT LPWSTR* pValue) +{ + LONG rc; + DWORD dwType; + DWORD cbData = 0; + LPWSTR Value; + + if (!pValue) + return ERROR_INVALID_PARAMETER; + + *pValue = NULL; + rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData); + if (rc != ERROR_SUCCESS) + return rc; + if (dwType != REG_SZ) + return ERROR_FILE_NOT_FOUND; + Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR)); + if (!Value) + return ERROR_NOT_ENOUGH_MEMORY; + rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData); + if (rc != ERROR_SUCCESS) + { + HeapFree(GetProcessHeap(), 0, Value); + return rc; + } + /* NULL-terminate the string */ + Value[cbData / sizeof(WCHAR)] = '\0'; + + *pValue = Value; + return ERROR_SUCCESS; +} + + +BOOL +SetupIsActive(VOID) +{ + HKEY hKey = NULL; + DWORD regType, active, size; + LONG rc; + BOOL ret = FALSE; + + rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey); + if (rc != ERROR_SUCCESS) + goto cleanup; + + size = sizeof(DWORD); + rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, ®Type, (LPBYTE)&active, &size); + if (rc != ERROR_SUCCESS) + goto cleanup; + if (regType != REG_DWORD || size != sizeof(DWORD)) + goto cleanup; + + ret = (active != 0); + +cleanup: + if (hKey != NULL) + RegCloseKey(hKey); + + DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO"); + + return ret; +} + + +static BOOL +IsConsoleBoot(VOID) +{ + HKEY ControlKey = NULL; + LPWSTR SystemStartOptions = NULL; + LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */ + BOOL ConsoleBoot = FALSE; + LONG rc; + + rc = RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Control", + 0, + KEY_QUERY_VALUE, + &ControlKey); + + rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions); + if (rc != ERROR_SUCCESS) + goto cleanup; + + /* Check for CONSOLE switch in SystemStartOptions */ + CurrentOption = SystemStartOptions; + while (CurrentOption) + { + NextOption = wcschr(CurrentOption, L' '); + if (NextOption) + *NextOption = L'\0'; + if (_wcsicmp(CurrentOption, L"CONSOLE") == 0) + { + DPRINT("Found %S. Switching to console boot\n", CurrentOption); + ConsoleBoot = TRUE; + goto cleanup; + } + CurrentOption = NextOption ? NextOption + 1 : NULL; + } + +cleanup: + if (ControlKey != NULL) + RegCloseKey(ControlKey); + HeapFree(GetProcessHeap(), 0, SystemStartOptions); + return ConsoleBoot; +} + + +/* Loop to install all queued devices installations */ +DWORD +WINAPI +DeviceInstallThread(LPVOID lpParameter) +{ + PSLIST_ENTRY ListEntry; + DeviceInstallParams* Params; + BOOL showWizard; + + UNREFERENCED_PARAMETER(lpParameter); + + WaitForSingleObject(hInstallEvent, INFINITE); + + showWizard = !SetupIsActive() && !IsConsoleBoot(); + + while (TRUE) + { + ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead); + + if (ListEntry == NULL) + { + SetEvent(hNoPendingInstalls); + WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE); + } + else + { + ResetEvent(hNoPendingInstalls); + Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry); + InstallDevice(Params->DeviceIds, showWizard); + HeapFree(GetProcessHeap(), 0, Params); + } + } + + return 0; +} diff --git a/base/services/umpnpmgr/precomp.h b/base/services/umpnpmgr/precomp.h new file mode 100644 index 00000000000..3c51aa47b21 --- /dev/null +++ b/base/services/umpnpmgr/precomp.h @@ -0,0 +1,75 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: base/services/umpnpmgr/install.c + * PURPOSE: Device installer + * PROGRAMMER: Eric Kohl (eric.kohl@reactos.org) + * Hervé Poussineau (hpoussin@reactos.org) + * Colin Finck (colin@reactos.org) + */ + +#ifndef _UMPNPMGR_PCH_ +#define _UMPNPMGR_PCH_ + +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct +{ + SLIST_ENTRY ListEntry; + WCHAR DeviceIds[1]; +} DeviceInstallParams; + + +/* install.c */ + +extern HANDLE hUserToken; +extern HANDLE hInstallEvent; +extern HANDLE hNoPendingInstalls; + +extern SLIST_HEADER DeviceInstallListHead; +extern HANDLE hDeviceInstallListNotEmpty; + +BOOL +SetupIsActive(VOID); + +DWORD +WINAPI +DeviceInstallThread( + LPVOID lpParameter); + + +/* rpcserver.c */ + +DWORD +WINAPI +RpcServerThread( + LPVOID lpParameter); + + +/* umpnpmgr.c */ + +extern HKEY hEnumKey; +extern HKEY hClassKey; + + +#endif /* _UMPNPMGR_PCH_ */ \ No newline at end of file diff --git a/base/services/umpnpmgr/rpcserver.c b/base/services/umpnpmgr/rpcserver.c new file mode 100644 index 00000000000..2d0c02da95d --- /dev/null +++ b/base/services/umpnpmgr/rpcserver.c @@ -0,0 +1,3762 @@ +/* + * ReactOS kernel + * Copyright (C) 2005 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: base/services/umpnpmgr/rpcserver.c + * PURPOSE: RPC server + * PROGRAMMER: Eric Kohl (eric.kohl@reactos.org) + * Hervé Poussineau (hpoussin@reactos.org) + * Colin Finck (colin@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include "precomp.h" + +#define NDEBUG +#include + + +/* GLOBALS ******************************************************************/ + +static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0"; + + +/* FUNCTIONS *****************************************************************/ + +DWORD WINAPI +RpcServerThread(LPVOID lpParameter) +{ + RPC_STATUS Status; + BOOLEAN RegisteredProtSeq = FALSE; + + UNREFERENCED_PARAMETER(lpParameter); + + DPRINT("RpcServerThread() called\n"); + +#if 0 + /* 2k/XP/2k3-compatible protocol sequence/endpoint */ + Status = RpcServerUseProtseqEpW(L"ncacn_np", + 20, + L"\\pipe\\ntsvcs", + NULL); // Security descriptor + if (Status == RPC_S_OK) + RegisteredProtSeq = TRUE; + else + DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); +#endif + + /* Vista/7-compatible protocol sequence/endpoint */ + Status = RpcServerUseProtseqEpW(L"ncacn_np", + 20, + L"\\pipe\\plugplay", + NULL); // Security descriptor + if (Status == RPC_S_OK) + RegisteredProtSeq = TRUE; + else + DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); + + /* Make sure there's a usable endpoint */ + if (RegisteredProtSeq == FALSE) + return 0; + + Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec, + NULL, + NULL); + if (Status != RPC_S_OK) + { + DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status); + return 0; + } + + Status = RpcServerListen(1, + 20, + FALSE); + if (Status != RPC_S_OK) + { + DPRINT1("RpcServerListen() failed (Status %lx)\n", Status); + return 0; + } + + /* ROS HACK (this should never happen...) */ + DPRINT1("*** Other devices won't be installed correctly. If something\n"); + DPRINT1("*** doesn't work, try to reboot to get a new chance.\n"); + + DPRINT("RpcServerThread() done\n"); + + return 0; +} + + +void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len) +{ + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); +} + + +void __RPC_USER midl_user_free(void __RPC_FAR * ptr) +{ + HeapFree(GetProcessHeap(), 0, ptr); +} + + +static CONFIGRET WINAPI +NtStatusToCrError(NTSTATUS Status) +{ + switch (Status) + { + case STATUS_NOT_IMPLEMENTED: + return CR_CALL_NOT_IMPLEMENTED; + + case STATUS_INVALID_PARAMETER: + return CR_INVALID_DATA; + + case STATUS_NO_SUCH_DEVICE: + return CR_NO_SUCH_DEVINST; + + case STATUS_ACCESS_DENIED: + return CR_ACCESS_DENIED; + + case STATUS_BUFFER_TOO_SMALL: + return CR_BUFFER_SMALL; + + case STATUS_OBJECT_NAME_NOT_FOUND: + return CR_NO_SUCH_VALUE; + + default: + return CR_FAILURE; + } +} + + +static VOID +SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID, + OUT LPWSTR pszEnumerator, + OUT LPWSTR pszDevice, + OUT LPWSTR pszInstance) +{ + WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN]; + LPWSTR lpEnumerator = NULL; + LPWSTR lpDevice = NULL; + LPWSTR lpInstance = NULL; + LPWSTR ptr; + + wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID); + + *pszEnumerator = 0; + *pszDevice = 0; + *pszInstance = 0; + + lpEnumerator = szLocalDeviceInstanceID; + + ptr = wcschr(lpEnumerator, L'\\'); + if (ptr != NULL) + { + *ptr = 0; + lpDevice = ++ptr; + + ptr = wcschr(lpDevice, L'\\'); + if (ptr != NULL) + { + *ptr = 0; + lpInstance = ++ptr; + } + } + + if (lpEnumerator != NULL) + wcscpy(pszEnumerator, lpEnumerator); + + if (lpDevice != NULL) + wcscpy(pszDevice, lpDevice); + + if (lpInstance != NULL) + wcscpy(pszInstance, lpInstance); +} + + +/* PUBLIC FUNCTIONS **********************************************************/ + +/* Function 0 */ +DWORD +WINAPI +PNP_Disconnect( + handle_t hBinding) +{ + UNREFERENCED_PARAMETER(hBinding); + return CR_SUCCESS; +} + + +/* Function 1 */ +DWORD +WINAPI +PNP_Connect( + handle_t hBinding) +{ + UNREFERENCED_PARAMETER(hBinding); + return CR_SUCCESS; +} + + +/* Function 2 */ +DWORD +WINAPI +PNP_GetVersion( + handle_t hBinding, + WORD *pVersion) +{ + UNREFERENCED_PARAMETER(hBinding); + + *pVersion = 0x0400; + return CR_SUCCESS; +} + + +/* Function 3 */ +DWORD +WINAPI +PNP_GetGlobalState( + handle_t hBinding, + DWORD *pulState, + DWORD ulFlags) +{ + UNREFERENCED_PARAMETER(hBinding); + UNREFERENCED_PARAMETER(ulFlags); + + *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE; + return CR_SUCCESS; +} + + +/* Function 4 */ +DWORD +WINAPI +PNP_InitDetection( + handle_t hBinding) +{ + UNREFERENCED_PARAMETER(hBinding); + + DPRINT("PNP_InitDetection() called\n"); + return CR_SUCCESS; +} + + +/* Function 5 */ +DWORD +WINAPI +PNP_ReportLogOn( + handle_t hBinding, + BOOL Admin, + DWORD ProcessId) +{ + DWORD ReturnValue = CR_FAILURE; + HANDLE hProcess; + + UNREFERENCED_PARAMETER(hBinding); + UNREFERENCED_PARAMETER(Admin); + + DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin, ProcessId); + + /* Get the users token */ + hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId); + + if (!hProcess) + { + DPRINT1("OpenProcess failed with error %u\n", GetLastError()); + goto cleanup; + } + + if (hUserToken) + { + CloseHandle(hUserToken); + hUserToken = NULL; + } + + if (!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken)) + { + DPRINT1("OpenProcessToken failed with error %u\n", GetLastError()); + goto cleanup; + } + + /* Trigger the installer thread */ + if (hInstallEvent) + SetEvent(hInstallEvent); + + ReturnValue = CR_SUCCESS; + +cleanup: + if (hProcess) + CloseHandle(hProcess); + + return ReturnValue; +} + + +/* Function 6 */ +DWORD +WINAPI +PNP_ValidateDeviceInstance( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulFlags) +{ + CONFIGRET ret = CR_SUCCESS; + HKEY hDeviceKey = NULL; + + UNREFERENCED_PARAMETER(hBinding); + UNREFERENCED_PARAMETER(ulFlags); + + DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n", + pDeviceID, ulFlags); + + if (RegOpenKeyExW(hEnumKey, + pDeviceID, + 0, + KEY_READ, + &hDeviceKey)) + { + DPRINT("Could not open the Device Key!\n"); + ret = CR_NO_SUCH_DEVNODE; + goto Done; + } + + /* FIXME: add more tests */ + +Done: + if (hDeviceKey != NULL) + RegCloseKey(hDeviceKey); + + DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret); + + return ret; +} + + +/* Function 7 */ +DWORD +WINAPI +PNP_GetRootDeviceInstance( + handle_t hBinding, + LPWSTR pDeviceID, + PNP_RPC_STRING_LEN ulLength) +{ + CONFIGRET ret = CR_SUCCESS; + + UNREFERENCED_PARAMETER(hBinding); + + DPRINT("PNP_GetRootDeviceInstance() called\n"); + + if (!pDeviceID) + { + ret = CR_INVALID_POINTER; + goto Done; + } + if (ulLength < lstrlenW(szRootDeviceId) + 1) + { + ret = CR_BUFFER_SMALL; + goto Done; + } + + lstrcpyW(pDeviceID, + szRootDeviceId); + +Done: + DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret); + + return ret; +} + + +/* Function 8 */ +DWORD +WINAPI +PNP_GetRelatedDeviceInstance( + handle_t hBinding, + DWORD ulRelationship, + LPWSTR pDeviceID, + LPWSTR pRelatedDeviceId, + PNP_RPC_STRING_LEN *pulLength, + DWORD ulFlags) +{ + PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData; + CONFIGRET ret = CR_SUCCESS; + NTSTATUS Status; + + UNREFERENCED_PARAMETER(hBinding); + UNREFERENCED_PARAMETER(ulFlags); + + DPRINT("PNP_GetRelatedDeviceInstance() called\n"); + DPRINT(" Relationship %ld\n", ulRelationship); + DPRINT(" DeviceId %S\n", pDeviceID); + + RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance, + pDeviceID); + + PlugPlayData.Relation = ulRelationship; + + PlugPlayData.RelatedDeviceInstanceLength = *pulLength; + PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId; + + Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice, + (PVOID)&PlugPlayData, + sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA)); + if (!NT_SUCCESS(Status)) + { + ret = NtStatusToCrError(Status); + } + + DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret); + if (ret == CR_SUCCESS) + { + DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance); + } + + return ret; +} + + +/* Function 9 */ +DWORD +WINAPI +PNP_EnumerateSubKeys( + handle_t hBinding, + DWORD ulBranch, + DWORD ulIndex, + LPWSTR Buffer, + PNP_RPC_STRING_LEN ulLength, + PNP_RPC_STRING_LEN *pulRequiredLen, + DWORD ulFlags) +{ + CONFIGRET ret = CR_SUCCESS; + HKEY hKey; + DWORD dwError; + + UNREFERENCED_PARAMETER(hBinding); + UNREFERENCED_PARAMETER(ulFlags); + + DPRINT("PNP_EnumerateSubKeys() called\n"); + + switch (ulBranch) + { + case PNP_ENUMERATOR_SUBKEYS: + hKey = hEnumKey; + break; + + case PNP_CLASS_SUBKEYS: + hKey = hClassKey; + break; + + default: + return CR_FAILURE; + } + + *pulRequiredLen = ulLength; + dwError = RegEnumKeyExW(hKey, + ulIndex, + Buffer, + pulRequiredLen, + NULL, + NULL, + NULL, + NULL); + if (dwError != ERROR_SUCCESS) + { + ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE; + } + else + { + (*pulRequiredLen)++; + } + + DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret); + + return ret; +} + + +static +CONFIGRET +GetRelationsInstanceList( + _In_ PWSTR pszDevice, + _In_ DWORD ulFlags, + _Inout_ PWSTR pszBuffer, + _Inout_ PDWORD pulLength) +{ + PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData; + NTSTATUS Status; + CONFIGRET ret = CR_SUCCESS; + + RtlInitUnicodeString(&PlugPlayData.DeviceInstance, + pszDevice); + + if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS) + { + PlugPlayData.Relations = 3; + } + else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS) + { + PlugPlayData.Relations = 2; + } + else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS) + { + PlugPlayData.Relations = 1; + } + else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS) + { + PlugPlayData.Relations = 0; + } + + PlugPlayData.BufferSize = *pulLength * sizeof(WCHAR); + PlugPlayData.Buffer = pszBuffer; + + Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations, + (PVOID)&PlugPlayData, + sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA)); + if (NT_SUCCESS(Status)) + { + *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR); + } + else + { + ret = NtStatusToCrError(Status); + } + + return ret; +} + + +static +CONFIGRET +GetServiceInstanceList( + _In_ PWSTR pszService, + _Inout_ PWSTR pszBuffer, + _Inout_ PDWORD pulLength) +{ + WCHAR szPathBuffer[512]; + WCHAR szName[16]; + HKEY hServicesKey = NULL, hServiceKey = NULL, hEnumKey = NULL; + DWORD dwValues, dwSize, dwIndex, dwUsedLength, dwPathLength; + DWORD dwError; + PWSTR pPtr; + CONFIGRET ret = CR_SUCCESS; + + /* Open the device key */ + dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"System\\CurrentControlSet\\Services", + 0, + KEY_READ, + &hServicesKey); + if (dwError != ERROR_SUCCESS) + { + DPRINT("Failed to open the services key (Error %lu)\n", dwError); + return CR_REGISTRY_ERROR; + } + + dwError = RegOpenKeyExW(hServicesKey, + pszService, + 0, + KEY_READ, + &hServiceKey); + if (dwError != ERROR_SUCCESS) + { + DPRINT("Failed to open the service key (Error %lu)\n", dwError); + ret = CR_REGISTRY_ERROR; + goto Done; + } + + dwError = RegOpenKeyExW(hServiceKey, + L"Enum", + 0, + KEY_READ, + &hEnumKey); + if (dwError != ERROR_SUCCESS) + { + DPRINT("Failed to open the service enum key (Error %lu)\n", dwError); + ret = CR_REGISTRY_ERROR; + goto Done; + } + + /* Retrieve the number of device instances */ + dwSize = sizeof(DWORD); + dwError = RegQueryValueExW(hEnumKey, + L"Count", + NULL, + NULL, + (LPBYTE)&dwValues, + &dwSize); + if (dwError != ERROR_SUCCESS) + { + DPRINT("RegQueryValueExW failed (Error %lu)\n", dwError); + dwValues = 1; + } + + DPRINT("dwValues %lu\n", dwValues); + + dwUsedLength = 0; + pPtr = pszBuffer; + + for (dwIndex = 0; dwIndex < dwValues; dwIndex++) + { + wsprintf(szName, L"%lu", dwIndex); + + dwSize = sizeof(szPathBuffer); + dwError = RegQueryValueExW(hEnumKey, + szName, + NULL, + NULL, + (LPBYTE)szPathBuffer, + &dwSize); + if (dwError != ERROR_SUCCESS) + break; + + DPRINT("Path: %S\n", szPathBuffer); + + dwPathLength = wcslen(szPathBuffer) + 1; + if (dwUsedLength + dwPathLength + 1 > *pulLength) + { + ret = CR_BUFFER_SMALL; + break; + } + + wcscpy(pPtr, szPathBuffer); + dwUsedLength += dwPathLength; + pPtr += dwPathLength; + + *pPtr = UNICODE_NULL; + } + +Done: + if (hEnumKey != NULL) + RegCloseKey(hEnumKey); + + if (hServiceKey != NULL) + RegCloseKey(hServiceKey); + + if (hServicesKey != NULL) + RegCloseKey(hServicesKey); + + if (ret == CR_SUCCESS) + *pulLength = dwUsedLength + 1; + else + *pulLength = 0; + + return ret; +} + + +static +CONFIGRET +GetDeviceInstanceList( + _In_ PWSTR pszDevice, + _Inout_ PWSTR pszBuffer, + _Inout_ PDWORD pulLength) +{ + WCHAR szInstanceBuffer[MAX_DEVICE_ID_LEN]; + WCHAR szPathBuffer[512]; + HKEY hDeviceKey; + DWORD dwInstanceLength, dwPathLength, dwUsedLength; + DWORD dwIndex, dwError; + PWSTR pPtr; + CONFIGRET ret = CR_SUCCESS; + + /* Open the device key */ + dwError = RegOpenKeyExW(hEnumKey, + pszDevice, + 0, + KEY_ENUMERATE_SUB_KEYS, + &hDeviceKey); + if (dwError != ERROR_SUCCESS) + { + DPRINT("Failed to open the device key (Error %lu)\n", dwError); + return CR_REGISTRY_ERROR; + } + + dwUsedLength = 0; + pPtr = pszBuffer; + + for (dwIndex = 0; ; dwIndex++) + { + dwInstanceLength = MAX_DEVICE_ID_LEN; + dwError = RegEnumKeyExW(hDeviceKey, + dwIndex, + szInstanceBuffer, + &dwInstanceLength, + NULL, + NULL, + NULL, + NULL); + if (dwError != ERROR_SUCCESS) + break; + + wsprintf(szPathBuffer, L"%s\\%s", pszDevice, szInstanceBuffer); + DPRINT("Path: %S\n", szPathBuffer); + + dwPathLength = wcslen(szPathBuffer) + 1; + if (dwUsedLength + dwPathLength + 1 > *pulLength) + { + ret = CR_BUFFER_SMALL; + break; + } + + wcscpy(pPtr, szPathBuffer); + dwUsedLength += dwPathLength; + pPtr += dwPathLength; + + *pPtr = UNICODE_NULL; + } + + RegCloseKey(hDeviceKey); + + if (ret == CR_SUCCESS) + *pulLength = dwUsedLength + 1; + else + *pulLength = 0; + + return ret; +} + + +CONFIGRET +GetEnumeratorInstanceList( + _In_ PWSTR pszEnumerator, + _Inout_ PWSTR pszBuffer, + _Inout_ PDWORD pulLength) +{ + WCHAR szDeviceBuffer[MAX_DEVICE_ID_LEN]; + WCHAR szPathBuffer[512]; + HKEY hEnumeratorKey; + PWSTR pPtr; + DWORD dwIndex, dwDeviceLength, dwUsedLength, dwRemainingLength, dwPathLength; + DWORD dwError; + CONFIGRET ret = CR_SUCCESS; + + /* Open the enumerator key */ + dwError = RegOpenKeyExW(hEnumKey, + pszEnumerator, + 0, + KEY_ENUMERATE_SUB_KEYS, + &hEnumeratorKey); + if (dwError != ERROR_SUCCESS) + { + DPRINT("Failed to open the enumerator key (Error %lu)\n", dwError); + return CR_REGISTRY_ERROR; + } + + dwUsedLength = 0; + dwRemainingLength = *pulLength; + pPtr = pszBuffer; + + for (dwIndex = 0; ; dwIndex++) + { + dwDeviceLength = MAX_DEVICE_ID_LEN; + dwError = RegEnumKeyExW(hEnumeratorKey, + dwIndex, + szDeviceBuffer, + &dwDeviceLength, + NULL, + NULL, + NULL, + NULL); + if (dwError != ERROR_SUCCESS) + break; + + wsprintf(szPathBuffer, L"%s\\%s", pszEnumerator, szDeviceBuffer); + DPRINT("Path: %S\n", szPathBuffer); + + dwPathLength = dwRemainingLength; + ret = GetDeviceInstanceList(szPathBuffer, + pPtr, + &dwPathLength); + if (ret != CR_SUCCESS) + break; + + dwUsedLength += dwPathLength - 1; + dwRemainingLength += dwPathLength - 1; + pPtr += dwPathLength - 1; + } + + RegCloseKey(hEnumeratorKey); + + if (ret == CR_SUCCESS) + *pulLength = dwUsedLength + 1; + else + *pulLength = 0; + + return ret; +} + + +static +CONFIGRET +GetAllInstanceList( + _Inout_ PWSTR pszBuffer, + _Inout_ PDWORD pulLength) +{ + WCHAR szEnumeratorBuffer[MAX_DEVICE_ID_LEN]; + PWSTR pPtr; + DWORD dwIndex, dwEnumeratorLength, dwUsedLength, dwRemainingLength, dwPathLength; + DWORD dwError; + CONFIGRET ret = CR_SUCCESS; + + dwUsedLength = 0; + dwRemainingLength = *pulLength; + pPtr = pszBuffer; + + for (dwIndex = 0; ; dwIndex++) + { + dwEnumeratorLength = MAX_DEVICE_ID_LEN; + dwError = RegEnumKeyExW(hEnumKey, + dwIndex, + szEnumeratorBuffer, + &dwEnumeratorLength, + NULL, NULL, NULL, NULL); + if (dwError != ERROR_SUCCESS) + break; + + dwPathLength = dwRemainingLength; + ret = GetEnumeratorInstanceList(szEnumeratorBuffer, + pPtr, + &dwPathLength); + if (ret != CR_SUCCESS) + break; + + dwUsedLength += dwPathLength - 1; + dwRemainingLength += dwPathLength - 1; + pPtr += dwPathLength - 1; + } + + if (ret == CR_SUCCESS) + *pulLength = dwUsedLength + 1; + else + *pulLength = 0; + + return ret; +} + + +/* Function 10 */ +DWORD +WINAPI +PNP_GetDeviceList( + handle_t hBinding, + LPWSTR pszFilter, + LPWSTR Buffer, + PNP_RPC_STRING_LEN *pulLength, + DWORD ulFlags) +{ + WCHAR szEnumerator[MAX_DEVICE_ID_LEN]; + WCHAR szDevice[MAX_DEVICE_ID_LEN]; + WCHAR szInstance[MAX_DEVICE_ID_LEN]; + CONFIGRET ret = CR_SUCCESS; + + DPRINT("PNP_GetDeviceList() called\n"); + + if (ulFlags & ~CM_GETIDLIST_FILTER_BITS) + return CR_INVALID_FLAG; + + if (pulLength == NULL) + return CR_INVALID_POINTER; + + if ((ulFlags != CM_GETIDLIST_FILTER_NONE) && + (pszFilter == NULL)) + return CR_INVALID_POINTER; + + if (ulFlags & + (CM_GETIDLIST_FILTER_BUSRELATIONS | + CM_GETIDLIST_FILTER_POWERRELATIONS | + CM_GETIDLIST_FILTER_REMOVALRELATIONS | + CM_GETIDLIST_FILTER_EJECTRELATIONS)) + { + ret = GetRelationsInstanceList(pszFilter, + ulFlags, + Buffer, + pulLength); + } + else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE) + { + ret = GetServiceInstanceList(pszFilter, + Buffer, + pulLength); + } + else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR) + { + SplitDeviceInstanceID(pszFilter, + szEnumerator, + szDevice, + szInstance); + + if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL) + { + ret = GetDeviceInstanceList(pszFilter, + Buffer, + pulLength); + } + else + { + ret = GetEnumeratorInstanceList(pszFilter, + Buffer, + pulLength); + } + } + else /* CM_GETIDLIST_FILTER_NONE */ + { + ret = GetAllInstanceList(Buffer, + pulLength); + } + + return ret; +} + + +static +CONFIGRET +GetRelationsInstanceListSize( + _In_ PWSTR pszDevice, + _In_ DWORD ulFlags, + _Inout_ PDWORD pulLength) +{ + PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData; + NTSTATUS Status; + CONFIGRET ret = CR_SUCCESS; + + RtlInitUnicodeString(&PlugPlayData.DeviceInstance, + pszDevice); + + if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS) + { + PlugPlayData.Relations = 3; + } + else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS) + { + PlugPlayData.Relations = 2; + } + else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS) + { + PlugPlayData.Relations = 1; + } + else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS) + { + PlugPlayData.Relations = 0; + } + + PlugPlayData.BufferSize = 0; + PlugPlayData.Buffer = NULL; + + Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations, + (PVOID)&PlugPlayData, + sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA)); + if (NT_SUCCESS(Status)) + { + *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR); + } + else + { + ret = NtStatusToCrError(Status); + } + + return ret; +} + + +static +CONFIGRET +GetServiceInstanceListSize( + _In_ PWSTR pszService, + _Out_ PDWORD pulLength) +{ + HKEY hServicesKey = NULL, hServiceKey = NULL, hEnumKey = NULL; + DWORD dwValues, dwMaxValueLength, dwSize; + DWORD dwError; + CONFIGRET ret = CR_SUCCESS; + + /* Open the device key */ + dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"System\\CurrentControlSet\\Services", + 0, + KEY_READ, + &hServicesKey); + if (dwError != ERROR_SUCCESS) + { + DPRINT("Failed to open the services key (Error %lu)\n", dwError); + return CR_REGISTRY_ERROR; + } + + dwError = RegOpenKeyExW(hServicesKey, + pszService, + 0, + KEY_READ, + &hServiceKey); + if (dwError != ERROR_SUCCESS) + { + DPRINT("Failed to open the service key (Error %lu)\n", dwError); + ret = CR_REGISTRY_ERROR; + goto Done; + } + + dwError = RegOpenKeyExW(hServiceKey, + L"Enum", + 0, + KEY_READ, + &hEnumKey); + if (dwError != ERROR_SUCCESS) + { + DPRINT("Failed to open the service enum key (Error %lu)\n", dwError); + ret = CR_REGISTRY_ERROR; + goto Done; + } + + /* Retrieve the number of device instances */ + dwSize = sizeof(DWORD); + dwError = RegQueryValueExW(hEnumKey, + L"Count", + NULL, + NULL, + (LPBYTE)&dwValues, + &dwSize); + if (dwError != ERROR_SUCCESS) + { + DPRINT("RegQueryValueExW failed (Error %lu)\n", dwError); + dwValues = 1; + } + + /* Retrieve the maximum instance name length */ + dwError = RegQueryInfoKeyW(hEnumKey, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &dwMaxValueLength, + NULL, + NULL); + if (dwError != ERROR_SUCCESS) + { + DPRINT("RegQueryInfoKeyW failed (Error %lu)\n", dwError); + dwMaxValueLength = MAX_DEVICE_ID_LEN; + } + + DPRINT("dwValues %lu dwMaxValueLength %lu\n", dwValues, dwMaxValueLength / sizeof(WCHAR)); + + /* Return the largest possible buffer size */ + *pulLength = dwValues * dwMaxValueLength / sizeof(WCHAR) + 2; + +Done: + if (hEnumKey != NULL) + RegCloseKey(hEnumKey); + + if (hServiceKey != NULL) + RegCloseKey(hServiceKey); + + if (hServicesKey != NULL) + RegCloseKey(hServicesKey); + + return ret; +} + + +static +CONFIGRET +GetDeviceInstanceListSize( + _In_ LPCWSTR pszDevice, + _Out_ PULONG pulLength) +{ + HKEY hDeviceKey; + DWORD dwSubKeys, dwMaxSubKeyLength; + DWORD dwError; + + /* Open the device key */ + dwError = RegOpenKeyExW(hEnumKey, + pszDevice, + 0, + KEY_READ, + &hDeviceKey); + if (dwError != ERROR_SUCCESS) + { + DPRINT("Failed to open the device key (Error %lu)\n", dwError); + return CR_REGISTRY_ERROR; + } + + /* Retrieve the number of device instances and the maximum name length */ + dwError = RegQueryInfoKeyW(hDeviceKey, + NULL, + NULL, + NULL, + &dwSubKeys, + &dwMaxSubKeyLength, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL); + if (dwError != ERROR_SUCCESS) + { + DPRINT("RegQueryInfoKeyW failed (Error %lu)\n", dwError); + dwSubKeys = 0; + dwMaxSubKeyLength = 0; + } + + /* Close the device key */ + RegCloseKey(hDeviceKey); + + /* Return the largest possible buffer size */ + *pulLength = dwSubKeys * (wcslen(pszDevice) + 1 + dwMaxSubKeyLength + 1); + + return CR_SUCCESS; +} + + +static +CONFIGRET +GetEnumeratorInstanceListSize( + _In_ LPCWSTR pszEnumerator, + _Out_ PULONG pulLength) +{ + WCHAR szDeviceBuffer[MAX_DEVICE_ID_LEN]; + WCHAR szPathBuffer[512]; + HKEY hEnumeratorKey; + DWORD dwIndex, dwDeviceLength, dwBufferLength; + DWORD dwError; + CONFIGRET ret = CR_SUCCESS; + + *pulLength = 0; + + /* Open the enumerator key */ + dwError = RegOpenKeyExW(hEnumKey, + pszEnumerator, + 0, + KEY_ENUMERATE_SUB_KEYS, + &hEnumeratorKey); + if (dwError != ERROR_SUCCESS) + { + DPRINT("Failed to open the enumerator key (Error %lu)\n", dwError); + return CR_REGISTRY_ERROR; + } + + for (dwIndex = 0; ; dwIndex++) + { + dwDeviceLength = MAX_DEVICE_ID_LEN; + dwError = RegEnumKeyExW(hEnumeratorKey, + dwIndex, + szDeviceBuffer, + &dwDeviceLength, + NULL, + NULL, + NULL, + NULL); + if (dwError != ERROR_SUCCESS) + break; + + wsprintf(szPathBuffer, L"%s\\%s", pszEnumerator, szDeviceBuffer); + DPRINT("Path: %S\n", szPathBuffer); + + ret = GetDeviceInstanceListSize(szPathBuffer, &dwBufferLength); + if (ret != CR_SUCCESS) + { + *pulLength = 0; + break; + } + + *pulLength += dwBufferLength; + } + + /* Close the enumerator key */ + RegCloseKey(hEnumeratorKey); + + return ret; +} + + +static +CONFIGRET +GetAllInstanceListSize( + _Out_ PULONG pulLength) +{ + WCHAR szEnumeratorBuffer[MAX_DEVICE_ID_LEN]; + DWORD dwIndex, dwEnumeratorLength, dwBufferLength; + DWORD dwError; + CONFIGRET ret = CR_SUCCESS; + + for (dwIndex = 0; ; dwIndex++) + { + dwEnumeratorLength = MAX_DEVICE_ID_LEN; + dwError = RegEnumKeyExW(hEnumKey, + dwIndex, + szEnumeratorBuffer, + &dwEnumeratorLength, + NULL, NULL, NULL, NULL); + if (dwError != ERROR_SUCCESS) + break; + + /* Get the size of all device instances for the enumerator */ + ret = GetEnumeratorInstanceListSize(szEnumeratorBuffer, + &dwBufferLength); + if (ret != CR_SUCCESS) + break; + + *pulLength += dwBufferLength; + } + + return ret; +} + + +/* Function 11 */ +DWORD +WINAPI +PNP_GetDeviceListSize( + handle_t hBinding, + LPWSTR pszFilter, + PNP_RPC_BUFFER_SIZE *pulLength, + DWORD ulFlags) +{ + WCHAR szEnumerator[MAX_DEVICE_ID_LEN]; + WCHAR szDevice[MAX_DEVICE_ID_LEN]; + WCHAR szInstance[MAX_DEVICE_ID_LEN]; + CONFIGRET ret = CR_SUCCESS; + + DPRINT("PNP_GetDeviceListSize(%p %S %p 0x%lx)\n", + hBinding, pszFilter, pulLength, ulFlags); + + if (ulFlags & ~CM_GETIDLIST_FILTER_BITS) + return CR_INVALID_FLAG; + + if (pulLength == NULL) + return CR_INVALID_POINTER; + + if ((ulFlags != CM_GETIDLIST_FILTER_NONE) && + (pszFilter == NULL)) + return CR_INVALID_POINTER; + + *pulLength = 0; + + if (ulFlags & + (CM_GETIDLIST_FILTER_BUSRELATIONS | + CM_GETIDLIST_FILTER_POWERRELATIONS | + CM_GETIDLIST_FILTER_REMOVALRELATIONS | + CM_GETIDLIST_FILTER_EJECTRELATIONS)) + { + ret = GetRelationsInstanceListSize(pszFilter, + ulFlags, + pulLength); + } + else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE) + { + ret = GetServiceInstanceListSize(pszFilter, + pulLength); + } + else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR) + { + SplitDeviceInstanceID(pszFilter, + szEnumerator, + szDevice, + szInstance); + + if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL) + { + ret = GetDeviceInstanceListSize(pszFilter, + pulLength); + } + else + { + ret = GetEnumeratorInstanceListSize(pszFilter, + pulLength); + } + } + else /* CM_GETIDLIST_FILTER_NONE */ + { + ret = GetAllInstanceListSize(pulLength); + } + + /* Add one character for the terminating double UNICODE_NULL */ + if (ret == CR_SUCCESS) + (*pulLength) += 1; + + return ret; +} + + +/* Function 12 */ +DWORD +WINAPI +PNP_GetDepth( + handle_t hBinding, + LPWSTR pszDeviceID, + DWORD *pulDepth, + DWORD ulFlags) +{ + PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData; + CONFIGRET ret = CR_SUCCESS; + NTSTATUS Status; + + UNREFERENCED_PARAMETER(hBinding); + UNREFERENCED_PARAMETER(ulFlags); + + DPRINT("PNP_GetDepth() called\n"); + + RtlInitUnicodeString(&PlugPlayData.DeviceInstance, + pszDeviceID); + + Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth, + (PVOID)&PlugPlayData, + sizeof(PLUGPLAY_CONTROL_DEPTH_DATA)); + if (NT_SUCCESS(Status)) + { + *pulDepth = PlugPlayData.Depth; + } + else + { + ret = NtStatusToCrError(Status); + } + + DPRINT("PNP_GetDepth() done (returns %lx)\n", ret); + + return ret; +} + + +/* Function 13 */ +DWORD +WINAPI +PNP_GetDeviceRegProp( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulProperty, + DWORD *pulRegDataType, + BYTE *Buffer, + PNP_PROP_SIZE *pulTransferLen, + PNP_PROP_SIZE *pulLength, + DWORD ulFlags) +{ + PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData; + CONFIGRET ret = CR_SUCCESS; + LPWSTR lpValueName = NULL; + HKEY hKey = NULL; + LONG lError; + NTSTATUS Status; + + UNREFERENCED_PARAMETER(hBinding); + + DPRINT("PNP_GetDeviceRegProp() called\n"); + + if (pulTransferLen == NULL || pulLength == NULL) + { + ret = CR_INVALID_POINTER; + goto done; + } + + if (ulFlags != 0) + { + ret = CR_INVALID_FLAG; + goto done; + } + + /* FIXME: Check pDeviceID */ + + if (*pulLength < *pulTransferLen) + *pulLength = *pulTransferLen; + + *pulTransferLen = 0; + + switch (ulProperty) + { + case CM_DRP_DEVICEDESC: + lpValueName = L"DeviceDesc"; + break; + + case CM_DRP_HARDWAREID: + lpValueName = L"HardwareID"; + break; + + case CM_DRP_COMPATIBLEIDS: + lpValueName = L"CompatibleIDs"; + break; + + case CM_DRP_SERVICE: + lpValueName = L"Service"; + break; + + case CM_DRP_CLASS: + lpValueName = L"Class"; + break; + + case CM_DRP_CLASSGUID: + lpValueName = L"ClassGUID"; + break; + + case CM_DRP_DRIVER: + lpValueName = L"Driver"; + break; + + case CM_DRP_CONFIGFLAGS: + lpValueName = L"ConfigFlags"; + break; + + case CM_DRP_MFG: + lpValueName = L"Mfg"; + break; + + case CM_DRP_FRIENDLYNAME: + lpValueName = L"FriendlyName"; + break; + + case CM_DRP_LOCATION_INFORMATION: + lpValueName = L"LocationInformation"; + break; + + case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME: + PlugPlayData.Property = PNP_PROPERTY_PHYSICAL_DEVICE_OBJECT_NAME; + break; + + case CM_DRP_CAPABILITIES: + lpValueName = L"Capabilities"; + break; + + case CM_DRP_UI_NUMBER: + PlugPlayData.Property = PNP_PROPERTY_UI_NUMBER; + break; + + case CM_DRP_UPPERFILTERS: + lpValueName = L"UpperFilters"; + break; + + case CM_DRP_LOWERFILTERS: + lpValueName = L"LowerFilters"; + break; + + case CM_DRP_BUSTYPEGUID: + PlugPlayData.Property = PNP_PROPERTY_BUSTYPEGUID; + break; + + case CM_DRP_LEGACYBUSTYPE: + PlugPlayData.Property = PNP_PROPERTY_LEGACYBUSTYPE; + break; + + case CM_DRP_BUSNUMBER: + PlugPlayData.Property = PNP_PROPERTY_BUSNUMBER; + break; + + case CM_DRP_ENUMERATOR_NAME: + PlugPlayData.Property = PNP_PROPERTY_ENUMERATOR_NAME; + break; + + case CM_DRP_SECURITY: + lpValueName = L"Security"; + break; + + case CM_DRP_DEVTYPE: + lpValueName = L"DeviceType"; + break; + + case CM_DRP_EXCLUSIVE: + lpValueName = L"Exclusive"; + break; + + case CM_DRP_CHARACTERISTICS: + lpValueName = L"DeviceCharacteristics"; + break; + + case CM_DRP_ADDRESS: + PlugPlayData.Property = PNP_PROPERTY_ADDRESS; + break; + + case CM_DRP_UI_NUMBER_DESC_FORMAT: + lpValueName = L"UINumberDescFormat"; + break; + + case CM_DRP_DEVICE_POWER_DATA: + PlugPlayData.Property = PNP_PROPERTY_POWER_DATA; + break; + + case CM_DRP_REMOVAL_POLICY: + PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY; + break; + + case CM_DRP_REMOVAL_POLICY_HW_DEFAULT: + PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY_HARDWARE_DEFAULT; + break; + + case CM_DRP_REMOVAL_POLICY_OVERRIDE: + lpValueName = L"RemovalPolicy"; + break; + + case CM_DRP_INSTALL_STATE: + PlugPlayData.Property = PNP_PROPERTY_INSTALL_STATE; + break; + +#if (WINVER >= _WIN32_WINNT_WS03) + case CM_DRP_LOCATION_PATHS: + PlugPlayData.Property = PNP_PROPERTY_LOCATION_PATHS; + break; +#endif + +#if (WINVER >= _WIN32_WINNT_WIN7) + case CM_DRP_BASE_CONTAINERID: + PlugPlayData.Property = PNP_PROPERTY_CONTAINERID; + break; +#endif + + default: + ret = CR_INVALID_PROPERTY; + goto done; + } + + DPRINT("Value name: %S\n", lpValueName); + + if (lpValueName) + { + /* Retrieve information from the Registry */ + lError = RegOpenKeyExW(hEnumKey, + pDeviceID, + 0, + KEY_QUERY_VALUE, + &hKey); + if (lError != ERROR_SUCCESS) + { + hKey = NULL; + *pulLength = 0; + ret = CR_INVALID_DEVNODE; + goto done; + } + + lError = RegQueryValueExW(hKey, + lpValueName, + NULL, + pulRegDataType, + Buffer, + pulLength); + if (lError != ERROR_SUCCESS) + { + if (lError == ERROR_MORE_DATA) + { + ret = CR_BUFFER_SMALL; + } + else + { + *pulLength = 0; + ret = CR_NO_SUCH_VALUE; + } + } + } + else + { + /* Retrieve information from the Device Node */ + RtlInitUnicodeString(&PlugPlayData.DeviceInstance, + pDeviceID); + PlugPlayData.Buffer = Buffer; + PlugPlayData.BufferSize = *pulLength; + + Status = NtPlugPlayControl(PlugPlayControlProperty, + (PVOID)&PlugPlayData, + sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA)); + if (NT_SUCCESS(Status)) + { + *pulLength = PlugPlayData.BufferSize; + } + else + { + ret = NtStatusToCrError(Status); + } + } + +done: + if (pulTransferLen) + *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0; + + if (hKey != NULL) + RegCloseKey(hKey); + + DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret); + + return ret; +} + + +/* Function 14 */ +DWORD +WINAPI +PNP_SetDeviceRegProp( + handle_t hBinding, + LPWSTR pDeviceId, + DWORD ulProperty, + DWORD ulDataType, + BYTE *Buffer, + PNP_PROP_SIZE ulLength, + DWORD ulFlags) +{ + CONFIGRET ret = CR_SUCCESS; + LPWSTR lpValueName = NULL; + HKEY hKey = 0; + + UNREFERENCED_PARAMETER(hBinding); + UNREFERENCED_PARAMETER(ulFlags); + + DPRINT("PNP_SetDeviceRegProp() called\n"); + + DPRINT("DeviceId: %S\n", pDeviceId); + DPRINT("Property: %lu\n", ulProperty); + DPRINT("DataType: %lu\n", ulDataType); + DPRINT("Length: %lu\n", ulLength); + + switch (ulProperty) + { + case CM_DRP_DEVICEDESC: + lpValueName = L"DeviceDesc"; + break; + + case CM_DRP_HARDWAREID: + lpValueName = L"HardwareID"; + break; + + case CM_DRP_COMPATIBLEIDS: + lpValueName = L"CompatibleIDs"; + break; + + case CM_DRP_SERVICE: + lpValueName = L"Service"; + break; + + case CM_DRP_CLASS: + lpValueName = L"Class"; + break; + + case CM_DRP_CLASSGUID: + lpValueName = L"ClassGUID"; + break; + + case CM_DRP_DRIVER: + lpValueName = L"Driver"; + break; + + case CM_DRP_CONFIGFLAGS: + lpValueName = L"ConfigFlags"; + break; + + case CM_DRP_MFG: + lpValueName = L"Mfg"; + break; + + case CM_DRP_FRIENDLYNAME: + lpValueName = L"FriendlyName"; + break; + + case CM_DRP_LOCATION_INFORMATION: + lpValueName = L"LocationInformation"; + break; + + case CM_DRP_UPPERFILTERS: + lpValueName = L"UpperFilters"; + break; + + case CM_DRP_LOWERFILTERS: + lpValueName = L"LowerFilters"; + break; + + case CM_DRP_SECURITY: + lpValueName = L"Security"; + break; + + case CM_DRP_DEVTYPE: + lpValueName = L"DeviceType"; + break; + + case CM_DRP_EXCLUSIVE: + lpValueName = L"Exclusive"; + break; + + case CM_DRP_CHARACTERISTICS: + lpValueName = L"DeviceCharacteristics"; + break; + + case CM_DRP_UI_NUMBER_DESC_FORMAT: + lpValueName = L"UINumberDescFormat"; + break; + + case CM_DRP_REMOVAL_POLICY_OVERRIDE: + lpValueName = L"RemovalPolicy"; + break; + + default: + return CR_INVALID_PROPERTY; + } + + DPRINT("Value name: %S\n", lpValueName); + + if (RegOpenKeyExW(hEnumKey, + pDeviceId, + 0, + KEY_SET_VALUE, + &hKey)) + return CR_INVALID_DEVNODE; + + if (ulLength == 0) + { + if (RegDeleteValueW(hKey, + lpValueName)) + ret = CR_REGISTRY_ERROR; + } + else + { + if (RegSetValueExW(hKey, + lpValueName, + 0, + ulDataType, + Buffer, + ulLength)) + ret = CR_REGISTRY_ERROR; + } + + RegCloseKey(hKey); + + DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret); + + return ret; +} + + +/* Function 15 */ +DWORD +WINAPI +PNP_GetClassInstance( + handle_t hBinding, + LPWSTR pDeviceId, + LPWSTR pszClassInstance, + PNP_RPC_STRING_LEN ulLength) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 16 */ +DWORD +WINAPI +PNP_CreateKey( + handle_t hBinding, + LPWSTR pszSubKey, + DWORD samDesired, + DWORD ulFlags) +{ + HKEY hKey = 0; + + if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, + pszSubKey, + 0, + NULL, + 0, + KEY_ALL_ACCESS, + NULL, + &hKey, + NULL)) + return CR_REGISTRY_ERROR; + + /* FIXME: Set security key */ + + RegCloseKey(hKey); + + return CR_SUCCESS; +} + + +/* Function 17 */ +DWORD +WINAPI +PNP_DeleteRegistryKey( + handle_t hBinding, + LPWSTR pszDeviceID, + LPWSTR pszParentKey, + LPWSTR pszChildKey, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 18 */ +DWORD +WINAPI +PNP_GetClassCount( + handle_t hBinding, + DWORD *pulClassCount, + DWORD ulFlags) +{ + HKEY hKey; + DWORD dwError; + + UNREFERENCED_PARAMETER(hBinding); + UNREFERENCED_PARAMETER(ulFlags); + + dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + REGSTR_PATH_CLASS, + 0, + KEY_QUERY_VALUE, + &hKey); + if (dwError != ERROR_SUCCESS) + return CR_INVALID_DATA; + + dwError = RegQueryInfoKeyW(hKey, + NULL, + NULL, + NULL, + pulClassCount, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL); + RegCloseKey(hKey); + if (dwError != ERROR_SUCCESS) + return CR_INVALID_DATA; + + return CR_SUCCESS; +} + + +/* Function 19 */ +DWORD +WINAPI +PNP_GetClassName( + handle_t hBinding, + LPWSTR pszClassGuid, + LPWSTR Buffer, + PNP_RPC_STRING_LEN *pulLength, + DWORD ulFlags) +{ + WCHAR szKeyName[MAX_PATH]; + CONFIGRET ret = CR_SUCCESS; + HKEY hKey; + DWORD dwSize; + + UNREFERENCED_PARAMETER(hBinding); + UNREFERENCED_PARAMETER(ulFlags); + + DPRINT("PNP_GetClassName() called\n"); + + lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\"); + if (lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR))) + lstrcatW(szKeyName, pszClassGuid); + else + return CR_INVALID_DATA; + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, + szKeyName, + 0, + KEY_QUERY_VALUE, + &hKey)) + return CR_REGISTRY_ERROR; + + dwSize = *pulLength * sizeof(WCHAR); + if (RegQueryValueExW(hKey, + L"Class", + NULL, + NULL, + (LPBYTE)Buffer, + &dwSize)) + { + *pulLength = 0; + ret = CR_REGISTRY_ERROR; + } + else + { + *pulLength = dwSize / sizeof(WCHAR); + } + + RegCloseKey(hKey); + + DPRINT("PNP_GetClassName() done (returns %lx)\n", ret); + + return ret; +} + + +/* Function 20 */ +DWORD +WINAPI +PNP_DeleteClassKey( + handle_t hBinding, + LPWSTR pszClassGuid, + DWORD ulFlags) +{ + CONFIGRET ret = CR_SUCCESS; + + UNREFERENCED_PARAMETER(hBinding); + + DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid, ulFlags); + + if (ulFlags & CM_DELETE_CLASS_SUBKEYS) + { + if (SHDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS) + ret = CR_REGISTRY_ERROR; + } + else + { + if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS) + ret = CR_REGISTRY_ERROR; + } + + DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret); + + return ret; +} + + +/* Function 21 */ +DWORD +WINAPI +PNP_GetInterfaceDeviceAlias( + handle_t hBinding, + LPWSTR pszInterfaceDevice, + GUID *AliasInterfaceGuid, + LPWSTR pszAliasInterfaceDevice, + PNP_RPC_STRING_LEN *pulLength, + PNP_RPC_STRING_LEN *pulTransferLen, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 22 */ +DWORD +WINAPI +PNP_GetInterfaceDeviceList( + handle_t hBinding, + GUID *InterfaceGuid, + LPWSTR pszDeviceID, + BYTE *Buffer, + PNP_RPC_BUFFER_SIZE *pulLength, + DWORD ulFlags) +{ + NTSTATUS Status; + PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData; + DWORD ret = CR_SUCCESS; + + UNREFERENCED_PARAMETER(hBinding); + + RtlInitUnicodeString(&PlugPlayData.DeviceInstance, + pszDeviceID); + + PlugPlayData.Flags = ulFlags; + PlugPlayData.FilterGuid = InterfaceGuid; + PlugPlayData.Buffer = Buffer; + PlugPlayData.BufferSize = *pulLength; + + Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList, + (PVOID)&PlugPlayData, + sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA)); + if (NT_SUCCESS(Status)) + { + *pulLength = PlugPlayData.BufferSize; + } + else + { + ret = NtStatusToCrError(Status); + } + + DPRINT("PNP_GetInterfaceDeviceListSize() done (returns %lx)\n", ret); + return ret; +} + + +/* Function 23 */ +DWORD +WINAPI +PNP_GetInterfaceDeviceListSize( + handle_t hBinding, + PNP_RPC_BUFFER_SIZE *pulLen, + GUID *InterfaceGuid, + LPWSTR pszDeviceID, + DWORD ulFlags) +{ + NTSTATUS Status; + PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData; + DWORD ret = CR_SUCCESS; + + UNREFERENCED_PARAMETER(hBinding); + + DPRINT("PNP_GetInterfaceDeviceListSize() called\n"); + + RtlInitUnicodeString(&PlugPlayData.DeviceInstance, + pszDeviceID); + + PlugPlayData.FilterGuid = InterfaceGuid; + PlugPlayData.Buffer = NULL; + PlugPlayData.BufferSize = 0; + PlugPlayData.Flags = ulFlags; + + Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList, + (PVOID)&PlugPlayData, + sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA)); + if (NT_SUCCESS(Status)) + { + *pulLen = PlugPlayData.BufferSize; + } + else + { + ret = NtStatusToCrError(Status); + } + + DPRINT("PNP_GetInterfaceDeviceListSize() done (returns %lx)\n", ret); + return ret; +} + + +/* Function 24 */ +DWORD +WINAPI +PNP_RegisterDeviceClassAssociation( + handle_t hBinding, + LPWSTR pszDeviceID, + GUID *InterfaceGuid, + LPWSTR pszReference, + LPWSTR pszSymLink, + PNP_RPC_STRING_LEN *pulLength, + PNP_RPC_STRING_LEN *pulTransferLen, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 25 */ +DWORD +WINAPI +PNP_UnregisterDeviceClassAssociation( + handle_t hBinding, + LPWSTR pszInterfaceDevice, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 26 */ +DWORD +WINAPI +PNP_GetClassRegProp( + handle_t hBinding, + LPWSTR pszClassGuid, + DWORD ulProperty, + DWORD *pulRegDataType, + BYTE *Buffer, + PNP_RPC_STRING_LEN *pulTransferLen, + PNP_RPC_STRING_LEN *pulLength, + DWORD ulFlags) +{ + CONFIGRET ret = CR_SUCCESS; + LPWSTR lpValueName = NULL; + HKEY hInstKey = NULL; + HKEY hPropKey = NULL; + LONG lError; + + UNREFERENCED_PARAMETER(hBinding); + + DPRINT("PNP_GetClassRegProp() called\n"); + + if (pulTransferLen == NULL || pulLength == NULL) + { + ret = CR_INVALID_POINTER; + goto done; + } + + if (ulFlags != 0) + { + ret = CR_INVALID_FLAG; + goto done; + } + + if (*pulLength < *pulTransferLen) + *pulLength = *pulTransferLen; + + *pulTransferLen = 0; + + switch (ulProperty) + { + case CM_CRP_SECURITY: + lpValueName = L"Security"; + break; + + case CM_CRP_DEVTYPE: + lpValueName = L"DeviceType"; + break; + + case CM_CRP_EXCLUSIVE: + lpValueName = L"Exclusive"; + break; + + case CM_CRP_CHARACTERISTICS: + lpValueName = L"DeviceCharacteristics"; + break; + + default: + ret = CR_INVALID_PROPERTY; + goto done; + } + + DPRINT("Value name: %S\n", lpValueName); + + lError = RegOpenKeyExW(hClassKey, + pszClassGuid, + 0, + KEY_READ, + &hInstKey); + if (lError != ERROR_SUCCESS) + { + *pulLength = 0; + ret = CR_NO_SUCH_REGISTRY_KEY; + goto done; + } + + lError = RegOpenKeyExW(hInstKey, + L"Properties", + 0, + KEY_READ, + &hPropKey); + if (lError != ERROR_SUCCESS) + { + *pulLength = 0; + ret = CR_NO_SUCH_REGISTRY_KEY; + goto done; + } + + lError = RegQueryValueExW(hPropKey, + lpValueName, + NULL, + pulRegDataType, + Buffer, + pulLength); + if (lError != ERROR_SUCCESS) + { + if (lError == ERROR_MORE_DATA) + { + ret = CR_BUFFER_SMALL; + } + else + { + *pulLength = 0; + ret = CR_NO_SUCH_VALUE; + } + } + +done: + if (ret == CR_SUCCESS) + *pulTransferLen = *pulLength; + + if (hPropKey != NULL) + RegCloseKey(hPropKey); + + if (hInstKey != NULL) + RegCloseKey(hInstKey); + + DPRINT("PNP_GetClassRegProp() done (returns %lx)\n", ret); + + return ret; +} + + +/* Function 27 */ +DWORD +WINAPI +PNP_SetClassRegProp( + handle_t hBinding, + LPWSTR pszClassGuid, + DWORD ulProperty, + DWORD ulDataType, + BYTE *Buffer, + PNP_PROP_SIZE ulLength, + DWORD ulFlags) +{ + CONFIGRET ret = CR_SUCCESS; + LPWSTR lpValueName = NULL; + HKEY hInstKey = 0; + HKEY hPropKey = 0; + LONG lError; + + UNREFERENCED_PARAMETER(hBinding); + + DPRINT("PNP_SetClassRegProp() called\n"); + + if (ulFlags != 0) + return CR_INVALID_FLAG; + + switch (ulProperty) + { + case CM_CRP_SECURITY: + lpValueName = L"Security"; + break; + + case CM_CRP_DEVTYPE: + lpValueName = L"DeviceType"; + break; + + case CM_CRP_EXCLUSIVE: + lpValueName = L"Exclusive"; + break; + + case CM_CRP_CHARACTERISTICS: + lpValueName = L"DeviceCharacteristics"; + break; + + default: + return CR_INVALID_PROPERTY; + } + + lError = RegOpenKeyExW(hClassKey, + pszClassGuid, + 0, + KEY_WRITE, + &hInstKey); + if (lError != ERROR_SUCCESS) + { + ret = CR_NO_SUCH_REGISTRY_KEY; + goto done; + } + + /* FIXME: Set security descriptor */ + lError = RegCreateKeyExW(hInstKey, + L"Properties", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hPropKey, + NULL); + if (lError != ERROR_SUCCESS) + { + ret = CR_REGISTRY_ERROR; + goto done; + } + + if (ulLength == 0) + { + if (RegDeleteValueW(hPropKey, + lpValueName)) + ret = CR_REGISTRY_ERROR; + } + else + { + if (RegSetValueExW(hPropKey, + lpValueName, + 0, + ulDataType, + Buffer, + ulLength)) + ret = CR_REGISTRY_ERROR; + } + +done: + if (hPropKey != NULL) + RegCloseKey(hPropKey); + + if (hInstKey != NULL) + RegCloseKey(hInstKey); + + return ret; +} + + +static CONFIGRET +CreateDeviceInstance(LPWSTR pszDeviceID) +{ + WCHAR szEnumerator[MAX_DEVICE_ID_LEN]; + WCHAR szDevice[MAX_DEVICE_ID_LEN]; + WCHAR szInstance[MAX_DEVICE_ID_LEN]; + HKEY hKeyEnumerator; + HKEY hKeyDevice; + HKEY hKeyInstance; + HKEY hKeyControl; + LONG lError; + + /* Split the instance ID */ + SplitDeviceInstanceID(pszDeviceID, + szEnumerator, + szDevice, + szInstance); + + /* Open or create the enumerator key */ + lError = RegCreateKeyExW(hEnumKey, + szEnumerator, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hKeyEnumerator, + NULL); + if (lError != ERROR_SUCCESS) + { + return CR_REGISTRY_ERROR; + } + + /* Open or create the device key */ + lError = RegCreateKeyExW(hKeyEnumerator, + szDevice, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hKeyDevice, + NULL); + + /* Close the enumerator key */ + RegCloseKey(hKeyEnumerator); + + if (lError != ERROR_SUCCESS) + { + return CR_REGISTRY_ERROR; + } + + /* Try to open the instance key and fail if it exists */ + lError = RegOpenKeyExW(hKeyDevice, + szInstance, + 0, + KEY_SET_VALUE, + &hKeyInstance); + if (lError == ERROR_SUCCESS) + { + DPRINT1("Instance %S already exists!\n", szInstance); + RegCloseKey(hKeyInstance); + RegCloseKey(hKeyDevice); + return CR_ALREADY_SUCH_DEVINST; + } + + /* Create a new instance key */ + lError = RegCreateKeyExW(hKeyDevice, + szInstance, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hKeyInstance, + NULL); + + /* Close the device key */ + RegCloseKey(hKeyDevice); + + if (lError != ERROR_SUCCESS) + { + return CR_REGISTRY_ERROR; + } + + /* Create the 'Control' sub key */ + lError = RegCreateKeyExW(hKeyInstance, + L"Control", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hKeyControl, + NULL); + if (lError == ERROR_SUCCESS) + { + RegCloseKey(hKeyControl); + } + + RegCloseKey(hKeyInstance); + + return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR; +} + + +/* Function 28 */ +DWORD +WINAPI +PNP_CreateDevInst( + handle_t hBinding, + LPWSTR pszDeviceID, + LPWSTR pszParentDeviceID, + PNP_RPC_STRING_LEN ulLength, + DWORD ulFlags) +{ + CONFIGRET ret = CR_SUCCESS; + + DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID); + + if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID) + { + WCHAR szGeneratedInstance[MAX_DEVICE_ID_LEN]; + DWORD dwInstanceNumber; + + /* Generated ID is: Root\\ */ + dwInstanceNumber = 0; + do + { + swprintf(szGeneratedInstance, L"Root\\%ls\\%04lu", + pszDeviceID, dwInstanceNumber); + + /* Try to create a device instance with this ID */ + ret = CreateDeviceInstance(szGeneratedInstance); + + dwInstanceNumber++; + } + while (ret == CR_ALREADY_SUCH_DEVINST); + + if (ret == CR_SUCCESS) + { + /* pszDeviceID is an out parameter too for generated IDs */ + if (wcslen(szGeneratedInstance) > ulLength) + { + ret = CR_BUFFER_SMALL; + } + else + { + wcscpy(pszDeviceID, szGeneratedInstance); + } + } + } + else + { + /* Create the device instance */ + ret = CreateDeviceInstance(pszDeviceID); + } + + DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret); + + return ret; +} + + +static CONFIGRET +MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination, + LPWSTR pszDeviceInstanceSource) +{ + DPRINT("MoveDeviceInstance: not implemented\n"); + /* FIXME */ + return CR_CALL_NOT_IMPLEMENTED; +} + + +static CONFIGRET +SetupDeviceInstance(LPWSTR pszDeviceInstance, + DWORD ulFlags) +{ + DPRINT("SetupDeviceInstance: not implemented\n"); + /* FIXME */ + return CR_CALL_NOT_IMPLEMENTED; +} + + +static CONFIGRET +EnableDeviceInstance(LPWSTR pszDeviceInstance) +{ + PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData; + CONFIGRET ret = CR_SUCCESS; + NTSTATUS Status; + + DPRINT("Enable device instance %S\n", pszDeviceInstance); + + RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance); + Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA)); + if (!NT_SUCCESS(Status)) + ret = NtStatusToCrError(Status); + + return ret; +} + + +static CONFIGRET +DisableDeviceInstance(LPWSTR pszDeviceInstance) +{ + DPRINT("DisableDeviceInstance: not implemented\n"); + /* FIXME */ + return CR_CALL_NOT_IMPLEMENTED; +} + + +static CONFIGRET +ReenumerateDeviceInstance( + _In_ LPWSTR pszDeviceInstance, + _In_ ULONG ulFlags) +{ + PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA EnumerateDeviceData; + CONFIGRET ret = CR_SUCCESS; + NTSTATUS Status; + + DPRINT1("ReenumerateDeviceInstance(%S 0x%08lx)\n", + pszDeviceInstance, ulFlags); + + if (ulFlags & ~CM_REENUMERATE_BITS) + return CR_INVALID_FLAG; + + if (ulFlags & CM_REENUMERATE_RETRY_INSTALLATION) + { + DPRINT1("CM_REENUMERATE_RETRY_INSTALLATION not implemented!\n"); + } + + RtlInitUnicodeString(&EnumerateDeviceData.DeviceInstance, + pszDeviceInstance); + EnumerateDeviceData.Flags = 0; + + Status = NtPlugPlayControl(PlugPlayControlEnumerateDevice, + &EnumerateDeviceData, + sizeof(PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA)); + if (!NT_SUCCESS(Status)) + ret = NtStatusToCrError(Status); + + return ret; +} + + +/* Function 29 */ +DWORD +WINAPI +PNP_DeviceInstanceAction( + handle_t hBinding, + DWORD ulAction, + DWORD ulFlags, + LPWSTR pszDeviceInstance1, + LPWSTR pszDeviceInstance2) +{ + CONFIGRET ret = CR_SUCCESS; + + UNREFERENCED_PARAMETER(hBinding); + + DPRINT("PNP_DeviceInstanceAction() called\n"); + + switch (ulAction) + { + case PNP_DEVINST_MOVE: + ret = MoveDeviceInstance(pszDeviceInstance1, + pszDeviceInstance2); + break; + + case PNP_DEVINST_SETUP: + ret = SetupDeviceInstance(pszDeviceInstance1, + ulFlags); + break; + + case PNP_DEVINST_ENABLE: + ret = EnableDeviceInstance(pszDeviceInstance1); + break; + + case PNP_DEVINST_DISABLE: + ret = DisableDeviceInstance(pszDeviceInstance1); + break; + + case PNP_DEVINST_REENUMERATE: + ret = ReenumerateDeviceInstance(pszDeviceInstance1, + ulFlags); + break; + + default: + DPRINT1("Unknown device action %lu: not implemented\n", ulAction); + ret = CR_CALL_NOT_IMPLEMENTED; + } + + DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret); + + return ret; +} + + +/* Function 30 */ +DWORD +WINAPI +PNP_GetDeviceStatus( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD *pulStatus, + DWORD *pulProblem, + DWORD ulFlags) +{ + PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData; + CONFIGRET ret = CR_SUCCESS; + NTSTATUS Status; + + UNREFERENCED_PARAMETER(hBinding); + UNREFERENCED_PARAMETER(ulFlags); + + DPRINT("PNP_GetDeviceStatus() called\n"); + + RtlInitUnicodeString(&PlugPlayData.DeviceInstance, + pDeviceID); + PlugPlayData.Operation = 0; /* Get status */ + + Status = NtPlugPlayControl(PlugPlayControlDeviceStatus, + (PVOID)&PlugPlayData, + sizeof(PLUGPLAY_CONTROL_STATUS_DATA)); + if (NT_SUCCESS(Status)) + { + *pulStatus = PlugPlayData.DeviceStatus; + *pulProblem = PlugPlayData.DeviceProblem; + } + else + { + ret = NtStatusToCrError(Status); + } + + DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret); + + return ret; +} + + +/* Function 31 */ +DWORD +WINAPI +PNP_SetDeviceProblem( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulProblem, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 32 */ +DWORD +WINAPI +PNP_DisableDevInst( + handle_t hBinding, + LPWSTR pDeviceID, + PPNP_VETO_TYPE pVetoType, + LPWSTR pszVetoName, + DWORD ulNameLength, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + +/* Function 33 */ +DWORD +WINAPI +PNP_UninstallDevInst( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +static BOOL +CheckForDeviceId(LPWSTR lpDeviceIdList, + LPWSTR lpDeviceId) +{ + LPWSTR lpPtr; + DWORD dwLength; + + lpPtr = lpDeviceIdList; + while (*lpPtr != 0) + { + dwLength = wcslen(lpPtr); + if (0 == _wcsicmp(lpPtr, lpDeviceId)) + return TRUE; + + lpPtr += (dwLength + 1); + } + + return FALSE; +} + + +static VOID +AppendDeviceId(LPWSTR lpDeviceIdList, + LPDWORD lpDeviceIdListSize, + LPWSTR lpDeviceId) +{ + DWORD dwLen; + DWORD dwPos; + + dwLen = wcslen(lpDeviceId); + dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1; + + wcscpy(&lpDeviceIdList[dwPos], lpDeviceId); + + dwPos += (dwLen + 1); + + lpDeviceIdList[dwPos] = 0; + + *lpDeviceIdListSize = dwPos * sizeof(WCHAR); +} + + +/* Function 34 */ +DWORD +WINAPI +PNP_AddID( + handle_t hBinding, + LPWSTR pszDeviceID, + LPWSTR pszID, + DWORD ulFlags) +{ + CONFIGRET ret = CR_SUCCESS; + HKEY hDeviceKey; + LPWSTR pszSubKey; + DWORD dwDeviceIdListSize; + DWORD dwNewDeviceIdSize; + WCHAR * pszDeviceIdList = NULL; + + UNREFERENCED_PARAMETER(hBinding); + + DPRINT("PNP_AddID() called\n"); + DPRINT(" DeviceInstance: %S\n", pszDeviceID); + DPRINT(" DeviceId: %S\n", pszID); + DPRINT(" Flags: %lx\n", ulFlags); + + if (RegOpenKeyExW(hEnumKey, + pszDeviceID, + 0, + KEY_QUERY_VALUE | KEY_SET_VALUE, + &hDeviceKey) != ERROR_SUCCESS) + { + DPRINT("Failed to open the device key!\n"); + return CR_INVALID_DEVNODE; + } + + pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID"; + + if (RegQueryValueExW(hDeviceKey, + pszSubKey, + NULL, + NULL, + NULL, + &dwDeviceIdListSize) != ERROR_SUCCESS) + { + DPRINT("Failed to query the desired ID string!\n"); + ret = CR_REGISTRY_ERROR; + goto Done; + } + + dwNewDeviceIdSize = lstrlenW(pszDeviceID); + if (!dwNewDeviceIdSize) + { + ret = CR_INVALID_POINTER; + goto Done; + } + + dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR); + + pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize); + if (!pszDeviceIdList) + { + DPRINT("Failed to allocate memory for the desired ID string!\n"); + ret = CR_OUT_OF_MEMORY; + goto Done; + } + + if (RegQueryValueExW(hDeviceKey, + pszSubKey, + NULL, + NULL, + (LPBYTE)pszDeviceIdList, + &dwDeviceIdListSize) != ERROR_SUCCESS) + { + DPRINT("Failed to query the desired ID string!\n"); + ret = CR_REGISTRY_ERROR; + goto Done; + } + + /* Check whether the device ID is already in use */ + if (CheckForDeviceId(pszDeviceIdList, pszDeviceID)) + { + DPRINT("Device ID was found in the ID string!\n"); + ret = CR_SUCCESS; + goto Done; + } + + /* Append the Device ID */ + AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID); + + if (RegSetValueExW(hDeviceKey, + pszSubKey, + 0, + REG_MULTI_SZ, + (LPBYTE)pszDeviceIdList, + dwDeviceIdListSize) != ERROR_SUCCESS) + { + DPRINT("Failed to set the desired ID string!\n"); + ret = CR_REGISTRY_ERROR; + } + +Done: + RegCloseKey(hDeviceKey); + if (pszDeviceIdList) + HeapFree(GetProcessHeap(), 0, pszDeviceIdList); + + DPRINT("PNP_AddID() done (returns %lx)\n", ret); + + return ret; +} + + +/* Function 35 */ +DWORD +WINAPI +PNP_RegisterDriver( + handle_t hBinding, + LPWSTR pszDeviceID, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 36 */ +DWORD +WINAPI +PNP_QueryRemove( + handle_t hBinding, + LPWSTR pszDeviceID, + PPNP_VETO_TYPE pVetoType, + LPWSTR pszVetoName, + DWORD ulNameLength, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 37 */ +DWORD +WINAPI +PNP_RequestDeviceEject( + handle_t hBinding, + LPWSTR pszDeviceID, + PPNP_VETO_TYPE pVetoType, + LPWSTR pszVetoName, + DWORD ulNameLength, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 38 */ +CONFIGRET +WINAPI +PNP_IsDockStationPresent( + handle_t hBinding, + BOOL *Present) +{ + HKEY hKey; + DWORD dwType; + DWORD dwValue; + DWORD dwSize; + CONFIGRET ret = CR_SUCCESS; + + UNREFERENCED_PARAMETER(hBinding); + + DPRINT1("PNP_IsDockStationPresent() called\n"); + + *Present = FALSE; + + if (RegOpenKeyExW(HKEY_CURRENT_CONFIG, + L"CurrentDockInfo", + 0, + KEY_READ, + &hKey) != ERROR_SUCCESS) + return CR_REGISTRY_ERROR; + + dwSize = sizeof(DWORD); + if (RegQueryValueExW(hKey, + L"DockingState", + NULL, + &dwType, + (LPBYTE)&dwValue, + &dwSize) != ERROR_SUCCESS) + ret = CR_REGISTRY_ERROR; + + RegCloseKey(hKey); + + if (ret == CR_SUCCESS) + { + if (dwType != REG_DWORD || dwSize != sizeof(DWORD)) + { + ret = CR_REGISTRY_ERROR; + } + else if (dwValue != 0) + { + *Present = TRUE; + } + } + + DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret); + + return ret; +} + + +/* Function 39 */ +DWORD +WINAPI +PNP_RequestEjectPC( + handle_t hBinding) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 40 */ +DWORD +WINAPI +PNP_HwProfFlags( + handle_t hBinding, + DWORD ulAction, + LPWSTR pDeviceID, + DWORD ulConfig, + DWORD *pulValue, + PPNP_VETO_TYPE pVetoType, + LPWSTR pszVetoName, + DWORD ulNameLength, + DWORD ulFlags) +{ + CONFIGRET ret = CR_SUCCESS; + WCHAR szKeyName[MAX_PATH]; + HKEY hKey; + HKEY hDeviceKey; + DWORD dwSize; + + UNREFERENCED_PARAMETER(hBinding); + + DPRINT("PNP_HwProfFlags() called\n"); + + if (ulConfig == 0) + { + wcscpy(szKeyName, + L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum"); + } + else + { + swprintf(szKeyName, + L"System\\CurrentControlSet\\HardwareProfiles\\%04lu\\System\\CurrentControlSet\\Enum", + ulConfig); + } + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, + szKeyName, + 0, + KEY_QUERY_VALUE, + &hKey) != ERROR_SUCCESS) + return CR_REGISTRY_ERROR; + + if (ulAction == PNP_GET_HWPROFFLAGS) + { + if (RegOpenKeyExW(hKey, + pDeviceID, + 0, + KEY_QUERY_VALUE, + &hDeviceKey) != ERROR_SUCCESS) + { + *pulValue = 0; + } + else + { + dwSize = sizeof(DWORD); + if (RegQueryValueExW(hDeviceKey, + L"CSConfigFlags", + NULL, + NULL, + (LPBYTE)pulValue, + &dwSize) != ERROR_SUCCESS) + { + *pulValue = 0; + } + + RegCloseKey(hDeviceKey); + } + } + else if (ulAction == PNP_SET_HWPROFFLAGS) + { + /* FIXME: not implemented yet */ + ret = CR_CALL_NOT_IMPLEMENTED; + } + + RegCloseKey(hKey); + + return ret; +} + + +/* Function 41 */ +DWORD +WINAPI +PNP_GetHwProfInfo( + handle_t hBinding, + DWORD ulIndex, + HWPROFILEINFO *pHWProfileInfo, + DWORD ulProfileInfoSize, + DWORD ulFlags) +{ + WCHAR szProfileName[5]; + HKEY hKeyConfig = NULL; + HKEY hKeyProfiles = NULL; + HKEY hKeyProfile = NULL; + DWORD dwDisposition; + DWORD dwSize; + LONG lError; + CONFIGRET ret = CR_SUCCESS; + + UNREFERENCED_PARAMETER(hBinding); + + DPRINT("PNP_GetHwProfInfo() called\n"); + + if (ulProfileInfoSize == 0) + { + ret = CR_INVALID_DATA; + goto done; + } + + if (ulFlags != 0) + { + ret = CR_INVALID_FLAG; + goto done; + } + + /* Initialize the profile information */ + pHWProfileInfo->HWPI_ulHWProfile = 0; + pHWProfileInfo->HWPI_szFriendlyName[0] = 0; + pHWProfileInfo->HWPI_dwFlags = 0; + + /* Open the 'IDConfigDB' key */ + lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE, + L"System\\CurrentControlSet\\Control\\IDConfigDB", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_QUERY_VALUE, + NULL, + &hKeyConfig, + &dwDisposition); + if (lError != ERROR_SUCCESS) + { + ret = CR_REGISTRY_ERROR; + goto done; + } + + /* Open the 'Hardware Profiles' subkey */ + lError = RegCreateKeyExW(hKeyConfig, + L"Hardware Profiles", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, + NULL, + &hKeyProfiles, + &dwDisposition); + if (lError != ERROR_SUCCESS) + { + ret = CR_REGISTRY_ERROR; + goto done; + } + + if (ulIndex == (ULONG)-1) + { + dwSize = sizeof(ULONG); + lError = RegQueryValueExW(hKeyConfig, + L"CurrentConfig", + NULL, + NULL, + (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile, + &dwSize); + if (lError != ERROR_SUCCESS) + { + pHWProfileInfo->HWPI_ulHWProfile = 0; + ret = CR_REGISTRY_ERROR; + goto done; + } + } + else + { + /* FIXME: not implemented yet */ + ret = CR_CALL_NOT_IMPLEMENTED; + goto done; + } + + swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile); + + lError = RegOpenKeyExW(hKeyProfiles, + szProfileName, + 0, + KEY_QUERY_VALUE, + &hKeyProfile); + if (lError != ERROR_SUCCESS) + { + ret = CR_REGISTRY_ERROR; + goto done; + } + + dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName); + lError = RegQueryValueExW(hKeyProfile, + L"FriendlyName", + NULL, + NULL, + (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName, + &dwSize); + if (lError != ERROR_SUCCESS) + { + ret = CR_REGISTRY_ERROR; + goto done; + } + +done: + if (hKeyProfile != NULL) + RegCloseKey(hKeyProfile); + + if (hKeyProfiles != NULL) + RegCloseKey(hKeyProfiles); + + if (hKeyConfig != NULL) + RegCloseKey(hKeyConfig); + + return ret; +} + + +/* Function 42 */ +DWORD +WINAPI +PNP_AddEmptyLogConf( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulPriority, + DWORD *pulLogConfTag, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 43 */ +DWORD +WINAPI +PNP_FreeLogConf( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulLogConfType, + DWORD ulLogConfTag, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 44 */ +DWORD +WINAPI +PNP_GetFirstLogConf( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulLogConfType, + DWORD *pulLogConfTag, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 45 */ +DWORD +WINAPI +PNP_GetNextLogConf( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulLogConfType, + DWORD ulCurrentTag, + DWORD *pulNextTag, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 46 */ +DWORD +WINAPI +PNP_GetLogConfPriority( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulType, + DWORD ulTag, + DWORD *pPriority, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 47 */ +DWORD +WINAPI +PNP_AddResDes( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulLogConfTag, + DWORD ulLogConfType, + RESOURCEID ResourceID, + DWORD *pulResourceTag, + BYTE *ResourceData, + PNP_RPC_BUFFER_SIZE ResourceLen, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 48 */ +DWORD +WINAPI +PNP_FreeResDes( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulLogConfTag, + DWORD ulLogConfType, + RESOURCEID ResourceID, + DWORD ulResourceTag, + DWORD *pulPreviousResType, + DWORD *pulPreviousResTag, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 49 */ +DWORD +WINAPI +PNP_GetNextResDes( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulLogConfTag, + DWORD ulLogConfType, + RESOURCEID ResourceID, + DWORD ulResourceTag, + DWORD *pulNextResType, + DWORD *pulNextResTag, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 50 */ +DWORD +WINAPI +PNP_GetResDesData( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulLogConfTag, + DWORD ulLogConfType, + RESOURCEID ResourceID, + DWORD ulResourceTag, + BYTE *Buffer, + PNP_RPC_BUFFER_SIZE BufferLen, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 51 */ +DWORD +WINAPI +PNP_GetResDesDataSize( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulLogConfTag, + DWORD ulLogConfType, + RESOURCEID ResourceID, + DWORD ulResourceTag, + DWORD *pulSize, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 52 */ +DWORD +WINAPI +PNP_ModifyResDes( + handle_t hBinding, + LPWSTR pDeviceID, + DWORD ulLogConfTag, + DWORD ulLogConfType, + RESOURCEID CurrentResourceID, + RESOURCEID NewResourceID, + DWORD ulResourceTag, + BYTE *ResourceData, + PNP_RPC_BUFFER_SIZE ResourceLen, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 53 */ +DWORD +WINAPI +PNP_DetectResourceConflict( + handle_t hBinding, + LPWSTR pDeviceID, + RESOURCEID ResourceID, + BYTE *ResourceData, + PNP_RPC_BUFFER_SIZE ResourceLen, + BOOL *pbConflictDetected, + DWORD ulFlags) +{ + DPRINT("PNP_DetectResourceConflict()\n"); + + if (pbConflictDetected != NULL) + *pbConflictDetected = FALSE; + + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 54 */ +DWORD +WINAPI +PNP_QueryResConfList( + handle_t hBinding, + LPWSTR pDeviceID, + RESOURCEID ResourceID, + BYTE *ResourceData, + PNP_RPC_BUFFER_SIZE ResourceLen, + BYTE *Buffer, + PNP_RPC_BUFFER_SIZE BufferLen, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 55 */ +DWORD +WINAPI +PNP_SetHwProf( + handle_t hBinding, + DWORD ulHardwareProfile, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 56 */ +DWORD +WINAPI +PNP_QueryArbitratorFreeData( + handle_t hBinding, + BYTE *pData, + DWORD DataLen, + LPWSTR pDeviceID, + RESOURCEID ResourceID, + DWORD ulFlags) +{ + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 57 */ +DWORD +WINAPI +PNP_QueryArbitratorFreeSize( + handle_t hBinding, + DWORD *pulSize, + LPWSTR pDeviceID, + RESOURCEID ResourceID, + DWORD ulFlags) +{ + if (pulSize != NULL) + *pulSize = 0; + + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 58 */ +CONFIGRET +WINAPI +PNP_RunDetection( + handle_t hBinding, + DWORD ulFlags) +{ + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 59 */ +DWORD +WINAPI +PNP_RegisterNotification( + handle_t hBinding, + DWORD ulFlags, + DWORD *pulNotify) +{ +#if 0 + PNOTIFY_DATA pNotifyData; +#endif + + DPRINT1("PNP_RegisterNotification(%p 0x%lx %p)\n", + hBinding, ulFlags, pulNotify); + +#if 0 + pNotifyData = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NOTIFY_DATA)); + if (pNotifyData == NULL) + return CR_OUT_OF_MEMORY; + + *pulNotify = (DWORD)pNotifyData; +#endif + + *pulNotify = 1; + + return CR_SUCCESS; +} + + +/* Function 60 */ +DWORD +WINAPI +PNP_UnregisterNotification( + handle_t hBinding, + DWORD ulNotify) +{ + DPRINT1("PNP_UnregisterNotification(%p 0x%lx)\n", + hBinding, ulNotify); + +#if 0 + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +#endif + + return CR_SUCCESS; +} + + +/* Function 61 */ +DWORD +WINAPI +PNP_GetCustomDevProp( + handle_t hBinding, + LPWSTR pDeviceID, + LPWSTR CustomPropName, + DWORD *pulRegDataType, + BYTE *Buffer, + PNP_RPC_STRING_LEN *pulTransferLen, + PNP_RPC_STRING_LEN *pulLength, + DWORD ulFlags) +{ + HKEY hDeviceKey = NULL; + HKEY hParamKey = NULL; + LONG lError; + CONFIGRET ret = CR_SUCCESS; + + UNREFERENCED_PARAMETER(hBinding); + + DPRINT("PNP_GetCustomDevProp() called\n"); + + if (pulTransferLen == NULL || pulLength == NULL) + { + ret = CR_INVALID_POINTER; + goto done; + } + + if (ulFlags & ~CM_CUSTOMDEVPROP_BITS) + { + ret = CR_INVALID_FLAG; + goto done; + } + + if (*pulLength < *pulTransferLen) + *pulLength = *pulTransferLen; + + *pulTransferLen = 0; + + lError = RegOpenKeyExW(hEnumKey, + pDeviceID, + 0, + KEY_READ, + &hDeviceKey); + if (lError != ERROR_SUCCESS) + { + ret = CR_REGISTRY_ERROR; + goto done; + } + + lError = RegOpenKeyExW(hDeviceKey, + L"Device Parameters", + 0, + KEY_READ, + &hParamKey); + if (lError != ERROR_SUCCESS) + { + ret = CR_REGISTRY_ERROR; + goto done; + } + + lError = RegQueryValueExW(hParamKey, + CustomPropName, + NULL, + pulRegDataType, + Buffer, + pulLength); + if (lError != ERROR_SUCCESS) + { + if (lError == ERROR_MORE_DATA) + { + ret = CR_BUFFER_SMALL; + } + else + { + *pulLength = 0; + ret = CR_NO_SUCH_VALUE; + } + } + +done: + if (ret == CR_SUCCESS) + *pulTransferLen = *pulLength; + + if (hParamKey != NULL) + RegCloseKey(hParamKey); + + if (hDeviceKey != NULL) + RegCloseKey(hDeviceKey); + + DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret); + + return ret; +} + + +/* Function 62 */ +DWORD +WINAPI +PNP_GetVersionInternal( + handle_t hBinding, + WORD *pwVersion) +{ + UNREFERENCED_PARAMETER(hBinding); + + *pwVersion = 0x501; + return CR_SUCCESS; +} + + +/* Function 63 */ +DWORD +WINAPI +PNP_GetBlockedDriverInfo( + handle_t hBinding, + BYTE *Buffer, + PNP_RPC_BUFFER_SIZE *pulTransferLen, + PNP_RPC_BUFFER_SIZE *pulLength, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 64 */ +DWORD +WINAPI +PNP_GetServerSideDeviceInstallFlags( + handle_t hBinding, + DWORD *pulSSDIFlags, + DWORD ulFlags) +{ + UNREFERENCED_PARAMETER(hBinding); + + DPRINT1("PNP_GetServerSideDeviceInstallFlags(%p %p %lu)\n", + hBinding, pulSSDIFlags, ulFlags); + + if (pulSSDIFlags == NULL) + return CR_INVALID_POINTER; + + if (ulFlags != 0) + return CR_INVALID_FLAG; + + /* FIXME */ + *pulSSDIFlags = 0; + + return CR_SUCCESS; +} + + +/* Function 65 */ +DWORD +WINAPI +PNP_GetObjectPropKeys( + handle_t hBinding, + LPWSTR ObjectName, + DWORD ObjectType, + LPWSTR PropertyCultureName, + PNP_PROP_COUNT *PropertyCount, + PNP_PROP_COUNT *TransferLen, + DEVPROPKEY *PropertyKeys, + DWORD Flags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 66 */ +DWORD +WINAPI +PNP_GetObjectProp( + handle_t hBinding, + LPWSTR ObjectName, + DWORD ObjectType, + LPWSTR PropertyCultureName, + const DEVPROPKEY *PropertyKey, + DEVPROPTYPE *PropertyType, + PNP_PROP_SIZE *PropertySize, + PNP_PROP_SIZE *TransferLen, + BYTE *PropertyBuffer, + DWORD Flags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 67 */ +DWORD +WINAPI +PNP_SetObjectProp( + handle_t hBinding, + LPWSTR ObjectName, + DWORD ObjectType, + LPWSTR PropertyCultureName, + const DEVPROPKEY *PropertyKey, + DEVPROPTYPE PropertyType, + PNP_PROP_SIZE PropertySize, + BYTE *PropertyBuffer, + DWORD Flags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 68 */ +DWORD +WINAPI +PNP_InstallDevInst( + handle_t hBinding) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 69 */ +DWORD +WINAPI +PNP_ApplyPowerSettings( + handle_t hBinding) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 70 */ +DWORD +WINAPI +PNP_DriverStoreAddDriverPackage( + handle_t hBinding) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 71 */ +DWORD +WINAPI +PNP_DriverStoreDeleteDriverPackage( + handle_t hBinding) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 72 */ +DWORD +WINAPI +PNP_RegisterServiceNotification( + handle_t hBinding) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 73 */ +DWORD +WINAPI +PNP_SetActiveService( + handle_t hBinding, + LPWSTR pszFilter, + DWORD ulFlags) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} + + +/* Function 74 */ +DWORD +WINAPI +PNP_DeleteServiceDevices( + handle_t hBinding) +{ + UNIMPLEMENTED; + return CR_CALL_NOT_IMPLEMENTED; +} diff --git a/base/services/umpnpmgr/umpnpmgr.c b/base/services/umpnpmgr/umpnpmgr.c index 4248879a50f..e26fa2f64d1 100644 --- a/base/services/umpnpmgr/umpnpmgr.c +++ b/base/services/umpnpmgr/umpnpmgr.c @@ -28,30 +28,12 @@ /* INCLUDES *****************************************************************/ -#define WIN32_NO_STATUS -#define _INC_WINDOWS -#define COM_NO_WINDOWS_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "precomp.h" #define NDEBUG #include + /* GLOBALS ******************************************************************/ static WCHAR ServiceName[] = L"PlugPlay"; @@ -59,4077 +41,12 @@ static WCHAR ServiceName[] = L"PlugPlay"; static SERVICE_STATUS_HANDLE ServiceStatusHandle; static SERVICE_STATUS ServiceStatus; -static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0"; +HKEY hEnumKey = NULL; +HKEY hClassKey = NULL; -static HKEY hEnumKey = NULL; -static HKEY hClassKey = NULL; - -static HANDLE hUserToken = NULL; -static HANDLE hInstallEvent = NULL; -static HANDLE hNoPendingInstalls = NULL; - -static SLIST_HEADER DeviceInstallListHead; -static HANDLE hDeviceInstallListNotEmpty; - -typedef struct -{ - SLIST_ENTRY ListEntry; - WCHAR DeviceIds[1]; -} DeviceInstallParams; /* FUNCTIONS *****************************************************************/ -static DWORD WINAPI -RpcServerThread(LPVOID lpParameter) -{ - RPC_STATUS Status; - BOOLEAN RegisteredProtSeq = FALSE; - - UNREFERENCED_PARAMETER(lpParameter); - - DPRINT("RpcServerThread() called\n"); - -#if 0 - /* 2k/XP/2k3-compatible protocol sequence/endpoint */ - Status = RpcServerUseProtseqEpW(L"ncacn_np", - 20, - L"\\pipe\\ntsvcs", - NULL); // Security descriptor - if (Status == RPC_S_OK) - RegisteredProtSeq = TRUE; - else - DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); -#endif - - /* Vista/7-compatible protocol sequence/endpoint */ - Status = RpcServerUseProtseqEpW(L"ncacn_np", - 20, - L"\\pipe\\plugplay", - NULL); // Security descriptor - if (Status == RPC_S_OK) - RegisteredProtSeq = TRUE; - else - DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); - - /* Make sure there's a usable endpoint */ - if (RegisteredProtSeq == FALSE) - return 0; - - Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec, - NULL, - NULL); - if (Status != RPC_S_OK) - { - DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status); - return 0; - } - - Status = RpcServerListen(1, - 20, - FALSE); - if (Status != RPC_S_OK) - { - DPRINT1("RpcServerListen() failed (Status %lx)\n", Status); - return 0; - } - - /* ROS HACK (this should never happen...) */ - DPRINT1("*** Other devices won't be installed correctly. If something\n"); - DPRINT1("*** doesn't work, try to reboot to get a new chance.\n"); - - DPRINT("RpcServerThread() done\n"); - - return 0; -} - - -void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len) -{ - return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); -} - - -void __RPC_USER midl_user_free(void __RPC_FAR * ptr) -{ - HeapFree(GetProcessHeap(), 0, ptr); -} - - -static CONFIGRET WINAPI -NtStatusToCrError(NTSTATUS Status) -{ - switch (Status) - { - case STATUS_NOT_IMPLEMENTED: - return CR_CALL_NOT_IMPLEMENTED; - - case STATUS_INVALID_PARAMETER: - return CR_INVALID_DATA; - - case STATUS_NO_SUCH_DEVICE: - return CR_NO_SUCH_DEVINST; - - case STATUS_ACCESS_DENIED: - return CR_ACCESS_DENIED; - - case STATUS_BUFFER_TOO_SMALL: - return CR_BUFFER_SMALL; - - case STATUS_OBJECT_NAME_NOT_FOUND: - return CR_NO_SUCH_VALUE; - - default: - return CR_FAILURE; - } -} - - -static VOID -SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID, - OUT LPWSTR pszEnumerator, - OUT LPWSTR pszDevice, - OUT LPWSTR pszInstance) -{ - WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN]; - LPWSTR lpEnumerator = NULL; - LPWSTR lpDevice = NULL; - LPWSTR lpInstance = NULL; - LPWSTR ptr; - - wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID); - - *pszEnumerator = 0; - *pszDevice = 0; - *pszInstance = 0; - - lpEnumerator = szLocalDeviceInstanceID; - - ptr = wcschr(lpEnumerator, L'\\'); - if (ptr != NULL) - { - *ptr = 0; - lpDevice = ++ptr; - - ptr = wcschr(lpDevice, L'\\'); - if (ptr != NULL) - { - *ptr = 0; - lpInstance = ++ptr; - } - } - - if (lpEnumerator != NULL) - wcscpy(pszEnumerator, lpEnumerator); - - if (lpDevice != NULL) - wcscpy(pszDevice, lpDevice); - - if (lpInstance != NULL) - wcscpy(pszInstance, lpInstance); -} - - -/* PUBLIC FUNCTIONS **********************************************************/ - -/* Function 0 */ -DWORD -WINAPI -PNP_Disconnect( - handle_t hBinding) -{ - UNREFERENCED_PARAMETER(hBinding); - return CR_SUCCESS; -} - - -/* Function 1 */ -DWORD -WINAPI -PNP_Connect( - handle_t hBinding) -{ - UNREFERENCED_PARAMETER(hBinding); - return CR_SUCCESS; -} - - -/* Function 2 */ -DWORD -WINAPI -PNP_GetVersion( - handle_t hBinding, - WORD *pVersion) -{ - UNREFERENCED_PARAMETER(hBinding); - - *pVersion = 0x0400; - return CR_SUCCESS; -} - - -/* Function 3 */ -DWORD -WINAPI -PNP_GetGlobalState( - handle_t hBinding, - DWORD *pulState, - DWORD ulFlags) -{ - UNREFERENCED_PARAMETER(hBinding); - UNREFERENCED_PARAMETER(ulFlags); - - *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE; - return CR_SUCCESS; -} - - -/* Function 4 */ -DWORD -WINAPI -PNP_InitDetection( - handle_t hBinding) -{ - UNREFERENCED_PARAMETER(hBinding); - - DPRINT("PNP_InitDetection() called\n"); - return CR_SUCCESS; -} - - -/* Function 5 */ -DWORD -WINAPI -PNP_ReportLogOn( - handle_t hBinding, - BOOL Admin, - DWORD ProcessId) -{ - DWORD ReturnValue = CR_FAILURE; - HANDLE hProcess; - - UNREFERENCED_PARAMETER(hBinding); - UNREFERENCED_PARAMETER(Admin); - - DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin, ProcessId); - - /* Get the users token */ - hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId); - - if (!hProcess) - { - DPRINT1("OpenProcess failed with error %u\n", GetLastError()); - goto cleanup; - } - - if (hUserToken) - { - CloseHandle(hUserToken); - hUserToken = NULL; - } - - if (!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken)) - { - DPRINT1("OpenProcessToken failed with error %u\n", GetLastError()); - goto cleanup; - } - - /* Trigger the installer thread */ - if (hInstallEvent) - SetEvent(hInstallEvent); - - ReturnValue = CR_SUCCESS; - -cleanup: - if (hProcess) - CloseHandle(hProcess); - - return ReturnValue; -} - - -/* Function 6 */ -DWORD -WINAPI -PNP_ValidateDeviceInstance( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulFlags) -{ - CONFIGRET ret = CR_SUCCESS; - HKEY hDeviceKey = NULL; - - UNREFERENCED_PARAMETER(hBinding); - UNREFERENCED_PARAMETER(ulFlags); - - DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n", - pDeviceID, ulFlags); - - if (RegOpenKeyExW(hEnumKey, - pDeviceID, - 0, - KEY_READ, - &hDeviceKey)) - { - DPRINT("Could not open the Device Key!\n"); - ret = CR_NO_SUCH_DEVNODE; - goto Done; - } - - /* FIXME: add more tests */ - -Done: - if (hDeviceKey != NULL) - RegCloseKey(hDeviceKey); - - DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret); - - return ret; -} - - -/* Function 7 */ -DWORD -WINAPI -PNP_GetRootDeviceInstance( - handle_t hBinding, - LPWSTR pDeviceID, - PNP_RPC_STRING_LEN ulLength) -{ - CONFIGRET ret = CR_SUCCESS; - - UNREFERENCED_PARAMETER(hBinding); - - DPRINT("PNP_GetRootDeviceInstance() called\n"); - - if (!pDeviceID) - { - ret = CR_INVALID_POINTER; - goto Done; - } - if (ulLength < lstrlenW(szRootDeviceId) + 1) - { - ret = CR_BUFFER_SMALL; - goto Done; - } - - lstrcpyW(pDeviceID, - szRootDeviceId); - -Done: - DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret); - - return ret; -} - - -/* Function 8 */ -DWORD -WINAPI -PNP_GetRelatedDeviceInstance( - handle_t hBinding, - DWORD ulRelationship, - LPWSTR pDeviceID, - LPWSTR pRelatedDeviceId, - PNP_RPC_STRING_LEN *pulLength, - DWORD ulFlags) -{ - PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData; - CONFIGRET ret = CR_SUCCESS; - NTSTATUS Status; - - UNREFERENCED_PARAMETER(hBinding); - UNREFERENCED_PARAMETER(ulFlags); - - DPRINT("PNP_GetRelatedDeviceInstance() called\n"); - DPRINT(" Relationship %ld\n", ulRelationship); - DPRINT(" DeviceId %S\n", pDeviceID); - - RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance, - pDeviceID); - - PlugPlayData.Relation = ulRelationship; - - PlugPlayData.RelatedDeviceInstanceLength = *pulLength; - PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId; - - Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice, - (PVOID)&PlugPlayData, - sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA)); - if (!NT_SUCCESS(Status)) - { - ret = NtStatusToCrError(Status); - } - - DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret); - if (ret == CR_SUCCESS) - { - DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance); - } - - return ret; -} - - -/* Function 9 */ -DWORD -WINAPI -PNP_EnumerateSubKeys( - handle_t hBinding, - DWORD ulBranch, - DWORD ulIndex, - LPWSTR Buffer, - PNP_RPC_STRING_LEN ulLength, - PNP_RPC_STRING_LEN *pulRequiredLen, - DWORD ulFlags) -{ - CONFIGRET ret = CR_SUCCESS; - HKEY hKey; - DWORD dwError; - - UNREFERENCED_PARAMETER(hBinding); - UNREFERENCED_PARAMETER(ulFlags); - - DPRINT("PNP_EnumerateSubKeys() called\n"); - - switch (ulBranch) - { - case PNP_ENUMERATOR_SUBKEYS: - hKey = hEnumKey; - break; - - case PNP_CLASS_SUBKEYS: - hKey = hClassKey; - break; - - default: - return CR_FAILURE; - } - - *pulRequiredLen = ulLength; - dwError = RegEnumKeyExW(hKey, - ulIndex, - Buffer, - pulRequiredLen, - NULL, - NULL, - NULL, - NULL); - if (dwError != ERROR_SUCCESS) - { - ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE; - } - else - { - (*pulRequiredLen)++; - } - - DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret); - - return ret; -} - - -static -CONFIGRET -GetRelationsInstanceList( - _In_ PWSTR pszDevice, - _In_ DWORD ulFlags, - _Inout_ PWSTR pszBuffer, - _Inout_ PDWORD pulLength) -{ - PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData; - NTSTATUS Status; - CONFIGRET ret = CR_SUCCESS; - - RtlInitUnicodeString(&PlugPlayData.DeviceInstance, - pszDevice); - - if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS) - { - PlugPlayData.Relations = 3; - } - else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS) - { - PlugPlayData.Relations = 2; - } - else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS) - { - PlugPlayData.Relations = 1; - } - else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS) - { - PlugPlayData.Relations = 0; - } - - PlugPlayData.BufferSize = *pulLength * sizeof(WCHAR); - PlugPlayData.Buffer = pszBuffer; - - Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations, - (PVOID)&PlugPlayData, - sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA)); - if (NT_SUCCESS(Status)) - { - *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR); - } - else - { - ret = NtStatusToCrError(Status); - } - - return ret; -} - - -static -CONFIGRET -GetServiceInstanceList( - _In_ PWSTR pszService, - _Inout_ PWSTR pszBuffer, - _Inout_ PDWORD pulLength) -{ - WCHAR szPathBuffer[512]; - WCHAR szName[16]; - HKEY hServicesKey = NULL, hServiceKey = NULL, hEnumKey = NULL; - DWORD dwValues, dwSize, dwIndex, dwUsedLength, dwPathLength; - DWORD dwError; - PWSTR pPtr; - CONFIGRET ret = CR_SUCCESS; - - /* Open the device key */ - dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - L"System\\CurrentControlSet\\Services", - 0, - KEY_READ, - &hServicesKey); - if (dwError != ERROR_SUCCESS) - { - DPRINT("Failed to open the services key (Error %lu)\n", dwError); - return CR_REGISTRY_ERROR; - } - - dwError = RegOpenKeyExW(hServicesKey, - pszService, - 0, - KEY_READ, - &hServiceKey); - if (dwError != ERROR_SUCCESS) - { - DPRINT("Failed to open the service key (Error %lu)\n", dwError); - ret = CR_REGISTRY_ERROR; - goto Done; - } - - dwError = RegOpenKeyExW(hServiceKey, - L"Enum", - 0, - KEY_READ, - &hEnumKey); - if (dwError != ERROR_SUCCESS) - { - DPRINT("Failed to open the service enum key (Error %lu)\n", dwError); - ret = CR_REGISTRY_ERROR; - goto Done; - } - - /* Retrieve the number of device instances */ - dwSize = sizeof(DWORD); - dwError = RegQueryValueExW(hEnumKey, - L"Count", - NULL, - NULL, - (LPBYTE)&dwValues, - &dwSize); - if (dwError != ERROR_SUCCESS) - { - DPRINT("RegQueryValueExW failed (Error %lu)\n", dwError); - dwValues = 1; - } - - DPRINT("dwValues %lu\n", dwValues); - - dwUsedLength = 0; - pPtr = pszBuffer; - - for (dwIndex = 0; dwIndex < dwValues; dwIndex++) - { - wsprintf(szName, L"%lu", dwIndex); - - dwSize = sizeof(szPathBuffer); - dwError = RegQueryValueExW(hEnumKey, - szName, - NULL, - NULL, - (LPBYTE)szPathBuffer, - &dwSize); - if (dwError != ERROR_SUCCESS) - break; - - DPRINT("Path: %S\n", szPathBuffer); - - dwPathLength = wcslen(szPathBuffer) + 1; - if (dwUsedLength + dwPathLength + 1 > *pulLength) - { - ret = CR_BUFFER_SMALL; - break; - } - - wcscpy(pPtr, szPathBuffer); - dwUsedLength += dwPathLength; - pPtr += dwPathLength; - - *pPtr = UNICODE_NULL; - } - -Done: - if (hEnumKey != NULL) - RegCloseKey(hEnumKey); - - if (hServiceKey != NULL) - RegCloseKey(hServiceKey); - - if (hServicesKey != NULL) - RegCloseKey(hServicesKey); - - if (ret == CR_SUCCESS) - *pulLength = dwUsedLength + 1; - else - *pulLength = 0; - - return ret; -} - - -static -CONFIGRET -GetDeviceInstanceList( - _In_ PWSTR pszDevice, - _Inout_ PWSTR pszBuffer, - _Inout_ PDWORD pulLength) -{ - WCHAR szInstanceBuffer[MAX_DEVICE_ID_LEN]; - WCHAR szPathBuffer[512]; - HKEY hDeviceKey; - DWORD dwInstanceLength, dwPathLength, dwUsedLength; - DWORD dwIndex, dwError; - PWSTR pPtr; - CONFIGRET ret = CR_SUCCESS; - - /* Open the device key */ - dwError = RegOpenKeyExW(hEnumKey, - pszDevice, - 0, - KEY_ENUMERATE_SUB_KEYS, - &hDeviceKey); - if (dwError != ERROR_SUCCESS) - { - DPRINT("Failed to open the device key (Error %lu)\n", dwError); - return CR_REGISTRY_ERROR; - } - - dwUsedLength = 0; - pPtr = pszBuffer; - - for (dwIndex = 0; ; dwIndex++) - { - dwInstanceLength = MAX_DEVICE_ID_LEN; - dwError = RegEnumKeyExW(hDeviceKey, - dwIndex, - szInstanceBuffer, - &dwInstanceLength, - NULL, - NULL, - NULL, - NULL); - if (dwError != ERROR_SUCCESS) - break; - - wsprintf(szPathBuffer, L"%s\\%s", pszDevice, szInstanceBuffer); - DPRINT("Path: %S\n", szPathBuffer); - - dwPathLength = wcslen(szPathBuffer) + 1; - if (dwUsedLength + dwPathLength + 1 > *pulLength) - { - ret = CR_BUFFER_SMALL; - break; - } - - wcscpy(pPtr, szPathBuffer); - dwUsedLength += dwPathLength; - pPtr += dwPathLength; - - *pPtr = UNICODE_NULL; - } - - RegCloseKey(hDeviceKey); - - if (ret == CR_SUCCESS) - *pulLength = dwUsedLength + 1; - else - *pulLength = 0; - - return ret; -} - - -CONFIGRET -GetEnumeratorInstanceList( - _In_ PWSTR pszEnumerator, - _Inout_ PWSTR pszBuffer, - _Inout_ PDWORD pulLength) -{ - WCHAR szDeviceBuffer[MAX_DEVICE_ID_LEN]; - WCHAR szPathBuffer[512]; - HKEY hEnumeratorKey; - PWSTR pPtr; - DWORD dwIndex, dwDeviceLength, dwUsedLength, dwRemainingLength, dwPathLength; - DWORD dwError; - CONFIGRET ret = CR_SUCCESS; - - /* Open the enumerator key */ - dwError = RegOpenKeyExW(hEnumKey, - pszEnumerator, - 0, - KEY_ENUMERATE_SUB_KEYS, - &hEnumeratorKey); - if (dwError != ERROR_SUCCESS) - { - DPRINT("Failed to open the enumerator key (Error %lu)\n", dwError); - return CR_REGISTRY_ERROR; - } - - dwUsedLength = 0; - dwRemainingLength = *pulLength; - pPtr = pszBuffer; - - for (dwIndex = 0; ; dwIndex++) - { - dwDeviceLength = MAX_DEVICE_ID_LEN; - dwError = RegEnumKeyExW(hEnumeratorKey, - dwIndex, - szDeviceBuffer, - &dwDeviceLength, - NULL, - NULL, - NULL, - NULL); - if (dwError != ERROR_SUCCESS) - break; - - wsprintf(szPathBuffer, L"%s\\%s", pszEnumerator, szDeviceBuffer); - DPRINT("Path: %S\n", szPathBuffer); - - dwPathLength = dwRemainingLength; - ret = GetDeviceInstanceList(szPathBuffer, - pPtr, - &dwPathLength); - if (ret != CR_SUCCESS) - break; - - dwUsedLength += dwPathLength - 1; - dwRemainingLength += dwPathLength - 1; - pPtr += dwPathLength - 1; - } - - RegCloseKey(hEnumeratorKey); - - if (ret == CR_SUCCESS) - *pulLength = dwUsedLength + 1; - else - *pulLength = 0; - - return ret; -} - - -static -CONFIGRET -GetAllInstanceList( - _Inout_ PWSTR pszBuffer, - _Inout_ PDWORD pulLength) -{ - WCHAR szEnumeratorBuffer[MAX_DEVICE_ID_LEN]; - PWSTR pPtr; - DWORD dwIndex, dwEnumeratorLength, dwUsedLength, dwRemainingLength, dwPathLength; - DWORD dwError; - CONFIGRET ret = CR_SUCCESS; - - dwUsedLength = 0; - dwRemainingLength = *pulLength; - pPtr = pszBuffer; - - for (dwIndex = 0; ; dwIndex++) - { - dwEnumeratorLength = MAX_DEVICE_ID_LEN; - dwError = RegEnumKeyExW(hEnumKey, - dwIndex, - szEnumeratorBuffer, - &dwEnumeratorLength, - NULL, NULL, NULL, NULL); - if (dwError != ERROR_SUCCESS) - break; - - dwPathLength = dwRemainingLength; - ret = GetEnumeratorInstanceList(szEnumeratorBuffer, - pPtr, - &dwPathLength); - if (ret != CR_SUCCESS) - break; - - dwUsedLength += dwPathLength - 1; - dwRemainingLength += dwPathLength - 1; - pPtr += dwPathLength - 1; - } - - if (ret == CR_SUCCESS) - *pulLength = dwUsedLength + 1; - else - *pulLength = 0; - - return ret; -} - - -/* Function 10 */ -DWORD -WINAPI -PNP_GetDeviceList( - handle_t hBinding, - LPWSTR pszFilter, - LPWSTR Buffer, - PNP_RPC_STRING_LEN *pulLength, - DWORD ulFlags) -{ - WCHAR szEnumerator[MAX_DEVICE_ID_LEN]; - WCHAR szDevice[MAX_DEVICE_ID_LEN]; - WCHAR szInstance[MAX_DEVICE_ID_LEN]; - CONFIGRET ret = CR_SUCCESS; - - DPRINT("PNP_GetDeviceList() called\n"); - - if (ulFlags & ~CM_GETIDLIST_FILTER_BITS) - return CR_INVALID_FLAG; - - if (pulLength == NULL) - return CR_INVALID_POINTER; - - if ((ulFlags != CM_GETIDLIST_FILTER_NONE) && - (pszFilter == NULL)) - return CR_INVALID_POINTER; - - if (ulFlags & - (CM_GETIDLIST_FILTER_BUSRELATIONS | - CM_GETIDLIST_FILTER_POWERRELATIONS | - CM_GETIDLIST_FILTER_REMOVALRELATIONS | - CM_GETIDLIST_FILTER_EJECTRELATIONS)) - { - ret = GetRelationsInstanceList(pszFilter, - ulFlags, - Buffer, - pulLength); - } - else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE) - { - ret = GetServiceInstanceList(pszFilter, - Buffer, - pulLength); - } - else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR) - { - SplitDeviceInstanceID(pszFilter, - szEnumerator, - szDevice, - szInstance); - - if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL) - { - ret = GetDeviceInstanceList(pszFilter, - Buffer, - pulLength); - } - else - { - ret = GetEnumeratorInstanceList(pszFilter, - Buffer, - pulLength); - } - } - else /* CM_GETIDLIST_FILTER_NONE */ - { - ret = GetAllInstanceList(Buffer, - pulLength); - } - - return ret; -} - - -static -CONFIGRET -GetRelationsInstanceListSize( - _In_ PWSTR pszDevice, - _In_ DWORD ulFlags, - _Inout_ PDWORD pulLength) -{ - PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData; - NTSTATUS Status; - CONFIGRET ret = CR_SUCCESS; - - RtlInitUnicodeString(&PlugPlayData.DeviceInstance, - pszDevice); - - if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS) - { - PlugPlayData.Relations = 3; - } - else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS) - { - PlugPlayData.Relations = 2; - } - else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS) - { - PlugPlayData.Relations = 1; - } - else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS) - { - PlugPlayData.Relations = 0; - } - - PlugPlayData.BufferSize = 0; - PlugPlayData.Buffer = NULL; - - Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations, - (PVOID)&PlugPlayData, - sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA)); - if (NT_SUCCESS(Status)) - { - *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR); - } - else - { - ret = NtStatusToCrError(Status); - } - - return ret; -} - - -static -CONFIGRET -GetServiceInstanceListSize( - _In_ PWSTR pszService, - _Out_ PDWORD pulLength) -{ - HKEY hServicesKey = NULL, hServiceKey = NULL, hEnumKey = NULL; - DWORD dwValues, dwMaxValueLength, dwSize; - DWORD dwError; - CONFIGRET ret = CR_SUCCESS; - - /* Open the device key */ - dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - L"System\\CurrentControlSet\\Services", - 0, - KEY_READ, - &hServicesKey); - if (dwError != ERROR_SUCCESS) - { - DPRINT("Failed to open the services key (Error %lu)\n", dwError); - return CR_REGISTRY_ERROR; - } - - dwError = RegOpenKeyExW(hServicesKey, - pszService, - 0, - KEY_READ, - &hServiceKey); - if (dwError != ERROR_SUCCESS) - { - DPRINT("Failed to open the service key (Error %lu)\n", dwError); - ret = CR_REGISTRY_ERROR; - goto Done; - } - - dwError = RegOpenKeyExW(hServiceKey, - L"Enum", - 0, - KEY_READ, - &hEnumKey); - if (dwError != ERROR_SUCCESS) - { - DPRINT("Failed to open the service enum key (Error %lu)\n", dwError); - ret = CR_REGISTRY_ERROR; - goto Done; - } - - /* Retrieve the number of device instances */ - dwSize = sizeof(DWORD); - dwError = RegQueryValueExW(hEnumKey, - L"Count", - NULL, - NULL, - (LPBYTE)&dwValues, - &dwSize); - if (dwError != ERROR_SUCCESS) - { - DPRINT("RegQueryValueExW failed (Error %lu)\n", dwError); - dwValues = 1; - } - - /* Retrieve the maximum instance name length */ - dwError = RegQueryInfoKeyW(hEnumKey, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - &dwMaxValueLength, - NULL, - NULL); - if (dwError != ERROR_SUCCESS) - { - DPRINT("RegQueryInfoKeyW failed (Error %lu)\n", dwError); - dwMaxValueLength = MAX_DEVICE_ID_LEN; - } - - DPRINT("dwValues %lu dwMaxValueLength %lu\n", dwValues, dwMaxValueLength / sizeof(WCHAR)); - - /* Return the largest possible buffer size */ - *pulLength = dwValues * dwMaxValueLength / sizeof(WCHAR) + 2; - -Done: - if (hEnumKey != NULL) - RegCloseKey(hEnumKey); - - if (hServiceKey != NULL) - RegCloseKey(hServiceKey); - - if (hServicesKey != NULL) - RegCloseKey(hServicesKey); - - return ret; -} - - -static -CONFIGRET -GetDeviceInstanceListSize( - _In_ LPCWSTR pszDevice, - _Out_ PULONG pulLength) -{ - HKEY hDeviceKey; - DWORD dwSubKeys, dwMaxSubKeyLength; - DWORD dwError; - - /* Open the device key */ - dwError = RegOpenKeyExW(hEnumKey, - pszDevice, - 0, - KEY_READ, - &hDeviceKey); - if (dwError != ERROR_SUCCESS) - { - DPRINT("Failed to open the device key (Error %lu)\n", dwError); - return CR_REGISTRY_ERROR; - } - - /* Retrieve the number of device instances and the maximum name length */ - dwError = RegQueryInfoKeyW(hDeviceKey, - NULL, - NULL, - NULL, - &dwSubKeys, - &dwMaxSubKeyLength, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); - if (dwError != ERROR_SUCCESS) - { - DPRINT("RegQueryInfoKeyW failed (Error %lu)\n", dwError); - dwSubKeys = 0; - dwMaxSubKeyLength = 0; - } - - /* Close the device key */ - RegCloseKey(hDeviceKey); - - /* Return the largest possible buffer size */ - *pulLength = dwSubKeys * (wcslen(pszDevice) + 1 + dwMaxSubKeyLength + 1); - - return CR_SUCCESS; -} - - -static -CONFIGRET -GetEnumeratorInstanceListSize( - _In_ LPCWSTR pszEnumerator, - _Out_ PULONG pulLength) -{ - WCHAR szDeviceBuffer[MAX_DEVICE_ID_LEN]; - WCHAR szPathBuffer[512]; - HKEY hEnumeratorKey; - DWORD dwIndex, dwDeviceLength, dwBufferLength; - DWORD dwError; - CONFIGRET ret = CR_SUCCESS; - - *pulLength = 0; - - /* Open the enumerator key */ - dwError = RegOpenKeyExW(hEnumKey, - pszEnumerator, - 0, - KEY_ENUMERATE_SUB_KEYS, - &hEnumeratorKey); - if (dwError != ERROR_SUCCESS) - { - DPRINT("Failed to open the enumerator key (Error %lu)\n", dwError); - return CR_REGISTRY_ERROR; - } - - for (dwIndex = 0; ; dwIndex++) - { - dwDeviceLength = MAX_DEVICE_ID_LEN; - dwError = RegEnumKeyExW(hEnumeratorKey, - dwIndex, - szDeviceBuffer, - &dwDeviceLength, - NULL, - NULL, - NULL, - NULL); - if (dwError != ERROR_SUCCESS) - break; - - wsprintf(szPathBuffer, L"%s\\%s", pszEnumerator, szDeviceBuffer); - DPRINT("Path: %S\n", szPathBuffer); - - ret = GetDeviceInstanceListSize(szPathBuffer, &dwBufferLength); - if (ret != CR_SUCCESS) - { - *pulLength = 0; - break; - } - - *pulLength += dwBufferLength; - } - - /* Close the enumerator key */ - RegCloseKey(hEnumeratorKey); - - return ret; -} - - -static -CONFIGRET -GetAllInstanceListSize( - _Out_ PULONG pulLength) -{ - WCHAR szEnumeratorBuffer[MAX_DEVICE_ID_LEN]; - DWORD dwIndex, dwEnumeratorLength, dwBufferLength; - DWORD dwError; - CONFIGRET ret = CR_SUCCESS; - - for (dwIndex = 0; ; dwIndex++) - { - dwEnumeratorLength = MAX_DEVICE_ID_LEN; - dwError = RegEnumKeyExW(hEnumKey, - dwIndex, - szEnumeratorBuffer, - &dwEnumeratorLength, - NULL, NULL, NULL, NULL); - if (dwError != ERROR_SUCCESS) - break; - - /* Get the size of all device instances for the enumerator */ - ret = GetEnumeratorInstanceListSize(szEnumeratorBuffer, - &dwBufferLength); - if (ret != CR_SUCCESS) - break; - - *pulLength += dwBufferLength; - } - - return ret; -} - - -/* Function 11 */ -DWORD -WINAPI -PNP_GetDeviceListSize( - handle_t hBinding, - LPWSTR pszFilter, - PNP_RPC_BUFFER_SIZE *pulLength, - DWORD ulFlags) -{ - WCHAR szEnumerator[MAX_DEVICE_ID_LEN]; - WCHAR szDevice[MAX_DEVICE_ID_LEN]; - WCHAR szInstance[MAX_DEVICE_ID_LEN]; - CONFIGRET ret = CR_SUCCESS; - - DPRINT("PNP_GetDeviceListSize(%p %S %p 0x%lx)\n", - hBinding, pszFilter, pulLength, ulFlags); - - if (ulFlags & ~CM_GETIDLIST_FILTER_BITS) - return CR_INVALID_FLAG; - - if (pulLength == NULL) - return CR_INVALID_POINTER; - - if ((ulFlags != CM_GETIDLIST_FILTER_NONE) && - (pszFilter == NULL)) - return CR_INVALID_POINTER; - - *pulLength = 0; - - if (ulFlags & - (CM_GETIDLIST_FILTER_BUSRELATIONS | - CM_GETIDLIST_FILTER_POWERRELATIONS | - CM_GETIDLIST_FILTER_REMOVALRELATIONS | - CM_GETIDLIST_FILTER_EJECTRELATIONS)) - { - ret = GetRelationsInstanceListSize(pszFilter, - ulFlags, - pulLength); - } - else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE) - { - ret = GetServiceInstanceListSize(pszFilter, - pulLength); - } - else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR) - { - SplitDeviceInstanceID(pszFilter, - szEnumerator, - szDevice, - szInstance); - - if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL) - { - ret = GetDeviceInstanceListSize(pszFilter, - pulLength); - } - else - { - ret = GetEnumeratorInstanceListSize(pszFilter, - pulLength); - } - } - else /* CM_GETIDLIST_FILTER_NONE */ - { - ret = GetAllInstanceListSize(pulLength); - } - - /* Add one character for the terminating double UNICODE_NULL */ - if (ret == CR_SUCCESS) - (*pulLength) += 1; - - return ret; -} - - -/* Function 12 */ -DWORD -WINAPI -PNP_GetDepth( - handle_t hBinding, - LPWSTR pszDeviceID, - DWORD *pulDepth, - DWORD ulFlags) -{ - PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData; - CONFIGRET ret = CR_SUCCESS; - NTSTATUS Status; - - UNREFERENCED_PARAMETER(hBinding); - UNREFERENCED_PARAMETER(ulFlags); - - DPRINT("PNP_GetDepth() called\n"); - - RtlInitUnicodeString(&PlugPlayData.DeviceInstance, - pszDeviceID); - - Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth, - (PVOID)&PlugPlayData, - sizeof(PLUGPLAY_CONTROL_DEPTH_DATA)); - if (NT_SUCCESS(Status)) - { - *pulDepth = PlugPlayData.Depth; - } - else - { - ret = NtStatusToCrError(Status); - } - - DPRINT("PNP_GetDepth() done (returns %lx)\n", ret); - - return ret; -} - - -/* Function 13 */ -DWORD -WINAPI -PNP_GetDeviceRegProp( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulProperty, - DWORD *pulRegDataType, - BYTE *Buffer, - PNP_PROP_SIZE *pulTransferLen, - PNP_PROP_SIZE *pulLength, - DWORD ulFlags) -{ - PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData; - CONFIGRET ret = CR_SUCCESS; - LPWSTR lpValueName = NULL; - HKEY hKey = NULL; - LONG lError; - NTSTATUS Status; - - UNREFERENCED_PARAMETER(hBinding); - - DPRINT("PNP_GetDeviceRegProp() called\n"); - - if (pulTransferLen == NULL || pulLength == NULL) - { - ret = CR_INVALID_POINTER; - goto done; - } - - if (ulFlags != 0) - { - ret = CR_INVALID_FLAG; - goto done; - } - - /* FIXME: Check pDeviceID */ - - if (*pulLength < *pulTransferLen) - *pulLength = *pulTransferLen; - - *pulTransferLen = 0; - - switch (ulProperty) - { - case CM_DRP_DEVICEDESC: - lpValueName = L"DeviceDesc"; - break; - - case CM_DRP_HARDWAREID: - lpValueName = L"HardwareID"; - break; - - case CM_DRP_COMPATIBLEIDS: - lpValueName = L"CompatibleIDs"; - break; - - case CM_DRP_SERVICE: - lpValueName = L"Service"; - break; - - case CM_DRP_CLASS: - lpValueName = L"Class"; - break; - - case CM_DRP_CLASSGUID: - lpValueName = L"ClassGUID"; - break; - - case CM_DRP_DRIVER: - lpValueName = L"Driver"; - break; - - case CM_DRP_CONFIGFLAGS: - lpValueName = L"ConfigFlags"; - break; - - case CM_DRP_MFG: - lpValueName = L"Mfg"; - break; - - case CM_DRP_FRIENDLYNAME: - lpValueName = L"FriendlyName"; - break; - - case CM_DRP_LOCATION_INFORMATION: - lpValueName = L"LocationInformation"; - break; - - case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME: - PlugPlayData.Property = PNP_PROPERTY_PHYSICAL_DEVICE_OBJECT_NAME; - break; - - case CM_DRP_CAPABILITIES: - lpValueName = L"Capabilities"; - break; - - case CM_DRP_UI_NUMBER: - PlugPlayData.Property = PNP_PROPERTY_UI_NUMBER; - break; - - case CM_DRP_UPPERFILTERS: - lpValueName = L"UpperFilters"; - break; - - case CM_DRP_LOWERFILTERS: - lpValueName = L"LowerFilters"; - break; - - case CM_DRP_BUSTYPEGUID: - PlugPlayData.Property = PNP_PROPERTY_BUSTYPEGUID; - break; - - case CM_DRP_LEGACYBUSTYPE: - PlugPlayData.Property = PNP_PROPERTY_LEGACYBUSTYPE; - break; - - case CM_DRP_BUSNUMBER: - PlugPlayData.Property = PNP_PROPERTY_BUSNUMBER; - break; - - case CM_DRP_ENUMERATOR_NAME: - PlugPlayData.Property = PNP_PROPERTY_ENUMERATOR_NAME; - break; - - case CM_DRP_SECURITY: - lpValueName = L"Security"; - break; - - case CM_DRP_DEVTYPE: - lpValueName = L"DeviceType"; - break; - - case CM_DRP_EXCLUSIVE: - lpValueName = L"Exclusive"; - break; - - case CM_DRP_CHARACTERISTICS: - lpValueName = L"DeviceCharacteristics"; - break; - - case CM_DRP_ADDRESS: - PlugPlayData.Property = PNP_PROPERTY_ADDRESS; - break; - - case CM_DRP_UI_NUMBER_DESC_FORMAT: - lpValueName = L"UINumberDescFormat"; - break; - - case CM_DRP_DEVICE_POWER_DATA: - PlugPlayData.Property = PNP_PROPERTY_POWER_DATA; - break; - - case CM_DRP_REMOVAL_POLICY: - PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY; - break; - - case CM_DRP_REMOVAL_POLICY_HW_DEFAULT: - PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY_HARDWARE_DEFAULT; - break; - - case CM_DRP_REMOVAL_POLICY_OVERRIDE: - lpValueName = L"RemovalPolicy"; - break; - - case CM_DRP_INSTALL_STATE: - PlugPlayData.Property = PNP_PROPERTY_INSTALL_STATE; - break; - -#if (WINVER >= _WIN32_WINNT_WS03) - case CM_DRP_LOCATION_PATHS: - PlugPlayData.Property = PNP_PROPERTY_LOCATION_PATHS; - break; -#endif - -#if (WINVER >= _WIN32_WINNT_WIN7) - case CM_DRP_BASE_CONTAINERID: - PlugPlayData.Property = PNP_PROPERTY_CONTAINERID; - break; -#endif - - default: - ret = CR_INVALID_PROPERTY; - goto done; - } - - DPRINT("Value name: %S\n", lpValueName); - - if (lpValueName) - { - /* Retrieve information from the Registry */ - lError = RegOpenKeyExW(hEnumKey, - pDeviceID, - 0, - KEY_QUERY_VALUE, - &hKey); - if (lError != ERROR_SUCCESS) - { - hKey = NULL; - *pulLength = 0; - ret = CR_INVALID_DEVNODE; - goto done; - } - - lError = RegQueryValueExW(hKey, - lpValueName, - NULL, - pulRegDataType, - Buffer, - pulLength); - if (lError != ERROR_SUCCESS) - { - if (lError == ERROR_MORE_DATA) - { - ret = CR_BUFFER_SMALL; - } - else - { - *pulLength = 0; - ret = CR_NO_SUCH_VALUE; - } - } - } - else - { - /* Retrieve information from the Device Node */ - RtlInitUnicodeString(&PlugPlayData.DeviceInstance, - pDeviceID); - PlugPlayData.Buffer = Buffer; - PlugPlayData.BufferSize = *pulLength; - - Status = NtPlugPlayControl(PlugPlayControlProperty, - (PVOID)&PlugPlayData, - sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA)); - if (NT_SUCCESS(Status)) - { - *pulLength = PlugPlayData.BufferSize; - } - else - { - ret = NtStatusToCrError(Status); - } - } - -done: - if (pulTransferLen) - *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0; - - if (hKey != NULL) - RegCloseKey(hKey); - - DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret); - - return ret; -} - - -/* Function 14 */ -DWORD -WINAPI -PNP_SetDeviceRegProp( - handle_t hBinding, - LPWSTR pDeviceId, - DWORD ulProperty, - DWORD ulDataType, - BYTE *Buffer, - PNP_PROP_SIZE ulLength, - DWORD ulFlags) -{ - CONFIGRET ret = CR_SUCCESS; - LPWSTR lpValueName = NULL; - HKEY hKey = 0; - - UNREFERENCED_PARAMETER(hBinding); - UNREFERENCED_PARAMETER(ulFlags); - - DPRINT("PNP_SetDeviceRegProp() called\n"); - - DPRINT("DeviceId: %S\n", pDeviceId); - DPRINT("Property: %lu\n", ulProperty); - DPRINT("DataType: %lu\n", ulDataType); - DPRINT("Length: %lu\n", ulLength); - - switch (ulProperty) - { - case CM_DRP_DEVICEDESC: - lpValueName = L"DeviceDesc"; - break; - - case CM_DRP_HARDWAREID: - lpValueName = L"HardwareID"; - break; - - case CM_DRP_COMPATIBLEIDS: - lpValueName = L"CompatibleIDs"; - break; - - case CM_DRP_SERVICE: - lpValueName = L"Service"; - break; - - case CM_DRP_CLASS: - lpValueName = L"Class"; - break; - - case CM_DRP_CLASSGUID: - lpValueName = L"ClassGUID"; - break; - - case CM_DRP_DRIVER: - lpValueName = L"Driver"; - break; - - case CM_DRP_CONFIGFLAGS: - lpValueName = L"ConfigFlags"; - break; - - case CM_DRP_MFG: - lpValueName = L"Mfg"; - break; - - case CM_DRP_FRIENDLYNAME: - lpValueName = L"FriendlyName"; - break; - - case CM_DRP_LOCATION_INFORMATION: - lpValueName = L"LocationInformation"; - break; - - case CM_DRP_UPPERFILTERS: - lpValueName = L"UpperFilters"; - break; - - case CM_DRP_LOWERFILTERS: - lpValueName = L"LowerFilters"; - break; - - case CM_DRP_SECURITY: - lpValueName = L"Security"; - break; - - case CM_DRP_DEVTYPE: - lpValueName = L"DeviceType"; - break; - - case CM_DRP_EXCLUSIVE: - lpValueName = L"Exclusive"; - break; - - case CM_DRP_CHARACTERISTICS: - lpValueName = L"DeviceCharacteristics"; - break; - - case CM_DRP_UI_NUMBER_DESC_FORMAT: - lpValueName = L"UINumberDescFormat"; - break; - - case CM_DRP_REMOVAL_POLICY_OVERRIDE: - lpValueName = L"RemovalPolicy"; - break; - - default: - return CR_INVALID_PROPERTY; - } - - DPRINT("Value name: %S\n", lpValueName); - - if (RegOpenKeyExW(hEnumKey, - pDeviceId, - 0, - KEY_SET_VALUE, - &hKey)) - return CR_INVALID_DEVNODE; - - if (ulLength == 0) - { - if (RegDeleteValueW(hKey, - lpValueName)) - ret = CR_REGISTRY_ERROR; - } - else - { - if (RegSetValueExW(hKey, - lpValueName, - 0, - ulDataType, - Buffer, - ulLength)) - ret = CR_REGISTRY_ERROR; - } - - RegCloseKey(hKey); - - DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret); - - return ret; -} - - -/* Function 15 */ -DWORD -WINAPI -PNP_GetClassInstance( - handle_t hBinding, - LPWSTR pDeviceId, - LPWSTR pszClassInstance, - PNP_RPC_STRING_LEN ulLength) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 16 */ -DWORD -WINAPI -PNP_CreateKey( - handle_t hBinding, - LPWSTR pszSubKey, - DWORD samDesired, - DWORD ulFlags) -{ - HKEY hKey = 0; - - if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, - pszSubKey, - 0, - NULL, - 0, - KEY_ALL_ACCESS, - NULL, - &hKey, - NULL)) - return CR_REGISTRY_ERROR; - - /* FIXME: Set security key */ - - RegCloseKey(hKey); - - return CR_SUCCESS; -} - - -/* Function 17 */ -DWORD -WINAPI -PNP_DeleteRegistryKey( - handle_t hBinding, - LPWSTR pszDeviceID, - LPWSTR pszParentKey, - LPWSTR pszChildKey, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 18 */ -DWORD -WINAPI -PNP_GetClassCount( - handle_t hBinding, - DWORD *pulClassCount, - DWORD ulFlags) -{ - HKEY hKey; - DWORD dwError; - - UNREFERENCED_PARAMETER(hBinding); - UNREFERENCED_PARAMETER(ulFlags); - - dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - REGSTR_PATH_CLASS, - 0, - KEY_QUERY_VALUE, - &hKey); - if (dwError != ERROR_SUCCESS) - return CR_INVALID_DATA; - - dwError = RegQueryInfoKeyW(hKey, - NULL, - NULL, - NULL, - pulClassCount, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); - RegCloseKey(hKey); - if (dwError != ERROR_SUCCESS) - return CR_INVALID_DATA; - - return CR_SUCCESS; -} - - -/* Function 19 */ -DWORD -WINAPI -PNP_GetClassName( - handle_t hBinding, - LPWSTR pszClassGuid, - LPWSTR Buffer, - PNP_RPC_STRING_LEN *pulLength, - DWORD ulFlags) -{ - WCHAR szKeyName[MAX_PATH]; - CONFIGRET ret = CR_SUCCESS; - HKEY hKey; - DWORD dwSize; - - UNREFERENCED_PARAMETER(hBinding); - UNREFERENCED_PARAMETER(ulFlags); - - DPRINT("PNP_GetClassName() called\n"); - - lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\"); - if (lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR))) - lstrcatW(szKeyName, pszClassGuid); - else - return CR_INVALID_DATA; - - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, - szKeyName, - 0, - KEY_QUERY_VALUE, - &hKey)) - return CR_REGISTRY_ERROR; - - dwSize = *pulLength * sizeof(WCHAR); - if (RegQueryValueExW(hKey, - L"Class", - NULL, - NULL, - (LPBYTE)Buffer, - &dwSize)) - { - *pulLength = 0; - ret = CR_REGISTRY_ERROR; - } - else - { - *pulLength = dwSize / sizeof(WCHAR); - } - - RegCloseKey(hKey); - - DPRINT("PNP_GetClassName() done (returns %lx)\n", ret); - - return ret; -} - - -/* Function 20 */ -DWORD -WINAPI -PNP_DeleteClassKey( - handle_t hBinding, - LPWSTR pszClassGuid, - DWORD ulFlags) -{ - CONFIGRET ret = CR_SUCCESS; - - UNREFERENCED_PARAMETER(hBinding); - - DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid, ulFlags); - - if (ulFlags & CM_DELETE_CLASS_SUBKEYS) - { - if (SHDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS) - ret = CR_REGISTRY_ERROR; - } - else - { - if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS) - ret = CR_REGISTRY_ERROR; - } - - DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret); - - return ret; -} - - -/* Function 21 */ -DWORD -WINAPI -PNP_GetInterfaceDeviceAlias( - handle_t hBinding, - LPWSTR pszInterfaceDevice, - GUID *AliasInterfaceGuid, - LPWSTR pszAliasInterfaceDevice, - PNP_RPC_STRING_LEN *pulLength, - PNP_RPC_STRING_LEN *pulTransferLen, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 22 */ -DWORD -WINAPI -PNP_GetInterfaceDeviceList( - handle_t hBinding, - GUID *InterfaceGuid, - LPWSTR pszDeviceID, - BYTE *Buffer, - PNP_RPC_BUFFER_SIZE *pulLength, - DWORD ulFlags) -{ - NTSTATUS Status; - PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData; - DWORD ret = CR_SUCCESS; - - UNREFERENCED_PARAMETER(hBinding); - - RtlInitUnicodeString(&PlugPlayData.DeviceInstance, - pszDeviceID); - - PlugPlayData.Flags = ulFlags; - PlugPlayData.FilterGuid = InterfaceGuid; - PlugPlayData.Buffer = Buffer; - PlugPlayData.BufferSize = *pulLength; - - Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList, - (PVOID)&PlugPlayData, - sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA)); - if (NT_SUCCESS(Status)) - { - *pulLength = PlugPlayData.BufferSize; - } - else - { - ret = NtStatusToCrError(Status); - } - - DPRINT("PNP_GetInterfaceDeviceListSize() done (returns %lx)\n", ret); - return ret; -} - - -/* Function 23 */ -DWORD -WINAPI -PNP_GetInterfaceDeviceListSize( - handle_t hBinding, - PNP_RPC_BUFFER_SIZE *pulLen, - GUID *InterfaceGuid, - LPWSTR pszDeviceID, - DWORD ulFlags) -{ - NTSTATUS Status; - PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData; - DWORD ret = CR_SUCCESS; - - UNREFERENCED_PARAMETER(hBinding); - - DPRINT("PNP_GetInterfaceDeviceListSize() called\n"); - - RtlInitUnicodeString(&PlugPlayData.DeviceInstance, - pszDeviceID); - - PlugPlayData.FilterGuid = InterfaceGuid; - PlugPlayData.Buffer = NULL; - PlugPlayData.BufferSize = 0; - PlugPlayData.Flags = ulFlags; - - Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList, - (PVOID)&PlugPlayData, - sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA)); - if (NT_SUCCESS(Status)) - { - *pulLen = PlugPlayData.BufferSize; - } - else - { - ret = NtStatusToCrError(Status); - } - - DPRINT("PNP_GetInterfaceDeviceListSize() done (returns %lx)\n", ret); - return ret; -} - - -/* Function 24 */ -DWORD -WINAPI -PNP_RegisterDeviceClassAssociation( - handle_t hBinding, - LPWSTR pszDeviceID, - GUID *InterfaceGuid, - LPWSTR pszReference, - LPWSTR pszSymLink, - PNP_RPC_STRING_LEN *pulLength, - PNP_RPC_STRING_LEN *pulTransferLen, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 25 */ -DWORD -WINAPI -PNP_UnregisterDeviceClassAssociation( - handle_t hBinding, - LPWSTR pszInterfaceDevice, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 26 */ -DWORD -WINAPI -PNP_GetClassRegProp( - handle_t hBinding, - LPWSTR pszClassGuid, - DWORD ulProperty, - DWORD *pulRegDataType, - BYTE *Buffer, - PNP_RPC_STRING_LEN *pulTransferLen, - PNP_RPC_STRING_LEN *pulLength, - DWORD ulFlags) -{ - CONFIGRET ret = CR_SUCCESS; - LPWSTR lpValueName = NULL; - HKEY hInstKey = NULL; - HKEY hPropKey = NULL; - LONG lError; - - UNREFERENCED_PARAMETER(hBinding); - - DPRINT("PNP_GetClassRegProp() called\n"); - - if (pulTransferLen == NULL || pulLength == NULL) - { - ret = CR_INVALID_POINTER; - goto done; - } - - if (ulFlags != 0) - { - ret = CR_INVALID_FLAG; - goto done; - } - - if (*pulLength < *pulTransferLen) - *pulLength = *pulTransferLen; - - *pulTransferLen = 0; - - switch (ulProperty) - { - case CM_CRP_SECURITY: - lpValueName = L"Security"; - break; - - case CM_CRP_DEVTYPE: - lpValueName = L"DeviceType"; - break; - - case CM_CRP_EXCLUSIVE: - lpValueName = L"Exclusive"; - break; - - case CM_CRP_CHARACTERISTICS: - lpValueName = L"DeviceCharacteristics"; - break; - - default: - ret = CR_INVALID_PROPERTY; - goto done; - } - - DPRINT("Value name: %S\n", lpValueName); - - lError = RegOpenKeyExW(hClassKey, - pszClassGuid, - 0, - KEY_READ, - &hInstKey); - if (lError != ERROR_SUCCESS) - { - *pulLength = 0; - ret = CR_NO_SUCH_REGISTRY_KEY; - goto done; - } - - lError = RegOpenKeyExW(hInstKey, - L"Properties", - 0, - KEY_READ, - &hPropKey); - if (lError != ERROR_SUCCESS) - { - *pulLength = 0; - ret = CR_NO_SUCH_REGISTRY_KEY; - goto done; - } - - lError = RegQueryValueExW(hPropKey, - lpValueName, - NULL, - pulRegDataType, - Buffer, - pulLength); - if (lError != ERROR_SUCCESS) - { - if (lError == ERROR_MORE_DATA) - { - ret = CR_BUFFER_SMALL; - } - else - { - *pulLength = 0; - ret = CR_NO_SUCH_VALUE; - } - } - -done: - if (ret == CR_SUCCESS) - *pulTransferLen = *pulLength; - - if (hPropKey != NULL) - RegCloseKey(hPropKey); - - if (hInstKey != NULL) - RegCloseKey(hInstKey); - - DPRINT("PNP_GetClassRegProp() done (returns %lx)\n", ret); - - return ret; -} - - -/* Function 27 */ -DWORD -WINAPI -PNP_SetClassRegProp( - handle_t hBinding, - LPWSTR pszClassGuid, - DWORD ulProperty, - DWORD ulDataType, - BYTE *Buffer, - PNP_PROP_SIZE ulLength, - DWORD ulFlags) -{ - CONFIGRET ret = CR_SUCCESS; - LPWSTR lpValueName = NULL; - HKEY hInstKey = 0; - HKEY hPropKey = 0; - LONG lError; - - UNREFERENCED_PARAMETER(hBinding); - - DPRINT("PNP_SetClassRegProp() called\n"); - - if (ulFlags != 0) - return CR_INVALID_FLAG; - - switch (ulProperty) - { - case CM_CRP_SECURITY: - lpValueName = L"Security"; - break; - - case CM_CRP_DEVTYPE: - lpValueName = L"DeviceType"; - break; - - case CM_CRP_EXCLUSIVE: - lpValueName = L"Exclusive"; - break; - - case CM_CRP_CHARACTERISTICS: - lpValueName = L"DeviceCharacteristics"; - break; - - default: - return CR_INVALID_PROPERTY; - } - - lError = RegOpenKeyExW(hClassKey, - pszClassGuid, - 0, - KEY_WRITE, - &hInstKey); - if (lError != ERROR_SUCCESS) - { - ret = CR_NO_SUCH_REGISTRY_KEY; - goto done; - } - - /* FIXME: Set security descriptor */ - lError = RegCreateKeyExW(hInstKey, - L"Properties", - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, - NULL, - &hPropKey, - NULL); - if (lError != ERROR_SUCCESS) - { - ret = CR_REGISTRY_ERROR; - goto done; - } - - if (ulLength == 0) - { - if (RegDeleteValueW(hPropKey, - lpValueName)) - ret = CR_REGISTRY_ERROR; - } - else - { - if (RegSetValueExW(hPropKey, - lpValueName, - 0, - ulDataType, - Buffer, - ulLength)) - ret = CR_REGISTRY_ERROR; - } - -done: - if (hPropKey != NULL) - RegCloseKey(hPropKey); - - if (hInstKey != NULL) - RegCloseKey(hInstKey); - - return ret; -} - - -static CONFIGRET -CreateDeviceInstance(LPWSTR pszDeviceID) -{ - WCHAR szEnumerator[MAX_DEVICE_ID_LEN]; - WCHAR szDevice[MAX_DEVICE_ID_LEN]; - WCHAR szInstance[MAX_DEVICE_ID_LEN]; - HKEY hKeyEnumerator; - HKEY hKeyDevice; - HKEY hKeyInstance; - HKEY hKeyControl; - LONG lError; - - /* Split the instance ID */ - SplitDeviceInstanceID(pszDeviceID, - szEnumerator, - szDevice, - szInstance); - - /* Open or create the enumerator key */ - lError = RegCreateKeyExW(hEnumKey, - szEnumerator, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, - NULL, - &hKeyEnumerator, - NULL); - if (lError != ERROR_SUCCESS) - { - return CR_REGISTRY_ERROR; - } - - /* Open or create the device key */ - lError = RegCreateKeyExW(hKeyEnumerator, - szDevice, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, - NULL, - &hKeyDevice, - NULL); - - /* Close the enumerator key */ - RegCloseKey(hKeyEnumerator); - - if (lError != ERROR_SUCCESS) - { - return CR_REGISTRY_ERROR; - } - - /* Try to open the instance key and fail if it exists */ - lError = RegOpenKeyExW(hKeyDevice, - szInstance, - 0, - KEY_SET_VALUE, - &hKeyInstance); - if (lError == ERROR_SUCCESS) - { - DPRINT1("Instance %S already exists!\n", szInstance); - RegCloseKey(hKeyInstance); - RegCloseKey(hKeyDevice); - return CR_ALREADY_SUCH_DEVINST; - } - - /* Create a new instance key */ - lError = RegCreateKeyExW(hKeyDevice, - szInstance, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, - NULL, - &hKeyInstance, - NULL); - - /* Close the device key */ - RegCloseKey(hKeyDevice); - - if (lError != ERROR_SUCCESS) - { - return CR_REGISTRY_ERROR; - } - - /* Create the 'Control' sub key */ - lError = RegCreateKeyExW(hKeyInstance, - L"Control", - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, - NULL, - &hKeyControl, - NULL); - if (lError == ERROR_SUCCESS) - { - RegCloseKey(hKeyControl); - } - - RegCloseKey(hKeyInstance); - - return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR; -} - - -/* Function 28 */ -DWORD -WINAPI -PNP_CreateDevInst( - handle_t hBinding, - LPWSTR pszDeviceID, - LPWSTR pszParentDeviceID, - PNP_RPC_STRING_LEN ulLength, - DWORD ulFlags) -{ - CONFIGRET ret = CR_SUCCESS; - - DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID); - - if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID) - { - WCHAR szGeneratedInstance[MAX_DEVICE_ID_LEN]; - DWORD dwInstanceNumber; - - /* Generated ID is: Root\\ */ - dwInstanceNumber = 0; - do - { - swprintf(szGeneratedInstance, L"Root\\%ls\\%04lu", - pszDeviceID, dwInstanceNumber); - - /* Try to create a device instance with this ID */ - ret = CreateDeviceInstance(szGeneratedInstance); - - dwInstanceNumber++; - } - while (ret == CR_ALREADY_SUCH_DEVINST); - - if (ret == CR_SUCCESS) - { - /* pszDeviceID is an out parameter too for generated IDs */ - if (wcslen(szGeneratedInstance) > ulLength) - { - ret = CR_BUFFER_SMALL; - } - else - { - wcscpy(pszDeviceID, szGeneratedInstance); - } - } - } - else - { - /* Create the device instance */ - ret = CreateDeviceInstance(pszDeviceID); - } - - DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret); - - return ret; -} - - -static CONFIGRET -MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination, - LPWSTR pszDeviceInstanceSource) -{ - DPRINT("MoveDeviceInstance: not implemented\n"); - /* FIXME */ - return CR_CALL_NOT_IMPLEMENTED; -} - - -static CONFIGRET -SetupDeviceInstance(LPWSTR pszDeviceInstance, - DWORD ulFlags) -{ - DPRINT("SetupDeviceInstance: not implemented\n"); - /* FIXME */ - return CR_CALL_NOT_IMPLEMENTED; -} - - -static CONFIGRET -EnableDeviceInstance(LPWSTR pszDeviceInstance) -{ - PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData; - CONFIGRET ret = CR_SUCCESS; - NTSTATUS Status; - - DPRINT("Enable device instance %S\n", pszDeviceInstance); - - RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance); - Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA)); - if (!NT_SUCCESS(Status)) - ret = NtStatusToCrError(Status); - - return ret; -} - - -static CONFIGRET -DisableDeviceInstance(LPWSTR pszDeviceInstance) -{ - DPRINT("DisableDeviceInstance: not implemented\n"); - /* FIXME */ - return CR_CALL_NOT_IMPLEMENTED; -} - - -static CONFIGRET -ReenumerateDeviceInstance( - _In_ LPWSTR pszDeviceInstance, - _In_ ULONG ulFlags) -{ - PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA EnumerateDeviceData; - CONFIGRET ret = CR_SUCCESS; - NTSTATUS Status; - - DPRINT1("ReenumerateDeviceInstance(%S 0x%08lx)\n", - pszDeviceInstance, ulFlags); - - if (ulFlags & ~CM_REENUMERATE_BITS) - return CR_INVALID_FLAG; - - if (ulFlags & CM_REENUMERATE_RETRY_INSTALLATION) - { - DPRINT1("CM_REENUMERATE_RETRY_INSTALLATION not implemented!\n"); - } - - RtlInitUnicodeString(&EnumerateDeviceData.DeviceInstance, - pszDeviceInstance); - EnumerateDeviceData.Flags = 0; - - Status = NtPlugPlayControl(PlugPlayControlEnumerateDevice, - &EnumerateDeviceData, - sizeof(PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA)); - if (!NT_SUCCESS(Status)) - ret = NtStatusToCrError(Status); - - return ret; -} - - -/* Function 29 */ -DWORD -WINAPI -PNP_DeviceInstanceAction( - handle_t hBinding, - DWORD ulAction, - DWORD ulFlags, - LPWSTR pszDeviceInstance1, - LPWSTR pszDeviceInstance2) -{ - CONFIGRET ret = CR_SUCCESS; - - UNREFERENCED_PARAMETER(hBinding); - - DPRINT("PNP_DeviceInstanceAction() called\n"); - - switch (ulAction) - { - case PNP_DEVINST_MOVE: - ret = MoveDeviceInstance(pszDeviceInstance1, - pszDeviceInstance2); - break; - - case PNP_DEVINST_SETUP: - ret = SetupDeviceInstance(pszDeviceInstance1, - ulFlags); - break; - - case PNP_DEVINST_ENABLE: - ret = EnableDeviceInstance(pszDeviceInstance1); - break; - - case PNP_DEVINST_DISABLE: - ret = DisableDeviceInstance(pszDeviceInstance1); - break; - - case PNP_DEVINST_REENUMERATE: - ret = ReenumerateDeviceInstance(pszDeviceInstance1, - ulFlags); - break; - - default: - DPRINT1("Unknown device action %lu: not implemented\n", ulAction); - ret = CR_CALL_NOT_IMPLEMENTED; - } - - DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret); - - return ret; -} - - -/* Function 30 */ -DWORD -WINAPI -PNP_GetDeviceStatus( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD *pulStatus, - DWORD *pulProblem, - DWORD ulFlags) -{ - PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData; - CONFIGRET ret = CR_SUCCESS; - NTSTATUS Status; - - UNREFERENCED_PARAMETER(hBinding); - UNREFERENCED_PARAMETER(ulFlags); - - DPRINT("PNP_GetDeviceStatus() called\n"); - - RtlInitUnicodeString(&PlugPlayData.DeviceInstance, - pDeviceID); - PlugPlayData.Operation = 0; /* Get status */ - - Status = NtPlugPlayControl(PlugPlayControlDeviceStatus, - (PVOID)&PlugPlayData, - sizeof(PLUGPLAY_CONTROL_STATUS_DATA)); - if (NT_SUCCESS(Status)) - { - *pulStatus = PlugPlayData.DeviceStatus; - *pulProblem = PlugPlayData.DeviceProblem; - } - else - { - ret = NtStatusToCrError(Status); - } - - DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret); - - return ret; -} - - -/* Function 31 */ -DWORD -WINAPI -PNP_SetDeviceProblem( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulProblem, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 32 */ -DWORD -WINAPI -PNP_DisableDevInst( - handle_t hBinding, - LPWSTR pDeviceID, - PPNP_VETO_TYPE pVetoType, - LPWSTR pszVetoName, - DWORD ulNameLength, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - -/* Function 33 */ -DWORD -WINAPI -PNP_UninstallDevInst( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -static BOOL -CheckForDeviceId(LPWSTR lpDeviceIdList, - LPWSTR lpDeviceId) -{ - LPWSTR lpPtr; - DWORD dwLength; - - lpPtr = lpDeviceIdList; - while (*lpPtr != 0) - { - dwLength = wcslen(lpPtr); - if (0 == _wcsicmp(lpPtr, lpDeviceId)) - return TRUE; - - lpPtr += (dwLength + 1); - } - - return FALSE; -} - - -static VOID -AppendDeviceId(LPWSTR lpDeviceIdList, - LPDWORD lpDeviceIdListSize, - LPWSTR lpDeviceId) -{ - DWORD dwLen; - DWORD dwPos; - - dwLen = wcslen(lpDeviceId); - dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1; - - wcscpy(&lpDeviceIdList[dwPos], lpDeviceId); - - dwPos += (dwLen + 1); - - lpDeviceIdList[dwPos] = 0; - - *lpDeviceIdListSize = dwPos * sizeof(WCHAR); -} - - -/* Function 34 */ -DWORD -WINAPI -PNP_AddID( - handle_t hBinding, - LPWSTR pszDeviceID, - LPWSTR pszID, - DWORD ulFlags) -{ - CONFIGRET ret = CR_SUCCESS; - HKEY hDeviceKey; - LPWSTR pszSubKey; - DWORD dwDeviceIdListSize; - DWORD dwNewDeviceIdSize; - WCHAR * pszDeviceIdList = NULL; - - UNREFERENCED_PARAMETER(hBinding); - - DPRINT("PNP_AddID() called\n"); - DPRINT(" DeviceInstance: %S\n", pszDeviceID); - DPRINT(" DeviceId: %S\n", pszID); - DPRINT(" Flags: %lx\n", ulFlags); - - if (RegOpenKeyExW(hEnumKey, - pszDeviceID, - 0, - KEY_QUERY_VALUE | KEY_SET_VALUE, - &hDeviceKey) != ERROR_SUCCESS) - { - DPRINT("Failed to open the device key!\n"); - return CR_INVALID_DEVNODE; - } - - pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID"; - - if (RegQueryValueExW(hDeviceKey, - pszSubKey, - NULL, - NULL, - NULL, - &dwDeviceIdListSize) != ERROR_SUCCESS) - { - DPRINT("Failed to query the desired ID string!\n"); - ret = CR_REGISTRY_ERROR; - goto Done; - } - - dwNewDeviceIdSize = lstrlenW(pszDeviceID); - if (!dwNewDeviceIdSize) - { - ret = CR_INVALID_POINTER; - goto Done; - } - - dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR); - - pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize); - if (!pszDeviceIdList) - { - DPRINT("Failed to allocate memory for the desired ID string!\n"); - ret = CR_OUT_OF_MEMORY; - goto Done; - } - - if (RegQueryValueExW(hDeviceKey, - pszSubKey, - NULL, - NULL, - (LPBYTE)pszDeviceIdList, - &dwDeviceIdListSize) != ERROR_SUCCESS) - { - DPRINT("Failed to query the desired ID string!\n"); - ret = CR_REGISTRY_ERROR; - goto Done; - } - - /* Check whether the device ID is already in use */ - if (CheckForDeviceId(pszDeviceIdList, pszDeviceID)) - { - DPRINT("Device ID was found in the ID string!\n"); - ret = CR_SUCCESS; - goto Done; - } - - /* Append the Device ID */ - AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID); - - if (RegSetValueExW(hDeviceKey, - pszSubKey, - 0, - REG_MULTI_SZ, - (LPBYTE)pszDeviceIdList, - dwDeviceIdListSize) != ERROR_SUCCESS) - { - DPRINT("Failed to set the desired ID string!\n"); - ret = CR_REGISTRY_ERROR; - } - -Done: - RegCloseKey(hDeviceKey); - if (pszDeviceIdList) - HeapFree(GetProcessHeap(), 0, pszDeviceIdList); - - DPRINT("PNP_AddID() done (returns %lx)\n", ret); - - return ret; -} - - -/* Function 35 */ -DWORD -WINAPI -PNP_RegisterDriver( - handle_t hBinding, - LPWSTR pszDeviceID, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 36 */ -DWORD -WINAPI -PNP_QueryRemove( - handle_t hBinding, - LPWSTR pszDeviceID, - PPNP_VETO_TYPE pVetoType, - LPWSTR pszVetoName, - DWORD ulNameLength, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 37 */ -DWORD -WINAPI -PNP_RequestDeviceEject( - handle_t hBinding, - LPWSTR pszDeviceID, - PPNP_VETO_TYPE pVetoType, - LPWSTR pszVetoName, - DWORD ulNameLength, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 38 */ -CONFIGRET -WINAPI -PNP_IsDockStationPresent( - handle_t hBinding, - BOOL *Present) -{ - HKEY hKey; - DWORD dwType; - DWORD dwValue; - DWORD dwSize; - CONFIGRET ret = CR_SUCCESS; - - UNREFERENCED_PARAMETER(hBinding); - - DPRINT1("PNP_IsDockStationPresent() called\n"); - - *Present = FALSE; - - if (RegOpenKeyExW(HKEY_CURRENT_CONFIG, - L"CurrentDockInfo", - 0, - KEY_READ, - &hKey) != ERROR_SUCCESS) - return CR_REGISTRY_ERROR; - - dwSize = sizeof(DWORD); - if (RegQueryValueExW(hKey, - L"DockingState", - NULL, - &dwType, - (LPBYTE)&dwValue, - &dwSize) != ERROR_SUCCESS) - ret = CR_REGISTRY_ERROR; - - RegCloseKey(hKey); - - if (ret == CR_SUCCESS) - { - if (dwType != REG_DWORD || dwSize != sizeof(DWORD)) - { - ret = CR_REGISTRY_ERROR; - } - else if (dwValue != 0) - { - *Present = TRUE; - } - } - - DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret); - - return ret; -} - - -/* Function 39 */ -DWORD -WINAPI -PNP_RequestEjectPC( - handle_t hBinding) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 40 */ -DWORD -WINAPI -PNP_HwProfFlags( - handle_t hBinding, - DWORD ulAction, - LPWSTR pDeviceID, - DWORD ulConfig, - DWORD *pulValue, - PPNP_VETO_TYPE pVetoType, - LPWSTR pszVetoName, - DWORD ulNameLength, - DWORD ulFlags) -{ - CONFIGRET ret = CR_SUCCESS; - WCHAR szKeyName[MAX_PATH]; - HKEY hKey; - HKEY hDeviceKey; - DWORD dwSize; - - UNREFERENCED_PARAMETER(hBinding); - - DPRINT("PNP_HwProfFlags() called\n"); - - if (ulConfig == 0) - { - wcscpy(szKeyName, - L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum"); - } - else - { - swprintf(szKeyName, - L"System\\CurrentControlSet\\HardwareProfiles\\%04lu\\System\\CurrentControlSet\\Enum", - ulConfig); - } - - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, - szKeyName, - 0, - KEY_QUERY_VALUE, - &hKey) != ERROR_SUCCESS) - return CR_REGISTRY_ERROR; - - if (ulAction == PNP_GET_HWPROFFLAGS) - { - if (RegOpenKeyExW(hKey, - pDeviceID, - 0, - KEY_QUERY_VALUE, - &hDeviceKey) != ERROR_SUCCESS) - { - *pulValue = 0; - } - else - { - dwSize = sizeof(DWORD); - if (RegQueryValueExW(hDeviceKey, - L"CSConfigFlags", - NULL, - NULL, - (LPBYTE)pulValue, - &dwSize) != ERROR_SUCCESS) - { - *pulValue = 0; - } - - RegCloseKey(hDeviceKey); - } - } - else if (ulAction == PNP_SET_HWPROFFLAGS) - { - /* FIXME: not implemented yet */ - ret = CR_CALL_NOT_IMPLEMENTED; - } - - RegCloseKey(hKey); - - return ret; -} - - -/* Function 41 */ -DWORD -WINAPI -PNP_GetHwProfInfo( - handle_t hBinding, - DWORD ulIndex, - HWPROFILEINFO *pHWProfileInfo, - DWORD ulProfileInfoSize, - DWORD ulFlags) -{ - WCHAR szProfileName[5]; - HKEY hKeyConfig = NULL; - HKEY hKeyProfiles = NULL; - HKEY hKeyProfile = NULL; - DWORD dwDisposition; - DWORD dwSize; - LONG lError; - CONFIGRET ret = CR_SUCCESS; - - UNREFERENCED_PARAMETER(hBinding); - - DPRINT("PNP_GetHwProfInfo() called\n"); - - if (ulProfileInfoSize == 0) - { - ret = CR_INVALID_DATA; - goto done; - } - - if (ulFlags != 0) - { - ret = CR_INVALID_FLAG; - goto done; - } - - /* Initialize the profile information */ - pHWProfileInfo->HWPI_ulHWProfile = 0; - pHWProfileInfo->HWPI_szFriendlyName[0] = 0; - pHWProfileInfo->HWPI_dwFlags = 0; - - /* Open the 'IDConfigDB' key */ - lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE, - L"System\\CurrentControlSet\\Control\\IDConfigDB", - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_QUERY_VALUE, - NULL, - &hKeyConfig, - &dwDisposition); - if (lError != ERROR_SUCCESS) - { - ret = CR_REGISTRY_ERROR; - goto done; - } - - /* Open the 'Hardware Profiles' subkey */ - lError = RegCreateKeyExW(hKeyConfig, - L"Hardware Profiles", - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, - NULL, - &hKeyProfiles, - &dwDisposition); - if (lError != ERROR_SUCCESS) - { - ret = CR_REGISTRY_ERROR; - goto done; - } - - if (ulIndex == (ULONG)-1) - { - dwSize = sizeof(ULONG); - lError = RegQueryValueExW(hKeyConfig, - L"CurrentConfig", - NULL, - NULL, - (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile, - &dwSize); - if (lError != ERROR_SUCCESS) - { - pHWProfileInfo->HWPI_ulHWProfile = 0; - ret = CR_REGISTRY_ERROR; - goto done; - } - } - else - { - /* FIXME: not implemented yet */ - ret = CR_CALL_NOT_IMPLEMENTED; - goto done; - } - - swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile); - - lError = RegOpenKeyExW(hKeyProfiles, - szProfileName, - 0, - KEY_QUERY_VALUE, - &hKeyProfile); - if (lError != ERROR_SUCCESS) - { - ret = CR_REGISTRY_ERROR; - goto done; - } - - dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName); - lError = RegQueryValueExW(hKeyProfile, - L"FriendlyName", - NULL, - NULL, - (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName, - &dwSize); - if (lError != ERROR_SUCCESS) - { - ret = CR_REGISTRY_ERROR; - goto done; - } - -done: - if (hKeyProfile != NULL) - RegCloseKey(hKeyProfile); - - if (hKeyProfiles != NULL) - RegCloseKey(hKeyProfiles); - - if (hKeyConfig != NULL) - RegCloseKey(hKeyConfig); - - return ret; -} - - -/* Function 42 */ -DWORD -WINAPI -PNP_AddEmptyLogConf( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulPriority, - DWORD *pulLogConfTag, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 43 */ -DWORD -WINAPI -PNP_FreeLogConf( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulLogConfType, - DWORD ulLogConfTag, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 44 */ -DWORD -WINAPI -PNP_GetFirstLogConf( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulLogConfType, - DWORD *pulLogConfTag, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 45 */ -DWORD -WINAPI -PNP_GetNextLogConf( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulLogConfType, - DWORD ulCurrentTag, - DWORD *pulNextTag, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 46 */ -DWORD -WINAPI -PNP_GetLogConfPriority( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulType, - DWORD ulTag, - DWORD *pPriority, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 47 */ -DWORD -WINAPI -PNP_AddResDes( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulLogConfTag, - DWORD ulLogConfType, - RESOURCEID ResourceID, - DWORD *pulResourceTag, - BYTE *ResourceData, - PNP_RPC_BUFFER_SIZE ResourceLen, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 48 */ -DWORD -WINAPI -PNP_FreeResDes( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulLogConfTag, - DWORD ulLogConfType, - RESOURCEID ResourceID, - DWORD ulResourceTag, - DWORD *pulPreviousResType, - DWORD *pulPreviousResTag, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 49 */ -DWORD -WINAPI -PNP_GetNextResDes( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulLogConfTag, - DWORD ulLogConfType, - RESOURCEID ResourceID, - DWORD ulResourceTag, - DWORD *pulNextResType, - DWORD *pulNextResTag, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 50 */ -DWORD -WINAPI -PNP_GetResDesData( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulLogConfTag, - DWORD ulLogConfType, - RESOURCEID ResourceID, - DWORD ulResourceTag, - BYTE *Buffer, - PNP_RPC_BUFFER_SIZE BufferLen, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 51 */ -DWORD -WINAPI -PNP_GetResDesDataSize( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulLogConfTag, - DWORD ulLogConfType, - RESOURCEID ResourceID, - DWORD ulResourceTag, - DWORD *pulSize, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 52 */ -DWORD -WINAPI -PNP_ModifyResDes( - handle_t hBinding, - LPWSTR pDeviceID, - DWORD ulLogConfTag, - DWORD ulLogConfType, - RESOURCEID CurrentResourceID, - RESOURCEID NewResourceID, - DWORD ulResourceTag, - BYTE *ResourceData, - PNP_RPC_BUFFER_SIZE ResourceLen, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 53 */ -DWORD -WINAPI -PNP_DetectResourceConflict( - handle_t hBinding, - LPWSTR pDeviceID, - RESOURCEID ResourceID, - BYTE *ResourceData, - PNP_RPC_BUFFER_SIZE ResourceLen, - BOOL *pbConflictDetected, - DWORD ulFlags) -{ - DPRINT("PNP_DetectResourceConflict()\n"); - - if (pbConflictDetected != NULL) - *pbConflictDetected = FALSE; - - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 54 */ -DWORD -WINAPI -PNP_QueryResConfList( - handle_t hBinding, - LPWSTR pDeviceID, - RESOURCEID ResourceID, - BYTE *ResourceData, - PNP_RPC_BUFFER_SIZE ResourceLen, - BYTE *Buffer, - PNP_RPC_BUFFER_SIZE BufferLen, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 55 */ -DWORD -WINAPI -PNP_SetHwProf( - handle_t hBinding, - DWORD ulHardwareProfile, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 56 */ -DWORD -WINAPI -PNP_QueryArbitratorFreeData( - handle_t hBinding, - BYTE *pData, - DWORD DataLen, - LPWSTR pDeviceID, - RESOURCEID ResourceID, - DWORD ulFlags) -{ - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 57 */ -DWORD -WINAPI -PNP_QueryArbitratorFreeSize( - handle_t hBinding, - DWORD *pulSize, - LPWSTR pDeviceID, - RESOURCEID ResourceID, - DWORD ulFlags) -{ - if (pulSize != NULL) - *pulSize = 0; - - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 58 */ -CONFIGRET -WINAPI -PNP_RunDetection( - handle_t hBinding, - DWORD ulFlags) -{ - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 59 */ -DWORD -WINAPI -PNP_RegisterNotification( - handle_t hBinding, - DWORD ulFlags, - DWORD *pulNotify) -{ -#if 0 - PNOTIFY_DATA pNotifyData; -#endif - - DPRINT1("PNP_RegisterNotification(%p 0x%lx %p)\n", - hBinding, ulFlags, pulNotify); - -#if 0 - pNotifyData = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NOTIFY_DATA)); - if (pNotifyData == NULL) - return CR_OUT_OF_MEMORY; - - *pulNotify = (DWORD)pNotifyData; -#endif - - *pulNotify = 1; - - return CR_SUCCESS; -} - - -/* Function 60 */ -DWORD -WINAPI -PNP_UnregisterNotification( - handle_t hBinding, - DWORD ulNotify) -{ - DPRINT1("PNP_UnregisterNotification(%p 0x%lx)\n", - hBinding, ulNotify); - -#if 0 - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -#endif - - return CR_SUCCESS; -} - - -/* Function 61 */ -DWORD -WINAPI -PNP_GetCustomDevProp( - handle_t hBinding, - LPWSTR pDeviceID, - LPWSTR CustomPropName, - DWORD *pulRegDataType, - BYTE *Buffer, - PNP_RPC_STRING_LEN *pulTransferLen, - PNP_RPC_STRING_LEN *pulLength, - DWORD ulFlags) -{ - HKEY hDeviceKey = NULL; - HKEY hParamKey = NULL; - LONG lError; - CONFIGRET ret = CR_SUCCESS; - - UNREFERENCED_PARAMETER(hBinding); - - DPRINT("PNP_GetCustomDevProp() called\n"); - - if (pulTransferLen == NULL || pulLength == NULL) - { - ret = CR_INVALID_POINTER; - goto done; - } - - if (ulFlags & ~CM_CUSTOMDEVPROP_BITS) - { - ret = CR_INVALID_FLAG; - goto done; - } - - if (*pulLength < *pulTransferLen) - *pulLength = *pulTransferLen; - - *pulTransferLen = 0; - - lError = RegOpenKeyExW(hEnumKey, - pDeviceID, - 0, - KEY_READ, - &hDeviceKey); - if (lError != ERROR_SUCCESS) - { - ret = CR_REGISTRY_ERROR; - goto done; - } - - lError = RegOpenKeyExW(hDeviceKey, - L"Device Parameters", - 0, - KEY_READ, - &hParamKey); - if (lError != ERROR_SUCCESS) - { - ret = CR_REGISTRY_ERROR; - goto done; - } - - lError = RegQueryValueExW(hParamKey, - CustomPropName, - NULL, - pulRegDataType, - Buffer, - pulLength); - if (lError != ERROR_SUCCESS) - { - if (lError == ERROR_MORE_DATA) - { - ret = CR_BUFFER_SMALL; - } - else - { - *pulLength = 0; - ret = CR_NO_SUCH_VALUE; - } - } - -done: - if (ret == CR_SUCCESS) - *pulTransferLen = *pulLength; - - if (hParamKey != NULL) - RegCloseKey(hParamKey); - - if (hDeviceKey != NULL) - RegCloseKey(hDeviceKey); - - DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret); - - return ret; -} - - -/* Function 62 */ -DWORD -WINAPI -PNP_GetVersionInternal( - handle_t hBinding, - WORD *pwVersion) -{ - UNREFERENCED_PARAMETER(hBinding); - - *pwVersion = 0x501; - return CR_SUCCESS; -} - - -/* Function 63 */ -DWORD -WINAPI -PNP_GetBlockedDriverInfo( - handle_t hBinding, - BYTE *Buffer, - PNP_RPC_BUFFER_SIZE *pulTransferLen, - PNP_RPC_BUFFER_SIZE *pulLength, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 64 */ -DWORD -WINAPI -PNP_GetServerSideDeviceInstallFlags( - handle_t hBinding, - DWORD *pulSSDIFlags, - DWORD ulFlags) -{ - UNREFERENCED_PARAMETER(hBinding); - - DPRINT1("PNP_GetServerSideDeviceInstallFlags(%p %p %lu)\n", - hBinding, pulSSDIFlags, ulFlags); - - if (pulSSDIFlags == NULL) - return CR_INVALID_POINTER; - - if (ulFlags != 0) - return CR_INVALID_FLAG; - - /* FIXME */ - *pulSSDIFlags = 0; - - return CR_SUCCESS; -} - - -/* Function 65 */ -DWORD -WINAPI -PNP_GetObjectPropKeys( - handle_t hBinding, - LPWSTR ObjectName, - DWORD ObjectType, - LPWSTR PropertyCultureName, - PNP_PROP_COUNT *PropertyCount, - PNP_PROP_COUNT *TransferLen, - DEVPROPKEY *PropertyKeys, - DWORD Flags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 66 */ -DWORD -WINAPI -PNP_GetObjectProp( - handle_t hBinding, - LPWSTR ObjectName, - DWORD ObjectType, - LPWSTR PropertyCultureName, - const DEVPROPKEY *PropertyKey, - DEVPROPTYPE *PropertyType, - PNP_PROP_SIZE *PropertySize, - PNP_PROP_SIZE *TransferLen, - BYTE *PropertyBuffer, - DWORD Flags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 67 */ -DWORD -WINAPI -PNP_SetObjectProp( - handle_t hBinding, - LPWSTR ObjectName, - DWORD ObjectType, - LPWSTR PropertyCultureName, - const DEVPROPKEY *PropertyKey, - DEVPROPTYPE PropertyType, - PNP_PROP_SIZE PropertySize, - BYTE *PropertyBuffer, - DWORD Flags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 68 */ -DWORD -WINAPI -PNP_InstallDevInst( - handle_t hBinding) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 69 */ -DWORD -WINAPI -PNP_ApplyPowerSettings( - handle_t hBinding) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 70 */ -DWORD -WINAPI -PNP_DriverStoreAddDriverPackage( - handle_t hBinding) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 71 */ -DWORD -WINAPI -PNP_DriverStoreDeleteDriverPackage( - handle_t hBinding) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 72 */ -DWORD -WINAPI -PNP_RegisterServiceNotification( - handle_t hBinding) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 73 */ -DWORD -WINAPI -PNP_SetActiveService( - handle_t hBinding, - LPWSTR pszFilter, - DWORD ulFlags) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -/* Function 74 */ -DWORD -WINAPI -PNP_DeleteServiceDevices( - handle_t hBinding) -{ - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; -} - - -static BOOL -InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard) -{ - BOOL DeviceInstalled = FALSE; - DWORD BytesWritten; - DWORD Value; - HANDLE hInstallEvent; - HANDLE hPipe = INVALID_HANDLE_VALUE; - LPVOID Environment = NULL; - PROCESS_INFORMATION ProcessInfo; - STARTUPINFOW StartupInfo; - UUID RandomUuid; - HKEY DeviceKey; - - /* The following lengths are constant (see below), they cannot overflow */ - WCHAR CommandLine[116]; - WCHAR InstallEventName[73]; - WCHAR PipeName[74]; - WCHAR UuidString[39]; - - DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard); - - ZeroMemory(&ProcessInfo, sizeof(ProcessInfo)); - - if (RegOpenKeyExW(hEnumKey, - DeviceInstance, - 0, - KEY_QUERY_VALUE, - &DeviceKey) == ERROR_SUCCESS) - { - if (RegQueryValueExW(DeviceKey, - L"Class", - NULL, - NULL, - NULL, - NULL) == ERROR_SUCCESS) - { - DPRINT("No need to install: %S\n", DeviceInstance); - RegCloseKey(DeviceKey); - return TRUE; - } - - BytesWritten = sizeof(DWORD); - if (RegQueryValueExW(DeviceKey, - L"ConfigFlags", - NULL, - NULL, - (PBYTE)&Value, - &BytesWritten) == ERROR_SUCCESS) - { - if (Value & CONFIGFLAG_FAILEDINSTALL) - { - DPRINT("No need to install: %S\n", DeviceInstance); - RegCloseKey(DeviceKey); - return TRUE; - } - } - - RegCloseKey(DeviceKey); - } - - DPRINT1("Installing: %S\n", DeviceInstance); - - /* Create a random UUID for the named pipe & event*/ - UuidCreate(&RandomUuid); - swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3, - RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2], - RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5], - RandomUuid.Data4[6], RandomUuid.Data4[7]); - - /* Create the event */ - wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0."); - wcscat(InstallEventName, UuidString); - hInstallEvent = CreateEventW(NULL, TRUE, FALSE, InstallEventName); - if (!hInstallEvent) - { - DPRINT1("CreateEventW('%ls') failed with error %lu\n", InstallEventName, GetLastError()); - goto cleanup; - } - - /* Create the named pipe */ - wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0."); - wcscat(PipeName, UuidString); - hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL); - if (hPipe == INVALID_HANDLE_VALUE) - { - DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError()); - goto cleanup; - } - - /* Launch rundll32 to call ClientSideInstallW */ - wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall "); - wcscat(CommandLine, PipeName); - - ZeroMemory(&StartupInfo, sizeof(StartupInfo)); - StartupInfo.cb = sizeof(StartupInfo); - - if (hUserToken) - { - /* newdev has to run under the environment of the current user */ - if (!CreateEnvironmentBlock(&Environment, hUserToken, FALSE)) - { - DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError()); - goto cleanup; - } - - if (!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo)) - { - DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError()); - goto cleanup; - } - } - else - { - /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges. - - Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here. - (ShowWizard is only set to FALSE for these two modes) */ - ASSERT(!ShowWizard); - - if (!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo)) - { - DPRINT1("CreateProcessW failed with error %u\n", GetLastError()); - goto cleanup; - } - } - - /* Wait for the function to connect to our pipe */ - if (!ConnectNamedPipe(hPipe, NULL)) - { - if (GetLastError() != ERROR_PIPE_CONNECTED) - { - DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError()); - goto cleanup; - } - } - - /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */ - Value = sizeof(InstallEventName); - WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL); - WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL); - - /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once. - Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */ - WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL); - - Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR); - WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL); - WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL); - - /* Wait for newdev.dll to finish processing */ - WaitForSingleObject(ProcessInfo.hProcess, INFINITE); - - /* If the event got signalled, this is success */ - DeviceInstalled = WaitForSingleObject(hInstallEvent, 0) == WAIT_OBJECT_0; - -cleanup: - if (hInstallEvent) - CloseHandle(hInstallEvent); - - if (hPipe != INVALID_HANDLE_VALUE) - CloseHandle(hPipe); - - if (Environment) - DestroyEnvironmentBlock(Environment); - - if (ProcessInfo.hProcess) - CloseHandle(ProcessInfo.hProcess); - - if (ProcessInfo.hThread) - CloseHandle(ProcessInfo.hThread); - - if (!DeviceInstalled) - { - DPRINT1("InstallDevice failed for DeviceInstance '%ws'\n", DeviceInstance); - } - - return DeviceInstalled; -} - - -static LONG -ReadRegSzKey( - IN HKEY hKey, - IN LPCWSTR pszKey, - OUT LPWSTR* pValue) -{ - LONG rc; - DWORD dwType; - DWORD cbData = 0; - LPWSTR Value; - - if (!pValue) - return ERROR_INVALID_PARAMETER; - - *pValue = NULL; - rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData); - if (rc != ERROR_SUCCESS) - return rc; - if (dwType != REG_SZ) - return ERROR_FILE_NOT_FOUND; - Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR)); - if (!Value) - return ERROR_NOT_ENOUGH_MEMORY; - rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData); - if (rc != ERROR_SUCCESS) - { - HeapFree(GetProcessHeap(), 0, Value); - return rc; - } - /* NULL-terminate the string */ - Value[cbData / sizeof(WCHAR)] = '\0'; - - *pValue = Value; - return ERROR_SUCCESS; -} - - -static BOOL -SetupIsActive(VOID) -{ - HKEY hKey = NULL; - DWORD regType, active, size; - LONG rc; - BOOL ret = FALSE; - - rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey); - if (rc != ERROR_SUCCESS) - goto cleanup; - - size = sizeof(DWORD); - rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, ®Type, (LPBYTE)&active, &size); - if (rc != ERROR_SUCCESS) - goto cleanup; - if (regType != REG_DWORD || size != sizeof(DWORD)) - goto cleanup; - - ret = (active != 0); - -cleanup: - if (hKey != NULL) - RegCloseKey(hKey); - - DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO"); - - return ret; -} - - -static BOOL -IsConsoleBoot(VOID) -{ - HKEY ControlKey = NULL; - LPWSTR SystemStartOptions = NULL; - LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */ - BOOL ConsoleBoot = FALSE; - LONG rc; - - rc = RegOpenKeyExW( - HKEY_LOCAL_MACHINE, - L"SYSTEM\\CurrentControlSet\\Control", - 0, - KEY_QUERY_VALUE, - &ControlKey); - - rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions); - if (rc != ERROR_SUCCESS) - goto cleanup; - - /* Check for CONSOLE switch in SystemStartOptions */ - CurrentOption = SystemStartOptions; - while (CurrentOption) - { - NextOption = wcschr(CurrentOption, L' '); - if (NextOption) - *NextOption = L'\0'; - if (_wcsicmp(CurrentOption, L"CONSOLE") == 0) - { - DPRINT("Found %S. Switching to console boot\n", CurrentOption); - ConsoleBoot = TRUE; - goto cleanup; - } - CurrentOption = NextOption ? NextOption + 1 : NULL; - } - -cleanup: - if (ControlKey != NULL) - RegCloseKey(ControlKey); - HeapFree(GetProcessHeap(), 0, SystemStartOptions); - return ConsoleBoot; -} - - -/* Loop to install all queued devices installations */ -static DWORD WINAPI -DeviceInstallThread(LPVOID lpParameter) -{ - PSLIST_ENTRY ListEntry; - DeviceInstallParams* Params; - BOOL showWizard; - - UNREFERENCED_PARAMETER(lpParameter); - - WaitForSingleObject(hInstallEvent, INFINITE); - - showWizard = !SetupIsActive() && !IsConsoleBoot(); - - while (TRUE) - { - ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead); - - if (ListEntry == NULL) - { - SetEvent(hNoPendingInstalls); - WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE); - } - else - { - ResetEvent(hNoPendingInstalls); - Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry); - InstallDevice(Params->DeviceIds, showWizard); - HeapFree(GetProcessHeap(), 0, Params); - } - } - - return 0; -} - - static DWORD WINAPI PnpEventThread(LPVOID lpParameter) {