NMFilter.sys(4.3.2.2485) 逆向源代码

来源:互联网 发布:桃蓓商城是网络传销吗 编辑:程序博客网 时间:2024/05/21 10:24
///////////////////////////////////////////////////
// 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

 
原创粉丝点击