windows内核编程 白话设备栈

在ntddk.h中定义了该函数原型:

 

#if (NTDDI_VERSION >= NTDDI_WINXP)

NTKERNELAPI

NTSTATUS

IoAttachDeviceToDeviceStackSafe(

    __in  PDEVICE_OBJECT SourceDevice,

    __in  PDEVICE_OBJECT TargetDevice,

    __deref_out PDEVICE_OBJECT *AttachedToDeviceObject

    );

#endif

 

我们加载微软的sfilter源码进行分析

1 创建sfilter的CDO

图1

驱动Sfilter.sys等待 文件系统驱动的加载 SfFsNotification

图2

我们可以看到 Ntfs.sys驱动的CDO地址是0x862c8270

这时候 我们的Sfilter即将创建一个FiDO附着在Ntfs的CDO上面
  

图3

新创建的FiDO的地址是0x86337998

而newDeviceObject->DriverObject的驱动地址正是我们的Sfilter的驱动地址

另外newDeviceObject->NextDevice是Sfilter!CDO的地址

这说明,IoCreateDevice的时候,新建的DeviceObject在会插在以往的DO之前 如图4

图4

下面的任务便是附着FiDO于Ntfs驱动的CDO之上

 

IoAttachDeviceToDeviceStackSafe(

  newDeviceObject,

    DeviceObject,

     &devExt->AttachedToDeviceObject );

 

继续用winDBG查看

图5

FiDO的地址是0x86337998

FiDO->AttachedDevice的地址是0x00000000 此时FiDO在设备栈的最顶层

现在明了了 DeviceObject->AttachedDevice指向的是上层的设备

图6

      
 

图7

我们用winDBG验证一下

图8

我们查看WRK源码 IopAttachDeviceToDeviceStackSafe

PDEVICE_OBJECT
IopAttachDeviceToDeviceStackSafe(
    IN PDEVICE_OBJECT SourceDevice,
    IN PDEVICE_OBJECT TargetDevice,
    OUT PDEVICE_OBJECT *AttachedToDeviceObject OPTIONAL
    )
{
    PDEVICE_OBJECT deviceObject;
    PDEVOBJ_EXTENSION sourceExtension;
    KIRQL irql;

    //
    // Retrieve a pointer to the source device object's extension outside
    // of the IopDatabaseLock, since it isn't protected by that.
    //

    sourceExtension = SourceDevice->DeviceObjectExtension;

    //
    // Get a pointer to the topmost device object in the stack of devices,
    // beginning with the TargetDevice, and attach to it.
    //

    irql = KeAcquireQueuedSpinLock( LockQueueIoDatabaseLock );

    //
    // Tell the Special IRP code the stack has changed. Code that will reexamine
    // the stack takes the database lock, so we can place the call here. This
    // also allows us to assert correct behavior *before* the stack is built up.
    //

    IOV_ATTACH_DEVICE_TO_DEVICE_STACK(SourceDevice, TargetDevice);

   <strong> deviceObject = IoGetAttachedDevice( TargetDevice );</strong>

    //
    // Make sure that the SourceDevice object isn't already attached to
    // something else, this is now illegal.
    //

    ASSERT( sourceExtension->AttachedTo == NULL );

    //
    // Now attach to the device, provided that it is not being unloaded,
    // deleted or initializing.
    //

    if (deviceObject->Flags & DO_DEVICE_INITIALIZING ||
        deviceObject->DeviceObjectExtension->ExtensionFlags &
        (DOE_UNLOAD_PENDING | DOE_DELETE_PENDING | DOE_REMOVE_PENDING | DOE_REMOVE_PROCESSED)) {

        //
        // The device currently at the top of the attachment chain is being
        // unloaded, deleted or initialized.
        //

        deviceObject = (PDEVICE_OBJECT) NULL;

    } else {

        //
        // Perform the attachment.  First update the device previously at the
        // top of the attachment chain.
        //
        <strong>deviceObject->AttachedDevice = SourceDevice;</strong>
        deviceObject->Spare1++;

        //
        // Now update the new top-of-attachment-chain.
        //

        <strong>SourceDevice->StackSize = (UCHAR) (deviceObject->StackSize + 1);</strong>
        SourceDevice->AlignmentRequirement = deviceObject->AlignmentRequirement;
        SourceDevice->SectorSize = deviceObject->SectorSize;

        if (deviceObject->DeviceObjectExtension->ExtensionFlags & DOE_START_PENDING)  {
            SourceDevice->DeviceObjectExtension->ExtensionFlags |= DOE_START_PENDING;
        }

        //
        // Attachment chain is doubly-linked.
        //

        sourceExtension->AttachedTo = deviceObject;
    }

    //
    // Atomically update this field inside the lock.
    // The caller has to ensure that this location is in non-paged pool.
    // This is required so that a filesystem filter can attach to a device and before it
    // gets an IRP it can update its lower device object pointer.
    //

    if (AttachedToDeviceObject) {
        *AttachedToDeviceObject = deviceObject;
    }

    KeReleaseQueuedSpinLock( LockQueueIoDatabaseLock, irql );

    return deviceObject;
}

deviceObject 会一直遍历 TargetDevice的设备栈,直到最上层的设备。这个deviceObject 也是最后返回的PDEVICE_OBJECT。


PDEVICE_OBJECT
IoGetAttachedDevice(
    IN PDEVICE_OBJECT DeviceObject
    )
{
    //
    // Loop through all of the device object's attached to the specified
    // device.  When the last device object is found that is not attached
    // to, return it.
    //

    while (DeviceObject->AttachedDevice) {
        <strong>DeviceObject = DeviceObject->AttachedDevice;</strong>
    }

    return DeviceObject;
}

然后 deviceObject->AttachedDevice = SourceDevice; 将我们的SourceDevice附着在设备栈的最顶层。

最后SourceDevice->StackSize = (UCHAR) (deviceObject->StackSize + 1); stackSize增加1。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值