IRP

IRP

 

IRP

Irp(I/O Resquet Package)即输入输出请求包,其处理机制类似于Ring3下应用程序的消息处理机制。Ring3 根据接收的消息类别进行处理Irp   驱动程序根据接收不同类型的Irp后,进入不同的派遣函数,在派遣函数中IRP得到相应的处理。

IRP的结构比较复杂,现先了解两个基本属性 MajorFuntion  MinorFuntion主类型和子类型,在一个驱动中DriverObject->MajorFunction 是一个数组,主要记录派遣函数的地址,操作系统会根据接收的IRP进入不同的派遣函数中,在派遣函数中还会判断这个IRP属于那种MinorFuntion。

下面代码ring3 下调用了WriteFile ReadFile GetFileSize,会产生3个不同的Irp IRP_MJ_READ  IRP_MJ_WRITE IRP_MJ_QUERY_INFORMATION.

 1 //Load函数 
 2 BOOL LoadNtDriver(char* pDriverName, char* pDriverPath )
 3 {
 4      SC_HANDLE hServiceMgr=NULL;         
 5      SC_HANDLE hServiceDDK=NULL;             
 6      DWORD dwRtn;
 7      __try
 8      {
 9 
10      hServiceMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
11      if (hServiceMgr==NULL)
12      {
13          return FALSE;
14      }
15      hServiceDDK = CreateService( hServiceMgr,//SCM管理器句柄 
16          pDriverName, //驱动程序的在注册表中的名字  
17          pDriverName, // 注册表驱动程序的 DisplayName 值  
18          SERVICE_ALL_ACCESS, // 加载驱动程序的访问权限  
19          SERVICE_KERNEL_DRIVER,// 表示加载的服务是驱动程序  
20          SERVICE_DEMAND_START, // 注册表驱动程序的 Start 值  
21          SERVICE_ERROR_IGNORE, // 注册表驱动程序的 ErrorControl 值  
22          pDriverPath, // 注册表驱动程序的 ImagePath 值  
23          NULL,              //要开启服务的 用户组
24          NULL,  //输出验证标签
25          NULL,   //所依赖的服务的名称
26          NULL,   //用户账户名称
27          NULL);  //用户口令
28      if( hServiceDDK == NULL ) 
29      {
30          //可能已经存在了
31         dwRtn=GetLastError();
32         if( dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS )
33         {
34             //其他错误引起的
35             return FALSE;
36         }
37         hServiceDDK = OpenService( hServiceMgr, pDriverName, SERVICE_ALL_ACCESS );  
38         if( hServiceDDK == NULL )  
39         {
40             //打开失败
41             return FALSE;
42         }
43      }
44      if(!StartService( hServiceDDK, NULL, NULL ))
45      {
46          AfxMessageBox(_T("启动失败"));
47      }
48      }
49      __finally
50      {
51 
52          if(hServiceDDK)
53          {
54              CloseServiceHandle(hServiceDDK);
55          }
56          if(hServiceMgr)
57          {
58              CloseServiceHandle(hServiceMgr);
59          }
60      }
61 return TRUE;
62 
63 }

//驱动卸载函数
BOOL UnloadNtDriver(char* pDriverName)
{
    BOOL bRet = FALSE;
    SC_HANDLE hSCM=NULL;//SCM管理器的句柄,用来存放OpenSCManager的返回值
    SC_HANDLE hService=NULL;//NT驱动程序的服务句柄,用来存放OpenService的返回值
    SERVICE_STATUS SvrSta;
    //二打开SCM管理器
    __try
    {

    hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );  
    if( hSCM == NULL )  
    {
        //带开SCM管理器失败
        TRACE( "OpenSCManager() Faild %d ! \n", GetLastError() );  
        bRet = FALSE;
        return bRet;
    }  
    else  
    {
        //打开SCM管理器成功
        TRACE( "OpenSCManager() ok ! \n" );  
    }
    //三打开驱动所对应的服务
        hService = OpenService( hSCM, pDriverName, SERVICE_ALL_ACCESS ); 
        if( hService == NULL )  
        {
            return FALSE;
        }

        if( !ControlService( hService, SERVICE_CONTROL_STOP , &SvrSta ) )  
        {  
            TRACE( "用ControlService() 停止驱动程序失败 错误号:%d !\n", GetLastError() );  
        }  
        if( !DeleteService( hService ) )  //TRUE//FALSE
        {
            //卸载失败
            TRACE( "卸载失败:DeleteSrevice()错误号:%d !\n", GetLastError() );  
        }  

    }
    __finally
    {
        if(hService>0)
        {
            CloseServiceHandle(hService);
        }
        if(hSCM>0)
        {
            CloseServiceHandle(hSCM);
        }

    }
    return TRUE;


}

