当前位置: 代码迷 >> 驱动开发 >> windows驱动 大白菜请问有关问题
  详细解决方案

windows驱动 大白菜请问有关问题

热度:124   发布时间:2016-04-28 10:13:01.0
windows驱动 大白菜请教问题
if (fcn == IRP_MN_DEVICE_USAGE_NOTIFICATION)
{ // usage notification
if (!fido->AttachedDevice || (fido->AttachedDevice->Flags & DO_POWER_PAGABLE))
fido->Flags |= DO_POWER_PAGABLE;
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) UsageNotificationCompletionRoutine,
(PVOID) pdx, TRUE, TRUE, TRUE);
return IoCallDriver(pdx->LowerDeviceObject, Irp);
} // usage notification

// Handle start device specially in order to correctly inherit
// FILE_REMOVABLE_MEDIA
if (fcn == IRP_MN_START_DEVICE)
{ // device start
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) StartDeviceCompletionRoutine,
(PVOID) pdx, TRUE, TRUE, TRUE);
return IoCallDriver(pdx->LowerDeviceObject, Irp);
} // device start

// Handle remove device specially in order to cleanup device stack
if (fcn == IRP_MN_REMOVE_DEVICE)
{ // remove device
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(pdx->LowerDeviceObject, Irp);
IoReleaseRemoveLockAndWait(&pdx->RemoveLock, Irp);
RemoveDevice(fido);
return status;
} // remove device

// Simply forward any other type of PnP request
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(pdx->LowerDeviceObject, Irp);
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return status;
} // DispatchPnp



书上的一段代码, IoCopyCurrentIrpStackLocationToNext 这个函数把当前IRP复制一份;那么,然后设置了回调历程。
    再然后 用IocallDriver把IRP传到了下一层;;

   那么,这里的 复制,为什么要复制呢? (别说,设置了回调函数);复制干嘛呢?  
  以及 为什么 if判断的就要做 复制IRP 然后设置回调函数?
------解决方案--------------------
这个原因还真是因为设置了回调函数,
回调函数在该IRP被下层执行完成之后去执行,如果不使用IoCopyCurrentIrpStackLocationToNext ,则该层的回调函数不能与该IRP的完成例程相对应。
在wdm.h文件中有该函数的实现过程:
VOID
IoCopyCurrentIrpStackLocationToNext(
    __inout PIRP Irp
)
{
    PIO_STACK_LOCATION irpSp;
    PIO_STACK_LOCATION nextIrpSp;
    irpSp = IoGetCurrentIrpStackLocation(Irp);
    nextIrpSp = IoGetNextIrpStackLocation(Irp);
    RtlCopyMemory( nextIrpSp, irpSp, FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine));
    nextIrpSp->Control = 0;
}

会将对应的完成例程地址发送给下层驱动。
而IoSkipCurrentIrpStackLocation 却不会有上述操作:
VOID
IoSkipCurrentIrpStackLocation (
    __inout PIRP Irp
)
{
    ASSERT(Irp->CurrentLocation <= Irp->StackCount);
    Irp->CurrentLocation++;
    Irp->Tail.Overlay.CurrentStackLocation++;
}
  相关解决方案