ReacOS源代码阅读之驱动--IoCreateDevice

       IoCreateDevice 是驱动程序创建设备时需要调用的,通过阅读IoCreateDevice函数,可以更好理解设备对象和驱动对象的关系,以及设备对象的各种成员是如何起作用的。

       windgb中显示DeviceObject的成员。

       

kd> dt nt!_device_object
   +0x000 Type             : Int2B
   +0x002 Size             : Uint2B
   +0x004 ReferenceCount   : Int4B
   +0x008 DriverObject     : Ptr32 _DRIVER_OBJECT
   +0x00c NextDevice       : Ptr32 _DEVICE_OBJECT
   +0x010 AttachedDevice   : Ptr32 _DEVICE_OBJECT
   +0x014 CurrentIrp       : Ptr32 _IRP
   +0x018 Timer            : Ptr32 _IO_TIMER
   +0x01c Flags            : Uint4B
   +0x020 Characteristics  : Uint4B
   +0x024 Vpb              : Ptr32 _VPB
   +0x028 DeviceExtension  : Ptr32 Void
   +0x02c DeviceType       : Uint4B
   +0x030 StackSize        : Char
   +0x034 Queue            : __unnamed
   +0x05c AlignmentRequirement : Uint4B
   +0x060 DeviceQueue      : _KDEVICE_QUEUE
   +0x074 Dpc              : _KDPC
   +0x094 ActiveThreadCount : Uint4B
   +0x098 SecurityDescriptor : Ptr32 Void
   +0x09c DeviceLock       : _KEVENT
   +0x0ac SectorSize       : Uint2B
   +0x0ae Spare1           : Uint2B
   +0x0b0 DeviceObjectExtension : Ptr32 _DEVOBJ_EXTENSION
   +0x0b4 Reserved         : Ptr32 Void

       该函数实现在 E:\Open_Source_Code\ReactOS\ntoskrnl\io\iomgr\device.c (E:\Open_Source_Code\ReactOS 保存ReactOS的源代码根目录)。原函数已经有必要的注释了。