void OnLoad() 
{
    m_Message.SetWindowText(_T(""));
     HANDLE hDevice = INVALID_HANDLE_VALUE;
     char buffer[1024]={
   0};
     char wbuf[64]={
   0};
      DWORD dwByteRead;
      DWORD dwByteWrite;
      DWORD dwSize;
    // TODO: Add extra validation here
    CFileDialog  file(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,_T("驱动文件(SYS)|*.sys|"),NULL);
    if(file.DoModal()==IDOK)
    {
        CString str1,str2;
        str1=file.GetFileName();
        str2=file.GetPathName();
        if(LoadNtDriver(str1.GetBuffer(str1.GetLength()),str2.GetBuffer(str2.GetLength())))
        {
            path=str1;
            m_Message.SetWindowText(_T("加载成功"));
            AddMessage(_T("加载成功"));
            hDevice = CreateFile(L"\\\\.\\LinkSmkDevice",GENERIC_READ | GENERIC_WRITE,0,                         
                            NULL,OPEN_EXISTING,     
                            FILE_ATTRIBUTE_NORMAL,NULL ); //发送IRP_MJ_CREATE
               if ( hDevice != INVALID_HANDLE_VALUE )
               {
                  
                   AddMessage(_T("打开设备成功"));
                  
               }

            memset(wbuf,'S',64);
              if ( WriteFile(hDevice,&wbuf, 64, &dwByteWrite, NULL  ) ) //向设备写入64个字节的 'S'
              {
                AddMessage(_T("W设备"));
              }
              
              if(ReadFile( hDevice, &buffer, sizeof(buffer), &dwByteRead, NULL ))//读取设备中缓存
              {
                  CString str;
                  str.Format(_T("%s-%d"),buffer,dwByteRead);
                  AddMessage(str);
             }
              DWORD ret=GetFileSize(hDevice,&dwSize);
              if (ret)
              {

                  CString st2r;
                  st2r.Format(_T("GetSize Success \r\n FileSize:%d"),ret);
                    AddMessage(st2r);
              }
               if( DeviceIoControl( hDevice,                        
                   CTL_CODE( FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS ),                        
                   &buffer, dwByteRead, &buffer, sizeof(buffer), &dwByteRead, NULL ) )


                    if ( hDevice != INVALID_HANDLE_VALUE) 
                    {                 
                        if ( CloseHandle( hDevice ) ) 
                        {                        
                            AddMessage( _T("关闭设备句柄成功!\n" ));                 
                        }
                        else 
                        {                         
                            AddMessage( _T("关闭设备句柄失败!\n" ));                
                        }         
                    } 
        }
    }
    
}
void AddMessage(CString str)
{
    CString temp;
    m_Message.GetWindowText(temp);
    temp.Format(_T("%s\r\n%s"),temp,str);
    m_Message.SetWindowText(temp);
}

load的代码包含了驱动加载 CreateFile ReadFile WriteFile GetFileSize DeviceControl CloseFile,都会发送相应的IRP

驱动的代码

//入口函数 只指定了 Read Wirte Close Create query,其他的派遣函数系统默认
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
{

#if DBG
    _asm int 3
#endif
        CreateComs(DriverObject);

    DriverObject->MajorFunction[IRP_MJ_READ]   = ReadDispatch;         
    DriverObject->MajorFunction[IRP_MJ_CLOSE]  = GenerDispatch;         
    DriverObject->MajorFunction[IRP_MJ_WRITE]  = WriteDispatch;        
    DriverObject->MajorFunction[IRP_MJ_CREATE] = GenerDispatch;        
    DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = QueFileDispatch;

        DriverObject->DriverUnload=UnLoad;
    return 1;
}

