阅读:3317回复:21
求助:创建IRP时黑屏
我的驱动中要创建IRP_MJ_WRITE, IRP_MJ_READ,发往低层驱动。但在创建IRP时,系统就黑屏了。请大侠指点,原程序如下:
NTSTATUS WD_SendtoLower(IN PDEVICE_OBJECT DeviceObject, IN OUT BYTE *rwbuf, IN OUT PULONG len, IN BOOLEAN write) { NTSTATUS status; KEVENT kevent; PIRP pIrp; IO_STATUS_BLOCK IoStatus; PIO_STACK_LOCATION pIrpStack; PAGED_CODE(); ASSERT(DeviceObject != NULL); KeInitializeEvent(&kevent, SynchronizationEvent, false); if(write) { pIrp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, DeviceObject, rwbuf, *len, 0, &kevent, &IoStatus); if(pIrp == NULL) { KdPrint((\"\\t%sWD_CardComand : Can\'t build the Write Irp\\n\",HEAD)); return STATUS_INSUFFICIENT_RESOURCES; } pIrpStack = IoGetNextIrpStackLocation(pIrp); pIrpStack->MajorFunction = IRP_MJ_WRITE; pIrpStack->Parameters.Write.Length = *len; pIrpStack->Parameters.Write.ByteOffset.QuadPart = 0; } else { pIrp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, DeviceObject, rwbuf, *len, 0, &kevent, &IoStatus); if(pIrp == NULL) { KdPrint((\"\\t%sWD_CardComand : Can\'t build the Read Irp\\n\",HEAD)); return STATUS_INSUFFICIENT_RESOURCES; } pIrpStack = IoGetNextIrpStackLocation(pIrp); pIrpStack->MajorFunction = IRP_MJ_READ; pIrpStack->Parameters.Read.Length = *len; pIrpStack->Parameters.Read.ByteOffset.QuadPart = 0; } status = IoCallDriver(DeviceObject, pIrp); if (status == STATUS_PENDING) { KeWaitForSingleObject( &kevent, Executive, KernelMode, FALSE, NULL ); status = IoStatus.Status; } return status; } |
|
沙发#
发布于:2004-04-12 11:32
检查下你得到的pTargetDeviceObject是SCSI设备的DeviceObject吗?
|
|
板凳#
发布于:2004-04-09 15:06
以下为代码拷贝,我用IoGetDeviceObjectPointer得到了一个scsi设备,此时想通过该设备句柄向scsi设备发送irp,但在IoCallDriver时老出错:
NTSTATUS status = 0; UNICODE_STRING uniNtNameString; PDEVICE_OBJECT pTargetDeviceObject = NULL; PFILE_OBJECT pTargetFileObject = NULL; RtlInitUnicodeString( &uniNtNameString, DeviceName);//SCSI_DEVICE_NAME ); status = IoGetDeviceObjectPointer( IN &uniNtNameString, IN FILE_ALL_ACCESS, OUT &pTargetFileObject, OUT &pTargetDeviceObject ); if( !NT_SUCCESS(status) ) { pTargetFileObject = NULL; pTargetDeviceObject = NULL; return( status ); } DbgPrint("Scsi设备句柄:%x,文件句柄:%xn",pTargetDeviceObject,pTargetFileObject); if(!pTargetDeviceObject) return status ; PIRP pIrp=NULL; KEVENT keIoctlComplete; IO_STATUS_BLOCK ioSb; SRB_SET_DEVOBJ iobuf; UINT ubuffer; PIO_STACK_LOCATION pIrpStack; KeInitializeEvent(&keIoctlComplete,NotificationEvent,FALSE); iobuf.SrbCtrl.HeaderLength = sizeof(SRB_IO_CONTROL); FILLSIGNATURE(iobuf.SrbCtrl.Signature); iobuf.SrbCtrl.Timeout = DEFAULT_TIMEOUT; iobuf.SrbCtrl.ControlCode = 1; iobuf.SrbCtrl.ReturnCode = 0xFFFFFFFF; iobuf.SrbCtrl.Length = sizeof(gDeviceObject); iobuf.pDeviceObj=gDeviceObject; pIrp=IoBuildDeviceIoControlRequest( IOCTL_SCSI_MINIPORT, pTargetDevObj, &iobuf, sizeof(iobuf), &ubuffer, sizeof(ubuffer), FALSE, &keIoctlComplete, &ioSb); IoCallDriver(pTargetDevObj,pIrp); (出错处,缺页错误) KeWaitForSingleObject(&keIoctlComplete,Executive,KernelMode,FALSE,NULL); DbgPrint("Send Successn"); 在scsi设备端,我使用了如下处理代码 DbgPrint("Get IoCtl_test eventn"); PIRP Pirp=(PIRP)Srb->OriginalRequest; Pirp->IoStatus.Status=STATUS_SUCCESS; Pirp->IoStatus.Information=0; 请大虾救命阿,搞了好久了 |
|
地板#
发布于:2004-03-20 20:36
pIrpStack->FileObject=fo;
fo是用户模式应用程序传给你的fileobject, 好像必须设置该域 |
|
地下室#
发布于:2004-03-18 18:51
read 和 write 时要填 StartingOffset 参数,而且它是个指针,不能填 0。
|
|
5楼#
发布于:2004-02-09 08:50
我找到了底层驱动的源代码,发现在创建IRP_MJ_READ/IRP_MJ_WRITE以前,底层驱动已经收到了系统发出的MN_START_DEVICE这个IRP, 但是我创建IRP_MJ_READ/IRP_MJ_WRITE,仍然黑屏,555。。。
|
|
6楼#
发布于:2004-02-04 09:03
在IoRegisterPlugPlayNotification()的回调函数中,我用IoGetDeviceObjectPointer()得到DeviceObject的。
|
|
7楼#
发布于:2004-02-03 21:23
IRP_MN_START_DEVICE应该由PnP Manager发出,你最好不要自己做。
还有一个问题,我一直没问你那个DeviceObject是怎么得到的?PnP Notification应该不会给你这个对象吧? |
|
|
8楼#
发布于:2004-02-02 15:37
我现在在我的驱动中自己创建了一个同步的IRP_MN_START_DEVICE,发给下层驱动,其也返回成功了。是否证明该DeviceObject已经启动了呢?但是我创建IRP_READ, IRP_WRITE还是黑屏。郁闷。。。 :(
|
|
9楼#
发布于:2004-01-18 14:28
OK,就先别想这些问题了,过个好年先. :):):)
|
|
|
10楼#
发布于:2004-01-18 10:43
呵呵,我已经把IoGetNextIrpStackLocation()那部分去掉了。明天回家过年了,春节过了再来整。春节快乐!
|
|
11楼#
发布于:2004-01-17 15:37
是有点奇怪... ...
一般情况下,只有PNP之类的IRP才需要IoGetNextIrpStackLocation(因为需要自己填写MinorFunction),如果你是MJ_READ或MJ_WRITE的话,只要在IoBuildSynchronousFsdRequest给出正确的参数(i.e. Buffer, Length, StartOffset), 然后就可以直接IoCallDriver了,用不着再去IoGetNextIrpStackLocation,因为Stack Location已经由系统帮你设置好了. |
|
|
12楼#
发布于:2004-01-17 14:41
不要这样撒,你已经帮了我很大的忙了,有些东东记不清了也很正常三。不要这么客气嘛。
我按照你说的做了,果然他好像没有处理IRP_MN_QUERY_PNP_DEVICE_STATE,看来我只有等写那个驱动的哥们过完年回来再说了。BTW,一个很奇怪的现象,我发了这个IRP给下层后,在发IRP_MJ_WRITE就不会黑屏了,但是建IRP_MJ_READ还是黑屏,真是奇怪了啊 :o :o :o |
|
13楼#
发布于:2004-01-17 14:05
Oops!!!
你是对的,我给搞错乐,对不起. :( 是用IoBuildSynchronousFsdRequest,完乐用IoGetNextIrpStackLocation. 对不起. :(:(:( [编辑 - 1/17/04 by cool-net] |
|
|
14楼#
发布于:2004-01-17 13:53
DDK的文档不是说IRP_MJ_PNP用IoBuildSynchronousFsdRequest()建吗?为什么要用IoBuildDeviceIoControlRequest()去建啊,他不是用来建IRP_MJ_DEVICE_CONTROL的IRP的么?不明白的说,迷茫
PIRP IoBuildSynchronousFsdRequest( IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN OUT PVOID Buffer OPTIONAL, IN ULONG Length OPTIONAL, IN PLARGE_INTEGER StartingOffset OPTIONAL, IN PKEVENT Event, OUT PIO_STATUS_BLOCK IoStatusBlock ); IoBuildSynchronousFsdRequest allocates and builds an IRP to be sent synchronously to lower driver(s). Parameters MajorFunction Specifies the major function code, one of IRP_MJ_PNP, IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS, or IRP_MJ_SHUTDOWN. |
|
15楼#
发布于:2004-01-17 12:48
对于PNP,你要用IoBuildDeviceIoControlRequest而不是IoBuildXXXXXXFsdRequest,用IoBuildDeviceIoControlRequest完了直接IoCallDriver就行了,不用理会Stack location.
对于IRP_MN_QUERY_PNP_DEVICE_STATE,inputBuffer和outputBuffer都为NULL,返回后检查你给的那个IoStatusBlock里的内容,Status为STATUS_SUCCESS时,Information里是一个PNP_DEVICE_STATE bitmask. 重申一下,驱动对IRP_MN_QUERY_PNP_DEVICE_STATE是Optional的,所以这种方式未必可用. |
|
|
16楼#
发布于:2004-01-17 09:58
谢谢你的指教。但是我还是有些不太明白,如果我不把我驱动的DeviceObject用IoAttachDeviceToDeviceStack()加入底层设备的IRP栈的话,那么我创建IRP_MN_QUERY_PNP_DEVICE_STATE这个IRP后,像要设置那个PIO_STACK_LOCATION的话,应该用IoGetNextIrpStackLocation()还是IoGetCurrentIrpStackLocation()。创建后,用IoCallDriver()发给底层设备,是根据返回的NTSTATUS来判断设备的状态吗?我发下去IRP还可以被我的驱动检查吗?
|
|
17楼#
发布于:2004-01-16 18:44
这个... ...Kernel Mode的PnPNotification我还真没用过,不过我想你是不是可以先Build一个MJ_PNP->IRP_MN_QUERY_PNP_DEVICE_STATE下去看看设备状态(但是,不幸的是驱动对这个Minor Code的支持是Optional的),也许还有别的什么方法(比如你可以Attach到那个DeviceObject上去,这样你可以收到它的MN_START_DEVICE),你可以试试先。
|
|
|
18楼#
发布于:2004-01-16 16:38
太感谢你了,果然是问题所在。那我怎么确定底层设备启动了没有呢,它的驱动我没有源码,只有Read和Write的接口。我是否是应该在监测到插入后做一个等待呢,还是如何?
|
|
19楼#
发布于:2004-01-16 16:18
这样啊,呵呵.:):):)
在调用IoBuildSynchronousFsdRequest之前你可能得先确定那个DeviceObject已经被启动了(就是已经收到MN_START_DEVICE了),否则你Build MJ_READ或WRITE恐怕不行吧? 你可以试试Build一个MJ_PNP给它,如果一样黑,那说明是别的问题,如果成功,十有八九是因为那个DeviceObject没启动. |
|
|
上一页
下一页