comcap_tst.h预定义一些值
InBlock.gif#ifndef _COMCAP_TST_HEADER_
InBlock.gif#define _COMCAP_TST_HEADER_
InBlock.gif
InBlock.gif// 获取包指令码
InBlock.gif#define CCPT_CMD_GETPCK  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
InBlock.gif// 使能
InBlock.gif#define CCPT_CMD_ENABLE  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
InBlock.gif// 禁止
InBlock.gif#define CCPT_CMD_DISABLE  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
InBlock.gif
InBlock.gif// 两种操作类型。
InBlock.gif#define CCPT_IN  1
InBlock.gif#define CCPT_OUT 2
InBlock.gif
InBlock.gif// 缓冲区中的包结构
InBlock.giftypedef struct CCPT_PCK_ {
InBlock.gif  unsigned long com_id;      // com口序列号
InBlock.gif  unsigned long opr_type;      // 操作类型(读和写)
InBlock.gif  unsigned long pid;          // 操作进程pid
InBlock.gif  unsigned long data_length;    // 数据长度    
InBlock.gif  unsigned char buf[1];        // 数据缓冲
InBlock.gif} CCPT_PCK,*PCCPT_PCK;
InBlock.gif
InBlock.gif#endif // _COMCAP_TST_HEADER_
copycat.h头文件
InBlock.gif#ifndef _COMCAP_HEADER_
InBlock.gif#define _COMCAP_HEADER_
InBlock.gif
InBlock.gif// 使能函数。
InBlock.gifvoid cppSetEnable(BOOLEAN enable);
InBlock.gif
InBlock.gif// 过滤掉所有的irp。对现有的irp
InBlock.gifBOOLEAN ccpIrpFilter(PDEVICE_OBJECT device,PIRP irp,NTSTATUS *status);
InBlock.gif
InBlock.gif// 在irp的时候过滤。如果返回TRUE则表示已经处理过的irp.
InBlock.gifBOOLEAN ccpFileIrpFilter(
InBlock.gif  PDEVICE_OBJECT next_dev,
InBlock.gif  PIRP irp,
InBlock.gif  PIO_STACK_LOCATION irpsp,
InBlock.gif  NTSTATUS *status);
InBlock.gif
InBlock.gif// 卸载的时候调用。可以解除绑定。
InBlock.gifvoid ccpUnload();
InBlock.gif
InBlock.gif// 这个函数在DriverEntry中调用,可以绑定所有的串口。
InBlock.gifvoid ccpAttachAllComs(PDRIVER_OBJECT driver);
InBlock.gif
InBlock.gifenum {
InBlock.gif  CCP_IRP_PASS = 0,
InBlock.gif  CCP_IRP_COMPLETED = 1,
InBlock.gif  CCP_IRP_GO_ON = 2
InBlock.gif};
InBlock.gif
InBlock.gifextern int ccpIrpPreCallback(
InBlock.gif  PDEVICE_OBJECT device,
InBlock.gif  PDEVICE_OBJECT next_dev,
InBlock.gif  PIRP irp,ULONG i,
InBlock.gif  PVOID *context);
InBlock.gif
InBlock.gifextern void ccpIrpPostCallback(
InBlock.gif  PDEVICE_OBJECT device,
InBlock.gif  PDEVICE_OBJECT next_dev,
InBlock.gif  PIRP irp,
InBlock.gif  PIO_STACK_LOCATION irpsp,
InBlock.gif  ULONG i,
InBlock.gif  PVOID context);
InBlock.gif
InBlock.gif#endif
comcap.c主要代码文件
InBlock.gif#include <ntddk.h>
InBlock.gif#define NTSTRSAFE_LIB
InBlock.gif#include <ntstrsafe.h>
InBlock.gif
InBlock.gif#ifndef SetFlag
InBlock.gif#define SetFlag(_F,_SF)             ((_F) |= (_SF))
InBlock.gif#endif
InBlock.gif#ifndef ClearFlag
InBlock.gif#define ClearFlag(_F,_SF)         ((_F) &= ~(_SF))
InBlock.gif#endif
InBlock.gif#define CCP_MAX_COM_ID 32
InBlock.gif
InBlock.gif// 过滤设备和真实设备
InBlock.gifstatic PDEVICE_OBJECT s_fltobj[CCP_MAX_COM_ID] = { 0 };
InBlock.gifstatic PDEVICE_OBJECT s_nextobj[CCP_MAX_COM_ID] = { 0 };
InBlock.gif
InBlock.gif// 打开一个端口设备
InBlock.gifPDEVICE_OBJECT ccpOpenCom(ULONG id,NTSTATUS *status)
InBlock.gif{
InBlock.gif  UNICODE_STRING name_str;
InBlock.gif  static WCHAR name[32] = { 0 };
InBlock.gif  PFILE_OBJECT fileobj = NULL;
InBlock.gif  PDEVICE_OBJECT devobj = NULL;
InBlock.gif
InBlock.gif  // 输入字符串。
InBlock.gif  memset(name,0,sizeof(WCHAR)*32);
InBlock.gif  RtlStringCchPrintfW(
InBlock.gif    name,32,
InBlock.gif    L"\\Device\\Serial%d",id);
InBlock.gif  RtlInitUnicodeString(&name_str,name);
InBlock.gif
InBlock.gif  // 打开设备对象
InBlock.gif  *status = IoGetDeviceObjectPointer(&name_str, FILE_ALL_ACCESS, &fileobj, &devobj);
InBlock.gif  if (*status == STATUS_SUCCESS)
InBlock.gif    ObDereferenceObject(fileobj);
InBlock.gif
InBlock.gif  return devobj;
InBlock.gif}
InBlock.gif
InBlock.gifNTSTATUS
InBlock.gifccpAttachDevice(
InBlock.gif        PDRIVER_OBJECT driver,    
InBlock.gif        PDEVICE_OBJECT oldobj,
InBlock.gif        PDEVICE_OBJECT *fltobj,    
InBlock.gif        PDEVICE_OBJECT *next)
InBlock.gif{
InBlock.gif  NTSTATUS status;
InBlock.gif  PDEVICE_OBJECT topdev = NULL;
InBlock.gif
InBlock.gif  // 生成设备,然后绑定之。
InBlock.gif  status = IoCreateDevice(driver,
InBlock.gif              0,
InBlock.gif              NULL,
InBlock.gif              oldobj->DeviceType,
InBlock.gif              0,
InBlock.gif              FALSE,
InBlock.gif              fltobj);
InBlock.gif
InBlock.gif  if (status != STATUS_SUCCESS)
InBlock.gif    return status;
InBlock.gif
InBlock.gif  // 拷贝重要标志位。
InBlock.gif  if(oldobj->Flags & DO_BUFFERED_IO)
InBlock.gif    (*fltobj)->Flags |= DO_BUFFERED_IO;
InBlock.gif  if(oldobj->Flags & DO_DIRECT_IO)
InBlock.gif    (*fltobj)->Flags |= DO_DIRECT_IO;
InBlock.gif  if(oldobj->Flags & DO_BUFFERED_IO)
InBlock.gif    (*fltobj)->Flags |= DO_BUFFERED_IO;
InBlock.gif  if(oldobj->Characteristics & FILE_DEVICE_SECURE_OPEN)
InBlock.gif    (*fltobj)->Characteristics |= FILE_DEVICE_SECURE_OPEN;
InBlock.gif  (*fltobj)->Flags |=    DO_POWER_PAGABLE;
InBlock.gif  // 绑定一个设备到另一个设备上
InBlock.gif  topdev = IoAttachDeviceToDeviceStack(*fltobj,oldobj);
InBlock.gif  if (topdev == NULL)
InBlock.gif  {
InBlock.gif    // 如果绑定失败了,销毁设备,重新来过。
InBlock.gif    IoDeleteDevice(*fltobj);
InBlock.gif    *fltobj = NULL;
InBlock.gif    status = STATUS_UNSUCCESSFUL;
InBlock.gif    return status;
InBlock.gif  }
InBlock.gif  *next = topdev;
InBlock.gif
InBlock.gif  // 设置这个设备已经启动。
InBlock.gif  (*fltobj)->Flags = (*fltobj)->Flags & ~DO_DEVICE_INITIALIZING;
InBlock.gif  return STATUS_SUCCESS;
InBlock.gif}
InBlock.gif
InBlock.gif// 这个函数绑定所有的串口。
InBlock.gifvoid ccpAttachAllComs(PDRIVER_OBJECT driver)
InBlock.gif{
InBlock.gif  ULONG i;
InBlock.gif  PDEVICE_OBJECT com_ob;
InBlock.gif  NTSTATUS status;
InBlock.gif  for(i = 0;i<CCP_MAX_COM_ID;i++)
InBlock.gif  {
InBlock.gif    // 获得object引用。
InBlock.gif    com_ob = ccpOpenCom(i,&status);
InBlock.gif    if(com_ob == NULL)
InBlock.gif      continue;
InBlock.gif    // 在这里绑定。并不管绑定是否成功。
InBlock.gif    ccpAttachDevice(driver,com_ob,&s_fltobj[i],&s_nextobj[i]);
InBlock.gif    // 取消object引用。
InBlock.gif  }
InBlock.gif}
InBlock.gif
InBlock.gif#define    DELAY_ONE_MICROSECOND    (-10)
InBlock.gif#define    DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
InBlock.gif#define    DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)
InBlock.gif
InBlock.gifvoid ccpUnload(PDRIVER_OBJECT drv)
InBlock.gif{
InBlock.gif  ULONG i;
InBlock.gif  LARGE_INTEGER interval;
InBlock.gif
InBlock.gif  // 首先解除绑定
InBlock.gif  for(i=0;i<CCP_MAX_COM_ID;i++)
InBlock.gif  {
InBlock.gif    if(s_nextobj[i] != NULL)
InBlock.gif      IoDetachDevice(s_nextobj[i]);
InBlock.gif  }
InBlock.gif
InBlock.gif  // 睡眠5秒。等待所有irp处理结束
InBlock.gif  interval.QuadPart = (5*1000 * DELAY_ONE_MILLISECOND);    
InBlock.gif  KeDelayExecutionThread(KernelMode,FALSE,&interval);
InBlock.gif
InBlock.gif  // 删除这些设备
InBlock.gif  for(i=0;i<CCP_MAX_COM_ID;i++)
InBlock.gif  {
InBlock.gif    if(s_fltobj[i] != NULL)
InBlock.gif      IoDeleteDevice(s_fltobj[i]);
InBlock.gif  }
InBlock.gif}
InBlock.gif
InBlock.gifNTSTATUS ccpDispatch(PDEVICE_OBJECT device,PIRP irp)
InBlock.gif{
InBlock.gif        PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(irp);
InBlock.gif        NTSTATUS status;
InBlock.gif        ULONG i,j;
InBlock.gif
InBlock.gif        // 首先得知道发送给了哪个设备。设备一共最多CCP_MAX_COM_ID
InBlock.gif        // 个,是前面的代码保存好的,都在s_fltobj中。
InBlock.gif        for(i=0;i<CCP_MAX_COM_ID;i++)
InBlock.gif        {
InBlock.gif                if(s_fltobj[i] == device)
InBlock.gif                {        
InBlock.gif                        // 所有电源操作,全部直接放过。
InBlock.gif                        if(irpsp->MajorFunction == IRP_MJ_POWER)
InBlock.gif                        {
InBlock.gif                                // 直接发送,然后返回说已经被处理了。
InBlock.gif                                PoStartNextPowerIrp(irp);
InBlock.gif                                IoSkipCurrentIrpStackLocation(irp);
InBlock.gif                                return PoCallDriver(s_nextobj[i],irp);
InBlock.gif                        }
InBlock.gif                        // 此外我们只过滤写请求。写请求的话,获得缓冲区以及其长度。
InBlock.gif                        // 然后打印一下。
InBlock.gif                        if(irpsp->MajorFunction == IRP_MJ_WRITE)
InBlock.gif                        {
InBlock.gif                                // 如果是写,先获得长度
InBlock.gif                                ULONG len = irpsp->Parameters.Write.Length;
InBlock.gif                                // 然后获得缓冲区
InBlock.gif                                PUCHAR buf = NULL;
InBlock.gif                                if(irp->MdlAddress != NULL)
InBlock.gif                                        buf =    
InBlock.gif                                        (PUCHAR)
InBlock.gif                                        MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority);
InBlock.gif                                else
InBlock.gif                                        buf = (PUCHAR)irp->UserBuffer;
InBlock.gif                                if(buf == NULL)
InBlock.gif                                        buf = (PUCHAR)irp->AssociatedIrp.SystemBuffer;
InBlock.gif
InBlock.gif                                // 打印内容
InBlock.gif                                for(j=0;j<len;++j)
InBlock.gif                                {
InBlock.gif                                        DbgPrint("comcap: Send Data: %2x\r\n",
InBlock.gif                                                buf[j]);
InBlock.gif                                }
InBlock.gif                        }
InBlock.gif
InBlock.gif                        // 这些请求直接下发执行即可。我们并不禁止或者改变它。
InBlock.gif                        IoSkipCurrentIrpStackLocation(irp);
InBlock.gif                        return IoCallDriver(s_nextobj[i],irp);
InBlock.gif                }
InBlock.gif        }
InBlock.gif
InBlock.gif        // 如果根本就不在被绑定的设备中,那是有问题的,直接返回参数错误。
InBlock.gif        irp->IoStatus.Information = 0;
InBlock.gif        irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
InBlock.gif        IoCompleteRequest(irp,IO_NO_INCREMENT);
InBlock.gif        return STATUS_SUCCESS;    
InBlock.gif}
InBlock.gif
InBlock.gifNTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
InBlock.gif{
InBlock.gif        size_t i;
InBlock.gif        // 所有的分发函数都设置成一样的。
InBlock.gif        for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
InBlock.gif        {
InBlock.gif                driver->MajorFunction[i] = ccpDispatch;
InBlock.gif        }
InBlock.gif
InBlock.gif        // 支持动态卸载。
InBlock.gif        driver->DriverUnload = ccpUnload;
InBlock.gif
InBlock.gif        // 绑定所有的串口。
InBlock.gif        ccpAttachAllComs(driver);
InBlock.gif
InBlock.gif        // 直接返回成功即可。
InBlock.gif        return STATUS_SUCCESS;
InBlock.gif}