//一般的派遣函数 基本不干事的
NTSTATUS GenerDispatch(PDEVICE_OBJECT pDevice, PIRP irp)
{
    /*IoSkipCurrentIrpStackLocation(irp);
    //return IoCallDriver(((PC2P_DEV_EXT)pDevice->DeviceExtension)->LowerObject,irp);
    return IoCallDriver(pDevice,irp);*/
        
        UCHAR type;
        PIO_STACK_LOCATION pStack = NULL;           //建立一个字符串数组与IRP类型对应起来        
        

          static char* SzIrpName[] = 
          {                        
              "IRP_MJ_CREATE",                         
              "IRP_MJ_CREATE_NAMED_PIPE",                         
              "IRP_MJ_CLOSE",                         
              "IRP_MJ_READ",                         
              "IRP_MJ_WRITE",                         
              "IRP_MJ_QUERY_INFORMATION",                         
              "IRP_MJ_SET_INFORMATION",                        
              "IRP_MJ_QUERY_EA",                        
              "IRP_MJ_SET_EA",                         
              "IRP_MJ_FLUSH_BUFFERS",                         
              "IRP_MJ_QUERY_VOLUME_INFORMATION",                         
              "IRP_MJ_SET_VOLUME_INFORMATION",                        
              "IRP_MJ_DIRECTORY_CONTROL",                         
              "IRP_MJ_FILE_SYSTEM_CONTROL",                         
              "IRP_MJ_DEVICE_CONTROL",                         
              "IRP_MJ_INTERNAL_DEVICE_CONTROL",                         
              "IRP_MJ_SHUTDOWN",                         
              "IRP_MJ_LOCK_CONTROL",                         
              "IRP_MJ_CLEANUP",                         
              "IRP_MJ_CREATE_MAILSLOT",                        
              "IRP_MJ_QUERY_SECURITY",                        
              "IRP_MJ_SET_SECURITY",                        
              "IRP_MJ_POWER",                        
              "IRP_MJ_SYSTEM_CONTROL",                         
              "IRP_MJ_DEVICE_CHANGE",                         
              "IRP_MJ_QUERY_QUOTA",                         
              "IRP_MJ_SET_QUOTA",                         
              "IRP_MJ_PNP", 
          };           
          pStack = IoGetCurrentIrpStackLocation( irp );        
          type =  pStack->MajorFunction;          
          if ( type >= 28) 
          {                
              KdPrint(( "未知的功能号 %d\n", type ));       
          }
          else 
          {                
              KdPrint(( "功能号为 %s\n", SzIrpName[type] ));
          }
          //一般分发函数的处理套路就是这样       
          irp->IoStatus.Information = 0;        
          irp->IoStatus.Status = STATUS_SUCCESS;         
          IoCompleteRequest( irp, IO_NO_INCREMENT );         
          KdPrint(( "Irp_DispatchRoutine 执行完毕" ));         
          return STATUS_SUCCESS; 
}

//wirte 派遣函数
#pragma  code_seg( "PAGE" )
NTSTATUS WriteDispatch(PDEVICE_OBJECT pDevice, PIRP irp)
{
    PCHAR buffer=NULL;
    ULONG BufferLenth=0;
    ULONG WriteOffset=0;
    PDEVICE_EXT pDExt;
    PIO_STACK_LOCATION pStack = NULL;  

    pDExt=(PDEVICE_EXT)pDevice->DeviceExtension;
    pStack = IoGetCurrentIrpStackLocation( irp );        
    BufferLenth=pStack->Parameters.Write.Length;//希望写得长度
    WriteOffset=pStack->Parameters.Write.ByteOffset.QuadPart;
    if(irp->MdlAddress!=NULL)
    {
        buffer=(PCHAR)MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority);
    }
    else
    {
        buffer=(PCHAR)irp->UserBuffer;
        if(buffer==NULL)
            buffer=(PCHAR)irp->AssociatedIrp.SystemBuffer;
    }
    if(buffer!=NULL)
    {
        KdPrint(("buffer form ring3 :%s\r\n",buffer));
        if(WriteOffset+BufferLenth>MAXFILE)
        {
            KdPrint(("Size > Max\r\n"));
        }
        else
        {
            KdPrint(("buffer offset :%d\r\n",WriteOffset));
            RtlCopyMemory(pDExt->buffer+WriteOffset,buffer,BufferLenth);
            pDExt->file_lenth=WriteOffset+BufferLenth;
            irp->IoStatus.Information = BufferLenth;     //实际写得长度 返回给WriteFile 中的第4个参数值
            irp->IoStatus.Status = STATUS_SUCCESS;         
            IoCompleteRequest( irp, IO_NO_INCREMENT );         
            KdPrint(( "Irp_DispatchRoutine 执行完毕 wirte lenth %d",BufferLenth ));         
            return STATUS_SUCCESS;
        }
    }
}

//query 派遣函数
#pragma  code_seg( "PAGE" )
NTSTATUS QueFileDispatch(PDEVICE_OBJECT pDevice, PIRP irp)
{

    ULONG BufferLenth=0;
    PDEVICE_EXT pDExt;
    FILE_INFORMATION_CLASS info;
    PFILE_STANDARD_INFORMATION pinfo;
    PIO_STACK_LOCATION pStack = NULL;  
    pDExt=(PDEVICE_EXT)pDevice->DeviceExtension;
    pStack = IoGetCurrentIrpStackLocation( irp );    

    info=pStack->Parameters.QueryFile.FileInformationClass;
    if(info==FileStandardInformation)
    {
        KdPrint(("FileStandardInformation\r\n"));
        pinfo=(PFILE_STANDARD_INFORMATION)irp->AssociatedIrp.SystemBuffer;
        pinfo->EndOfFile=RtlConvertLongToLargeInteger(pDExt->file_lenth);
    }
    BufferLenth=pStack->Parameters.QueryFile.Length;
    irp->IoStatus.Information = BufferLenth;        
    irp->IoStatus.Status = STATUS_SUCCESS; 
    KdPrint(( "IRP_MJ_QUERY_INFORMATION 执行完毕 %d" ,pStack->Parameters.QueryFile.Length));  
    IoCompleteRequest( irp, IO_NO_INCREMENT );         

    return STATUS_SUCCESS; 
}

