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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 基于人脸识别的考勤系统:Python3 + Qt5 + OpenCV3 + FaceNet + MySQL

    基于人脸识别的考勤系统:Python3 + Qt5 + OpenCV3 + FaceNet + MySQL本项目使用Python3.8编写,QtDesigner(QT5)设计主界面,PyQt5库编写控件的功能,使用开源FaceNet人脸识别算法进行人脸识别,使用眨眼检测来实现活体识别,使用OpenCV3实现实时人脸识别。同时,将班级学生信息,各班级学生人数、考勤信息录入到MySQL数据库中,方便集中统一化管理。因为本项目仅由我一个人开发,能力精力有限,实现了预期的绝大多数功能,但是活体检测功能还存在bug,如果小伙伴对本项目中有不懂的地方或者发现问题,欢迎提出。

  • Observability:运用 Fleet 来轻松地导入 Nginx 日志及指标

    Observability:运用 Fleet 来轻松地导入 Nginx 日志及指标在我之前的文章: Observability:使用ElasticAgent和IngestManager简化数据导入(一) Observability:使用ElasticAgent和IngestManager简化数据导入(二) 我有讲到如何使用IngestManager简化数据输入。今天我重新看了一下界面确实变了很多,这就是为什么实验版本的功能一直在演化中。在今天的文章中,我将基于7.13的版本如何使用Fleet导入Nginx日志。..

  • 阶乘相加

    阶乘相加阶乘相加

  • mac dg破解激活码-激活码分享2022.02.22

    (mac dg破解激活码)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.htmlHCIQ56F36O-eyJsaWNlbnNlSW…

  • 解决Unable to connect to Redis server: 192.168.110.1/192.168.110.1:6379[通俗易懂]

    解决Unable to connect to Redis server: 192.168.110.1/192.168.110.1:6379[通俗易懂]出现场景:springboot整合redis,启动项目时出现原因:redis的一系列配置不正确解决方案:首先在window安装redis,找到安装目录下的redis.windows.confredis.windows-service.conf1)修改protected-modeyes改为:protected-modeno2)注释掉#bin127.0.0.13…

  • mac全选文字的快捷键_Mac文本的快捷键 你晓得否?

    mac全选文字的快捷键_Mac文本的快捷键 你晓得否?我们在MAC电脑上码字的时候,经常会遇到需要对某段文字进行修改或者操作的情况,相信很多人的做法是用鼠标去移动光标快速定位,如果字数篇幅比较小也是可以的,但是如果遇到大篇幅的文章,一点点的用鼠标去找会非常麻烦,今天我就教大家几个MAC文本快捷键,让你在最短的时间内把光标移动到你想要的位置,提高在电脑上码字的效率。1、全文&段落定位目标位置比较远的时候,需要对光标远程定位,下面的组合键可以帮到…

发表回复

您的电子邮箱地址不会被公开。

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