From 5d611535e7eca30e34a702e753fd5152e7f6118d Mon Sep 17 00:00:00 2001 From: JKornev <8bit.dosninja@gmail.com> Date: Mon, 12 Dec 2016 23:40:35 +0300 Subject: [PATCH] Added 'state' command --- Hidden/Device.c | 28 ++++++++++ Hidden/DeviceAPI.h | 5 ++ Hidden/Driver.c | 12 ++-- Hidden/Driver.h | 4 +- Hidden/ExcludeList.c | 2 +- Hidden/FsFilter.c | 14 ++++- Hidden/PsMonitor.c | 7 +++ Hidden/todo.txt | 9 +-- HiddenCLI/Commands.cpp | 2 + HiddenCLI/Helper.cpp | 17 ++++++ HiddenCLI/Helper.h | 2 + HiddenCLI/HiddenCLI.vcxproj | 2 + HiddenCLI/HiddenCLI.vcxproj.filters | 6 ++ HiddenCLI/Query.cpp | 85 ++++++++++++++++------------- HiddenCLI/Query.h | 8 ++- HiddenCLI/State.cpp | 44 +++++++++++++++ HiddenCLI/State.h | 19 +++++++ HiddenCLI/cli.txt | 9 +-- HiddenLib/HiddenLib.cpp | 46 ++++++++++++++-- 19 files changed, 259 insertions(+), 62 deletions(-) create mode 100644 HiddenCLI/State.cpp create mode 100644 HiddenCLI/State.h diff --git a/Hidden/Device.c b/Hidden/Device.c index 9c86689..fa86679 100644 --- a/Hidden/Device.c +++ b/Hidden/Device.c @@ -3,6 +3,7 @@ #include "PsMonitor.h" #include "Device.h" #include "DeviceAPI.h" +#include "Driver.h" BOOLEAN g_deviceInited = FALSE; PDEVICE_OBJECT g_deviceObject = NULL; @@ -319,6 +320,26 @@ NTSTATUS RemoveAllPsObjects(PHid_RemoveAllPsObjectsPacket Packet, USHORT Size) return status; } +NTSTATUS SetDriverStateObject(PHid_DriverStatus Packet, USHORT Size) +{ + if (Size != sizeof(Hid_DriverStatus)) + return STATUS_INVALID_PARAMETER; + + EnableDisableDriver(Packet->state ? TRUE : FALSE); + return STATUS_SUCCESS; +} + +NTSTATUS GetDriverStateObject(PHid_DriverStatus Packet, USHORT Size, PULONG state) +{ + UNREFERENCED_PARAMETER(Packet); + + if (Size != sizeof(Hid_DriverStatus)) + return STATUS_INVALID_PARAMETER; + + *state = IsDriverEnabled(); + return STATUS_SUCCESS; +} + NTSTATUS IrpDeviceControlHandler(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION irpStack; @@ -363,6 +384,13 @@ NTSTATUS IrpDeviceControlHandler(PDEVICE_OBJECT DeviceObject, PIRP Irp) // data in the same time you should make the copy of input data and work with it. switch (ioctl) { + // Driver + case HID_IOCTL_SET_DRIVER_STATE: + result.status = SetDriverStateObject((PHid_DriverStatus)inputBuffer, (USHORT)inputBufferSize); + break; + case HID_IOCTL_GET_DRIVER_STATE: + result.status = GetDriverStateObject((PHid_DriverStatus)inputBuffer, (USHORT)inputBufferSize, &result.info.state); + break; // Reg/Fs case HID_IOCTL_ADD_HIDDEN_OBJECT: result.status = AddHiddenObject((PHid_HideObjectPacket)inputBuffer, (USHORT)inputBufferSize, &result.info.id); diff --git a/Hidden/DeviceAPI.h b/Hidden/DeviceAPI.h index 2b5fcec..3fad06c 100644 --- a/Hidden/DeviceAPI.h +++ b/Hidden/DeviceAPI.h @@ -38,6 +38,11 @@ enum Hid_ObjectTypes { // Fs/Reg packets +typedef struct _Hid_DriverStatusPacket { + unsigned short state; + unsigned short reserved; +} Hid_DriverStatus, *PHid_DriverStatus; + typedef struct _Hid_HideObjectPacket { unsigned short objType; unsigned short dataSize; diff --git a/Hidden/Driver.c b/Hidden/Driver.c index da0e705..c587bd2 100644 --- a/Hidden/Driver.c +++ b/Hidden/Driver.c @@ -11,18 +11,18 @@ PDRIVER_OBJECT g_driverObject = NULL; -BOOLEAN g_driverActive = FALSE; +volatile LONG g_driverActive = FALSE; // ========================================================================================= -VOID SetDriverActivityState(BOOLEAN state) +VOID EnableDisableDriver(BOOLEAN enabled) { - g_driverActive = state; + InterlockedExchange(&g_driverActive, (LONG)enabled); } -BOOLEAN GetDriverActiviteState() +BOOLEAN IsDriverEnabled() { - return g_driverActive; + return (g_driverActive ? TRUE : FALSE); } // ========================================================================================= @@ -43,7 +43,7 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) UNREFERENCED_PARAMETER(RegistryPath); - g_driverActive = TRUE; + EnableDisableDriver(TRUE); status = InitializePsMonitor(DriverObject); if (!NT_SUCCESS(status)) diff --git a/Hidden/Driver.h b/Hidden/Driver.h index 90cc29e..6cd5d25 100644 --- a/Hidden/Driver.h +++ b/Hidden/Driver.h @@ -1,4 +1,4 @@ #pragma once -VOID SetDriverActivityState(BOOLEAN state); -BOOLEAN GetDriverActiviteState(); +VOID EnableDisableDriver(BOOLEAN enabled); +BOOLEAN IsDriverEnabled(); diff --git a/Hidden/ExcludeList.c b/Hidden/ExcludeList.c index cb38a92..a270b55 100644 --- a/Hidden/ExcludeList.c +++ b/Hidden/ExcludeList.c @@ -170,7 +170,7 @@ NTSTATUS AddExcludeListEntry(ExcludeContext Context, PUNICODE_STRING FilePath, U NTSTATUS RemoveExcludeListEntry(ExcludeContext Context, ExcludeEntryId EntryId) { - NTSTATUS status = STATUS_SUCCESS; + NTSTATUS status = STATUS_NOT_FOUND; PEXCLUDE_FILE_CONTEXT cntx = (PEXCLUDE_FILE_CONTEXT)Context; KLOCK_QUEUE_HANDLE lockHandle; PEXCLUDE_FILE_LIST_ENTRY entry; diff --git a/Hidden/FsFilter.c b/Hidden/FsFilter.c index c630741..76b5a75 100644 --- a/Hidden/FsFilter.c +++ b/Hidden/FsFilter.c @@ -7,6 +7,7 @@ #include "FsFilter.h" #include "Helper.h" #include "PsMonitor.h" +#include "Driver.h" NTSTATUS FilterSetup(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_SETUP_FLAGS Flags, DEVICE_TYPE VolumeDeviceType, FLT_FILESYSTEM_TYPE VolumeFilesystemType); @@ -101,6 +102,9 @@ FLT_PREOP_CALLBACK_STATUS FltCreatePreOperation( UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(CompletionContext); + if (!IsDriverEnabled()) + return FLT_PREOP_SUCCESS_NO_CALLBACK; + //DbgPrint("!!!!! " __FUNCTION__ ": Entered %d\n", (ULONG)KeGetCurrentIrql()); //DbgPrint("%wZ %x\n", &Data->Iopb->TargetFileObject->FileName, Data->Iopb->Parameters.Create.Options); @@ -147,10 +151,13 @@ FLT_PREOP_CALLBACK_STATUS FltCreatePreOperation( FLT_PREOP_CALLBACK_STATUS FltDirCtrlPreOperation(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID *CompletionContext) { - PAGED_CODE(); - UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(CompletionContext); + + PAGED_CODE(); + + if (!IsDriverEnabled()) + return FLT_POSTOP_FINISHED_PROCESSING; //DbgPrint("!!!!! " __FUNCTION__ ": Entered\n"); //DbgPrint("%wZ\n", &Data->Iopb->TargetFileObject->FileName); @@ -186,6 +193,9 @@ FLT_POSTOP_CALLBACK_STATUS FltDirCtrlPostOperation(PFLT_CALLBACK_DATA Data, PCFL PAGED_CODE(); + if (!IsDriverEnabled()) + return FLT_POSTOP_FINISHED_PROCESSING; + if (!NT_SUCCESS(Data->IoStatus.Status)) return FLT_POSTOP_FINISHED_PROCESSING; diff --git a/Hidden/PsMonitor.c b/Hidden/PsMonitor.c index 5fb8453..1792d97 100644 --- a/Hidden/PsMonitor.c +++ b/Hidden/PsMonitor.c @@ -3,6 +3,7 @@ #include "Helper.h" #include "PsTable.h" #include "PsRules.h" +#include "Driver.h" #define PROCESS_QUERY_LIMITED_INFORMATION 0x1000 #define SYSTEM_PROCESS_ID (HANDLE)4 @@ -112,6 +113,9 @@ OB_PREOP_CALLBACK_STATUS ProcessPreCallback(PVOID RegistrationContext, POB_PRE_O { UNREFERENCED_PARAMETER(RegistrationContext); + if (!IsDriverEnabled()) + return OB_PREOP_SUCCESS; + if (OperationInformation->KernelHandle) return OB_PREOP_SUCCESS; @@ -141,6 +145,9 @@ OB_PREOP_CALLBACK_STATUS ThreadPreCallback(PVOID RegistrationContext, POB_PRE_OP { UNREFERENCED_PARAMETER(RegistrationContext); + if (!IsDriverEnabled()) + return OB_PREOP_SUCCESS; + if (OperationInformation->KernelHandle) return OB_PREOP_SUCCESS; diff --git a/Hidden/todo.txt b/Hidden/todo.txt index 346f212..ec1f010 100644 --- a/Hidden/todo.txt +++ b/Hidden/todo.txt @@ -43,16 +43,17 @@ + Слинковать с IOCTL API lib + Добавить поддержку флага автоприсвоение состояния существующим процессам для Hid_AddExcludedImage\Hid_AddProtectedImage + Проверить как ведёт себя файловый фильтр с файлами открытыми по ID или по короткому пути -- Реализовать HiddenCLI ++ Реализовать HiddenCLI + ignore + unignore + protect + unprotect + query - - Протестировать все комманды -- При выполнении /unhide с любым ID возвращается статус ок -- Проверить чтобы все ObjId генерировались начиная с 1 + + Протестировать все комманды ++ При выполнении /unhide с любым ID возвращается статус ок ++ Проверить чтобы все ObjId генерировались начиная с 1 - Реализовать функционал вкл\выкл драйвера через IOCTL + - Написать тест для данного функционала - Написать тест HiddenCLITests + Портировать драйвер под архитектуру x64 + Портировать под версии Windows 8, 8.1, 10 diff --git a/HiddenCLI/Commands.cpp b/HiddenCLI/Commands.cpp index 35cf82e..03267b5 100644 --- a/HiddenCLI/Commands.cpp +++ b/HiddenCLI/Commands.cpp @@ -3,6 +3,7 @@ #include "Ignore.h" #include "Protect.h" #include "Query.h" +#include "State.h" using namespace std; @@ -52,6 +53,7 @@ void Commands::LoadCommandsStack() m_commandsStack.push_back(CommandPtr(new CommandProtect())); m_commandsStack.push_back(CommandPtr(new CommandUnprotect())); m_commandsStack.push_back(CommandPtr(new CommandQuery())); + m_commandsStack.push_back(CommandPtr(new CommandState())); } void Commands::Perform(Connection& connection) diff --git a/HiddenCLI/Helper.cpp b/HiddenCLI/Helper.cpp index 5e0e363..34c2452 100644 --- a/HiddenCLI/Helper.cpp +++ b/HiddenCLI/Helper.cpp @@ -148,3 +148,20 @@ bool LoadApplyOption(Arguments& args, bool applyByDefault) return applyByDefault; } + +const wchar_t* ConvertInheritTypeToUnicode(HidPsInheritTypes type) +{ + switch (type) + { + case HidPsInheritTypes::WithoutInherit: + return L"none"; + break; + case HidPsInheritTypes::InheritOnce: + return L"once"; + break; + case HidPsInheritTypes::InheritAlways: + return L"always"; + break; + } + return L"unknown"; +} diff --git a/HiddenCLI/Helper.h b/HiddenCLI/Helper.h index 64fe067..52ab19a 100644 --- a/HiddenCLI/Helper.h +++ b/HiddenCLI/Helper.h @@ -69,3 +69,5 @@ HidRegRootTypes GetRegType(std::wstring& path); HidPsInheritTypes LoadInheritOption(Arguments& args, HidPsInheritTypes default); bool LoadApplyOption(Arguments& args, bool applyByDefault); + +const wchar_t* ConvertInheritTypeToUnicode(HidPsInheritTypes type); diff --git a/HiddenCLI/HiddenCLI.vcxproj b/HiddenCLI/HiddenCLI.vcxproj index 341f253..be2f8a0 100644 --- a/HiddenCLI/HiddenCLI.vcxproj +++ b/HiddenCLI/HiddenCLI.vcxproj @@ -159,6 +159,7 @@ + @@ -168,6 +169,7 @@ + diff --git a/HiddenCLI/HiddenCLI.vcxproj.filters b/HiddenCLI/HiddenCLI.vcxproj.filters index f0ecb77..ef84ed1 100644 --- a/HiddenCLI/HiddenCLI.vcxproj.filters +++ b/HiddenCLI/HiddenCLI.vcxproj.filters @@ -17,6 +17,9 @@ Commands + + Commands + @@ -37,6 +40,9 @@ Commands + + Commands + diff --git a/HiddenCLI/Query.cpp b/HiddenCLI/Query.cpp index 5a3310c..4ec84bb 100644 --- a/HiddenCLI/Query.cpp +++ b/HiddenCLI/Query.cpp @@ -23,53 +23,62 @@ void CommandQuery::LoadArgs(Arguments& args) if (!args.GetNext(object)) throw WException(-2, L"Error, mismatched argument #1 for command 'query'"); - if (object != L"process") - throw WException(-2, L"Error, invalid object type for command 'query'"); - - if (!args.GetNext(target)) - throw WException(-2, L"Error, mismatched argument #2 for command 'query'"); - - m_targetProcId = _wtol(target.c_str()); - if (!m_targetProcId) - throw WException(-2, L"Error, invalid target pid for command 'query'"); -} - -const wchar_t* ConvertInheritTypeToUnicode(HidPsInheritTypes type) -{ - switch (type) + if (object == L"process") { - case HidPsInheritTypes::WithoutInherit: - return L"none"; - break; - case HidPsInheritTypes::InheritOnce: - return L"once"; - break; - case HidPsInheritTypes::InheritAlways: - return L"always"; - break; + m_queryType = EQueryType::QueryProcess; + + if (!args.GetNext(target)) + throw WException(-2, L"Error, mismatched argument #2 for command 'query'"); + + m_targetProcId = _wtol(target.c_str()); + if (!m_targetProcId) + throw WException(-2, L"Error, invalid target pid for command 'query'"); + } + else if (object == L"state") + { + m_queryType = EQueryType::QueryState; + } + else + { + + throw WException(-2, L"Error, invalid object type for command 'query'"); } - return L"unknown"; } void CommandQuery::PerformCommand(Connection& connection) { HidStatus status; - HidActiveState excludeState, protectedState; - HidPsInheritTypes excludedInherit, protectedInherit; - status = Hid_GetExcludedState(connection.GetContext(), m_targetProcId, &excludeState, &excludedInherit); - if (!HID_STATUS_SUCCESSFUL(status)) - throw WException(HID_STATUS_CODE(status), L"Error, query ignored state rejected"); + if (m_queryType == EQueryType::QueryState) + { + HidActiveState state; - status = Hid_GetProtectedState(connection.GetContext(), m_targetProcId, &protectedState, &protectedInherit); - if (!HID_STATUS_SUCCESSFUL(status)) - throw WException(HID_STATUS_CODE(status), L"Error, query protected state rejected"); + status = Hid_GetState(connection.GetContext(), &state); + if (!HID_STATUS_SUCCESSFUL(status)) + throw WException(HID_STATUS_CODE(status), L"Error, query state rejected"); - wcerr << L"Ignored state:" << (excludeState == HidActiveState::StateEnabled ? L"true" : L"false") - << L", inherit:" << ConvertInheritTypeToUnicode(excludedInherit) << endl; - wcerr << L"Protected state:" << (protectedState == HidActiveState::StateEnabled ? L"true" : L"false") - << L", inherit:" << ConvertInheritTypeToUnicode(protectedInherit) << endl; + wcerr << L"Driver state:" << (state == HidActiveState::StateEnabled ? L"enabled" : L"disabled") << endl; + wcout << L"status:ok;state:" << (state == HidActiveState::StateEnabled ? 1 : 0) << endl; + } + else if (m_queryType == EQueryType::QueryProcess) + { + HidActiveState excludeState, protectedState; + HidPsInheritTypes excludedInherit, protectedInherit; - wcout << L"status:ok;ignored:" << excludeState << L"," << excludedInherit - << L";protected:" << protectedState << L"," << protectedInherit << endl; + status = Hid_GetExcludedState(connection.GetContext(), m_targetProcId, &excludeState, &excludedInherit); + if (!HID_STATUS_SUCCESSFUL(status)) + throw WException(HID_STATUS_CODE(status), L"Error, query ignored state rejected"); + + status = Hid_GetProtectedState(connection.GetContext(), m_targetProcId, &protectedState, &protectedInherit); + if (!HID_STATUS_SUCCESSFUL(status)) + throw WException(HID_STATUS_CODE(status), L"Error, query protected state rejected"); + + wcerr << L"Ignored state:" << (excludeState == HidActiveState::StateEnabled ? L"true" : L"false") + << L", inherit:" << ConvertInheritTypeToUnicode(excludedInherit) << endl; + wcerr << L"Protected state:" << (protectedState == HidActiveState::StateEnabled ? L"true" : L"false") + << L", inherit:" << ConvertInheritTypeToUnicode(protectedInherit) << endl; + + wcout << L"status:ok;ignored:" << excludeState << L"," << excludedInherit + << L";protected:" << protectedState << L"," << protectedInherit << endl; + } } diff --git a/HiddenCLI/Query.h b/HiddenCLI/Query.h index a1166b5..c13c3bd 100644 --- a/HiddenCLI/Query.h +++ b/HiddenCLI/Query.h @@ -4,9 +4,15 @@ class CommandQuery : public ICommand { + enum EQueryType { + QueryProcess, + QueryState, + }; + const wchar_t* m_command = nullptr; - HidProcId m_targetProcId; + EQueryType m_queryType; + HidProcId m_targetProcId; public: diff --git a/HiddenCLI/State.cpp b/HiddenCLI/State.cpp new file mode 100644 index 0000000..378b770 --- /dev/null +++ b/HiddenCLI/State.cpp @@ -0,0 +1,44 @@ +#include "State.h" +#include + +using namespace std; + +CommandState::CommandState() : m_command(L"/state") +{ +} + +CommandState::~CommandState() +{ +} + +bool CommandState::CompareCommand(std::wstring& command) +{ + return (command == m_command); +} + +void CommandState::LoadArgs(Arguments& args) +{ + wstring state, enable; + + if (!args.GetNext(state)) + throw WException(-2, L"Error, mismatched argument #1 for command 'state'"); + + if (state == L"on") + m_state = true; + else if (state == L"off") + m_state = false; + else + throw WException(-2, L"Error, mismatched argument #2 for command 'state'"); +} + +void CommandState::PerformCommand(Connection& connection) +{ + HidStatus status; + + status = Hid_SetState(connection.GetContext(), (m_state ? HidActiveState::StateEnabled : HidActiveState::StateDisabled)); + if (!HID_STATUS_SUCCESSFUL(status)) + throw WException(HID_STATUS_CODE(status), L"Error, command 'state' rejected"); + + wcerr << L"Command 'state' successful" << endl; + wcout << L"status:ok" << endl; +} diff --git a/HiddenCLI/State.h b/HiddenCLI/State.h new file mode 100644 index 0000000..e944d1e --- /dev/null +++ b/HiddenCLI/State.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Commands.h" + +class CommandState : public ICommand +{ + const wchar_t* m_command = nullptr; + + bool m_state; + +public: + + CommandState(); + virtual ~CommandState(); + + virtual bool CompareCommand(std::wstring& command); + virtual void LoadArgs(Arguments& args); + virtual void PerformCommand(Connection& connection); +}; diff --git a/HiddenCLI/cli.txt b/HiddenCLI/cli.txt index 4788c59..2a895ca 100644 --- a/HiddenCLI/cli.txt +++ b/HiddenCLI/cli.txt @@ -10,7 +10,10 @@ connection: commands: state - Enable or disable hidden + Enable or disable enforcement (hiding, protecting, ignoring etc) + + query state + Get enforcement state hide <%path%> Hide filesystem or registry object by path @@ -21,7 +24,6 @@ commands: unhide <%ruleid%> Unhide all filesystem or registry object by selected type and rule ID - ignore image [inherit:] [apply:] <%path%> Set rule that allows to see hidden filesystem and registry objects for processes with specific image path @@ -37,7 +39,6 @@ commands: unignore pid <%pid%> Turn off abillity to see hidden filesystem and registry objects for specific process by PID - protect image [inherit:] [apply:] <%path%> Set rule that allows to enable process protection for processes with specific image path @@ -54,4 +55,4 @@ commands: Turn off protection for specific process by PID query process <%pid%> - Query information about state of the process by PID \ No newline at end of file + Query information about state of the process by PID diff --git a/HiddenLib/HiddenLib.cpp b/HiddenLib/HiddenLib.cpp index f6de377..a4746fd 100644 --- a/HiddenLib/HiddenLib.cpp +++ b/HiddenLib/HiddenLib.cpp @@ -249,6 +249,46 @@ void FreeNormalizedPath(wchar_t* normalized) free(normalized); } +HidStatus SendIoctl_QueryDriverStatusPacket(PHidContextInternal context, HidActiveState* state) +{ + Hid_DriverStatus packet = { 0 }; + Hid_StatusPacket result; + DWORD returned; + + if (!DeviceIoControl(context->hdevice, HID_IOCTL_GET_DRIVER_STATE, &packet, sizeof(packet), &result, sizeof(result), &returned, NULL)) + return HID_SET_STATUS(FALSE, GetLastError()); + + if (returned != sizeof(result)) + return HID_SET_STATUS(FALSE, ERROR_INVALID_PARAMETER); + + if (!NT_SUCCESS(result.status)) + return HID_SET_STATUS(FALSE, result.status); + + *state = (result.info.state ? HidActiveState::StateEnabled : HidActiveState::StateDisabled); + return HID_SET_STATUS(TRUE, 0); +} + +HidStatus SendIoctl_SetDriverStatusPacket(PHidContextInternal context, HidActiveState state) +{ + Hid_DriverStatus packet; + Hid_StatusPacket result; + DWORD returned; + + packet.state = (state == HidActiveState::StateEnabled ? 1 : 0); + packet.reserved = 0; + + if (!DeviceIoControl(context->hdevice, HID_IOCTL_SET_DRIVER_STATE, &packet, sizeof(packet), &result, sizeof(result), &returned, NULL)) + return HID_SET_STATUS(FALSE, GetLastError()); + + if (returned != sizeof(result)) + return HID_SET_STATUS(FALSE, ERROR_INVALID_PARAMETER); + + if (!NT_SUCCESS(result.status)) + return HID_SET_STATUS(FALSE, result.status); + + return HID_SET_STATUS(TRUE, 0); +} + HidStatus SendIoctl_HideObjectPacket(PHidContextInternal context, const wchar_t* path, unsigned short type, HidObjId* objId) { PHid_HideObjectPacket hide; @@ -498,14 +538,12 @@ HidStatus SendIoctl_SetPsStatePacket(PHidContextInternal context, HidProcId proc HidStatus _API Hid_SetState(HidContext context, HidActiveState state) { - PHidContextInternal cntx = (PHidContextInternal)context; - return HID_SET_STATUS(FALSE, ERROR_CALL_NOT_IMPLEMENTED); + return SendIoctl_SetDriverStatusPacket((PHidContextInternal)context, state); } HidStatus _API Hid_GetState(HidContext context, HidActiveState* pstate) { - PHidContextInternal cntx = (PHidContextInternal)context; - return HID_SET_STATUS(FALSE, ERROR_CALL_NOT_IMPLEMENTED); + return SendIoctl_QueryDriverStatusPacket((PHidContextInternal)context, pstate); } // Registry hiding interface