//Read派遣函数
#pragma  code_seg( "PAGE" )
NTSTATUS ReadDispatch(PDEVICE_OBJECT pDevice, PIRP irp)
{        
        PCHAR buffer=NULL;
        ULONG BufferLenth=0;
        ULONG ReadOffset=0;
        PDEVICE_EXT pDExt;
        PIO_STACK_LOCATION pStack = NULL;  

        pDExt=(PDEVICE_EXT)pDevice->DeviceExtension;
        pStack = IoGetCurrentIrpStackLocation( irp );        
        BufferLenth=pStack->Parameters.Read.Length;
        ReadOffset=pStack->Parameters.Read.ByteOffset.QuadPart;

        if (ReadOffset+BufferLenth>MAXFILE)
        {
            KdPrint(("Read Size > Max\r\n"));
             BufferLenth=0;
        }
        else
        {
            RtlCopyMemory(irp->AssociatedIrp.SystemBuffer,pDExt->buffer+ReadOffset,BufferLenth);
            
        }
        irp->IoStatus.Information = BufferLenth;        
        irp->IoStatus.Status = STATUS_SUCCESS;         
        IoCompleteRequest( irp, IO_NO_INCREMENT );         
        KdPrint(( "Irp_DispatchRoutine 执行完毕" ));         
        return STATUS_SUCCESS; 

}

程序流程是这样的,加载驱动创建一个设备,向该设备写入64个字节(’S’),从该设备读取1024个自己,获取设备大小

IRP

转载于:https://www.cnblogs.com/xmcc/archive/2012/04/09/2439639.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/110436.html原文链接:https://javaforall.net

(0)
上一篇 2021年8月17日 下午8:00
下一篇 2021年8月17日 下午9:00


相关推荐

  • 硬件知识–LM393的应用总结「建议收藏」

    硬件知识–LM393的应用总结「建议收藏」总结:正向输入的电压高于负向输入电压,比较器将输出高电平;反之则低。 最近要做一个光电传感器模块,去年的电赛上因为光电传感器的失败,心里总是有些不甘心。要做光电传感器模块首先,就参考某宝上的模块的设计。在那些成品模块上,用到了LM393;并且LM393是常用的比较器的芯片,所以有必要仔细研究一下它的电路应用,为以后参考。 某宝上有大量的这样的成品模块。一般是用于光电传感器,主要的芯片就是

    2022年7月22日
    12
  • abstract修改方法

    abstract修改方法

    2021年12月31日
    60
  • jQuery Validate插入 reomte使用详细的说明

    jQuery Validate插入 reomte使用详细的说明

    2022年1月13日
    68
  • Android 蓝牙Hid开发

    Android 蓝牙Hid开发Demo 下载 http www demodashi com demo 13891 html 最近客户需求 android 系统的一个设备 想连接一个扫描枪 类似蓝牙键盘 只支持 hid 协议 并且可以收到其数据 填写到输入框中 我这里借了一个蓝牙鼠标 用来与 android 设备连接 1Hid 简介 HID 设备 HunmanInterf 即人机交互设备 常见的有鼠标 键盘 游戏手柄 等等 一般有线方式都是通过 USB 连线连接到机器设备 作为用户输入设备 在蓝牙技术中 HI

    2026年3月18日
    2
  • 新突破!科大讯飞最新发布

    新突破!科大讯飞最新发布

    2026年3月14日
    3
  • voliate关键字的应用误区

    voliate关键字的应用误区写下这篇博客也是因为本人之前对voliate关键字理解不透彻,才有了应用误区,希望同样没有理解到位的朋友可以一起踩坑,也欢迎上帝视角明明白白的大佬指出本文的不当之处。先说一下自己之前对voliate的理解,voliate通过内存屏障可以禁止指令重排序和保证可见性,但是不能保证并发安全。禁止指令重排序就不说了,主要说一说如何保证可见性以及为什么不能保证并发安全。首先理解一下一个线程如何去修改…

    2022年5月20日
    57

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号