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)
blank

相关推荐

  • navicat 15 激活码_在线激活

    (navicat 15 激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.html…

  • fileinput基本使用[通俗易懂]

    fileinput基本使用[通俗易懂]新增$(“#attachmentsFile”).fileinput({theme:”fa”,showPreview:true,//是否显示预览hideThumbnailContent:true,//是否在缩略图中隐藏预览内容(图像,pdf内容,文本内容等)。showUpload:false,//隐藏上传按钮…

  • Windows Phone 8.1 新功能 – 应用栏控件

    Windows Phone 8.1 新功能 – 应用栏控件

  • 机器学习之数据预处理

    在sklearn之数据分析中总结了数据分析常用方法,接下来对数据预处理进行总结当我们拿到数据集后一般需要进行以下步骤:(1)明确有数据集有多少特征,哪些是连续的,哪些是类别的(2)检查有没有缺失

    2021年12月30日
  • 常用的数据链路层协议_数据链路层和网络层

    常用的数据链路层协议_数据链路层和网络层由于以太网中的所有的主机共享一个通信信道,因此在同一时刻只允许有一台主机发送数据,否则各个主机发送的数据就会相互干扰。站在系统的角度来看,这里各个主机所共享的通信信道就是一种临界资源,这个临界资源同一时刻只允许一台主机使用。……

    2022年10月22日
  • Django(70)接口版本控制

    Django(70)接口版本控制前言在RESTful规范中,有关版本的问题,用restful规范做开放接口的时候,用户请求API,系统返回数据。但是难免在系统发展的过程中,不可避免的需要添加新的资源,或者修改现有资源。因此,改动升

发表回复

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

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