robot241 2014-01-29 10:18 采纳率: 0%
浏览 1025

C++驱动开发的小问题,求大家指点,算是初学者的问题,我弄好久了。。

#include "Driver.h"

#pragma code_seg("INIT")
extern "C"
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj,PUNICODE_STRING pustrRegisterPath)
{
KdPrint(("Enter DriverEntry\n"));
NTSTATUS status = STATUS_SUCCESS;

pDriverObj->DriverUnload = UnloadDR;
pDriverObj->MajorFunction[IRP_MJ_CREATE] = CreateDR;
pDriverObj->MajorFunction[IRP_MJ_READ] = ReadDR;

PDEVICE_OBJECT pDeviceObj;
UNICODE_STRING ustrDeviceName;
RtlInitUnicodeString(&ustrDeviceName,L"\\Device\\Timeout");
IoCreateDevice(pDriverObj,sizeof(DEVICE_EXTENSION),&ustrDeviceName,FILE_DEVICE_UNKNOWN,\
               0,FALSE,&pDeviceObj);
UNICODE_STRING ustrSymbLinkName;
RtlInitUnicodeString(&ustrSymbLinkName,L"\\DosDevices\\Timeout");
status = IoCreateSymbolicLink(&ustrSymbLinkName,&ustrDeviceName);
if(!NT_SUCCESS(status))
{
    KdPrint(("Error: IoCreateSymbolicLink\n"));
    IoDeleteSymbolicLink(&ustrSymbLinkName);
    IoDeleteDevice(pDeviceObj);
    return status;
}
PDEVICE_EXTENSION pDeviceExt = (PDEVICE_EXTENSION)pDeviceObj->DeviceExtension;
pDeviceExt->pDeviceObj = pDeviceObj;
pDeviceExt->ustrDeviceName = ustrDeviceName;
pDeviceExt->ustrSymbLinkName = ustrSymbLinkName;

KdPrint(("Leave DriverEntry\n"));
return status;

}

#pragma code_seg("PAGED")
VOID UnloadDR(PDRIVER_OBJECT pDriverObj)
{
KdPrint(("Enter UnloadDR\n"));
PDEVICE_EXTENSION pDeviceExt = (PDEVICE_EXTENSION)pDriverObj->DeviceObject->DeviceExtension;
IoDeleteSymbolicLink(&pDeviceExt->ustrSymbLinkName);
IoDeleteDevice(pDeviceExt->pDeviceObj);
KdPrint(("Leave UnloadDR\n"));
}

#pragma code_seg("PAGED")
NTSTATUS CreateDR(PDEVICE_OBJECT pDeviceObj,PIRP pIrp)
{
KdPrint(("Enter CreateDR\n"));
NTSTATUS status = STATUS_SUCCESS;

PDEVICE_EXTENSION pDeviceExt = (PDEVICE_EXTENSION)pDeviceObj->DeviceExtension;
KeInitializeDpc(&pDeviceExt->kDpc,OnDpc,(PVOID)pDeviceObj);
KeInitializeTimer(&pDeviceExt->kTimer);

pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp,IO_NO_INCREMENT);

KdPrint(("Leave CreateDR\n"));
return status;

}

#pragma code_seg("PAGED")
NTSTATUS ReadDR(PDEVICE_OBJECT pDeviceObj,PIRP pIrp)
{
KdPrint(("Enter ReadDR\n"));
NTSTATUS status = STATUS_SUCCESS;

PDEVICE_EXTENSION pDeviceExt = (PDEVICE_EXTENSION)pDeviceObj->DeviceExtension;
IoMarkIrpPending(pIrp);
pDeviceExt->pPendingIrp = pIrp;
ULONG ulInterval = 3000000;
pDeviceExt->liInterval = RtlConvertLongToLargeInteger(-10*ulInterval);
KeSetTimer(&pDeviceExt->kTimer,pDeviceExt->liInterval,&pDeviceExt->kDpc);
status = STATUS_PENDING;

KdPrint(("Leave ReadDR\n"));
return status;

}

#pragma code_seg()
VOID OnDpc(
__in struct _KDPC *Dpc,
__in_opt PVOID DeferredContext,
__in_opt PVOID SystemArgument1,
__in_opt PVOID SystemArgument2
)
{
KdPrint(("Enter OnDpc\n"));
PDEVICE_OBJECT pDeviceObj = (PDEVICE_OBJECT)DeferredContext;
PDEVICE_EXTENSION pDeviceExt = (PDEVICE_EXTENSION)pDeviceObj;
PIRP pIrp = pDeviceExt->pPendingIrp;
KdPrint(("timeout\n"));
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(pIrp,IO_NO_INCREMENT);

KdPrint(("Leave OnDpc\n"));

/* _asm
{
int 3;
}
*/
}

上面是我写的简单的代码,就是读这个驱动程序的时候,它会先挂起这个读IRP,当超时时结束这个IRP.
但是这儿我遇到个问题,一旦我在DPC里调用IOCompleteRequest之后就出错,但是不调用这个又不行,这样调用程序始终处于等待状态。
求指点,万分感谢。

  • 写回答

1条回答

  • ChatGPTᴼᴾᴱᴺᴬᴵ 2023-02-27 19:35
    关注

    该回答引用ChatGPT

    您的问题可能是由于在DPC例程中调用IoCompleteRequest而不是在IRP的处理例程中调用引起的。


    由于DPC运行在被中断的上下文中,因此在其中调用IoCompleteRequest可能会引发意外的结果。相反,您应该在IRP的处理例程中完成IRP并调用IoCompleteRequest。在DPC中,您可以将IRP标记为已取消并将其放回队列中,以便在IRP的处理例程中取消处理。


    因此,在您的代码中,您应该在DPC例程中取消IRP,而不是完成IRP并调用IoCompleteRequest。以下是修改后的OnDpc函数:

    VOID OnDpc(
        __in struct _KDPC *Dpc,
        __in_opt PVOID DeferredContext,
        __in_opt PVOID SystemArgument1,
        __in_opt PVOID SystemArgument2
    )
    {
        KdPrint(("Enter OnDpc\n"));
        PDEVICE_OBJECT pDeviceObj = (PDEVICE_OBJECT)DeferredContext;
        PDEVICE_EXTENSION pDeviceExt = (PDEVICE_EXTENSION)pDeviceObj;
        PIRP pIrp = pDeviceExt->pPendingIrp;
        KdPrint(("timeout\n"));
        pIrp->IoStatus.Information = 0;
        pIrp->IoStatus.Status = STATUS_CANCELLED;
        IoMarkIrpPending(pIrp);
        IoQueueIoCompletion(pIrp, NULL, NULL, STATUS_CANCELLED);
        KeSetEvent(&pDeviceExt->kEvent, IO_NO_INCREMENT, FALSE);
        KdPrint(("Leave OnDpc\n"));
    }
    

    注意,我添加了IoMarkIrpPending和IoQueueIoCompletion函数来取消IRP并将其放回队列中。此外,我还添加了一个事件对象kEvent,以便在IRP处理例程中等待取消的IRP。

    评论

报告相同问题?

悬赏问题

  • ¥50 易语言把MYSQL数据库中的数据添加至组合框
  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况