首页
社区
课程
招聘
[旧帖] [分享]windows内核学习笔记 0.00雪花
发表于: 2010-6-15 23:30 2726

[旧帖] [分享]windows内核学习笔记 0.00雪花

2010-6-15 23:30
2726
大家好,第一发帖,小小紧张下。最近才开始学习内核,做了点笔记,有不足的地方也希望大家可以指出来,一起进步,谢谢。

#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);

  // 打开设备对象
  //IoGetDeviceObjectPointer在知道名字的情况下,可以打开设备的指针
  //返回文件对象fileobj和设备对象devobj。
  *status = IoGetDeviceObjectPointer(&name_str, FILE_ALL_ACCESS, &fileobj, &devobj);
  //打开了之后将文件对象接触引用。我们不需要
  if (*status == STATUS_SUCCESS)
    ObDereferenceObject(fileobj);

  return devobj;
}

//NTSTATUS ccpAttachDevice
//传入driver和被绑定的的设备oldobj
//和需要初始化的绑定设备fltobj和绑定后的新地址*next
//函数完成后得到过滤设备设备对象fltobj和被绑定后的对象的设备栈最顶上对象的指针
//返回状态值
//绑定一个设备 
NTSTATUS
ccpAttachDevice(
    PDRIVER_OBJECT driver, 
    PDEVICE_OBJECT oldobj,
    PDEVICE_OBJECT *fltobj, 
    PDEVICE_OBJECT *next)
{
  NTSTATUS status;
  //声明一个设备表示绑定后的最顶上设备的指针.
  PDEVICE_OBJECT topdev = NULL;

  // 生成设备,然后绑定之。
  status = IoCreateDevice(driver,        //DriverEntry的传入值
    IN  0,          //设备扩张 填0
    IN  NULL,          //过滤设备名字,一般填NULL
    IN  oldobj->DeviceType,      //生成的设备类型,与绑定的设备一致就好了
    IN  0,  //设备特征,一般先试0
    IN  FALSE,
    OUT  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);
  //如果为NULL说明绑定失败了
  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;
    // 在这里绑定。并不管绑定是否成功
    //绑定之后,s_fltobj[i]是每个过滤驱动的地址的数组。而s_nextobj[i]是被绑定后的对象的设备栈最顶上对象的指针
    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
支持
分享
最新回复 (7)
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
LZ只贴代码什么意思?
2010-6-16 08:09
0
雪    币: 29
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
YSI
3
代码里的注释是我的一些理解。
2010-6-16 12:35
0
雪    币: 15
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
这样就叫windows内核?
2010-6-17 12:14
0
雪    币: 61
活跃值: (35)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
这好像和寒江独钓上的差不多
2010-6-17 19:50
0
雪    币: 14
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
楼主,我看不懂呀
2010-6-17 21:28
0
雪    币: 29
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
YSI
7
这个是寒江上的,不过我有自己加一点代码,以及注释。

感觉那本书确实是本好书
2010-6-17 23:55
0
雪    币: 14
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
哎,,,水平有限,,看不懂。。
2010-6-18 17:42
0
游客
登录 | 注册 方可回帖
返回
//