Windows内核代码片段
+ -

寒江独钓串口过滤驱动程序源代码

2022-08-22 47 0
  • comcap_tst.c
///
/// @file        comcap_tst.c
/// @author    crazy_chu
/// @date        2008-6-20
/// 

#ifndef _COMCAP_TST_HEADER_
#define _COMCAP_TST_HEADER_

// 获取包指令码
#define CCPT_CMD_GETPCK    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
// 使能
#define CCPT_CMD_ENABLE    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
// 禁止
#define CCPT_CMD_DISABLE    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)

// 两种操作类型。
#define CCPT_IN    1
#define CCPT_OUT 2

// 缓冲区中的包结构
typedef struct CCPT_PCK_ {
    unsigned long com_id;            // com口序列号
    unsigned long opr_type;            // 操作类型(读和写)
    unsigned long pid;                    // 操作进程pid
    unsigned long data_length;        // 数据长度        
    unsigned char buf[1];                // 数据缓冲
} CCPT_PCK,*PCCPT_PCK;

#endif // _COMCAP_TST_HEADER_
  • comcap.h
///
/// @file        copycat.h
/// @author    crazy_chu
/// @date        2008-6-19
/// 

#ifndef _COMCAP_HEADER_
#define _COMCAP_HEADER_

// 使能函数。
void cppSetEnable(BOOLEAN enable);

// 过滤掉所有的irp。对现有的irp
BOOLEAN ccpIrpFilter(PDEVICE_OBJECT device,PIRP irp,NTSTATUS *status);

// 在irp的时候过滤。如果返回TRUE则表示已经处理过的irp.
BOOLEAN ccpFileIrpFilter(
    PDEVICE_OBJECT next_dev,
    PIRP irp,
    PIO_STACK_LOCATION irpsp,
    NTSTATUS *status);

// 卸载的时候调用。可以解除绑定。
void ccpUnload();

// 这个函数在DriverEntry中调用,可以绑定所有的串口。
void ccpAttachAllComs(PDRIVER_OBJECT driver);

enum {
    CCP_IRP_PASS = 0,
    CCP_IRP_COMPLETED = 1,
    CCP_IRP_GO_ON = 2
};

extern int ccpIrpPreCallback(
    PDEVICE_OBJECT device,
    PDEVICE_OBJECT next_dev,
    PIRP irp,ULONG i,
    PVOID *context);

extern void ccpIrpPostCallback(
    PDEVICE_OBJECT device,
    PDEVICE_OBJECT next_dev,
    PIRP irp,
    PIO_STACK_LOCATION irpsp,
    ULONG i,
    PVOID context);

#endif
  • comcap.c
///
/// @file        comcap.c
/// @author    crazy_chu
/// @date        2008-6-18
/// 

#include <ntddk.h>
#define NTSTRSAFE_LIB
#include <ntstrsafe.h>

#ifndef SetFlag
#define SetFlag(_F,_SF)       ((_F) |= (_SF))
#endif
#ifndef ClearFlag
#define ClearFlag(_F,_SF)     ((_F) &= ~(_SF))
#endif
#define CCP_MAX_COM_ID 32

// 过滤设备和真实设备
static PDEVICE_OBJECT s_fltobj[CCP_MAX_COM_ID] = { 0 };
static PDEVICE_OBJECT s_nextobj[CCP_MAX_COM_ID] = { 0 };

// 打开一个端口设备
PDEVICE_OBJECT ccpOpenCom(ULONG id,NTSTATUS *status)
{
    UNICODE_STRING name_str;
    static WCHAR name[32] = { 0 };
    PFILE_OBJECT fileobj = NULL;
    PDEVICE_OBJECT devobj = NULL;

    // 输入字符串。
    memset(name,0,sizeof(WCHAR)*32);
    RtlStringCchPrintfW(
        name,32,
        L"\\Device\\Serial%d",id);
    RtlInitUnicodeString(&name_str,name);

    // 打开设备对象
    *status = IoGetDeviceObjectPointer(&name_str, FILE_ALL_ACCESS, &fileobj, &devobj);
    if (*status == STATUS_SUCCESS)
        ObDereferenceObject(fileobj);

    return devobj;
}

