#ifndef __CTRL2CAP_H__
#define __CTRL2CAP_H__
#pragma once
typedef struct _C2P_DEV_EXT
{
// 结构的大小
ULONG NodeSize;
// 过滤设备对象
PDEVICE_OBJECT pFilterDeviceObject;
// 同时调用时的保护锁
KSPIN_LOCK IoRequestsSpinLock;
// 进程间同步处理
KEVENT IoInProgressEvent;
// 绑定的设备对象
PDEVICE_OBJECT TargetDeviceObject;
// 绑定前底层设备对象
PDEVICE_OBJECT LowerDeviceObject;
} C2P_DEV_EXT, *PC2P_DEV_EXT;
// Kbdclass驱动的名字
#define KBD_DRIVER_NAME L"\\Driver\\kbdclass"
#define DELAY_ONE_MICROSECOND (-10)
#define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
#define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)
NTSTATUS c2pDevExtInit(IN PC2P_DEV_EXT devExt
, IN PDEVICE_OBJECT pFilterDeviceObject
, IN PDEVICE_OBJECT pTargetDeviceObject
, IN PDEVICE_OBJECT pLowerDeviceObject);
// 这个函数是事实存在的,只是文档中没有公开。声明一下
// 就可以直接使用了。
NTSTATUS ObReferenceObjectByName(
PUNICODE_STRING ObjectName
, ULONG Attributes
, PACCESS_STATE AccessState
, ACCESS_MASK DesiredAccess
, POBJECT_TYPE ObjectType
, KPROCESSOR_MODE AccessMode
, PVOID ParseContext
, PVOID *Object);
NTSTATUS c2pDispatchGeneral(IN PDEVICE_OBJECT DeviceObject
, IN PIRP irp);
NTSTATUS c2pPower(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp);
NTSTATUS c2pDispatchRead(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp);
NTSTATUS c2pReadComplete(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
, IN PVOID Context);
NTSTATUS c2pPnp(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp);
VOID c2pDetach(IN PDEVICE_OBJECT pDeviceObject);
VOID c2pUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS c2pDevExtInit(IN PC2P_DEV_EXT devExt
, IN PDEVICE_OBJECT pFilterDeviceObject
, IN PDEVICE_OBJECT pTargetDeviceObject
, IN PDEVICE_OBJECT pLowerDeviceObject);
// 打开驱动对象Kbdclass,然后绑定它下面的所有的设备:
NTSTATUS c2pAttachDevices(IN PDRIVER_OBJECT DriverObject
, IN PUNICODE_STRING RegistryPath);
#endif // __CTRL2CAP_H__#include
#include "ctrl2cap.h"
// IoDriverObjectType
extern POBJECT_TYPE *IoDriverObjectType;
ULONG gC2pKeyCount = 0;
PDRIVER_OBJECT gDriverObject = NULL;
NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
ULONG i;
NTSTATUS status;
KdPrint(("MyAttach: enter DriverEntry!\n"));
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i)
{
DriverObject->MajorFunction[i] = c2pDispatchGeneral;
}
DriverObject->MajorFunction[IRP_MJ_READ] = c2pDispatchRead;
DriverObject->MajorFunction[IRP_MJ_POWER] = c2pPower;
DriverObject->MajorFunction[IRP_MJ_PNP] = c2pPnp;
DriverObject->DriverUnload = c2pUnload;
gDriverObject = DriverObject;
status = c2pAttachDevices (DriverObject, RegistryPath);
return status;
}
NTSTATUS c2pDispatchGeneral(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp)
{
KdPrint(("Other Dispath!"));
IoSkipCurrentIrpStackLocation (Irp);
return IoCallDriver(((PC2P_DEV_EXT)DeviceObject->DeviceExtension)->LowerDeviceObject, Irp);
}
NTSTATUS c2pDispatchRead(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
PC2P_DEV_EXT devExt;
PIO_STACK_LOCATION currentIrpStack;
KEVENT waitEvent;
KeInitializeEvent (&waitEvent, NotificationEvent, FALSE);
if (Irp->CurrentLocation == 1)
{
ULONG Returnedinformation = 0;
KdPrint(("Dispatch encountered bogus current location \n"));
status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = Returnedinformation;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
gC2pKeyCount++;
devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension;
currentIrpStack = IoGetCurrentIrpStackLocation (Irp);
IoCopyCurrentIrpStackLocationToNext (Irp);
IoSetCompletionRoutine (Irp, c2pReadComplete, DeviceObject, TRUE, TRUE, TRUE);
return IoCallDriver(devExt->LowerDeviceObject, Irp);
}
NTSTATUS c2pPower(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp)
{
PC2P_DEV_EXT devExt;
devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension;
PoStartNextPowerIrp (Irp);
IoSkipCurrentIrpStackLocation (Irp);
return PoCallDriver (devExt->LowerDeviceObject, Irp);
}
NTSTATUS c2pPnp(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp)
{
PC2P_DEV_EXT devExt;
PIO_STACK_LOCATION irpStack;
NTSTATUS status = STATUS_SUCCESS;
KIRQL oldIrql;
KEVENT event;
devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation (Irp);
switch (irpStack->MinorFunction)
{
case IRP_MN_REMOVE_DEVICE:
KdPrint(("IRP_MN_REMOVE_DEVICE\n"));
IoSkipCurrentIrpStackLocation (Irp);
IoCallDriver(devExt->LowerDeviceObject, Irp);
IoDetachDevice (devExt->LowerDeviceObject);
IoDeleteDevice (DeviceObject);
return STATUS_SUCCESS;
default:
// 对于其他类型的IRP,全部都直接下发即可。
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(devExt->LowerDeviceObject, Irp);
}
return status;
}
NTSTATUS c2pAttachDevices(
IN PDRIVER_OBJECT DriverObject
, IN PUNICODE_STRING RegistryPath)
{
NTSTATUS status = 0;
UNICODE_STRING uniNtNameString;
PC2P_DEV_EXT devExt;
PDEVICE_OBJECT pFilterDeviceObject = NULL;
PDEVICE_OBJECT pTargetDeviceObject = NULL;
PDEVICE_OBJECT pLowerDeviceObject = NULL;
PDRIVER_OBJECT KbdDriverObject = NULL;
KdPrint(("MyAttach!\n"));
// 初始化Kdbclass驱动的名字。
RtlInitUnicodeString (&uniNtNameString, KBD_DRIVER_NAME);
// 打开驱动对象
status = ObReferenceObjectByName(&uniNtNameString
, OBJ_CASE_INSENSITIVE
, NULL
, 0
, *IoDriverObjectType
, KernelMode
, NULL
, &KbdDriverObject);
// 如果失败了就直接返回
if (!NT_SUCCESS(status))
{
KdPrint(("MyAttach: couldn't get the MyTest Device Object\n"));
return status;
}
else
{
// 这个打开需要解引用。早点解除了免得之后忘记。
ObDereferenceObject(DriverObject);
}
// 设备链中的第一个设备
pTargetDeviceObject = KbdDriverObject->DeviceObject;
// 遍历这个设备链
while (pTargetDeviceObject)
{
// 生成一个过滤设备
status = IoCreateDevice (DriverObject
, sizeof(C2P_DEV_EXT)
, NULL
, pTargetDeviceObject->DeviceType
, pTargetDeviceObject->Characteristics
, FALSE
, &pFilterDeviceObject);
// 如果失败了就直接退出。
if (!NT_SUCCESS(status))
{
KdPrint(("MyAttach: couldn't create the MyFilter Filter Device Object!\n"));
return status;
}
// 绑定。pLowerDeviceObject是绑定之后得到的下一个设备。
// 也就是所谓真实设备。
pLowerDeviceObject = IoAttachDeviceToDeviceStack (pFilterDeviceObject, pTargetDeviceObject);
// 如果绑定失败了,放弃之前的操作,退出。
if (!pLowerDeviceObject)
{
KdPrint(("MyAttach: couldn't attach to MyTest Device Object!\n"));
IoDeleteDevice(pFilterDeviceObject);
pFilterDeviceObject = NULL;
return status;
}
// 取到设备扩展
devExt = (PC2P_DEV_EXT)(pFilterDeviceObject->DeviceExtension);
c2pDevExtInit (devExt
, pFilterDeviceObject
, pTargetDeviceObject
, pLowerDeviceObject);
pFilterDeviceObject->DeviceType = pLowerDeviceObject->DeviceType;
pFilterDeviceObject->Characteristics = pLowerDeviceObject->Characteristics;
pFilterDeviceObject->StackSize = pLowerDeviceObject->StackSize+1;
pFilterDeviceObject->Flags |= pLowerDeviceObject->Flags
& (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE);
pTargetDeviceObject = pTargetDeviceObject->NextDevice;
}
return status;
}
NTSTATUS c2pDevExtInit(IN PC2P_DEV_EXT devExt
, IN PDEVICE_OBJECT pFilterDeviceObject
, IN PDEVICE_OBJECT pTargetDeviceObject
, IN PDEVICE_OBJECT pLowerDeviceObject)
{
memset (devExt, 0, sizeof(C2P_DEV_EXT));
devExt->NodeSize = sizeof(C2P_DEV_EXT);
devExt->pFilterDeviceObject = pFilterDeviceObject;
devExt->TargetDeviceObject = pTargetDeviceObject;
devExt->LowerDeviceObject = pLowerDeviceObject;
KeInitializeSpinLock (&(devExt->IoRequestsSpinLock));
KeInitializeEvent(&(devExt->IoInProgressEvent), NotificationEvent, FALSE);
return STATUS_SUCCESS;
}
// WIN7卸载的时候会导致电脑蓝屏重启。新手不知道什么原因。
VOID c2pUnload(IN PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT OldDeviceObject;
PC2P_DEV_EXT devExt;
LARGE_INTEGER lDelay;
PRKTHREAD Currentthread;
lDelay = RtlConvertLongToLargeInteger (100* DELAY_ONE_MILLISECOND);
Currentthread = KeGetCurrentThread ();
KeSetPriorityThread (Currentthread, LOW_REALTIME_PRIORITY);
UNREFERENCED_PARAMETER(DeviceObject);
KdPrint(("DriverEntry unLoading...\n"));
DeviceObject = DriverObject->DeviceObject;
while (DeviceObject)
{
c2pDetach(DeviceObject);
DeviceObject = DeviceObject->NextDevice;
}
ASSERT(NULL == DriverObject->DeviceObject);
while (gC2pKeyCount)
{
KeDelayExecutionThread (KernelMode, FALSE, &lDelay);
}
KdPrint(("DriverEntry unLoad Ok!\n"));
return ;
}
NTSTATUS c2pReadComplete(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
, IN PVOID Context)
{
PIO_STACK_LOCATION Irpsp;
ULONG buf_len = 0;
PUCHAR buf = NULL;
size_t i;
Irpsp = IoGetCurrentIrpStackLocation (Irp);
if (NT_SUCCESS(Irp->IoStatus.Status))
{
buf = Irp->AssociatedIrp.SystemBuffer;
buf_len = Irp->IoStatus.Information;
for (i =0; i < buf_len; ++i)
{
DbgPrint("ctrl2cap: %2x\r\n", buf[i]);
}
}
gC2pKeyCount--;
if (Irp->PendingReturned)
{
IoMarkIrpPending (Irp);
}
return Irp->IoStatus.Status;
}
VOID c2pDetach(IN PDEVICE_OBJECT pDeviceObject)
{
PC2P_DEV_EXT devExt;
BOOLEAN NoRequestsOutstanding = FALSE;
devExt = (PC2P_DEV_EXT)pDeviceObject->DeviceExtension;
__try
{
__try
{
IoDetachDevice(devExt->TargetDeviceObject);
devExt->TargetDeviceObject = NULL;
IoDeleteDevice(pDeviceObject);
devExt->pFilterDeviceObject = NULL;
DbgPrint(("Detach Finished\n"));
}
__except (EXCEPTION_EXECUTE_HANDLER){}
}
__finally{}
return;
}!IF 0
Copyright (C) Microsoft Corporation, 1997 - 1999
Module Name:
sources.
!ENDIF
TARGETNAME=ctrl2cap
TARGETPATH=obj
TARGETTYPE=DRIVER
SOURCES =ctrl2cap.c!IF 0
Copyright (C) Microsoft Corporation, 1997 - 1998
Module Name:
makefile.
!ENDIF
#
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the components of Windows NT
#
#
# if building in a DDK environment
#
!IF defined(DDK_TARGET_OS)
#
# ensure that said build environment is at least Windows XP
# 0x500 == Windows 2000
# 0x501 == Windows XP
# 0x502 == Windows .NET
#
! IF defined(_NT_TARGET_VERSION) && $(_NT_TARGET_VERSION)>=0x501
! INCLUDE $(NTMAKEENV)\makefile.def
! ELSE
! message BUILDMSG: Warning : The sample "$(MAKEDIR)" is not valid for the current OS target.
! ENDIF
!ELSE
#
# not a DDK environment, probably RAZZLE, so build
#
! INCLUDE $(NTMAKEENV)\makefile.def
!ENDIF