X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fbase%2Fservices%2Fumpnpmgr%2Fumpnpmgr.c;h=47049270caa8b19b20678ae1cd8ee979b03d45d7;hp=8dc8a16e0311d52c45eb6a0ef6acabf0dcb6af94;hb=971a0b7b63234c7bc338c84a29c16f9116a2452e;hpb=1cca0351e1ce1bb5da6a34539fa648d251f4e259 diff --git a/reactos/base/services/umpnpmgr/umpnpmgr.c b/reactos/base/services/umpnpmgr/umpnpmgr.c index 8dc8a16e031..47049270caa 100644 --- a/reactos/base/services/umpnpmgr/umpnpmgr.c +++ b/reactos/base/services/umpnpmgr/umpnpmgr.c @@ -51,15 +51,17 @@ /* GLOBALS ******************************************************************/ -static VOID CALLBACK -ServiceMain(DWORD argc, LPTSTR *argv); - -static SERVICE_TABLE_ENTRY ServiceTable[2] = +static VOID CALLBACK ServiceMain(DWORD argc, LPWSTR *argv); +static WCHAR ServiceName[] = L"PlugPlay"; +static SERVICE_TABLE_ENTRYW ServiceTable[] = { - {TEXT("PlugPlay"), ServiceMain}, + {ServiceName, ServiceMain}, {NULL, NULL} }; +static SERVICE_STATUS_HANDLE ServiceStatusHandle; +static SERVICE_STATUS ServiceStatus; + static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0"; static HKEY hEnumKey = NULL; @@ -92,20 +94,37 @@ static DWORD WINAPI RpcServerThread(LPVOID lpParameter) { RPC_STATUS Status; + BOOLEAN RegisteredProtSeq = FALSE; UNREFERENCED_PARAMETER(lpParameter); DPRINT("RpcServerThread() called\n"); +#if 0 + /* XP-compatible protocol sequence/endpoint */ Status = RpcServerUseProtseqEpW(L"ncacn_np", 20, - L"\\pipe\\umpnpmgr", + L"\\pipe\\ntsvcs", NULL); // Security descriptor - if (Status != RPC_S_OK) - { + if (Status == RPC_S_OK) + RegisteredProtSeq = TRUE; + else DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); +#endif + + /* Vista-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, @@ -168,8 +187,7 @@ DWORD PNP_Disconnect( handle_t hBinding) { UNREFERENCED_PARAMETER(hBinding); - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; + return CR_SUCCESS; } @@ -178,8 +196,7 @@ DWORD PNP_Connect( handle_t hBinding) { UNREFERENCED_PARAMETER(hBinding); - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; + return CR_SUCCESS; } @@ -519,14 +536,33 @@ DWORD PNP_GetDeviceRegProp( PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData; CONFIGRET ret = CR_SUCCESS; LPWSTR lpValueName = NULL; - HKEY hKey = 0; + HKEY hKey = NULL; + LONG lError; NTSTATUS Status; UNREFERENCED_PARAMETER(hBinding); - UNREFERENCED_PARAMETER(ulFlags); 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: @@ -609,8 +645,65 @@ DWORD PNP_GetDeviceRegProp( lpValueName = NULL; 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: + lpValueName = NULL; + break; + + case CM_DRP_UI_NUMBER_DESC_FORMAT: + lpValueName = L"UINumberDescFormat"; + break; + + case CM_DRP_DEVICE_POWER_DATA: + lpValueName = NULL; + break; + + case CM_DRP_REMOVAL_POLICY: + lpValueName = NULL; + break; + + case CM_DRP_REMOVAL_POLICY_HW_DEFAULT: + lpValueName = NULL; + break; + + case CM_DRP_REMOVAL_POLICY_OVERRIDE: + lpValueName = L"RemovalPolicy"; + break; + + case CM_DRP_INSTALL_STATE: + lpValueName = NULL; + break; + +#if (WINVER >= _WIN32_WINNT_WS03) + case CM_DRP_LOCATION_PATHS: + lpValueName = NULL; + break; +#endif + +#if (WINVER >= _WIN32_WINNT_WIN7) + case CM_DRP_BASE_CONTAINERID: + lpValueName = NULL; + break; +#endif + default: - return CR_INVALID_PROPERTY; + ret = CR_INVALID_PROPERTY; + goto done; } DPRINT("Value name: %S\n", lpValueName); @@ -618,24 +711,34 @@ DWORD PNP_GetDeviceRegProp( if (lpValueName) { /* Retrieve information from the Registry */ - if (RegOpenKeyExW(hEnumKey, - pDeviceID, - 0, - KEY_ALL_ACCESS, - &hKey)) - return CR_INVALID_DEVNODE; - - if (RegQueryValueExW(hKey, - lpValueName, - NULL, - pulRegDataType, - Buffer, - pulLength)) - ret = CR_REGISTRY_ERROR; - - /* FIXME: Check buffer size */ + lError = RegOpenKeyExW(hEnumKey, + pDeviceID, + 0, + KEY_QUERY_VALUE, + &hKey); + if (lError != ERROR_SUCCESS) + { + hKey = NULL; + *pulLength = 0; + ret = CR_INVALID_DEVNODE; + goto done; + } - RegCloseKey(hKey); + lError = RegQueryValueExW(hKey, + lpValueName, + NULL, + pulRegDataType, + Buffer, + pulLength); + if (lError == ERROR_MORE_DATA) + { + ret = CR_BUFFER_SMALL; + } + else + { + *pulLength = 0; + ret = CR_NO_SUCH_VALUE; + } } else { @@ -647,32 +750,65 @@ DWORD PNP_GetDeviceRegProp( switch (ulProperty) { -#if 0 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME: - PlugPlayData.Property = DevicePropertyPhysicalDeviceObjectName; + PlugPlayData.Property = 0xb; // DevicePropertyPhysicalDeviceObjectName; break; case CM_DRP_UI_NUMBER: - PlugPlayData.Property = DevicePropertyUINumber; + PlugPlayData.Property = 0x11; // DevicePropertyUINumber; break; case CM_DRP_BUSTYPEGUID: - PlugPlayData.Property = DevicePropertyBusTypeGuid; + PlugPlayData.Property = 0xc; // DevicePropertyBusTypeGuid; break; case CM_DRP_LEGACYBUSTYPE: - PlugPlayData.Property = DevicePropertyLegacyBusType; + PlugPlayData.Property = 0xd; // DevicePropertyLegacyBusType; break; case CM_DRP_BUSNUMBER: - PlugPlayData.Property = DevicePropertyBusNumber; + PlugPlayData.Property = 0xe; // DevicePropertyBusNumber; break; -#endif case CM_DRP_ENUMERATOR_NAME: - PlugPlayData.Property = 15; //DevicePropertyEnumeratorName; + PlugPlayData.Property = 0xf; // DevicePropertyEnumeratorName; + break; + + case CM_DRP_ADDRESS: + PlugPlayData.Property = 0x10; // DevicePropertyAddress; break; +#if 0 + /* FIXME: This property is not supported by IoGetDeviceProperty */ + case CM_DRP_DEVICE_POWER_DATA: +#endif + + case CM_DRP_REMOVAL_POLICY: + PlugPlayData.Property = 0x12; // DevicePropertyRemovalPolicy + break; + +#if 0 + /* FIXME: This property is not supported by IoGetDeviceProperty */ + case CM_DRP_REMOVAL_POLICY_HW_DEFAULT: +#endif + + case CM_DRP_INSTALL_STATE: + PlugPlayData.Property = 0x12; // DevicePropertyInstallState; + break; + +#if 0 + /* FIXME: This property is not supported by IoGetDeviceProperty */ +#if (WINVER >= _WIN32_WINNT_WS03) + case CM_DRP_LOCATION_PATHS: +#endif +#endif + +#if (WINVER >= _WIN32_WINNT_WIN7) + case CM_DRP_BASE_CONTAINERID: + PlugPlayData.Property = 0x16; // DevicePropertyContainerID; + break; +#endif + default: return CR_INVALID_PROPERTY; } @@ -690,6 +826,12 @@ DWORD PNP_GetDeviceRegProp( } } +done:; + *pulTransferLen = (ret != CR_SUCCESS) ? 0 : *pulLength; + + if (hKey != NULL) + RegCloseKey(hKey); + DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret); return ret; @@ -774,6 +916,30 @@ DWORD PNP_SetDeviceRegProp( 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; } @@ -783,7 +949,7 @@ DWORD PNP_SetDeviceRegProp( if (RegOpenKeyExW(hEnumKey, pDeviceId, 0, - KEY_ALL_ACCESS, /* FIXME: so much? */ + KEY_SET_VALUE, &hKey)) return CR_INVALID_DEVNODE; @@ -1088,6 +1254,157 @@ DWORD PNP_SetClassRegProp( } +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); +} + + +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 PNP_CreateDevInst( handle_t hBinding, @@ -1096,8 +1413,25 @@ DWORD PNP_CreateDevInst( PNP_RPC_STRING_LEN ulLength, DWORD ulFlags) { - UNIMPLEMENTED; - return CR_CALL_NOT_IMPLEMENTED; + CONFIGRET ret = CR_SUCCESS; + + DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID); + + if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID) + { + /* FIXME */ + DPRINT1("CM_CREATE_DEVNODE_GENERATE_ID support not implemented yet!\n", ret); + ret = CR_CALL_NOT_IMPLEMENTED; + goto done; + } + + /* Create the device instance */ + ret = CreateDeviceInstance(pszDeviceID); + +done:; + DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret); + + return ret; } @@ -1836,7 +2170,12 @@ DWORD PNP_SetHwProf( /* Function 56 */ DWORD PNP_QueryArbitratorFreeData( - handle_t hBinding) + handle_t hBinding, + BYTE *pData, + DWORD DataLen, + LPWSTR pDeviceID, + RESOURCEID ResourceID, + DWORD ulFlags) { UNIMPLEMENTED; return CR_CALL_NOT_IMPLEMENTED; @@ -1845,7 +2184,11 @@ DWORD PNP_QueryArbitratorFreeData( /* Function 57 */ DWORD PNP_QueryArbitratorFreeSize( - handle_t hBinding) + handle_t hBinding, + DWORD *pulSize, + LPWSTR pDeviceID, + RESOURCEID ResourceID, + DWORD ulFlags) { UNIMPLEMENTED; return CR_CALL_NOT_IMPLEMENTED; @@ -1858,7 +2201,6 @@ PNP_RunDetection( handle_t hBinding, DWORD ulFlags) { - UNIMPLEMENTED; return CR_CALL_NOT_IMPLEMENTED; } @@ -2048,8 +2390,6 @@ DWORD PNP_DeleteServiceDevices( static BOOL InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard) { - PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData; - NTSTATUS Status; BOOL DeviceInstalled = FALSE; DWORD BytesWritten; DWORD Value; @@ -2058,6 +2398,7 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard) PROCESS_INFORMATION ProcessInfo; STARTUPINFOW StartupInfo; UUID RandomUuid; + HKEY DeviceKey; /* The following lengths are constant (see below), they cannot overflow */ WCHAR CommandLine[116]; @@ -2069,27 +2410,29 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard) ZeroMemory(&ProcessInfo, sizeof(ProcessInfo)); - RtlInitUnicodeString(&PlugPlayData.DeviceInstance, - DeviceInstance); - PlugPlayData.Operation = 0; /* Get status */ - - /* Get device status */ - Status = NtPlugPlayControl(PlugPlayControlDeviceStatus, - (PVOID)&PlugPlayData, - sizeof(PLUGPLAY_CONTROL_STATUS_DATA)); - if (!NT_SUCCESS(Status)) + if (RegOpenKeyExW(hEnumKey, + DeviceInstance, + 0, + KEY_QUERY_VALUE, + &DeviceKey) == ERROR_SUCCESS) { - DPRINT1("NtPlugPlayControl('%S') failed with status 0x%08lx\n", DeviceInstance, Status); - return FALSE; - } + if (RegQueryValueExW(DeviceKey, + L"ClassGUID", + NULL, + NULL, + NULL, + NULL) == ERROR_SUCCESS) + { + DPRINT("No need to install: %S\n", DeviceInstance); + RegCloseKey(DeviceKey); + return TRUE; + } - if ((PlugPlayData.DeviceStatus & (DNF_STARTED | DNF_START_FAILED)) != 0) - { - /* Device is already started, or disabled due to some problem. Don't install it */ - DPRINT("No need to install '%S'\n", DeviceInstance); - return TRUE; + RegCloseKey(DeviceKey); } + DPRINT1("Installing: %S\n", DeviceInstance); + /* Create a random UUID for the named pipe */ UuidCreate(&RandomUuid); swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", @@ -2194,6 +2537,8 @@ cleanup: if(ProcessInfo.hThread) CloseHandle(ProcessInfo.hThread); + DPRINT1("Success? %d\n", DeviceInstalled); + return DeviceInstalled; } @@ -2402,7 +2747,7 @@ PnpEventThread(LPVOID lpParameter) DWORD len; DWORD DeviceIdLength; - DPRINT("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds); + DPRINT1("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds); DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds); if (DeviceIdLength) @@ -2424,7 +2769,7 @@ PnpEventThread(LPVOID lpParameter) } else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus)) { - DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds); + DPRINT1("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds); /* FIXME: ? */ } else @@ -2446,6 +2791,72 @@ PnpEventThread(LPVOID lpParameter) } +static VOID +UpdateServiceStatus(DWORD dwState) +{ + ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + ServiceStatus.dwCurrentState = dwState; + ServiceStatus.dwControlsAccepted = 0; + ServiceStatus.dwWin32ExitCode = 0; + ServiceStatus.dwServiceSpecificExitCode = 0; + ServiceStatus.dwCheckPoint = 0; + + if (dwState == SERVICE_START_PENDING || + dwState == SERVICE_STOP_PENDING || + dwState == SERVICE_PAUSE_PENDING || + dwState == SERVICE_CONTINUE_PENDING) + ServiceStatus.dwWaitHint = 10000; + else + ServiceStatus.dwWaitHint = 0; + + SetServiceStatus(ServiceStatusHandle, + &ServiceStatus); +} + + +static DWORD WINAPI +ServiceControlHandler(DWORD dwControl, + DWORD dwEventType, + LPVOID lpEventData, + LPVOID lpContext) +{ + DPRINT1("ServiceControlHandler() called\n"); + + switch (dwControl) + { + case SERVICE_CONTROL_STOP: + DPRINT1(" SERVICE_CONTROL_STOP received\n"); + UpdateServiceStatus(SERVICE_STOPPED); + return ERROR_SUCCESS; + + case SERVICE_CONTROL_PAUSE: + DPRINT1(" SERVICE_CONTROL_PAUSE received\n"); + UpdateServiceStatus(SERVICE_PAUSED); + return ERROR_SUCCESS; + + case SERVICE_CONTROL_CONTINUE: + DPRINT1(" SERVICE_CONTROL_CONTINUE received\n"); + UpdateServiceStatus(SERVICE_RUNNING); + return ERROR_SUCCESS; + + case SERVICE_CONTROL_INTERROGATE: + DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n"); + SetServiceStatus(ServiceStatusHandle, + &ServiceStatus); + return ERROR_SUCCESS; + + case SERVICE_CONTROL_SHUTDOWN: + DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n"); + UpdateServiceStatus(SERVICE_STOPPED); + return ERROR_SUCCESS; + + default : + DPRINT1(" Control %lu received\n"); + return ERROR_CALL_NOT_IMPLEMENTED; + } +} + + static VOID CALLBACK ServiceMain(DWORD argc, LPTSTR *argv) { @@ -2457,6 +2868,17 @@ ServiceMain(DWORD argc, LPTSTR *argv) DPRINT("ServiceMain() called\n"); + ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName, + ServiceControlHandler, + NULL); + if (!ServiceStatusHandle) + { + DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError()); + return; + } + + UpdateServiceStatus(SERVICE_START_PENDING); + hThread = CreateThread(NULL, 0, PnpEventThread, @@ -2484,6 +2906,8 @@ ServiceMain(DWORD argc, LPTSTR *argv) if (hThread != NULL) CloseHandle(hThread); + UpdateServiceStatus(SERVICE_RUNNING); + DPRINT("ServiceMain() done\n"); }