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


相关推荐

  • 实现迪杰斯特拉算法求某个源点到其余个点_迪杰斯特拉算法应用举例

    实现迪杰斯特拉算法求某个源点到其余个点_迪杰斯特拉算法应用举例如下图,使用迪杰斯特拉算法求下图的最短路径跌代过程:1)初始时从1开始寻找各节点到该节点的距离,路不通设置为maxint,此时把1归为s里面2)从1)得到距离1最短的路径对应的结点如上图为2,

    2022年8月1日
    10
  • java写一个冒泡排序_冒泡排序 一个java例程

    java写一个冒泡排序_冒泡排序 一个java例程冒泡排序的算法的思想其实很简单就是逐个比较交换位次从而实现一个完整的排序,下面直接看代码吧。packagealgorithm;importjava.text.SimpleDateFormat;importjava.util.Date;/**时间:2019822*作者:latefly*功能:一个冒泡排序的展示,包含一个原始的方法以及一个优化以后的方法****/publicclass…

    2022年7月7日
    25
  • java中page的对象,page对象[通俗易懂]

    java中page的对象,page对象[通俗易懂]page对象是JSP九大内置对象之一。JSP全称JavaServerPage,是一种动态网页技术标准,以Java语言作为脚本语言。在JSP中预先定义了九个内置对象,这个九个内置对象不需要声明就可以在脚本代码和表达式中任意使用,九个内置对象分别是:request、response、session、application、out、pageContext、config、page、exception。pa…

    2022年7月27日
    14
  • monty python喜剧-看美剧学托福:最受美国人喜欢的100部美剧「建议收藏」

    monty python喜剧-看美剧学托福:最受美国人喜欢的100部美剧「建议收藏」在之前做了一个百大电影的清单之后,好莱坞知名媒体THR再次发布年度重量级策划,他们邀请了2800多名好莱坞影视从业人员,包括779名演员,365名制片人,268名导演等等,由他们选出自己最爱的剧集(主要是美剧,也有一些其他的秀),最终汇总成为这个百大剧集清单,你放心,这里面,一定有你超爱的。以及,第一,果然是那部,当之无愧的热门剧。100、绝望主妇DesperateHousewives(200…

    2022年9月30日
    7
  • 豆包大模型上车赛力斯自有品牌|36氪独家

    豆包大模型上车赛力斯自有品牌|36氪独家

    2026年3月12日
    2
  • Ubuntu PyCharm安装与卸载

    Ubuntu PyCharm安装与卸载1 安装包下载下载地址 https www jetbrains com pycharm download section linux 社区版是免费的 不需要支付额外的费用 但是功能略微筛选 适合于学生群体 而专业版需要支付一定的费用 功能比较多 适用于企业 但整体的安装过程相同 2 安装在安装包过程启动终端命令 解压缩下载后的安装包修改自己的安装包版本号即可 tar zxvfpycharm professional 2021 3 1 tar gz 将解压缩后的目录移动到

    2026年3月18日
    2

发表回复

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

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