挂起当前IRP

挂起当前IRP

如果需要将IRP异步完成, 一般不会在处理函数中调用IoCompleteRequest函数, 因为调用IoCompleteRequest函数就意味着,该IRP请求处理完成了, 事实上很多时候是需要多次处理, 或者有其他需求的, 这边先谈谈将当前IRP挂起.

挂起意味着,是异步操作, 那么需要等待以后某个时机再处理, 当然这个时机问题的话, 以后会了解到, 目前需要解决的是挂起当前IRP的方法.

下面这个驱动的功能就是这样, 将所有的IRP都挂起, 在最后Win32这边调用CloseHandle的时候再统一处理, 完成那些IRP请求. 一种异步完成IRP的例子. 除了挂起还要取消什么的. 下一篇说.

主要说说这一篇的挂起操作. 挂起其实也很简单, 就是不调用IoCompleteRequest, 改为调用IoMarkIrpPending. 当然这些IRP需要自己用某种手段存放起来, 不然的话回头取就不知道怎么取出来了, 这边用的是系统提供的双向链表了. 调用IoMarkIrpPending以后返回STASTUS_PENDING那么, Win32调用函数这边就会返回ERROR_IO_PENDING, 当然这样并不代表有错误的, 只是IRP还没有完成而已..

这几天兴致不是很高啊, 上代码吧. 这边是用户层的.

001/*
002    Windows内核下挂起当前IRP, 在IRP_MJ_CLEANUP中统一完成 3环代码
003    编译方法参见makefile. TAB = 8
004*/
005#include <stdio.h>
006#include <windows.h>
007 
008#pragma comment( linker, "/Entry:Jmain" )
009 
010#define SYS_LINK_NAME   "\\\\.\\SysLinkPendingIrp"
011//===========================================================================
012//线程等待函数
013//===========================================================================
014DWORD WINAPI ThreadProc( LPVOID lpParameter ) {
015    HANDLE hEvent;
016 
017    hEvent = *( HANDLE* )lpParameter;
018    printf( "线程开始进入等待状态!\n" );
019    WaitForSingleObject( hEvent, INFINITE );
020    ExitThread( 0 );
021}
022 
023//===========================================================================
024//用户层的启动函数
025//===========================================================================
026int __stdcall Jmain( int argc, char* argv[] ) {
027    HANDLE  hFile = 0;
028    BOOL    bRet;
029    DWORD   dwByteWrite;
030    HANDLE  hThread[2] = {0};
031    DWORD   dwThreadId[2];
032    BYTE    byBuf[10];
033    OVERLAPPED StOverLapped1 = {0};
034    OVERLAPPED StOverLapped2 = {0};
035 
036    __try {
037        //异步打开设备. 下面操作的函数都是异步的
038        hFile = CreateFile( SYS_LINK_NAME, GENERIC_READ | GENERIC_WRITE,
039                            0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0 );
040 
041        if ( hFile == INVALID_HANDLE_VALUE ) {
042            printf( "打开设备失败!\n" );
043            return -1;
044        }
045 
046        //创建两个事件用于异步读取文件
047        StOverLapped1.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
048        StOverLapped2.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
049 
050        //创建两个线程等待内核设置事件, 不然看不到效果
051        hThread[0] = CreateThread( NULL, 0, &ThreadProc, &StOverLapped1.hEvent, 0, &dwThreadId[0]  );
052 
053        if ( hThread[0] == NULL ) {
054            printf( "创建线程1失败!\n" );
055            return -1;
056        }
057 
058        hThread[1] = CreateThread( NULL, 0, &ThreadProc, &StOverLapped2.hEvent, 0, &dwThreadId[1]  );
059        if ( hThread[1] == NULL ) {
060            printf( "创建线程2失败!\n" );
061        }
062 
063        Sleep( 1000 );
064//---------------------------------------------------------------------------
065        //向设备发送了两次写入请求, 都会被挂起.
066//---------------------------------------------------------------------------
067        RtlFillMemory( byBuf, sizeof( byBuf ), 'a' );
068        bRet =  WriteFile( hFile, byBuf, sizeof( byBuf ), &dwByteWrite, &StOverLapped1 );
069 
070        if ( !bRet && GetLastError() != ERROR_IO_PENDING ) {
071            printf( "写入设备失败\n" );
072            return -1;
073        }
074 
075        RtlFillMemory( byBuf, sizeof( byBuf ), 'b' );
076        bRet =  WriteFile( hFile, byBuf, sizeof( byBuf ), &dwByteWrite, &StOverLapped2 );
077 
078        if ( !bRet && GetLastError() != ERROR_IO_PENDING ) {
079            printf( "写入设备失败\n" );
080            return -1;
081        }
082 
083        if ( hFile ) {
084            CloseHandle( hFile );
085        }
086 
087        //等待多个对象返回(必须同时返回)
088        WaitForMultipleObjects( 2, hThread, TRUE, INFINITE );
089        printf( "两个对象都已经返回!\n" );
090//---------------------------------------------------------------------------
091    } __finally {
092        if ( hThread[0] ) {
093            CloseHandle( hThread[0] );
094        }
095 
096        if ( hThread[1] ) {
097            CloseHandle( hThread[1] );
098        }
099 
100        if ( StOverLapped1.hEvent ) {
101            CloseHandle( StOverLapped1.hEvent );
102        }
103 
104        if ( StOverLapped2.hEvent ) {
105            CloseHandle( StOverLapped2.hEvent );
106        }
107 
108        if ( hFile ) {
109            CloseHandle( hFile );
110        }
111        system( "pause" );
112    }
113 
114    return 0;
115}

