7677|13

3

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

为什么这样调用IoCallDriver分发自己创建的IRP会引起蓝屏? [复制链接]

NTSTATUS
MixPortDriverWriteDispatch(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP pIrp
    )

{

    NTSTATUS ntStatus = STATUS_SUCCESS;// Assume success

        PSERIAL_DEVICE_EXTENSION pExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( pIrp );

        //获取用户写数据的字节数目
        ULONG DataLen = irpSp->Parameters.Write.Length;

        //获取用户数据的首地址
        PCHAR pData = pIrp->AssociatedIrp.SystemBuffer;

        ULONG i;
    KIRQL OldIrql;

    PIRP            pOldReadIrp = NULL;
    PDRIVER_CANCEL  pOldCancelRoutine;
        PCHAR outBuf, inBuf;
        KdPrint(("%u MixPortDriverWriteDispatch", DeviceObject));
KdPrint(("%u irpSp->Parameters.Write.Length=%d\n", DeviceObject, irpSp->Parameters.Write.Length));
//#if DBG
//                _asm int 3;
//#endif

        pIrp->IoStatus.Information = 0;
        ntStatus = STATUS_SUCCESS;

        //没有数据要写,或者已经写完毕
        if (DataLen == 0)
    {
                ntStatus = STATUS_SUCCESS;
    }
        else//还有数据待写
        {
                //获得写操作自旋锁
                KeAcquireSpinLock(&pExtension->WriteSpinLock, &OldIrql);
KdPrint(("%u KeAcquireSpinLock(&pExtension->WriteSpinLock,DeviceObject,&OldIrql)"));
                //将用户数据复制到缓冲区,可能存在的问题,数据覆盖?
//                for (i=0; i //                {
//KdPrint(("%u pData[%d]=%c\n",DeviceObject,i, pData ));
//                        pExtension->Buffer[pExtension->BufHead] = pData;
//                        pExtension->BufHead++;
//KdPrint(("%u head=%d\n",DeviceObject,pExtension->BufHead));
//                        pExtension->BufHead %= COMBUFLEN;
//                }


                //管道另一端正等待读数据
                if (pExtension->pReadIrp != NULL) // drop it out
                {

                        pOldReadIrp = pExtension->pReadIrp;

                        //删除管道另一头的等待读取数据的请求
                        pOldCancelRoutine = IoSetCancelRoutine(pOldReadIrp, NULL);

                        // wurde Cancel-Routine schon aufgerufen?
                        //取消例行已经叫什么名字?
                        if (pOldCancelRoutine != NULL)
                        {
                                // Nein, also Request beenden
                                //没有,所以退出申请
                                //设置管道另一端读请求的处理结果,实际上不让读了
                                pOldReadIrp->IoStatus.Information = 0;
                                pOldReadIrp->IoStatus.Status = STATUS_SUCCESS;

                                //清除管道另一端的读请求
                                pExtension->pReadIrp      = NULL;
                        }
                        else
                        {
                                // Ja, Cancel-Routine wird Request beenden 对比某处? 是的,取消例程将退出请求
                                pOldReadIrp = NULL;
                        }

                }
                KdPrint(("%u IoGetDeviceObjectPointer symbolicName=%ws !\n",DeviceObject, pExtension->getDeviceContext->symbolicName.Buffer));       
                KdPrint(("%u IoGetDeviceObjectPointer accessMask=%u !\n",DeviceObject, pExtension->getDeviceContext->accessMask));       

                if (pExtension->getDeviceContext->device == NULL)
                {
                ntStatus = IoGetDeviceObjectPointer(&pExtension->getDeviceContext->symbolicName,
                        pExtension->getDeviceContext->accessMask,
                        &pExtension->getDeviceContext->file,
                        &pExtension->getDeviceContext->device);
                }
                if (!NT_SUCCESS(ntStatus))
                {
                        KdPrint(("%u IoGetDeviceObjectPointer failed ! status=%l\n",DeviceObject, ntStatus));       
                }

                //have digits to translate.
                if (0 != DataLen)
                {
                                KdPrint(("%u 0 != DataLen\n",DeviceObject));       
                        inBuf = ExAllocatePool(NonPagedPool, DataLen);
                        outBuf = ExAllocatePool(NonPagedPool, DataLen*2);
                        if (NULL == inBuf || outBuf == NULL)
                        {
                                KdPrint(("%u STATUS_INSUFFICIENT_RESOURCES\n",DeviceObject));       
                                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
                        }
                        else
                        {
                                strncpy(inBuf, pData, DataLen);//copy datas to build the irp instead of send to extension buffer
                                KdPrint(("%u pExtension->getDeviceContext->device=%u\n",DeviceObject, pExtension->getDeviceContext->device));       
                                ntStatus = MakeSynchronousIoctl(pExtension->getDeviceContext->device,
                                                                        IOCTL_SERIAL_TRANSLATE,
                                                                        inBuf,
                                                                        DataLen,
                                                                        outBuf,
                                                                        DataLen*2);
                                KdPrint(("%u MakeSynchronousIoctl\n",DeviceObject));       
                                if (NT_SUCCESS(ntStatus))
                                {
                                        KdPrint(("%u NT_SUCCESS(ntStatus)\n",DeviceObject));       
                                        for (i = 0; i                                         {
                                                pExtension->Buffer[pExtension->BufHead++] = outBuf;
                                        }
                                        KdPrint(("%u Datalen=%u\n",DeviceObject, i));       
                                }
                        }       

                        if (inBuf != NULL)
                        {
                                KdPrint(("%u inBuf != NULL\n",DeviceObject));       
                                ExFreePool(inBuf);
                                inBuf = NULL;
                        }
                        if (outBuf != NULL)
                        {
                                KdPrint(("%u outBuf != NULL\n",DeviceObject));       
                                ExFreePool(outBuf);
                                outBuf = NULL;
                        }

                }
                //检查管道另一端的事件状态
                DriverCheckEvent(pExtension, SERIAL_EV_RXCHAR | SERIAL_EV_RX80FULL);

                //检查管道本端事件状态
                DriverCheckEvent(pExtension, SERIAL_EV_TXEMPTY);

                //释放写操作自旋锁
        KeReleaseSpinLock(&pExtension->WriteSpinLock, OldIrql);
               

            if (pOldReadIrp != NULL)
                    IoCompleteRequest(pOldReadIrp, IO_NO_INCREMENT);
        }

        //给用户返回写操作的执行情况
    pIrp->IoStatus.Status = ntStatus;
    pIrp->IoStatus.Information = DataLen;
    IoCompleteRequest( pIrp, IO_NO_INCREMENT );

    return ntStatus;
}


NTSTATUS
MakeSynchronousIoctl(
      IN PDEVICE_OBJECT TopOfDeivceStack,
      IN ULONG IoctlControlCode,
      PVOID InputBuffer,
      ULONG InputBufferLength,
      PVOID OutputBuffer,
      ULONG OutputBufferLength)
{
KEVENT event;
PIRP irp;
IO_STATUS_BLOCK ioStatus;
NTSTATUS status;

//创建设备控制IRP给其它驱动
//初始化同步事件
KeInitializeEvent(&event,NotificationEvent,FALSE);
//用IoBuildDeviceIoControlRequest创建IRP
irp = IoBuildDeviceIoControlRequest(IoctlControlCode,
                                  TopOfDeivceStack,
          InputBuffer,
          InputBufferLength,
          OutputBuffer,
          OutputBufferLength,
          FALSE,
          &event,
          &ioStatus);
//判断IRP是否为零

        KdPrint((" devicepointer=%u\n",  TopOfDeivceStack));
        KdPrint((" InputBuffer=%s\n",  InputBuffer));
        KdPrint((" InputBufferLength=%u\n",  InputBufferLength));
        KdPrint((" OutputBuffer=%s\n",  OutputBuffer));
        KdPrint((" OutputBufferLength=%u\n",  OutputBufferLength));
if (NULL == irp)
{
                 KdPrint((" (NULL == irp)\n" ));
                return STATUS_INSUFFICIENT_RESOURCES;
}
//调用底层驱动程序  就是这一行会引起蓝屏
status = IoCallDriver(TopOfDeivceStack,irp);
if (status == STATUS_PENDING)
{
         KdPrint((" status == STATUS_PENDING\n" ));
        status = KeWaitForSingleObject(&event,
                              Executive,
            KernelMode,
            FALSE,
            NULL);
  status = ioStatus.Status;
}

IoCompleteRequest(irp, IO_NO_INCREMENT);
KdPrint(("status=%x \n",  ioStatus.Status ));
return  status;
}

我写了两个虚拟串口的驱动程序A和B,其中B有一个控制码IOCTL_SERIAL_TRANSLATE能将阿拉伯数字装换为中文数字,我现在是在A的writeFile响应例程里面自己通过IoBuildDeviceIoControlRequest创建了IRP,然后获得设备B的指针,通过IoCallDriver来调用IOCTL_SERIAL_TRANSLATE实现转换,B的该控制码是没有问题的,用MFC对该控制码进行过测试,能正确转换且没有异常,但是我在A里面调用IoCallDriver的时候就会蓝屏,不知道是什么原因?各位前辈指点一下。谢谢!

最新回复

感谢再次提醒,不好意思,刚才没有试,我只是打印了Event的地址看了,现在将event放到Device_extension里面了,蓝屏停止了,问题就在这里,高手就是高手,很早就判断出可能出现问题的地方了。 赞扬您这种诲新人不倦的精神!  详情 回复 发表于 2010-5-12 15:19
点赞 关注

回复
举报

5

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
没遇到过,

MARK,
 
 

回复

22

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
不清楚为什么会在IoCallDriver(TopOfDeivceStack,irp);异常了,估计是TopOfDeivceStack有问题,如果这里没问题,我觉得应该在IoCompleteRequest(irp, IO_NO_INCREMENT)这里异常,IoCallDriver传递irp后,这个irp就失效了!该在回调里处理吧!
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

4
 
路过  关注   
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

5
 
两个独立的驱动之间这样IoCallDriver()好像不被允许吧?

WDK里面有介绍两个驱动之间的一些通讯方式,我不记得有LZ说的这种。我记得有一种方法是B驱动得注册一个Interface,A驱动Query该Interface,通过该Interface的handle可以进行通讯。具体的操作方式得LZ自己多看看文档和代码。

BTW,如果LZ的方式是WDK允许的方式,只是LZ代码写的不好,请将蓝屏的完整信息贴出来,根据蓝屏信息,你可以知道是社么类型的问题。
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

6
 
引用 4 楼 huntercao 的回复:
两个独立的驱动之间这样IoCallDriver()好像不被允许吧?

WDK里面有介绍两个驱动之间的一些通讯方式,我不记得有LZ说的这种。我记得有一种方法是B驱动得注册一个Interface,A驱动Query该Interface,通过该Interface的handle可以进行通讯。具体的操作方式得LZ自己多看看文档和代码。

BTW,如果LZ的方式是WDK允许的方式,只是LZ代码写的不好,……

很感谢,给我指明了前进的道路。两个独立的串口驱动间该如何一个获得另一个的服务啊?谢谢,能不能给以些资料。我也感觉问题是出在这里了,但是我将两个串口attach以后还是不通过。还是调用IoCallDriver有蓝屏。期待您解答!
 
 
 

回复

83

帖子

0

TA的资源

一粒金砂(初级)

7
 
OSR 有文章介绍了你用的这种方法,写很具体,去看看吧: Buddy Drivers - Methods for Driver to Driver Communication
http://www.osronline.com/article.cfm?id=24

里面有谈到LZ的这种调用方法. 文章中强调了2点:
1.驱动的加载顺序要正确。DriverA 在通过IoGetDeviceObjectPointer获取DriverB的PDO时,需要确保DriverB已经加载到系统中;
2.文章建议在DriverA调用DriverB时,在DriverA中通过queue a work item来进行IoGetDeviceObjectPointer/IoCallDriver;

BTW:没有蓝屏信息,大家很难知道你碰到的问题是什么。最起码你要告诉大家BSOD的Code是什么。
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

8
 
蓝屏信息如下(附加了些解释信息):
An attempt was made to touch pageable memory at an IRQL that is too high.
Parameter 1 - Memory referenced.
Parameter 2 - IRQL
Parameter 3 - Value (0=read, 1=write)
Parameter 4 - Address that referenced memory.

0x0000000A (0x00000016, 0x00000002, 0x00000000, 0x804F9E4A)

停止错误编号: 0x0000000A (parameter, parameter, parameter, parameter) IRQL_NOT_LESS_OR_EQUAL

解释:
This is a Windows 2000 Executive character-mode STOP message. It indicates an attempt was made to touch pageable  memory at a process IRQL (interrupt request level) that is too high. This is usually caused by drivers using  incorrect addresses. The fourth parameter in the message parameter list is the memory address at which the fault  happened. The second parameter shows the IRQL. If the IRQL was not equal to 2, then the interrupt most likely  came from a driver. Compare the memory address in the fourth parameter with the base addresses of the drivers in  the driver table on the STOP screen to find the driver that is the problem. Note that the third parameter  encodes read/write access (0 = read, 1= write).
请那位大侠帮忙分析下谢谢。
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

9
 
引用 7 楼 nwpu043814 的回复:

蓝屏信息如下(附加了些解释信息):
An attempt was made to touch pageable memory at an IRQL that is too high.
Parameter 1 - Memory referenced.
Parameter 2 - IRQL
Parameter 3 - Value (0=read, 1=write)
Parameter 4……

提示信息说的很清除,你DeviceA或者DeviceB访问了不合适的内存空间。如果用WinDBG调试,那么会有更多的信息告诉你到底0x804F9E4A指向什么。
我怀疑IoBuildDeviceIoControlRequest的倒数第二个参数event在pageable memory 中分配造成问题。可以考虑将event申明在Device Extension中试试。
//用IoBuildDeviceIoControlRequest创建IRP
irp = IoBuildDeviceIoControlRequest(IoctlControlCode,
  TopOfDeivceStack,
  InputBuffer,
  InputBufferLength,
  OutputBuffer,
  OutputBufferLength,
  FALSE,
  &event,
  &ioStatus);
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

10
 
引用 8 楼 huntercao 的回复:
引用 7 楼 nwpu043814 的回复:

蓝屏信息如下(附加了些解释信息):
An attempt was made to touch pageable memory at an IRQL that is too high.
Parameter 1 - Memory referenced.
Parameter 2 - IRQL
Parameter 3 - Value (0=rea……

大侠,我试过了,dump出来的地址不是event的地址,我能不能把程序发给您,帮我看看,两个驱动都发。您在哪里的?在西安的话我请您吃饭。
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

11
 
引用 8 楼 huntercao 的回复:
引用 7 楼 nwpu043814 的回复:

蓝屏信息如下(附加了些解释信息):
An attempt was made to touch pageable memory at an IRQL that is too high.
Parameter 1 - Memory referenced.
Parameter 2 - IRQL
Parameter 3 - Value (0=rea……

大侠,我试过了,dump出来的地址不是event的地址,我能不能把程序发给您,帮我看看,两个驱动都发。您在哪里的?在西安的话我请您吃饭。
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

12
 
引用 10 楼 nwpu043814 的回复:
大侠,我试过了,dump出来的地址不是event的地址,我能不能把程序发给您,帮我看看,两个驱动都发。您在哪里的?在西安的话我请您吃饭。


偶在北京。
你试过将event放在Device Extension中了?照样BSOD?

会用WinDBG联机调试么?
请试着将BSOD产生的Dump文件用WinDBG打开,用"!analyze -v"获取更详细的信息,然后贴出来大家帮助看看。

把程序发给我就免了,还得靠你自己调试的。
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

13
 
另外,你有办法确认蓝屏到底发生在哪个驱动么?DriverA or DriverB
如果发生在DriverA,那么可能IoCallDriver()能够成功返回,是你某些地方处理不对;
如果发生在DriverB,那么你需要查看DriverB中,对IOCTL_SERIAL_TRANSLATE的处理是否正确,是否有访问越界的地方。如果是这样,把IOCTL_SERIAL_TRANSLATE的处理代码发给大家看看。

 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

14
 
引用 11 楼 huntercao 的回复:
引用 10 楼 nwpu043814 的回复:
你试过将event放在Device Extension中了?照样BSOD?

感谢再次提醒,不好意思,刚才没有试,我只是打印了Event的地址看了,现在将event放到Device_extension里面了,蓝屏停止了,问题就在这里,高手就是高手,很早就判断出可能出现问题的地方了。
赞扬您这种诲新人不倦的精神!
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表