为什么这样调用IoCallDriver分发自己创建的IRP会引起蓝屏?

leon32455   2010-5-4 21:39 楼主
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的时候就会蓝屏,不知道是什么原因?各位前辈指点一下。谢谢!

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复