NTSTATUS
ccpAttachDevice(
                PDRIVER_OBJECT driver, 
                PDEVICE_OBJECT oldobj,
                PDEVICE_OBJECT *fltobj, 
                PDEVICE_OBJECT *next)
{
    NTSTATUS status;
    PDEVICE_OBJECT topdev = NULL;

    // 生成设备,然后绑定之。
    status = IoCreateDevice(driver,
                            0,
                            NULL,
                            oldobj->DeviceType,
                            0,
                            FALSE,
                            fltobj);

    if (status != STATUS_SUCCESS)
        return status;

    // 拷贝重要标志位。
    if(oldobj->Flags & DO_BUFFERED_IO)
        (*fltobj)->Flags |= DO_BUFFERED_IO;
    if(oldobj->Flags & DO_DIRECT_IO)
        (*fltobj)->Flags |= DO_DIRECT_IO;
    if(oldobj->Flags & DO_BUFFERED_IO)
        (*fltobj)->Flags |= DO_BUFFERED_IO;
    if(oldobj->Characteristics & FILE_DEVICE_SECURE_OPEN)
        (*fltobj)->Characteristics |= FILE_DEVICE_SECURE_OPEN;
    (*fltobj)->Flags |=  DO_POWER_PAGABLE;
    // 绑定一个设备到另一个设备上
    topdev = IoAttachDeviceToDeviceStack(*fltobj,oldobj);
    if (topdev == NULL)
    {
        // 如果绑定失败了,销毁设备,重新来过。
        IoDeleteDevice(*fltobj);
        *fltobj = NULL;
        status = STATUS_UNSUCCESSFUL;
        return status;
    }
    *next = topdev;

    // 设置这个设备已经启动。
    (*fltobj)->Flags = (*fltobj)->Flags & ~DO_DEVICE_INITIALIZING;
    return STATUS_SUCCESS;
}

// 这个函数绑定所有的串口。
void ccpAttachAllComs(PDRIVER_OBJECT driver)
{
    ULONG i;
    PDEVICE_OBJECT com_ob;
    NTSTATUS status;
    for(i = 0;i<CCP_MAX_COM_ID;i++)
    {
        // 获得object引用。
        com_ob = ccpOpenCom(i,&status);
        if(com_ob == NULL)
            continue;
        // 在这里绑定。并不管绑定是否成功。
        ccpAttachDevice(driver,com_ob,&s_fltobj[i],&s_nextobj[i]);
        // 取消object引用。
    }
}

#define  DELAY_ONE_MICROSECOND  (-10)
#define  DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
#define  DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)

void ccpUnload(PDRIVER_OBJECT drv)
{
    ULONG i;
    LARGE_INTEGER interval;

    // 首先解除绑定
    for(i=0;i<CCP_MAX_COM_ID;i++)
    {
        if(s_nextobj[i] != NULL)
            IoDetachDevice(s_nextobj[i]);
    }

    // 睡眠5秒。等待所有irp处理结束
    interval.QuadPart = (5*1000 * DELAY_ONE_MILLISECOND);        
    KeDelayExecutionThread(KernelMode,FALSE,&interval);

    // 删除这些设备
    for(i=0;i<CCP_MAX_COM_ID;i++)
    {
        if(s_fltobj[i] != NULL)
            IoDeleteDevice(s_fltobj[i]);
    }
}