这边是内核态的代码:

001/*
002    Windows内核下挂起当前IRP, 在IRP_MJ_CLEANUP中统一完成 0环代码
003    编译方法参见makefile. TAB = 8
004*/
005#include <ntddk.h>
006 
007#define DEVICE_NAME L"\\Device\\DevPendingIrp"
008#define SYS_LINK_NAME   L"\\??\\SysLinkPendingIrp"
009 
010//---------------------------------------------------------------------------
011typedef struct tagDevice_Ext {
012    PDEVICE_OBJECT  pDeviceObj;
013    PLIST_ENTRY pIrpListHead;   //链表头结点, 用于存放IRP请求
014    UNICODE_STRING  USzDeviceName;
015    UNICODE_STRING  USzSysLinkName;
016} DEVICE_EXT, *PDEVICE_EXT;
017 
018typedef struct Irp_Entry {
019    PIRP pIRP;
020    LIST_ENTRY ListEntry;
021} IRP_ENTRY, *PIRP_ENTRY;
022//===========================================================================
023//驱动卸载例程
024//===========================================================================
025#pragma  code_seg( "PAGE" )
026VOID    DriverUnLoad( PDRIVER_OBJECT pDriverObj ) {
027    PDEVICE_EXT pDeviceExt = NULL;
028    PDEVICE_OBJECT pNextDevice = NULL;
029 
030    PAGED_CODE();
031    pNextDevice = pDriverObj->DeviceObject;
032 
033    while ( pNextDevice != NULL ) {
034        pDeviceExt = pNextDevice->DeviceExtension;
035 
036        IoDeleteDevice( pDeviceExt->pDeviceObj );
037        IoDeleteSymbolicLink( &pDeviceExt->USzSysLinkName );
038        KdPrint( ( "删除%wZ设备成功!\n", &pDeviceExt->USzDeviceName ) );
039 
040        pNextDevice = pNextDevice->NextDevice;
041    }
042}
043//===========================================================================
044//所有不关心的IRP处理例程
045//===========================================================================
046NTSTATUS DispatchRoutine( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
047 
048    PAGED_CODE();
049 
050    pIrp->IoStatus.Information = 0;
051    pIrp->IoStatus.Status = STATUS_SUCCESS;
052    IoCompleteRequest( pIrp, IO_NO_INCREMENT );
053    return STATUS_SUCCESS;
054}
055//===========================================================================
056//IRP_MJ_WRITE的处理, 将所有的IRP都返回为pending状态
057//===========================================================================
058NTSTATUS DispatchWrite( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
059    PDEVICE_EXT pDeviceExt = NULL;
060    PIRP_ENTRY pIrpEntry = NULL;
061 
062    PAGED_CODE();
063 
064    pDeviceExt = pDeviceObj->DeviceExtension;
065    ASSERT( pDeviceExt != NULL );
066 
067    pIrpEntry = ( PIRP_ENTRY )ExAllocatePool( PagedPool, sizeof( IRP_ENTRY ) );
068    ASSERT ( pIrpEntry != NULL );
069    pIrpEntry->pIRP = pIrp;
070 
071    //插入队列
072    InsertHeadList( pDeviceExt->pIrpListHead, &pIrpEntry->ListEntry );
073 
074    //将IRP设置为挂起
075    IoMarkIrpPending( pIrp );
076    KdPrint( ( "在IRP_MJ_WRITE请求中将IRP挂起!\n" ) );
077    //返回pending状态
078    return STATUS_PENDING;
079}
080//===========================================================================
081//将未决的写入请求完成
082//===========================================================================
083NTSTATUS Write_CompleteRequest( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
084    ULONG i;
085    ULONG ulWriteLength;
086    ULONG ulWriteOffset;
087    PIO_STACK_LOCATION WriteStack = NULL;
088 
089    PAGED_CODE();
090    WriteStack = IoGetCurrentIrpStackLocation( pIrp );
091 
092    //欲写入的长度, 偏移
093    ulWriteLength = WriteStack->Parameters.Write.Length;
094    ulWriteOffset = ( ULONG )WriteStack->Parameters.Write.ByteOffset.QuadPart;
095 
096    for( i = 0; i < ulWriteLength; i++ ) {
097        KdPrint( ( "%c\t", *( ( ( UCHAR* )pIrp->AssociatedIrp.SystemBuffer ) + i ) ) );
098    }
099 
100    KdPrint( ( "\n" ) );
101 
102    //简单的完成IRP请求
103    pIrp->IoStatus.Status = STATUS_SUCCESS;
104    pIrp->IoStatus.Information = ulWriteLength;
105    IoCompleteRequest( pIrp, IO_NO_INCREMENT );
106    KdPrint( ( "写入请求处理完毕!\n" ) );
107    return STATUS_SUCCESS;
108}
109//===========================================================================
110//IRP_MJ_CLEANUP IRP的处理, 将IRP_MJ_WRITE未决的IRP全部处理下
111//===========================================================================
112NTSTATUS DispatchCleanUp( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
113    NTSTATUS    Status;
114    PDEVICE_EXT pDeviceExt = NULL;
115    PIRP_ENTRY  pIrpEntry = NULL;
116    PLIST_ENTRY pListEntry = NULL;
117 
118    PAGED_CODE();
119    pDeviceExt = ( PDEVICE_EXT ) pDeviceObj->DeviceExtension;
120    Status = STATUS_UNSUCCESSFUL;
121 
122    for( ; !IsListEmpty( pDeviceExt->pIrpListHead ); pIrpEntry = NULL ) {
123 
124        pListEntry = RemoveTailList( pDeviceExt->pIrpListHead );
125 
126        //获取IRP的数据指针
127        pIrpEntry = CONTAINING_RECORD( pListEntry, IRP_ENTRY, ListEntry );
128 
129        if ( !pIrpEntry ) {
130            KdPrint( ( "获取结点数据失败!\n" ) );
131            Status = STATUS_UNSUCCESSFUL;
132        } else {
133            //完成写入请求
134            Status = Write_CompleteRequest( pDeviceObj, pIrpEntry->pIRP );
135 
136            if ( !NT_SUCCESS( Status ) ) {
137                KdPrint( ( "完成写入请求时失败!\n" ) );
138            }
139 
140            ExFreePool( pIrpEntry );
141 
142            KdPrint( ( "未决请求处理完成!\n" ) );
143        }
144    }
145 
146    //处理IRP_MJ_CLEANUP自身的IRP请求
147    pIrp->IoStatus.Status = Status;
148    pIrp->IoStatus.Information = 0;
149    IoCompleteRequest( pIrp, IO_NO_INCREMENT );
150    return Status;
151}
152//===========================================================================
153//驱动程序的入口函数
154//===========================================================================
155#pragma code_seg( "INIT" )
156NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pUSzRegPath ) {
157    ULONG i;
158    NTSTATUS Status;
159    PDEVICE_OBJECT pDevice = NULL;
160    PDEVICE_EXT pDeviceExt = NULL;
161    UNICODE_STRING USzDeviceName = RTL_CONSTANT_STRING( DEVICE_NAME );
162    UNICODE_STRING UszSysLink = RTL_CONSTANT_STRING( SYS_LINK_NAME );
163 
164    Status = IoCreateDevice( pDriverObj, sizeof( DEVICE_EXT ), &USzDeviceName,
165                             FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevice );
166 
167    if ( !NT_SUCCESS( Status ) ) {
168        KdPrint( ( "创建设备失败!\n" ) );
169        return Status;
170    }
171 
172    Status = IoCreateSymbolicLink( &UszSysLink, &USzDeviceName );
173 
174    if ( !NT_SUCCESS( Status ) ) {
175        IoDeleteDevice( pDevice );
176        KdPrint( ( "创建符号链接失败!\n" ) );
177        return Status;
178    }
179 
180    //带缓冲区的IO方式
181    pDevice->Flags |= DO_BUFFERED_IO;
182    pDeviceExt = pDevice->DeviceExtension;
183    pDeviceExt->pDeviceObj = pDevice;
184    pDeviceExt->USzDeviceName = USzDeviceName;
185    pDeviceExt->USzSysLinkName = UszSysLink;
186 
187    //初始化链表头结点
188    pDeviceExt->pIrpListHead = ( PLIST_ENTRY )ExAllocatePool( PagedPool, sizeof( LIST_ENTRY ) );
189    InitializeListHead( pDeviceExt->pIrpListHead );
190 
191    //设置分发函数, 驱动卸载函数
192    for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ ) {
193        pDriverObj->MajorFunction[i] = &DispatchRoutine;
194    }
195 
196    pDriverObj->DriverUnload = &DriverUnLoad;
197    pDriverObj->MajorFunction[IRP_MJ_WRITE] = &DispatchWrite;
198    pDriverObj->MajorFunction[IRP_MJ_CLEANUP] = &DispatchCleanUp;
199 
200    return Status;
201}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值