NTSTATUS
NTAPI
IoCreateDevice(IN PDRIVER_OBJECT DriverObject,
               IN ULONG DeviceExtensionSize,
               IN PUNICODE_STRING DeviceName,
               IN DEVICE_TYPE DeviceType,
               IN ULONG DeviceCharacteristics,
               IN BOOLEAN Exclusive,
               OUT PDEVICE_OBJECT *DeviceObject)
{
    WCHAR AutoNameBuffer[20];
    UNICODE_STRING AutoName;
    PDEVICE_OBJECT CreatedDeviceObject;
    PDEVOBJ_EXTENSION DeviceObjectExtension;
    OBJECT_ATTRIBUTES ObjectAttributes;
    NTSTATUS Status;
    ULONG AlignedDeviceExtensionSize;
    ULONG TotalSize;
    HANDLE TempHandle;
    PAGED_CODE();

    /* Check if we have to generate a name */
    if (DeviceCharacteristics & FILE_AUTOGENERATED_DEVICE_NAME)
    {
        /* Generate it 生成一个自动的设备名称 */
        swprintf(AutoNameBuffer,
                 L"\\Device\\%08lx",
                 InterlockedIncrementUL(&IopDeviceObjectNumber));

        /* Initialize the name */
        RtlInitUnicodeString(&AutoName, AutoNameBuffer);
        DeviceName = &AutoName;
    }

    /* Initialize the Object Attributes */
    InitializeObjectAttributes(&ObjectAttributes,
                               DeviceName,
                               OBJ_KERNEL_HANDLE,
                               NULL,
                               SePublicOpenUnrestrictedSd);

    /* Honor exclusive flag */
    if (Exclusive) ObjectAttributes.Attributes |= OBJ_EXCLUSIVE;

    /* Create a permanent object for named devices */
    if (DeviceName) ObjectAttributes.Attributes |= OBJ_PERMANENT;

    /* Align the Extension Size to 8-bytes  8字节对齐*/
    AlignedDeviceExtensionSize = (DeviceExtensionSize + 7) &~ 7;

    /* Total Size */
    TotalSize = AlignedDeviceExtensionSize +
                sizeof(DEVICE_OBJECT) +
                sizeof(EXTENDED_DEVOBJ_EXTENSION);

    /* Create the Device Object */
    *DeviceObject = NULL;
    Status = ObCreateObject(KernelMode,
                            IoDeviceObjectType,
                            &ObjectAttributes,
                            KernelMode,
                            NULL,
                            TotalSize,
                            0,
                            0,
                            (PVOID*)&CreatedDeviceObject);
    if (!NT_SUCCESS(Status)) return Status;

    /* Clear the whole Object and extension so we don't null stuff manually */
    RtlZeroMemory(CreatedDeviceObject, TotalSize);

    /*
     * Setup the Type and Size. Note that we don't use the aligned size,
     * because that's only padding for the DevObjExt and not part of the Object.
     */
    CreatedDeviceObject->Type = IO_TYPE_DEVICE;
    CreatedDeviceObject->Size = sizeof(DEVICE_OBJECT) + (USHORT)DeviceExtensionSize;

    /* The kernel extension is after the driver internal extension */
    DeviceObjectExtension = (PDEVOBJ_EXTENSION)
                            ((ULONG_PTR)(CreatedDeviceObject + 1) +
                             AlignedDeviceExtensionSize);

    /* Set the Type and Size. Question: why is Size 0 on Windows? */
    DeviceObjectExtension->Type = IO_TYPE_DEVICE_OBJECT_EXTENSION;
    DeviceObjectExtension->Size = 0;

    /* Initialize with Power Manager */
    PoInitializeDeviceObject(DeviceObjectExtension);

    /* Link the Object and Extension */
    DeviceObjectExtension->DeviceObject = CreatedDeviceObject;
    CreatedDeviceObject->DeviceObjectExtension = DeviceObjectExtension;

    /* Set Device Object Data */
    CreatedDeviceObject->DeviceType = DeviceType;
    CreatedDeviceObject->Characteristics = DeviceCharacteristics;
    CreatedDeviceObject->DeviceExtension = DeviceExtensionSize ?
                                           CreatedDeviceObject + 1 :
                                           NULL;
    CreatedDeviceObject->StackSize = 1;
    CreatedDeviceObject->AlignmentRequirement = 0;

    /* Set the Flags */
    CreatedDeviceObject->Flags = DO_DEVICE_INITIALIZING;
    if (Exclusive) CreatedDeviceObject->Flags |= DO_EXCLUSIVE;
    if (DeviceName) CreatedDeviceObject->Flags |= DO_DEVICE_HAS_NAME;

    /* Attach a Vpb for Disks and Tapes, and create the Device Lock */
    if ((CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK) ||
        (CreatedDeviceObject->DeviceType == FILE_DEVICE_VIRTUAL_DISK) ||
        (CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM) ||
        (CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE))
    {
        /* Create Vpb */
        Status = IopCreateVpb(CreatedDeviceObject);
        if (!NT_SUCCESS(Status))
        {
            /* Dereference the device object and fail */
            ObDereferenceObject(CreatedDeviceObject);
            return Status;
        }

        /* Initialize Lock Event */
        KeInitializeEvent(&CreatedDeviceObject->DeviceLock,
                          SynchronizationEvent,
                          TRUE);
    }

    /* Set the right Sector Size */
    switch (DeviceType)
    {
        /* All disk systems */
        case FILE_DEVICE_DISK_FILE_SYSTEM:
        case FILE_DEVICE_DISK:
        case FILE_DEVICE_VIRTUAL_DISK:

            /* The default is 512 bytes */
            CreatedDeviceObject->SectorSize  = 512;
            break;

        /* CD-ROM file systems */
        case FILE_DEVICE_CD_ROM_FILE_SYSTEM:

            /* The default is 2048 bytes */
            CreatedDeviceObject->SectorSize = 2048;
    }

    /* Create the Device Queue */
    if ((CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) ||
        (CreatedDeviceObject->DeviceType == FILE_DEVICE_FILE_SYSTEM) ||
        (CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) ||
        (CreatedDeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) ||
        (CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM))
    {
        /* Simple FS Devices, they don't need a real Device Queue */
        InitializeListHead(&CreatedDeviceObject->Queue.ListEntry);
    }
    else
    {
        /* An actual Device, initialize its DQ */
        KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue);
    }

    /* Insert the Object */
    Status = ObInsertObject(CreatedDeviceObject,
                            NULL,
                            FILE_READ_DATA | FILE_WRITE_DATA,
                            1,
                            (PVOID*)&CreatedDeviceObject,
                            &TempHandle);
    if (!NT_SUCCESS(Status)) return Status;

    /* Now do the final linking */
    ObReferenceObject(DriverObject);
    ASSERT((DriverObject->Flags & DRVO_UNLOAD_INVOKED) == 0);
    CreatedDeviceObject->DriverObject = DriverObject;
    IopEditDeviceList(DriverObject, CreatedDeviceObject, IopAdd);

    /* Link with the power manager */
    if (CreatedDeviceObject->Vpb) PoVolumeDevice(CreatedDeviceObject);

    /* Close the temporary handle and return to caller */
    ObCloseHandle(TempHandle, KernelMode);
    *DeviceObject = CreatedDeviceObject;
    return STATUS_SUCCESS;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值