NTSTATUS ccpDispatch(PDEVICE_OBJECT device,PIRP irp)
{
    PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(irp);
    NTSTATUS status;
    ULONG i,j;

    // 首先得知道发送给了哪个设备。设备一共最多CCP_MAX_COM_ID
    // 个,是前面的代码保存好的,都在s_fltobj中。
    for(i=0;i<CCP_MAX_COM_ID;i++)
    {
        if(s_fltobj[i] == device)
        {            
            // 所有电源操作,全部直接放过。
            if(irpsp->MajorFunction == IRP_MJ_POWER)
            {
                // 直接发送,然后返回说已经被处理了。
                PoStartNextPowerIrp(irp);
                IoSkipCurrentIrpStackLocation(irp);
                return PoCallDriver(s_nextobj[i],irp);
            }
            // 此外我们只过滤写请求。写请求的话,获得缓冲区以及其长度。
            // 然后打印一下。
            if(irpsp->MajorFunction == IRP_MJ_WRITE)
            {
                // 如果是写,先获得长度
                ULONG len = irpsp->Parameters.Write.Length;
                // 然后获得缓冲区
                PUCHAR buf = NULL;
                if(irp->MdlAddress != NULL)
                    buf = 
                    (PUCHAR)
                    MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority);
                else
                    buf = (PUCHAR)irp->UserBuffer;
                if(buf == NULL)
                    buf = (PUCHAR)irp->AssociatedIrp.SystemBuffer;

                // 打印内容
                for(j=0;j<len;++j)
                {
                    DbgPrint("comcap: Send Data: %2x\r\n",
                        buf[j]);
                }
            }

            // 这些请求直接下发执行即可。我们并不禁止或者改变它。
            IoSkipCurrentIrpStackLocation(irp);
            return IoCallDriver(s_nextobj[i],irp);
        }
    }

    // 如果根本就不在被绑定的设备中,那是有问题的,直接返回参数错误。
    irp->IoStatus.Information = 0;
    irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
    IoCompleteRequest(irp,IO_NO_INCREMENT);
    return STATUS_SUCCESS;    
}

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
    size_t i;
    // 所有的分发函数都设置成一样的。
    for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
    {
        driver->MajorFunction[i] = ccpDispatch;
    }

    // 支持动态卸载。
    driver->DriverUnload = ccpUnload;

    // 绑定所有的串口。
    ccpAttachAllComs(driver);

    // 直接返回成功即可。
    return STATUS_SUCCESS;
}

0 篇笔记 写笔记

寒江独钓串口过滤驱动程序源代码
comcap_tst.c////// @file comcap_tst.c/// @author crazy_chu/// @date 2008-6-20/// #ifndef _COMCAP_TST_HEADER_#define _COMCAP_......
串口过滤驱动调试过程蓝屏NO_MORE_IRP_STACK_LOCATIONS(35)问题分析
最近在搞一个串口过滤驱动程序,在调度过程中报了一个蓝屏问题。NO_MORE_IRP_STACK_LOCATIONS (35)A higher level driver has attempted to call a lower level driver throughthe IoCallDr......
Windows串口编程的IOCTL和函数
下面是常见的IOCTL及对应的Win32 API函数列表,包括COM端口和USB设备的操作。IOCTRL的宏定义位于文件:C:Program Files (x86)Windows Kits10Include10.0.18362.0shared tddser.h中IOCTL......
同步方式串口收发数据
以下是一个简单的win32串口通信程序,该程序使用了Windows API中的CreateFile、SetCommTimeouts、SetCommState、WriteFile和ReadFile等函数来进行串口通信。#include #include
以下是一个简单的win32串口异步通信程序,该程序使用了Windows API中的CreateIoCompletionPort、CreateFile、SetCommTimeouts、SetCommState、WriteFile和ReadFileEx等函数来进行串口通信。相较于同步通信,异步通信更加灵......
以下是一个使用WaitCommEvent函数的简单的win32串口通信程序,该程序使用了Windows API中的CreateFile、SetCommTimeouts、SetCommState、.WriteFile和ReadFile等函数来进行串口通信。#include
在Windows系统中,IOCTL_SERIAL_PURGE 是指清空串口设备的读写缓冲区的 IOCTL 码。使用该 IOCTL 命令可以清空串口设备的读写缓冲区并丢弃其中的所有数据。该 IOCTL 命令可以用于以下情况:丢弃全部的写缓冲数据,以确保不会发送任何未完成的数据。丢弃全部的读缓冲数......
在 Windows 操作系统下,IOCTL_SERIAL_INTERNAL_CANCEL_WAIT_WAKE 是指撤销等待唤醒(Wait-Wake)操作的内部标识(ioctl command code)。Wait-Wake 操作是指,在计算机系统待机时,通过唤醒设备的方式,让设备执行某些操作。当设......
在 Win32 API 中,用于操作串口通讯的函数主要包括:CreateFile该函数用于打开一个串口通讯接口,返回的句柄可以用于读写串口。在调用 CreateFile 函数时需要指定串口通讯接口的名称和一些访问权限等参数,详见 MSDN 文档:HANDLE CreateFile( LP......
作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!