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

来源:互联网 发布:linux怎么看内存大小 编辑:程序博客网 时间:2024/06/06 15:35

       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的源代码根目录)。原函数已经有必要的注释了。

NTSTATUSNTAPIIoCreateDevice(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
原创粉丝点击