///
// NMFilter.sys(4.3.2.2485)逆向源代码。
// Reverse by 张敏,sczhangmin@163.com。
// 在vc2003+ddk下编译通过,未调试验证,仅供参考!
// 转载请注明作者。
#include "ntifs.h"
///
typedef int BOOL;
#ifdef ExAllocatePool
#undef ExAllocatePool
#endif
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'tliF')
///
#define NT_DEV_NAME L"//Device//NMFILTER"
#define PORT_NAME L"COMPORT"
#define KEYBOARD_CONTROLLER L"I8042"
#define CLASS_GUID L"ClassGUID"
#define KEYBOARD_GUID L"{4D36E96B-E325-11CE-BFC1-08002BE10318}"
#define GUID_STR_LEN (38 + 1)
#define DEV_REG_KEY L"//Registry//Machine//System//CurrentControlSet//Enum//"
///
typedef struct _DEVICE_EXTENSION {
ULONG Tag;
ULONG nPortNo;
UCHAR nChips;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
typedef struct _FILT_DEV_EXT {
ULONG Tag;
POWER_STATE DeviceState;
PDEVICE_OBJECT Self;
PDEVICE_OBJECT PDO;
PDEVICE_OBJECT TargetDevObj;
DEVICE_CAPABILITIES DevCapa;
LONG lRefCount;
KEVENT event;
BOOLEAN bIsSerial;
BOOLEAN bIsKeyboard;
BOOLEAN bIsOther;
BOOLEAN bConnectInterrupt;
PKINTERRUPT InterruptObject;
ULONG nBasePort;
ULONG InterruptVector;
UCHAR InterruptLevel;
KINTERRUPT_MODE InterruptMode;
} FILT_DEV_EXT, *PFILT_DEV_EXT;
typedef struct _DEVICE_NODE *PDEVICE_NODE;
typedef struct _DEVICE_NODE {
PDEVICE_NODE Sibling;
PDEVICE_NODE Child;
PDEVICE_NODE Parent;
PDEVICE_NODE LastChild;
ULONG Level;
//PPO_DEVICE_NOTIFY Notify;
PVOID Notify;
ULONG Flags;
ULONG UserFlags;
ULONG Problem;
PDEVICE_OBJECT PhysicalDeviceObject;
PCM_RESOURCE_LIST ResourceList;
PCM_RESOURCE_LIST ResourceListTranslated;
KEVENT EnumerationMutex;
//
// InstancePath is the path of the instance node in the registry,
// i.e. <EnumBus>/<DeviceId>/<uniqueid>
//
UNICODE_STRING InstancePath;
//......
} DEVICE_NODE;
typedef struct _OBJECT_HEADER_NAME_INFO {
POBJECT_DIRECTORY Directory;
UNICODE_STRING Name;
ULONG Reserved;
#if DBG
ULONG Reserved2 ;
LONG DbgDereferenceCount ;
#endif
} OBJECT_HEADER_NAME_INFO, *POBJECT_HEADER_NAME_INFO;
struct FAKE_DEVOBJ_EXTENSION {
CSHORT Type;
USHORT Size;
PDEVICE_OBJECT DeviceObject;
ULONG PowerFlags;
PVOID Dope;
ULONG ExtensionFlags;
PDEVICE_NODE DeviceNode;
//......
};
typedef FAKE_DEVOBJ_EXTENSION *PFAKE_DEVOBJ_EXTENSION;
typedef void(*KB_DRV_HOOK_FUNC)(void);
struct KB_DRV_HOOKS
{
KB_DRV_HOOK_FUNC pfnHook1;
KB_DRV_HOOK_FUNC pfnHook2;
KB_DRV_HOOK_FUNC pfnHook3;
KB_DRV_HOOK_FUNC pfnHook4;
KB_DRV_HOOK_FUNC pfnHook5;
KB_DRV_HOOK_FUNC pfnHook6;
};
struct INTERNAL_CTRL
{
ULONG Tag;
ULONG unknown;
ULONG nCmd;
ULONG nCount;
KB_DRV_HOOK_FUNC *pHooks;
};
///
PDEVICE_OBJECT g_pDevObj = NULL;
PWSTR g_SERIAL_NAMES[] = { L"Serial0", L"Serial1", L"Serial2", L"Serial3" };
#define SERIAL_NAME_LEN 7
KB_DRV_HOOKS *g_pDrvHooks = NULL;
///
#ifdef __cplusplus
extern "C" {
#endif
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
PUNICODE_STRING pRegistryPath);
NTSTATUS
NMFilterAddDevice(PDRIVER_OBJECT DriverObject,
PDEVICE_OBJECT PhysicalDeviceObject);
NTSTATUS ForwardIrpSynchronous(PDEVICE_OBJECT DeviceObject,
PIRP Irp);
NTSTATUS NMFilterForwardIrpSync(FILT_DEV_EXT *pDevExt,
PIRP Irp);
NTSTATUS QueryRegKeyValue(HANDLE KeyHandle,
PCWSTR pwName,
PVOID pBuf,
ULONG nBufLen);
NTSTATUS QryDevCapabilities(FILT_DEV_EXT *pDevExt);
NTSTATUS NMFilterPnp(FILT_DEV_EXT *pDevExt,
PIRP Irp);
VOID
NMFilterUnload(PDRIVER_OBJECT DriverObject);
NTSTATUS
NMFilterDispatchPassThrough(PDEVICE_OBJECT DeviceObject,
PIRP Irp);
#ifdef __cplusplus
}
#endif
///
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, NMFilterAddDevice)
#pragma alloc_text (PAGE, ForwardIrpSynchronous)
#pragma alloc_text (PAGE, NMFilterForwardIrpSync)
#pragma alloc_text (PAGE, QueryRegKeyValue)
#pragma alloc_text (PAGE, QryDevCapabilities)
#pragma alloc_text (PAGE, NMFilterPnp)
#pragma alloc_text (PAGE, NMFilterUnload)
#endif
///
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
UNICODE_STRING usNtDevName;
RtlInitUnicodeString(&usNtDevName, NT_DEV_NAME);
NTSTATUS Status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
&usNtDevName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&g_pDevObj
);
if( !NT_SUCCESS(Status) ) return Status;
PDEVICE_EXTENSION pDevExt = PDEVICE_EXTENSION(g_pDevObj->DeviceExtension);
pDevExt->Tag = 'NFME'; // 0x4E4D4645
OBJECT_ATTRIBUTES ObjAttr;
InitializeObjectAttributes(
&ObjAttr,
RegistryPath,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
HANDLE KeyHandle;
Status = ZwOpenKey(
&KeyHandle,
KEY_READ,
&ObjAttr
);
#define MAX_COM_PORTS 4
if( NT_SUCCESS(Status) )
{
ULONG nPort;
Status = QueryRegKeyValue(KeyHandle, PORT_NAME, (PVOID)&nPort, sizeof(ULONG));
if( NT_SUCCESS(Status) && nPort <= MAX_COM_PORTS )
{
pDevExt->nPortNo = nPort - 1;
}
else
{
pDevExt->nPortNo = ULONG(-1);
}
ULONG nChips;
Status = QueryRegKeyValue(KeyHandle, KEYBOARD_CONTROLLER, (PVOID)&nChips, sizeof(ULONG));
if( NT_SUCCESS(Status) )
{
pDevExt->nChips = UCHAR(nChips);
}
else
{
pDevExt->nChips = 1;
}
}
ULONG ulIndex;
PDRIVER_DISPATCH *dispatch;
for( ulIndex = 0, dispatch = DriverObject->MajorFunction;
ulIndex <= IRP_MJ_MAXIMUM_FUNCTION;
ulIndex++, dispatch++ )
{
*dispatch = NMFilterDispatchPassThrough;
}
DriverObject->DriverExtension->AddDevice = NMFilterAddDevice;
DriverObject->DriverUnload = NMFilterUnload;
g_pDevObj->Flags |= DO_BUFFERED_IO;
g_pDevObj->Flags |= DO_POWER_PAGABLE;
g_pDevObj->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
NTSTATUS QueryRegKeyValue(HANDLE KeyHandle,
PCWSTR pwName,
PVOID pBuf,
ULONG nBufLen)
{
UNICODE_STRING usValueName;
RtlInitUnicodeString(&usValueName, pwName);
ULONG nValLen = usValueName.MaximumLength + nBufLen + sizeof(KEY_VALUE_FULL_INFORMATION);
PKEY_VALUE_FULL_INFORMATION pValue;
pValue = (PKEY_VALUE_FULL_INFORMATION)ExAllocatePool(PagedPool, nValLen);
if( !pValue ) return STATUS_NO_MEMORY;
NTSTATUS Status = ZwQueryValueKey(
KeyHandle,
&usValueName,
KeyValueFullInformation,
pValue,
nValLen,
&nValLen
);
if( pValue->DataLength <= nBufLen && NT_SUCCESS(Status) )
{
RtlMoveMemory(pBuf, (PCHAR)pValue + pValue->DataOffset, pValue->DataLength);
}
ExFreePool(pValue);
return Status;
}
NTSTATUS OpenDeviceRegKey(PDEVICE_OBJECT PDO, HANDLE *pKeyHandle)
{
CHAR Buf[0x200];
RtlZeroMemory(Buf, 0x200);
UNICODE_STRING usDevRegPath;
usDevRegPath.Length = 0;
usDevRegPath.MaximumLength = 0x200;
usDevRegPath.Buffer = PWSTR(Buf);
__try
{
NTSTATUS status = RtlAppendUnicodeToString(&usDevRegPath, DEV_REG_KEY);
if( NT_SUCCESS(status) )
{
PFAKE_DEVOBJ_EXTENSION pDevObjExt = PFAKE_DEVOBJ_EXTENSION(PDO->DeviceObjectExtension);
UNICODE_STRING *pInstPath = &pDevObjExt->DeviceNode->InstancePath;
status = RtlAppendUnicodeStringToString(&usDevRegPath, pInstPath);
OBJECT_ATTRIBUTES attributes;
InitializeObjectAttributes(
&attributes,
&usDevRegPath,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL
);
status = ZwOpenKey(
pKeyHandle,
KEY_READ,
&attributes
);
}
return status;
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
return STATUS_UNSUCCESSFUL;
}
}
int MyWStrCmpNI(PWSTR pwStr1, PWSTR pwStr2, int nStrLen)
{
__try
{
WCHAR wc1, wc2;
if( pwStr1 && pwStr2 && nStrLen )
{
do {
wc1 = *pwStr1; // ax
wc2 = *pwStr2; // dx
if( wc1 == 0 || wc2 == 0 )
break;
if( wc1 >= 'a' && wc1 <= 'z' )
wc1 -= 'a' - 'A';
if( wc2 >= 'a' && wc2 <= 'z' )
wc2 -= 'a' - 'A';
if( wc1 != wc2 || --nStrLen == 0 )
break;
pwStr1++;
pwStr2++;
} while( 1 );
//loc_10C7B:
wc1 = *pwStr1;
if( wc1 >= 'a' && wc1 <= 'z' )
wc1 -= 'a' - 'A';
wc2 = *pwStr2;
if( wc2 >= 'a' && wc2 <= 'z' )
wc2 -= 'a' - 'A';
return (wc1 - wc2);
}
else
{
return (pwStr1 == pwStr2 ? 1 : 0);
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
return -1;
}
}
BOOLEAN IsKeyboard(PDEVICE_OBJECT PDO)
{
BOOLEAN bRet = FALSE;
if( ULONG(PDO) < 0x80000000 ) return FALSE;
HANDLE KeyHandle;
if( NT_SUCCESS( OpenDeviceRegKey(PDO, &KeyHandle) ) )
{
PVOID pBuf = ExAllocatePool(PagedPool, 0x100);
if( pBuf )
{
if( NT_SUCCESS( QueryRegKeyValue(KeyHandle, CLASS_GUID, pBuf, 0x100) ) )
{
if( !MyWStrCmpNI(KEYBOARD_GUID, (PWSTR)pBuf, GUID_STR_LEN) )
bRet = TRUE;
}
ExFreePool(pBuf);
}
ZwClose(KeyHandle);
}
return bRet;
}
POBJECT_HEADER_NAME_INFO GetObjNameInfo(PDEVICE_OBJECT pDevObj)
{
__try
{
POBJECT_HEADER pObjHead = CONTAINING_RECORD(pDevObj, OBJECT_HEADER, Body);
UCHAR Offset = pObjHead->Flags.NameInfoOffset;
return( Offset ? POBJECT_HEADER_NAME_INFO((PCHAR)pObjHead - Offset) :
POBJECT_HEADER_NAME_INFO(pObjHead) );
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
return NULL;
}
}
PUNICODE_STRING GetObjName(PDEVICE_OBJECT pDevObj)
{
__try
{
POBJECT_HEADER_NAME_INFO pNameInfo = GetObjNameInfo(pDevObj);
USHORT nLength = pNameInfo->Name.Length;
PWSTR pStr = pNameInfo->Name.Buffer;
return &pNameInfo->Name;
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
return NULL;
}
}
BOOLEAN IsSerialPort(PDEVICE_OBJECT pTargetDevice)
{
__try
{
PDEVICE_EXTENSION pDevExt = PDEVICE_EXTENSION(g_pDevObj->DeviceExtension);
ULONG nPort = pDevExt->nPortNo;
if( nPort != 0xFFFFFFFF )
{
PUNICODE_STRING pName = GetObjName(pTargetDevice);
USHORT nLength = pName->Length;
PWSTR pStr = pName->Buffer;
if( ULONG(pStr) >= 0x80000000 && pStr != NULL )
{
if( !MyWStrCmpNI(pStr, g_SERIAL_NAMES[nPort], SERIAL_NAME_LEN) )
return TRUE;
}
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
}
return FALSE;
}
NTSTATUS
NMFilterAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
{
PAGED_CODE();
PDEVICE_OBJECT pDevObj;
NTSTATUS status = IoCreateDevice(
DriverObject,
sizeof(FILT_DEV_EXT),
NULL,
FILE_DEVICE_UNKNOWN,
FILE_AUTOGENERATED_DEVICE_NAME,
FALSE,
&pDevObj
);
if( !NT_SUCCESS(status) ) return status;
PFILT_DEV_EXT pDevExt = (PFILT_DEV_EXT)pDevObj->DeviceExtension;
RtlZeroMemory(pDevExt, sizeof(FILT_DEV_EXT));
pDevExt->Tag = 'rtlF'; // 0x72746C46
pDevExt->DeviceState.SystemState = PowerSystemUnspecified;
pDevExt->Self = pDevObj;
pDevExt->PDO = PhysicalDeviceObject;
pDevExt->lRefCount = 0;
KeInitializeEvent(&pDevExt->event, NotificationEvent, FALSE);
pDevExt->TargetDevObj = IoAttachDeviceToDeviceStack(pDevObj, PhysicalDeviceObject);
if( pDevExt->TargetDevObj->DeviceType == FILE_DEVICE_SERIAL_PORT )
{
//loc_11126:
if( IsSerialPort(pDevExt->TargetDevObj) )
pDevExt->bIsSerial = TRUE;
}
else if( pDevExt->TargetDevObj->DeviceType == FILE_DEVICE_8042_PORT )
{
if( (PDEVICE_EXTENSION(g_pDevObj->DeviceExtension))->nChips )
{
if( IsKeyboard(pDevExt->PDO) )
pDevExt->bIsKeyboard = TRUE;
else
pDevExt->bIsOther = TRUE;
}
}
//loc_11134:
pDevObj->Flags |= pDevExt->TargetDevObj->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO);
pDevObj->Flags |= pDevExt->TargetDevObj->Flags & (DO_POWER_PAGABLE | DO_POWER_INRUSH);
pDevObj->Flags &= ~DO_DEVICE_INITIALIZING;
return status;
}
NTSTATUS SetupHooks(INTERNAL_CTRL *pCtrl)
{
if( pCtrl->Tag == 'sfic' &&
pCtrl->nCmd == 0x40501 &&
pCtrl->pHooks != NULL )
{
if( pCtrl->nCount > 0 )
{
KB_DRV_HOOK_FUNC *p = pCtrl->pHooks;
for( ULONG i = 0; i < pCtrl->nCount; i++ )
{
if( *p++ == NULL ) return STATUS_UNSUCCESSFUL;
}
}
g_pDrvHooks = (KB_DRV_HOOKS*)(pCtrl->pHooks);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
void CallBackHook1(void)
{
if( g_pDrvHooks ) g_pDrvHooks->pfnHook1();
}
void CallBackHook2(void)
{
if( g_pDrvHooks ) g_pDrvHooks->pfnHook2();
}
void CallBackHook3(void)
{
if( g_pDrvHooks ) g_pDrvHooks->pfnHook3();
}
void CallBackHook4(void)
{
if( g_pDrvHooks ) g_pDrvHooks->pfnHook4();
}
void CallBackHook5(void)
{
if( g_pDrvHooks ) g_pDrvHooks->pfnHook5();
}
void CallBackHook6(void)
{
if( g_pDrvHooks ) g_pDrvHooks->pfnHook6();
}
NTSTATUS QueryDevRes(FILT_DEV_EXT *pDevExt,
PCM_RESOURCE_LIST pResourceList,
PCM_RESOURCE_LIST pResourceListTranslated)
{
if( !pResourceList || !pResourceListTranslated ) return STATUS_INVALID_PARAMETER;
ULONG nMultDev, nSResIdx, nQryPortIdx;
nMultDev = nSResIdx = nQryPortIdx = 0;
BOOL bQryPort = FALSE, bQryInterrupt = FALSE;
HANDLE DevInstRegKey;
NTSTATUS status = IoOpenDeviceRegistryKey(pDevExt->PDO,
PLUGPLAY_REGKEY_DEVICE,
READ_CONTROL,
&DevInstRegKey);
if( !NT_SUCCESS(status) ) return status;
status = QueryRegKeyValue(DevInstRegKey, L"MultiportDevice", &nMultDev, sizeof(ULONG));
if( !NT_SUCCESS(status) ) nMultDev = 0;
status = QueryRegKeyValue(DevInstRegKey, L"SerialIoResourcesIndex", &nSResIdx, sizeof(ULONG));
if( !NT_SUCCESS(status) ) nSResIdx = 0;
ZwClose(DevInstRegKey);
ULONG I;
PCM_FULL_RESOURCE_DESCRIPTOR pFrd = &pResourceList->List[0];
if( pFrd )
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR pPrd;
for( I = 0, pPrd = &pFrd->PartialResourceList.PartialDescriptors[0];
I < pFrd->PartialResourceList.Count;
I++, pPrd++ )
{
switch( pPrd->Type )
{
//loc_106B7:
case CmResourceTypePort:
if( !bQryPort )
{
if( nQryPortIdx == nSResIdx )
{
bQryPort = TRUE;
pDevExt->nBasePort = pPrd->u.Port.Start.LowPart;
}
else nQryPortIdx++;
}
break;
case CmResourceTypeInterrupt:
pDevExt->InterruptMode = KINTERRUPT_MODE(pPrd->Flags & CM_RESOURCE_INTERRUPT_LATCHED);
break;
}
}
}
PCM_FULL_RESOURCE_DESCRIPTOR pFrdTranslated = &pResourceListTranslated->List[0];
//loc_106DD
if( pFrdTranslated )
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR pPrdTranslated;
for( I = 0, pPrdTranslated = &pFrdTranslated->PartialResourceList.PartialDescriptors[0];
I < pFrdTranslated->PartialResourceList.Count;
I++, pPrdTranslated++ )
{
BOOL bQryP = FALSE;
ULONG nPIdx = 0;
switch( pPrdTranslated->Type )
{
case CmResourceTypePort:
if( !bQryP )
{
if( nPIdx == nSResIdx )
{
bQryP = TRUE;
pDevExt->nBasePort = pPrdTranslated->u.Port.Start.LowPart;
}
else nPIdx++;
}
break;
case CmResourceTypeInterrupt:
if( !bQryInterrupt )
{
pDevExt->InterruptVector = pPrdTranslated->u.Interrupt.Vector;
bQryInterrupt = TRUE;
pDevExt->InterruptLevel = (UCHAR)pPrdTranslated->u.Interrupt.Level;
}
break;
}
}
}
return STATUS_SUCCESS;
}
BOOLEAN NMFilterInterruptHandle(struct _KINTERRUPT *, PVOID)
{
return TRUE;
}
NTSTATUS SerialPnp(FILT_DEV_EXT *pDevExt, PIRP Irp)
{
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
UCHAR nMinorFunc = pIrpStack->MinorFunction;
NTSTATUS status;
switch( nMinorFunc )
{
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_STOP_DEVICE:
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_SURPRISE_REMOVAL:
status = STATUS_UNSUCCESSFUL;
break;
case IRP_MN_START_DEVICE:
//loc_107B6:
QueryDevRes(pDevExt,
pIrpStack->Parameters.StartDevice.AllocatedResources,
pIrpStack->Parameters.StartDevice.AllocatedResourcesTranslated);
status = IoConnectInterrupt(&pDevExt->InterruptObject,
NMFilterInterruptHandle,
pDevExt, // ISR Context
NULL,
pDevExt->InterruptVector,
pDevExt->InterruptLevel,
pDevExt->InterruptLevel,
pDevExt->InterruptMode,
TRUE,
KAFFINITY(-1),
FALSE);
if( NT_SUCCESS(status) )
{
pDevExt->bConnectInterrupt = TRUE;
}
//loc_107B2:
status = STATUS_SUCCESS;
break;
case IRP_MN_REMOVE_DEVICE:
//loc_10782:
if( pDevExt->DeviceState.SystemState != PowerSystemMaximum )
{
pDevExt->DeviceState.SystemState = PowerSystemMaximum;
if( pDevExt->bConnectInterrupt )
{
IoDisconnectInterrupt(pDevExt->InterruptObject);
pDevExt->bConnectInterrupt = FALSE;
}
IoDeleteDevice(pDevExt->TargetDevObj);
IoDeleteDevice(pDevExt->Self);
//loc_107B2:
status = STATUS_SUCCESS;
break;
}
//case IRP_MN_QUERY_REMOVE_DEVICE:
default:
//loc_107F1:
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(pDevExt->TargetDevObj, Irp);
}
//loc_1076E:
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS SerialPower(FILT_DEV_EXT *pDevExt, PIRP Irp)
{
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
if( pIrpStack->MinorFunction == IRP_MN_SET_POWER )
{
POWER_STATE_TYPE powerType = pIrpStack->Parameters.Power.Type;
POWER_STATE powerState = pIrpStack->Parameters.Power.State;
if( (powerType == SystemPowerState && powerState.SystemState == PowerSystemWorking) ||
(powerType == DevicePowerState && powerState.DeviceState == PowerDeviceD0) )
{
//loc_10907:
if( pDevExt->DeviceState.SystemState != PowerSystemSleeping1 )
{
CallBackHook2();
pDevExt->DeviceState.SystemState = PowerSystemSleeping1;
}
}
else if( powerType == SystemPowerState ||
( powerType == DevicePowerState &&
powerState.DeviceState > PowerDeviceD0 &&
powerState.DeviceState <= PowerDeviceD3 )
)
{
//loc_108F1:
if( pDevExt->DeviceState.SystemState == PowerSystemSleeping1 )
{
pDevExt->DeviceState.SystemState = PowerSystemHibernate;
CallBackHook1();
}
}
}
//loc_10917
//loc_10918
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS SerialDispatch(FILT_DEV_EXT *pDevExt, PIRP Irp)
{
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
switch( pIrpStack->MajorFunction )
{
case IRP_MJ_POWER:
return SerialPower(pDevExt, Irp);
case IRP_MJ_PNP:
return SerialPnp(pDevExt, Irp);
default:
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
}
void NMFilterAddRef(FILT_DEV_EXT *pDevExt)
{
InterlockedIncrement(&pDevExt->lRefCount);
}
void NMFilterRelease(FILT_DEV_EXT *pDevExt)
{
InterlockedDecrement(&pDevExt->lRefCount);
if( pDevExt->lRefCount < 0 )
{
KeSetEvent(&pDevExt->event, 0, FALSE);
}
}
NTSTATUS IrpSyncCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
PKEVENT event = (PKEVENT)Context;
KeSetEvent(event, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS ForwardIrpSynchronous(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
KEVENT event;
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoSetCompletionRoutine(Irp, IrpSyncCompletion,
&event, TRUE, TRUE, TRUE);
IoCallDriver(DeviceObject, Irp);
KeWaitForSingleObject(
&event,
Executive,
KernelMode,
FALSE,
NULL);
return Irp->IoStatus.Status;
}
NTSTATUS NMFilterForwardIrpSync(FILT_DEV_EXT *pDevExt, PIRP Irp)
{
NMFilterAddRef(pDevExt);
NTSTATUS status = ForwardIrpSynchronous(pDevExt->TargetDevObj, Irp);
NMFilterRelease(pDevExt);
return status;
}
NTSTATUS QryDevCapabilities(FILT_DEV_EXT *pDevExt)
{
PIRP Irp = IoAllocateIrp(pDevExt->TargetDevObj->StackSize, FALSE);
if( !Irp ) return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(&pDevExt->DevCapa, sizeof(DEVICE_CAPABILITIES));
pDevExt->DevCapa.Address = 0xFFFFFFFF;
pDevExt->DevCapa.UINumber = 0xFFFFFFFF;
pDevExt->DevCapa.Size = sizeof(DEVICE_CAPABILITIES);
pDevExt->DevCapa.Version = 1;
PIO_STACK_LOCATION pNextStack = IoGetNextIrpStackLocation(Irp);
pNextStack->MajorFunction = IRP_MJ_PNP;
pNextStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
pNextStack->Parameters.DeviceCapabilities.Capabilities = &pDevExt->DevCapa;
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
NTSTATUS status = NMFilterForwardIrpSync(pDevExt, Irp);
IoFreeIrp(Irp);
return status;
}
NTSTATUS NMFilterPnp(FILT_DEV_EXT *pDevExt, PIRP Irp)
{
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
UCHAR nMinorFunc = pIrpStack->MinorFunction;
NTSTATUS status;
switch( nMinorFunc )
{
case IRP_MN_START_DEVICE:
//loc_112B7:
pDevExt->DeviceState.SystemState = PowerSystemWorking;
IoCopyCurrentIrpStackLocationToNext(Irp);
status = NMFilterForwardIrpSync(pDevExt, Irp);
if( NT_SUCCESS(status) )
{
status = QryDevCapabilities(pDevExt);
pDevExt->DeviceState.SystemState = NT_SUCCESS(status) ? PowerSystemSleeping1 : PowerSystemSleeping2;
}
else
{
pDevExt->DeviceState.SystemState = PowerSystemSleeping2;
}
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_QUERY_STOP_DEVICE:
//loc_112AF
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_REMOVE_DEVICE:
//loc_11262
if( pDevExt->DeviceState.SystemState != PowerSystemMaximum)
{
IoCopyCurrentIrpStackLocationToNext(Irp);
status = IoCallDriver(pDevExt->TargetDevObj, Irp);
NMFilterRelease(pDevExt);
KeWaitForSingleObject(
&pDevExt->event,
Executive,
KernelMode,
FALSE,
NULL);
IoDetachDevice(pDevExt->TargetDevObj);
IoDetachDevice(pDevExt->Self);
return status;
}
break;
case IRP_MN_STOP_DEVICE:
//loc_11242
if( pDevExt->DeviceState.SystemState == PowerSystemHibernate )
{
status = STATUS_DEVICE_POWER_FAILURE;
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
else if( pDevExt->DeviceState.SystemState == PowerSystemSleeping1 )
{
pDevExt->DeviceState.SystemState = PowerSystemSleeping3;
}
break;
case IRP_MN_SURPRISE_REMOVAL:
Irp->IoStatus.Status = STATUS_SUCCESS;
pDevExt->DeviceState.SystemState = PowerSystemShutdown;
break;
}
//loc_1121E:
IoCopyCurrentIrpStackLocationToNext(Irp);
return IoCallDriver(pDevExt->TargetDevObj, Irp);
}
void KbPowerWorkerRoutine(PDEVICE_OBJECT DeviceObject, PVOID Context)
{
CallBackHook4();
IoFreeWorkItem( PIO_WORKITEM(Context) );
}
void OtherPowerWorkerRoutine(PDEVICE_OBJECT DeviceObject, PVOID Context)
{
CallBackHook6();
IoFreeWorkItem( PIO_WORKITEM(Context) );
}
NTSTATUS PowerCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
if( Irp->PendingReturned )
IoMarkIrpPending(Irp);
FILT_DEV_EXT *pDevExt = (FILT_DEV_EXT*)Context;
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
if( NT_SUCCESS(Irp->IoStatus.Status) &&
pIrpStack->MinorFunction == IRP_MN_SET_POWER &&
pIrpStack->Parameters.Power.Type == DevicePowerState &&
pIrpStack->Parameters.Power.State.SystemState == PowerSystemWorking &&
pDevExt->DeviceState.SystemState == PowerSystemHibernate
)
{
pDevExt->DeviceState.SystemState = PowerSystemSleeping1;
if( pDevExt->bIsKeyboard )
{
PIO_WORKITEM pItem = IoAllocateWorkItem(DeviceObject);
IoQueueWorkItem(pItem, KbPowerWorkerRoutine, DelayedWorkQueue, pItem);
}
else if( pDevExt->bIsOther )
{
PIO_WORKITEM pItem = IoAllocateWorkItem(DeviceObject);
IoQueueWorkItem(pItem, OtherPowerWorkerRoutine, DelayedWorkQueue, pItem);
}
}
//loc_108A4
PoStartNextPowerIrp(Irp);
NMFilterRelease(pDevExt);
return STATUS_SUCCESS;
}
NTSTATUS NMFilterPower(FILT_DEV_EXT *pDevExt, PIRP Irp)
{
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
UCHAR nMinorFunc = pIrpStack->MinorFunction;
if( nMinorFunc == IRP_MN_SET_POWER &&
pIrpStack->Parameters.Power.Type == DevicePowerState &&
pIrpStack->Parameters.Power.State.SystemState >= 2 &&
pIrpStack->Parameters.Power.State.SystemState <= 4 &&
pDevExt->DeviceState.SystemState == PowerSystemSleeping1 )
{
pDevExt->DeviceState.SystemState = PowerSystemHibernate;
if( pDevExt->bIsKeyboard )
{
CallBackHook3();
}
else if( pDevExt->bIsOther )
{
CallBackHook5();
}
}
//loc_10984:
NMFilterAddRef(pDevExt);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, PowerCompletion,
pDevExt, TRUE, TRUE, TRUE);
return PoCallDriver(pDevExt->TargetDevObj, Irp);
}
NTSTATUS
NMFilterDispatchPassThrough(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
UCHAR nMajorFunc = pIrpStack->MajorFunction;
UCHAR nMinorFunc = pIrpStack->MinorFunction;
PFILT_DEV_EXT pDevExt = (PFILT_DEV_EXT)DeviceObject->DeviceExtension;
NTSTATUS status = STATUS_SUCCESS;
if( DeviceObject == g_pDevObj )
{
switch( nMajorFunc )
{
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
break;
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
if( pIrpStack->Parameters.DeviceIoControl.IoControlCode == 0x9C416030 )
SetupHooks((INTERNAL_CTRL*)Irp->UserBuffer);
else
status = NTSTATUS(Irp);
break;
case IRP_MJ_POWER:
case IRP_MJ_PNP:
break;
default :
status = STATUS_UNSUCCESSFUL;
}
// loc_104F9:
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
// loc_10508
else if( pDevExt->bIsSerial )
{
status = SerialDispatch(pDevExt, Irp);
}
else
{
if( nMajorFunc == IRP_MJ_PNP )
{
if( nMinorFunc != IRP_MN_REMOVE_DEVICE )
//loc_10523
NMFilterAddRef(pDevExt);
//loc_10563:
status = NMFilterPnp(pDevExt, Irp);
if( nMinorFunc == IRP_MN_REMOVE_DEVICE )
return status;
}
else
{
//loc_10523
NMFilterAddRef(pDevExt);
if( nMajorFunc != IRP_MJ_CLOSE &&
(pDevExt->DeviceState.SystemState == 6 || pDevExt->DeviceState.SystemState == 7)
)
{
//loc_10543:
status = STATUS_DELETE_PENDING;
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
//loc_10559
else if( nMajorFunc == IRP_MJ_POWER )
{
status = NMFilterPower(pDevExt, Irp);
}
else
{
//loc_1058C
IoCopyCurrentIrpStackLocationToNext(Irp);
status = IoCallDriver(pDevExt->TargetDevObj, Irp);
}
}
// loc_10572
NMFilterRelease(pDevExt);
}
//loc_10578
return status;
}
VOID
NMFilterUnload(
IN PDRIVER_OBJECT DriverObject
)
{
}
///
// NMFilter.sys(4.3.2.2485)逆向源代码。
// Reverse by 张敏,sczhangmin@163.com。
// 在vc2003+ddk下编译通过,未调试验证,仅供参考!
// 转载请注明作者。
#include "ntifs.h"
///
typedef int BOOL;
#ifdef ExAllocatePool
#undef ExAllocatePool
#endif
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'tliF')
///
#define NT_DEV_NAME L"//Device//NMFILTER"
#define PORT_NAME L"COMPORT"
#define KEYBOARD_CONTROLLER L"I8042"
#define CLASS_GUID L"ClassGUID"
#define KEYBOARD_GUID L"{4D36E96B-E325-11CE-BFC1-08002BE10318}"
#define GUID_STR_LEN (38 + 1)
#define DEV_REG_KEY L"//Registry//Machine//System//CurrentControlSet//Enum//"
///
typedef struct _DEVICE_EXTENSION {
ULONG Tag;
ULONG nPortNo;
UCHAR nChips;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
typedef struct _FILT_DEV_EXT {
ULONG Tag;
POWER_STATE DeviceState;
PDEVICE_OBJECT Self;
PDEVICE_OBJECT PDO;
PDEVICE_OBJECT TargetDevObj;
DEVICE_CAPABILITIES DevCapa;
LONG lRefCount;
KEVENT event;
BOOLEAN bIsSerial;
BOOLEAN bIsKeyboard;
BOOLEAN bIsOther;
BOOLEAN bConnectInterrupt;
PKINTERRUPT InterruptObject;
ULONG nBasePort;
ULONG InterruptVector;
UCHAR InterruptLevel;
KINTERRUPT_MODE InterruptMode;
} FILT_DEV_EXT, *PFILT_DEV_EXT;
typedef struct _DEVICE_NODE *PDEVICE_NODE;
typedef struct _DEVICE_NODE {
PDEVICE_NODE Sibling;
PDEVICE_NODE Child;
PDEVICE_NODE Parent;
PDEVICE_NODE LastChild;
ULONG Level;
//PPO_DEVICE_NOTIFY Notify;
PVOID Notify;
ULONG Flags;
ULONG UserFlags;
ULONG Problem;
PDEVICE_OBJECT PhysicalDeviceObject;
PCM_RESOURCE_LIST ResourceList;
PCM_RESOURCE_LIST ResourceListTranslated;
KEVENT EnumerationMutex;
//
// InstancePath is the path of the instance node in the registry,
// i.e. <EnumBus>/<DeviceId>/<uniqueid>
//
UNICODE_STRING InstancePath;
//......
} DEVICE_NODE;
typedef struct _OBJECT_HEADER_NAME_INFO {
POBJECT_DIRECTORY Directory;
UNICODE_STRING Name;
ULONG Reserved;
#if DBG
ULONG Reserved2 ;
LONG DbgDereferenceCount ;
#endif
} OBJECT_HEADER_NAME_INFO, *POBJECT_HEADER_NAME_INFO;
struct FAKE_DEVOBJ_EXTENSION {
CSHORT Type;
USHORT Size;
PDEVICE_OBJECT DeviceObject;
ULONG PowerFlags;
PVOID Dope;
ULONG ExtensionFlags;
PDEVICE_NODE DeviceNode;
//......
};
typedef FAKE_DEVOBJ_EXTENSION *PFAKE_DEVOBJ_EXTENSION;
typedef void(*KB_DRV_HOOK_FUNC)(void);
struct KB_DRV_HOOKS
{
KB_DRV_HOOK_FUNC pfnHook1;
KB_DRV_HOOK_FUNC pfnHook2;
KB_DRV_HOOK_FUNC pfnHook3;
KB_DRV_HOOK_FUNC pfnHook4;
KB_DRV_HOOK_FUNC pfnHook5;
KB_DRV_HOOK_FUNC pfnHook6;
};
struct INTERNAL_CTRL
{
ULONG Tag;
ULONG unknown;
ULONG nCmd;
ULONG nCount;
KB_DRV_HOOK_FUNC *pHooks;
};
///
PDEVICE_OBJECT g_pDevObj = NULL;
PWSTR g_SERIAL_NAMES[] = { L"Serial0", L"Serial1", L"Serial2", L"Serial3" };
#define SERIAL_NAME_LEN 7
KB_DRV_HOOKS *g_pDrvHooks = NULL;
///
#ifdef __cplusplus
extern "C" {
#endif
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
PUNICODE_STRING pRegistryPath);
NTSTATUS
NMFilterAddDevice(PDRIVER_OBJECT DriverObject,
PDEVICE_OBJECT PhysicalDeviceObject);
NTSTATUS ForwardIrpSynchronous(PDEVICE_OBJECT DeviceObject,
PIRP Irp);
NTSTATUS NMFilterForwardIrpSync(FILT_DEV_EXT *pDevExt,
PIRP Irp);
NTSTATUS QueryRegKeyValue(HANDLE KeyHandle,
PCWSTR pwName,
PVOID pBuf,
ULONG nBufLen);
NTSTATUS QryDevCapabilities(FILT_DEV_EXT *pDevExt);
NTSTATUS NMFilterPnp(FILT_DEV_EXT *pDevExt,
PIRP Irp);
VOID
NMFilterUnload(PDRIVER_OBJECT DriverObject);
NTSTATUS
NMFilterDispatchPassThrough(PDEVICE_OBJECT DeviceObject,
PIRP Irp);
#ifdef __cplusplus
}
#endif
///
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, NMFilterAddDevice)
#pragma alloc_text (PAGE, ForwardIrpSynchronous)
#pragma alloc_text (PAGE, NMFilterForwardIrpSync)
#pragma alloc_text (PAGE, QueryRegKeyValue)
#pragma alloc_text (PAGE, QryDevCapabilities)
#pragma alloc_text (PAGE, NMFilterPnp)
#pragma alloc_text (PAGE, NMFilterUnload)
#endif
///
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
UNICODE_STRING usNtDevName;
RtlInitUnicodeString(&usNtDevName, NT_DEV_NAME);
NTSTATUS Status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
&usNtDevName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&g_pDevObj
);
if( !NT_SUCCESS(Status) ) return Status;
PDEVICE_EXTENSION pDevExt = PDEVICE_EXTENSION(g_pDevObj->DeviceExtension);
pDevExt->Tag = 'NFME'; // 0x4E4D4645
OBJECT_ATTRIBUTES ObjAttr;
InitializeObjectAttributes(
&ObjAttr,
RegistryPath,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
HANDLE KeyHandle;
Status = ZwOpenKey(
&KeyHandle,
KEY_READ,
&ObjAttr
);
#define MAX_COM_PORTS 4
if( NT_SUCCESS(Status) )
{
ULONG nPort;
Status = QueryRegKeyValue(KeyHandle, PORT_NAME, (PVOID)&nPort, sizeof(ULONG));
if( NT_SUCCESS(Status) && nPort <= MAX_COM_PORTS )
{
pDevExt->nPortNo = nPort - 1;
}
else
{
pDevExt->nPortNo = ULONG(-1);
}
ULONG nChips;
Status = QueryRegKeyValue(KeyHandle, KEYBOARD_CONTROLLER, (PVOID)&nChips, sizeof(ULONG));
if( NT_SUCCESS(Status) )
{
pDevExt->nChips = UCHAR(nChips);
}
else
{
pDevExt->nChips = 1;
}
}
ULONG ulIndex;
PDRIVER_DISPATCH *dispatch;
for( ulIndex = 0, dispatch = DriverObject->MajorFunction;
ulIndex <= IRP_MJ_MAXIMUM_FUNCTION;
ulIndex++, dispatch++ )
{
*dispatch = NMFilterDispatchPassThrough;
}
DriverObject->DriverExtension->AddDevice = NMFilterAddDevice;
DriverObject->DriverUnload = NMFilterUnload;
g_pDevObj->Flags |= DO_BUFFERED_IO;
g_pDevObj->Flags |= DO_POWER_PAGABLE;
g_pDevObj->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
NTSTATUS QueryRegKeyValue(HANDLE KeyHandle,
PCWSTR pwName,
PVOID pBuf,
ULONG nBufLen)
{
UNICODE_STRING usValueName;
RtlInitUnicodeString(&usValueName, pwName);
ULONG nValLen = usValueName.MaximumLength + nBufLen + sizeof(KEY_VALUE_FULL_INFORMATION);
PKEY_VALUE_FULL_INFORMATION pValue;
pValue = (PKEY_VALUE_FULL_INFORMATION)ExAllocatePool(PagedPool, nValLen);
if( !pValue ) return STATUS_NO_MEMORY;
NTSTATUS Status = ZwQueryValueKey(
KeyHandle,
&usValueName,
KeyValueFullInformation,
pValue,
nValLen,
&nValLen
);
if( pValue->DataLength <= nBufLen && NT_SUCCESS(Status) )
{
RtlMoveMemory(pBuf, (PCHAR)pValue + pValue->DataOffset, pValue->DataLength);
}
ExFreePool(pValue);
return Status;
}
NTSTATUS OpenDeviceRegKey(PDEVICE_OBJECT PDO, HANDLE *pKeyHandle)
{
CHAR Buf[0x200];
RtlZeroMemory(Buf, 0x200);
UNICODE_STRING usDevRegPath;
usDevRegPath.Length = 0;
usDevRegPath.MaximumLength = 0x200;
usDevRegPath.Buffer = PWSTR(Buf);
__try
{
NTSTATUS status = RtlAppendUnicodeToString(&usDevRegPath, DEV_REG_KEY);
if( NT_SUCCESS(status) )
{
PFAKE_DEVOBJ_EXTENSION pDevObjExt = PFAKE_DEVOBJ_EXTENSION(PDO->DeviceObjectExtension);
UNICODE_STRING *pInstPath = &pDevObjExt->DeviceNode->InstancePath;
status = RtlAppendUnicodeStringToString(&usDevRegPath, pInstPath);
OBJECT_ATTRIBUTES attributes;
InitializeObjectAttributes(
&attributes,
&usDevRegPath,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL
);
status = ZwOpenKey(
pKeyHandle,
KEY_READ,
&attributes
);
}
return status;
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
return STATUS_UNSUCCESSFUL;
}
}
int MyWStrCmpNI(PWSTR pwStr1, PWSTR pwStr2, int nStrLen)
{
__try
{
WCHAR wc1, wc2;
if( pwStr1 && pwStr2 && nStrLen )
{
do {
wc1 = *pwStr1; // ax
wc2 = *pwStr2; // dx
if( wc1 == 0 || wc2 == 0 )
break;
if( wc1 >= 'a' && wc1 <= 'z' )
wc1 -= 'a' - 'A';
if( wc2 >= 'a' && wc2 <= 'z' )
wc2 -= 'a' - 'A';
if( wc1 != wc2 || --nStrLen == 0 )
break;
pwStr1++;
pwStr2++;
} while( 1 );
//loc_10C7B:
wc1 = *pwStr1;
if( wc1 >= 'a' && wc1 <= 'z' )
wc1 -= 'a' - 'A';
wc2 = *pwStr2;
if( wc2 >= 'a' && wc2 <= 'z' )
wc2 -= 'a' - 'A';
return (wc1 - wc2);
}
else
{
return (pwStr1 == pwStr2 ? 1 : 0);
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
return -1;
}
}
BOOLEAN IsKeyboard(PDEVICE_OBJECT PDO)
{
BOOLEAN bRet = FALSE;
if( ULONG(PDO) < 0x80000000 ) return FALSE;
HANDLE KeyHandle;
if( NT_SUCCESS( OpenDeviceRegKey(PDO, &KeyHandle) ) )
{
PVOID pBuf = ExAllocatePool(PagedPool, 0x100);
if( pBuf )
{
if( NT_SUCCESS( QueryRegKeyValue(KeyHandle, CLASS_GUID, pBuf, 0x100) ) )
{
if( !MyWStrCmpNI(KEYBOARD_GUID, (PWSTR)pBuf, GUID_STR_LEN) )
bRet = TRUE;
}
ExFreePool(pBuf);
}
ZwClose(KeyHandle);
}
return bRet;
}
POBJECT_HEADER_NAME_INFO GetObjNameInfo(PDEVICE_OBJECT pDevObj)
{
__try
{
POBJECT_HEADER pObjHead = CONTAINING_RECORD(pDevObj, OBJECT_HEADER, Body);
UCHAR Offset = pObjHead->Flags.NameInfoOffset;
return( Offset ? POBJECT_HEADER_NAME_INFO((PCHAR)pObjHead - Offset) :
POBJECT_HEADER_NAME_INFO(pObjHead) );
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
return NULL;
}
}
PUNICODE_STRING GetObjName(PDEVICE_OBJECT pDevObj)
{
__try
{
POBJECT_HEADER_NAME_INFO pNameInfo = GetObjNameInfo(pDevObj);
USHORT nLength = pNameInfo->Name.Length;
PWSTR pStr = pNameInfo->Name.Buffer;
return &pNameInfo->Name;
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
return NULL;
}
}
BOOLEAN IsSerialPort(PDEVICE_OBJECT pTargetDevice)
{
__try
{
PDEVICE_EXTENSION pDevExt = PDEVICE_EXTENSION(g_pDevObj->DeviceExtension);
ULONG nPort = pDevExt->nPortNo;
if( nPort != 0xFFFFFFFF )
{
PUNICODE_STRING pName = GetObjName(pTargetDevice);
USHORT nLength = pName->Length;
PWSTR pStr = pName->Buffer;
if( ULONG(pStr) >= 0x80000000 && pStr != NULL )
{
if( !MyWStrCmpNI(pStr, g_SERIAL_NAMES[nPort], SERIAL_NAME_LEN) )
return TRUE;
}
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
}
return FALSE;
}
NTSTATUS
NMFilterAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
{
PAGED_CODE();
PDEVICE_OBJECT pDevObj;
NTSTATUS status = IoCreateDevice(
DriverObject,
sizeof(FILT_DEV_EXT),
NULL,
FILE_DEVICE_UNKNOWN,
FILE_AUTOGENERATED_DEVICE_NAME,
FALSE,
&pDevObj
);
if( !NT_SUCCESS(status) ) return status;
PFILT_DEV_EXT pDevExt = (PFILT_DEV_EXT)pDevObj->DeviceExtension;
RtlZeroMemory(pDevExt, sizeof(FILT_DEV_EXT));
pDevExt->Tag = 'rtlF'; // 0x72746C46
pDevExt->DeviceState.SystemState = PowerSystemUnspecified;
pDevExt->Self = pDevObj;
pDevExt->PDO = PhysicalDeviceObject;
pDevExt->lRefCount = 0;
KeInitializeEvent(&pDevExt->event, NotificationEvent, FALSE);
pDevExt->TargetDevObj = IoAttachDeviceToDeviceStack(pDevObj, PhysicalDeviceObject);
if( pDevExt->TargetDevObj->DeviceType == FILE_DEVICE_SERIAL_PORT )
{
//loc_11126:
if( IsSerialPort(pDevExt->TargetDevObj) )
pDevExt->bIsSerial = TRUE;
}
else if( pDevExt->TargetDevObj->DeviceType == FILE_DEVICE_8042_PORT )
{
if( (PDEVICE_EXTENSION(g_pDevObj->DeviceExtension))->nChips )
{
if( IsKeyboard(pDevExt->PDO) )
pDevExt->bIsKeyboard = TRUE;
else
pDevExt->bIsOther = TRUE;
}
}
//loc_11134:
pDevObj->Flags |= pDevExt->TargetDevObj->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO);
pDevObj->Flags |= pDevExt->TargetDevObj->Flags & (DO_POWER_PAGABLE | DO_POWER_INRUSH);
pDevObj->Flags &= ~DO_DEVICE_INITIALIZING;
return status;
}
NTSTATUS SetupHooks(INTERNAL_CTRL *pCtrl)
{
if( pCtrl->Tag == 'sfic' &&
pCtrl->nCmd == 0x40501 &&
pCtrl->pHooks != NULL )
{
if( pCtrl->nCount > 0 )
{
KB_DRV_HOOK_FUNC *p = pCtrl->pHooks;
for( ULONG i = 0; i < pCtrl->nCount; i++ )
{
if( *p++ == NULL ) return STATUS_UNSUCCESSFUL;
}
}
g_pDrvHooks = (KB_DRV_HOOKS*)(pCtrl->pHooks);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
void CallBackHook1(void)
{
if( g_pDrvHooks ) g_pDrvHooks->pfnHook1();
}
void CallBackHook2(void)
{
if( g_pDrvHooks ) g_pDrvHooks->pfnHook2();
}
void CallBackHook3(void)
{
if( g_pDrvHooks ) g_pDrvHooks->pfnHook3();
}
void CallBackHook4(void)
{
if( g_pDrvHooks ) g_pDrvHooks->pfnHook4();
}
void CallBackHook5(void)
{
if( g_pDrvHooks ) g_pDrvHooks->pfnHook5();
}
void CallBackHook6(void)
{
if( g_pDrvHooks ) g_pDrvHooks->pfnHook6();
}
NTSTATUS QueryDevRes(FILT_DEV_EXT *pDevExt,
PCM_RESOURCE_LIST pResourceList,
PCM_RESOURCE_LIST pResourceListTranslated)
{
if( !pResourceList || !pResourceListTranslated ) return STATUS_INVALID_PARAMETER;
ULONG nMultDev, nSResIdx, nQryPortIdx;
nMultDev = nSResIdx = nQryPortIdx = 0;
BOOL bQryPort = FALSE, bQryInterrupt = FALSE;
HANDLE DevInstRegKey;
NTSTATUS status = IoOpenDeviceRegistryKey(pDevExt->PDO,
PLUGPLAY_REGKEY_DEVICE,
READ_CONTROL,
&DevInstRegKey);
if( !NT_SUCCESS(status) ) return status;
status = QueryRegKeyValue(DevInstRegKey, L"MultiportDevice", &nMultDev, sizeof(ULONG));
if( !NT_SUCCESS(status) ) nMultDev = 0;
status = QueryRegKeyValue(DevInstRegKey, L"SerialIoResourcesIndex", &nSResIdx, sizeof(ULONG));
if( !NT_SUCCESS(status) ) nSResIdx = 0;
ZwClose(DevInstRegKey);
ULONG I;
PCM_FULL_RESOURCE_DESCRIPTOR pFrd = &pResourceList->List[0];
if( pFrd )
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR pPrd;
for( I = 0, pPrd = &pFrd->PartialResourceList.PartialDescriptors[0];
I < pFrd->PartialResourceList.Count;
I++, pPrd++ )
{
switch( pPrd->Type )
{
//loc_106B7:
case CmResourceTypePort:
if( !bQryPort )
{
if( nQryPortIdx == nSResIdx )
{
bQryPort = TRUE;
pDevExt->nBasePort = pPrd->u.Port.Start.LowPart;
}
else nQryPortIdx++;
}
break;
case CmResourceTypeInterrupt:
pDevExt->InterruptMode = KINTERRUPT_MODE(pPrd->Flags & CM_RESOURCE_INTERRUPT_LATCHED);
break;
}
}
}
PCM_FULL_RESOURCE_DESCRIPTOR pFrdTranslated = &pResourceListTranslated->List[0];
//loc_106DD
if( pFrdTranslated )
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR pPrdTranslated;
for( I = 0, pPrdTranslated = &pFrdTranslated->PartialResourceList.PartialDescriptors[0];
I < pFrdTranslated->PartialResourceList.Count;
I++, pPrdTranslated++ )
{
BOOL bQryP = FALSE;
ULONG nPIdx = 0;
switch( pPrdTranslated->Type )
{
case CmResourceTypePort:
if( !bQryP )
{
if( nPIdx == nSResIdx )
{
bQryP = TRUE;
pDevExt->nBasePort = pPrdTranslated->u.Port.Start.LowPart;
}
else nPIdx++;
}
break;
case CmResourceTypeInterrupt:
if( !bQryInterrupt )
{
pDevExt->InterruptVector = pPrdTranslated->u.Interrupt.Vector;
bQryInterrupt = TRUE;
pDevExt->InterruptLevel = (UCHAR)pPrdTranslated->u.Interrupt.Level;
}
break;
}
}
}
return STATUS_SUCCESS;
}
BOOLEAN NMFilterInterruptHandle(struct _KINTERRUPT *, PVOID)
{
return TRUE;
}
NTSTATUS SerialPnp(FILT_DEV_EXT *pDevExt, PIRP Irp)
{
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
UCHAR nMinorFunc = pIrpStack->MinorFunction;
NTSTATUS status;
switch( nMinorFunc )
{
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_STOP_DEVICE:
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_SURPRISE_REMOVAL:
status = STATUS_UNSUCCESSFUL;
break;
case IRP_MN_START_DEVICE:
//loc_107B6:
QueryDevRes(pDevExt,
pIrpStack->Parameters.StartDevice.AllocatedResources,
pIrpStack->Parameters.StartDevice.AllocatedResourcesTranslated);
status = IoConnectInterrupt(&pDevExt->InterruptObject,
NMFilterInterruptHandle,
pDevExt, // ISR Context
NULL,
pDevExt->InterruptVector,
pDevExt->InterruptLevel,
pDevExt->InterruptLevel,
pDevExt->InterruptMode,
TRUE,
KAFFINITY(-1),
FALSE);
if( NT_SUCCESS(status) )
{
pDevExt->bConnectInterrupt = TRUE;
}
//loc_107B2:
status = STATUS_SUCCESS;
break;
case IRP_MN_REMOVE_DEVICE:
//loc_10782:
if( pDevExt->DeviceState.SystemState != PowerSystemMaximum )
{
pDevExt->DeviceState.SystemState = PowerSystemMaximum;
if( pDevExt->bConnectInterrupt )
{
IoDisconnectInterrupt(pDevExt->InterruptObject);
pDevExt->bConnectInterrupt = FALSE;
}
IoDeleteDevice(pDevExt->TargetDevObj);
IoDeleteDevice(pDevExt->Self);
//loc_107B2:
status = STATUS_SUCCESS;
break;
}
//case IRP_MN_QUERY_REMOVE_DEVICE:
default:
//loc_107F1:
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(pDevExt->TargetDevObj, Irp);
}
//loc_1076E:
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS SerialPower(FILT_DEV_EXT *pDevExt, PIRP Irp)
{
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
if( pIrpStack->MinorFunction == IRP_MN_SET_POWER )
{
POWER_STATE_TYPE powerType = pIrpStack->Parameters.Power.Type;
POWER_STATE powerState = pIrpStack->Parameters.Power.State;
if( (powerType == SystemPowerState && powerState.SystemState == PowerSystemWorking) ||
(powerType == DevicePowerState && powerState.DeviceState == PowerDeviceD0) )
{
//loc_10907:
if( pDevExt->DeviceState.SystemState != PowerSystemSleeping1 )
{
CallBackHook2();
pDevExt->DeviceState.SystemState = PowerSystemSleeping1;
}
}
else if( powerType == SystemPowerState ||
( powerType == DevicePowerState &&
powerState.DeviceState > PowerDeviceD0 &&
powerState.DeviceState <= PowerDeviceD3 )
)
{
//loc_108F1:
if( pDevExt->DeviceState.SystemState == PowerSystemSleeping1 )
{
pDevExt->DeviceState.SystemState = PowerSystemHibernate;
CallBackHook1();
}
}
}
//loc_10917
//loc_10918
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS SerialDispatch(FILT_DEV_EXT *pDevExt, PIRP Irp)
{
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
switch( pIrpStack->MajorFunction )
{
case IRP_MJ_POWER:
return SerialPower(pDevExt, Irp);
case IRP_MJ_PNP:
return SerialPnp(pDevExt, Irp);
default:
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
}
void NMFilterAddRef(FILT_DEV_EXT *pDevExt)
{
InterlockedIncrement(&pDevExt->lRefCount);
}
void NMFilterRelease(FILT_DEV_EXT *pDevExt)
{
InterlockedDecrement(&pDevExt->lRefCount);
if( pDevExt->lRefCount < 0 )
{
KeSetEvent(&pDevExt->event, 0, FALSE);
}
}
NTSTATUS IrpSyncCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
PKEVENT event = (PKEVENT)Context;
KeSetEvent(event, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS ForwardIrpSynchronous(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
KEVENT event;
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoSetCompletionRoutine(Irp, IrpSyncCompletion,
&event, TRUE, TRUE, TRUE);
IoCallDriver(DeviceObject, Irp);
KeWaitForSingleObject(
&event,
Executive,
KernelMode,
FALSE,
NULL);
return Irp->IoStatus.Status;
}
NTSTATUS NMFilterForwardIrpSync(FILT_DEV_EXT *pDevExt, PIRP Irp)
{
NMFilterAddRef(pDevExt);
NTSTATUS status = ForwardIrpSynchronous(pDevExt->TargetDevObj, Irp);
NMFilterRelease(pDevExt);
return status;
}
NTSTATUS QryDevCapabilities(FILT_DEV_EXT *pDevExt)
{
PIRP Irp = IoAllocateIrp(pDevExt->TargetDevObj->StackSize, FALSE);
if( !Irp ) return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(&pDevExt->DevCapa, sizeof(DEVICE_CAPABILITIES));
pDevExt->DevCapa.Address = 0xFFFFFFFF;
pDevExt->DevCapa.UINumber = 0xFFFFFFFF;
pDevExt->DevCapa.Size = sizeof(DEVICE_CAPABILITIES);
pDevExt->DevCapa.Version = 1;
PIO_STACK_LOCATION pNextStack = IoGetNextIrpStackLocation(Irp);
pNextStack->MajorFunction = IRP_MJ_PNP;
pNextStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
pNextStack->Parameters.DeviceCapabilities.Capabilities = &pDevExt->DevCapa;
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
NTSTATUS status = NMFilterForwardIrpSync(pDevExt, Irp);
IoFreeIrp(Irp);
return status;
}
NTSTATUS NMFilterPnp(FILT_DEV_EXT *pDevExt, PIRP Irp)
{
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
UCHAR nMinorFunc = pIrpStack->MinorFunction;
NTSTATUS status;
switch( nMinorFunc )
{
case IRP_MN_START_DEVICE:
//loc_112B7:
pDevExt->DeviceState.SystemState = PowerSystemWorking;
IoCopyCurrentIrpStackLocationToNext(Irp);
status = NMFilterForwardIrpSync(pDevExt, Irp);
if( NT_SUCCESS(status) )
{
status = QryDevCapabilities(pDevExt);
pDevExt->DeviceState.SystemState = NT_SUCCESS(status) ? PowerSystemSleeping1 : PowerSystemSleeping2;
}
else
{
pDevExt->DeviceState.SystemState = PowerSystemSleeping2;
}
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_QUERY_STOP_DEVICE:
//loc_112AF
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_REMOVE_DEVICE:
//loc_11262
if( pDevExt->DeviceState.SystemState != PowerSystemMaximum)
{
IoCopyCurrentIrpStackLocationToNext(Irp);
status = IoCallDriver(pDevExt->TargetDevObj, Irp);
NMFilterRelease(pDevExt);
KeWaitForSingleObject(
&pDevExt->event,
Executive,
KernelMode,
FALSE,
NULL);
IoDetachDevice(pDevExt->TargetDevObj);
IoDetachDevice(pDevExt->Self);
return status;
}
break;
case IRP_MN_STOP_DEVICE:
//loc_11242
if( pDevExt->DeviceState.SystemState == PowerSystemHibernate )
{
status = STATUS_DEVICE_POWER_FAILURE;
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
else if( pDevExt->DeviceState.SystemState == PowerSystemSleeping1 )
{
pDevExt->DeviceState.SystemState = PowerSystemSleeping3;
}
break;
case IRP_MN_SURPRISE_REMOVAL:
Irp->IoStatus.Status = STATUS_SUCCESS;
pDevExt->DeviceState.SystemState = PowerSystemShutdown;
break;
}
//loc_1121E:
IoCopyCurrentIrpStackLocationToNext(Irp);
return IoCallDriver(pDevExt->TargetDevObj, Irp);
}
void KbPowerWorkerRoutine(PDEVICE_OBJECT DeviceObject, PVOID Context)
{
CallBackHook4();
IoFreeWorkItem( PIO_WORKITEM(Context) );
}
void OtherPowerWorkerRoutine(PDEVICE_OBJECT DeviceObject, PVOID Context)
{
CallBackHook6();
IoFreeWorkItem( PIO_WORKITEM(Context) );
}
NTSTATUS PowerCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
if( Irp->PendingReturned )
IoMarkIrpPending(Irp);
FILT_DEV_EXT *pDevExt = (FILT_DEV_EXT*)Context;
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
if( NT_SUCCESS(Irp->IoStatus.Status) &&
pIrpStack->MinorFunction == IRP_MN_SET_POWER &&
pIrpStack->Parameters.Power.Type == DevicePowerState &&
pIrpStack->Parameters.Power.State.SystemState == PowerSystemWorking &&
pDevExt->DeviceState.SystemState == PowerSystemHibernate
)
{
pDevExt->DeviceState.SystemState = PowerSystemSleeping1;
if( pDevExt->bIsKeyboard )
{
PIO_WORKITEM pItem = IoAllocateWorkItem(DeviceObject);
IoQueueWorkItem(pItem, KbPowerWorkerRoutine, DelayedWorkQueue, pItem);
}
else if( pDevExt->bIsOther )
{
PIO_WORKITEM pItem = IoAllocateWorkItem(DeviceObject);
IoQueueWorkItem(pItem, OtherPowerWorkerRoutine, DelayedWorkQueue, pItem);
}
}
//loc_108A4
PoStartNextPowerIrp(Irp);
NMFilterRelease(pDevExt);
return STATUS_SUCCESS;
}
NTSTATUS NMFilterPower(FILT_DEV_EXT *pDevExt, PIRP Irp)
{
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
UCHAR nMinorFunc = pIrpStack->MinorFunction;
if( nMinorFunc == IRP_MN_SET_POWER &&
pIrpStack->Parameters.Power.Type == DevicePowerState &&
pIrpStack->Parameters.Power.State.SystemState >= 2 &&
pIrpStack->Parameters.Power.State.SystemState <= 4 &&
pDevExt->DeviceState.SystemState == PowerSystemSleeping1 )
{
pDevExt->DeviceState.SystemState = PowerSystemHibernate;
if( pDevExt->bIsKeyboard )
{
CallBackHook3();
}
else if( pDevExt->bIsOther )
{
CallBackHook5();
}
}
//loc_10984:
NMFilterAddRef(pDevExt);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, PowerCompletion,
pDevExt, TRUE, TRUE, TRUE);
return PoCallDriver(pDevExt->TargetDevObj, Irp);
}
NTSTATUS
NMFilterDispatchPassThrough(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
UCHAR nMajorFunc = pIrpStack->MajorFunction;
UCHAR nMinorFunc = pIrpStack->MinorFunction;
PFILT_DEV_EXT pDevExt = (PFILT_DEV_EXT)DeviceObject->DeviceExtension;
NTSTATUS status = STATUS_SUCCESS;
if( DeviceObject == g_pDevObj )
{
switch( nMajorFunc )
{
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
break;
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
if( pIrpStack->Parameters.DeviceIoControl.IoControlCode == 0x9C416030 )
SetupHooks((INTERNAL_CTRL*)Irp->UserBuffer);
else
status = NTSTATUS(Irp);
break;
case IRP_MJ_POWER:
case IRP_MJ_PNP:
break;
default :
status = STATUS_UNSUCCESSFUL;
}
// loc_104F9:
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
// loc_10508
else if( pDevExt->bIsSerial )
{
status = SerialDispatch(pDevExt, Irp);
}
else
{
if( nMajorFunc == IRP_MJ_PNP )
{
if( nMinorFunc != IRP_MN_REMOVE_DEVICE )
//loc_10523
NMFilterAddRef(pDevExt);
//loc_10563:
status = NMFilterPnp(pDevExt, Irp);
if( nMinorFunc == IRP_MN_REMOVE_DEVICE )
return status;
}
else
{
//loc_10523
NMFilterAddRef(pDevExt);
if( nMajorFunc != IRP_MJ_CLOSE &&
(pDevExt->DeviceState.SystemState == 6 || pDevExt->DeviceState.SystemState == 7)
)
{
//loc_10543:
status = STATUS_DELETE_PENDING;
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
//loc_10559
else if( nMajorFunc == IRP_MJ_POWER )
{
status = NMFilterPower(pDevExt, Irp);
}
else
{
//loc_1058C
IoCopyCurrentIrpStackLocationToNext(Irp);
status = IoCallDriver(pDevExt->TargetDevObj, Irp);
}
}
// loc_10572
NMFilterRelease(pDevExt);
}
//loc_10578
return status;
}
VOID
NMFilterUnload(
IN PDRIVER_OBJECT DriverObject
)
{
}
///
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1752590