IoCreateDevice Changes:

- IoAllocateVpb renamed to IopAllocateVpb and made cleaner
    - Let ObCreateObject do all the memory allocation since the extra data belongs to the
      object and it should be responsible for allocating it. No more extra pool allocations
      or deallocations.
    - Zero out everythign a single time.
    - Remove useless code duplication
    - Use proper I/O Manager types for the object headers.
    - Honour Exclusive Flag, and Has Name Flag.
    - Only initialize event if there is a volume.
    - Initialize a VPB for Virtual Disks also.
    - Set up Device Object Extension properly
    - Set DO_DEVICE_INITIALIZING flag.
    - Use proper sector sizes, don't hardcode 512 (should be 2048 for cds)
    - Actually insert the object into the object table with ObInsertObject. This might seem
      useless, but remember that's simply because ROS has a broken Ob Manager which does way
      too much in ObCreateObject. It will be easier to use the rewrite if this is done properly.
    - Set the right sizes in some places.

svn path=/trunk/; revision=14643
This commit is contained in:
Alex Ionescu 2005-04-17 04:20:16 +00:00
parent f4c3dd909b
commit 24b6532712
4 changed files with 189 additions and 174 deletions

View file

@ -892,8 +892,19 @@ struct _FAST_IO_DISPATCH_TABLE
} FAST_IO_DISPATCH_TABLE, * PFAST_IO_DISPATCH_TABLE; } FAST_IO_DISPATCH_TABLE, * PFAST_IO_DISPATCH_TABLE;
#endif #endif
#define IO_TYPE_DRIVER 4L #define IO_TYPE_ADAPTER 0x1L
#define IO_TYPE_FILE 0x0F5L #define IO_TYPE_CONTROLLER 0x2L
#define IO_TYPE_DEVICE 0x3L
#define IO_TYPE_DRIVER 0x4L
#define IO_TYPE_FILE 0x0F5L /* Temp Hack */
#define IO_TYPE_IRP 0x6L
#define IO_TYPE_MASTER_ADAPTER 0x7L
#define IO_TYPE_OPEN_PACKET 0x8L
#define IO_TYPE_TIMER 0x9L
#define IO_TYPE_VPB 0xaL
#define IO_TYPE_ERROR_LOG 0xbL
#define IO_TYPE_ERROR_MESSAGE 0xcL
#define IO_TYPE_DEVICE_OBJECT_EXTENSION 0xdL
#define DRVO_UNLOAD_INVOKED 0x1L #define DRVO_UNLOAD_INVOKED 0x1L
#define DRVO_LEGACY_DRIVER 0x2L #define DRVO_LEGACY_DRIVER 0x2L
@ -959,7 +970,6 @@ typedef VOID STDCALL_FUNC
/* /*
* PURPOSE: Special timer associated with each device * PURPOSE: Special timer associated with each device
*/ */
#define IO_TYPE_TIMER 9
typedef struct _IO_TIMER { typedef struct _IO_TIMER {
USHORT Type; /* Every IO Object has a Type */ USHORT Type; /* Every IO Object has a Type */
USHORT TimerEnabled; /* Tells us if the Timer is enabled or not */ USHORT TimerEnabled; /* Tells us if the Timer is enabled or not */

View file

@ -370,7 +370,10 @@ IopCreateDevice(PVOID ObjectBody,
PVOID Parent, PVOID Parent,
PWSTR RemainingPath, PWSTR RemainingPath,
POBJECT_ATTRIBUTES ObjectAttributes); POBJECT_ATTRIBUTES ObjectAttributes);
NTSTATUS IoAttachVpb(PDEVICE_OBJECT DeviceObject);
NTSTATUS
STDCALL
IopAttachVpb(PDEVICE_OBJECT DeviceObject);
PIRP IoBuildSynchronousFsdRequestWithMdl(ULONG MajorFunction, PIRP IoBuildSynchronousFsdRequestWithMdl(ULONG MajorFunction,
PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceObject,

View file

@ -307,7 +307,6 @@ IoAttachDeviceToDeviceStackSafe(IN PDEVICE_OBJECT SourceDevice,
SourceDeviceExtension = SourceDevice->DeviceObjectExtension; SourceDeviceExtension = SourceDevice->DeviceObjectExtension;
/* Make sure that it's in a correct state */ /* Make sure that it's in a correct state */
DPRINT1("flags %d\n", AttachedDevice->DeviceObjectExtension->ExtensionFlags);
if (!(AttachedDevice->DeviceObjectExtension->ExtensionFlags & if (!(AttachedDevice->DeviceObjectExtension->ExtensionFlags &
(DOE_UNLOAD_PENDING | DOE_DELETE_PENDING | (DOE_UNLOAD_PENDING | DOE_DELETE_PENDING |
DOE_REMOVE_PENDING | DOE_REMOVE_PROCESSED))) DOE_REMOVE_PENDING | DOE_REMOVE_PROCESSED)))
@ -355,10 +354,6 @@ IoDeleteDevice(PDEVICE_OBJECT DeviceObject)
ExFreePool(DeviceObject->Timer); ExFreePool(DeviceObject->Timer);
} }
/* Free device extension */
if (DeviceObject->DeviceObjectExtension)
ExFreePool(DeviceObject->DeviceObjectExtension);
/* Remove device from driver device list */ /* Remove device from driver device list */
Previous = DeviceObject->DriverObject->DeviceObject; Previous = DeviceObject->DriverObject->DeviceObject;
if (Previous == DeviceObject) if (Previous == DeviceObject)
@ -652,9 +647,9 @@ IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
* Status * Status
* @implemented * @implemented
*/ */
NTSTATUS STDCALL NTSTATUS
IoCreateDevice( STDCALL
PDRIVER_OBJECT DriverObject, IoCreateDevice(PDRIVER_OBJECT DriverObject,
ULONG DeviceExtensionSize, ULONG DeviceExtensionSize,
PUNICODE_STRING DeviceName, PUNICODE_STRING DeviceName,
DEVICE_TYPE DeviceType, DEVICE_TYPE DeviceType,
@ -668,140 +663,152 @@ IoCreateDevice(
PDEVOBJ_EXTENSION DeviceObjectExtension; PDEVOBJ_EXTENSION DeviceObjectExtension;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status; NTSTATUS Status;
ULONG AlignedDeviceExtensionSize;
ULONG TotalSize;
HANDLE TempHandle;
ASSERT_IRQL(PASSIVE_LEVEL); ASSERT_IRQL(PASSIVE_LEVEL);
if (DeviceName != NULL)
{
DPRINT("IoCreateDevice(DriverObject %x, DeviceName %S)\n",
DriverObject, DeviceName->Buffer);
}
else
{
DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject); DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject);
}
/* Generate a name if we have to */
if (DeviceCharacteristics & FILE_AUTOGENERATED_DEVICE_NAME) if (DeviceCharacteristics & FILE_AUTOGENERATED_DEVICE_NAME)
{ {
swprintf(AutoNameBuffer, swprintf(AutoNameBuffer,
L"\\Device\\%08lx", L"\\Device\\%08lx",
InterlockedIncrementUL(&IopDeviceObjectNumber)); InterlockedIncrementUL(&IopDeviceObjectNumber));
RtlInitUnicodeString(&AutoName, RtlInitUnicodeString(&AutoName, AutoNameBuffer);
AutoNameBuffer);
DeviceName = &AutoName; DeviceName = &AutoName;
} }
if (DeviceName != NULL) /* Initialize the Object Attributes */
{
InitializeObjectAttributes(&ObjectAttributes, DeviceName, 0, NULL, NULL); InitializeObjectAttributes(&ObjectAttributes, DeviceName, 0, NULL, NULL);
Status = ObCreateObject(
KernelMode, /* Honour exclusive flag */
ObjectAttributes.Attributes |= OBJ_EXCLUSIVE;
/* Align the Extension Size to 8-bytes */
AlignedDeviceExtensionSize = (DeviceExtensionSize + 7) &~ 7;
DPRINT("AlignedDeviceExtensionSize %x\n", AlignedDeviceExtensionSize);
/* Total Size */
TotalSize = AlignedDeviceExtensionSize +
sizeof(DEVICE_OBJECT) + sizeof(DEVOBJ_EXTENSION);
DPRINT("TotalSize %x\n", TotalSize);
/* Create the Device Object */
Status = ObCreateObject(KernelMode,
IoDeviceObjectType, IoDeviceObjectType,
&ObjectAttributes, &ObjectAttributes,
KernelMode, KernelMode,
NULL, NULL,
sizeof(DEVICE_OBJECT), TotalSize,
0, 0,
0, 0,
(PVOID*)&CreatedDeviceObject); (PVOID*)&CreatedDeviceObject);
}
else
{
Status = ObCreateObject(
KernelMode,
IoDeviceObjectType,
NULL,
KernelMode,
NULL,
sizeof(DEVICE_OBJECT),
0,
0,
(PVOID*)&CreatedDeviceObject);
}
*DeviceObject = NULL;
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status); DPRINT1("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status);
return Status; return Status;
} }
if (DriverObject->DeviceObject == NULL) /* Clear the whole Object and extension so we don't null stuff manually */
{ RtlZeroMemory(CreatedDeviceObject, TotalSize);
DriverObject->DeviceObject = CreatedDeviceObject; DPRINT("CreatedDeviceObject %x\n", CreatedDeviceObject);
CreatedDeviceObject->NextDevice = NULL;
}
else
{
CreatedDeviceObject->NextDevice = DriverObject->DeviceObject;
DriverObject->DeviceObject = CreatedDeviceObject;
}
CreatedDeviceObject->Type = DeviceType;
CreatedDeviceObject->DriverObject = DriverObject;
CreatedDeviceObject->CurrentIrp = NULL;
CreatedDeviceObject->Flags = 0;
CreatedDeviceObject->DeviceExtension =
ExAllocatePoolWithTag(
NonPagedPool,
DeviceExtensionSize,
TAG_DEVICE_EXTENSION);
if (DeviceExtensionSize > 0 && CreatedDeviceObject->DeviceExtension == NULL)
{
ExFreePool(CreatedDeviceObject);
DPRINT("IoCreateDevice() ExAllocatePoolWithTag failed, returning: 0x%08X\n", STATUS_INSUFFICIENT_RESOURCES);
return STATUS_INSUFFICIENT_RESOURCES;
}
if (DeviceExtensionSize > 0)
{
RtlZeroMemory(CreatedDeviceObject->DeviceExtension, DeviceExtensionSize);
}
/*
* 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) + DeviceExtensionSize; CreatedDeviceObject->Size = sizeof(DEVICE_OBJECT) + DeviceExtensionSize;
CreatedDeviceObject->ReferenceCount = 1;
CreatedDeviceObject->AttachedDevice = NULL; /* 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? */
DPRINT("DeviceObjectExtension %x\n", DeviceObjectExtension);
DeviceObjectExtension->Type = IO_TYPE_DEVICE_OBJECT_EXTENSION;
DeviceObjectExtension->Size = 0;
/* Link the Object and Extension */
DeviceObjectExtension->DeviceObject = CreatedDeviceObject;
CreatedDeviceObject->DeviceObjectExtension = DeviceObjectExtension;
/* Set Device Object Data */
CreatedDeviceObject->DeviceType = DeviceType; CreatedDeviceObject->DeviceType = DeviceType;
CreatedDeviceObject->StackSize = 1;
CreatedDeviceObject->AlignmentRequirement = 1;
CreatedDeviceObject->Characteristics = DeviceCharacteristics; CreatedDeviceObject->Characteristics = DeviceCharacteristics;
CreatedDeviceObject->Timer = NULL; CreatedDeviceObject->DeviceExtension = CreatedDeviceObject + 1;
CreatedDeviceObject->Vpb = NULL; CreatedDeviceObject->StackSize = 1;
KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue); CreatedDeviceObject->AlignmentRequirement = 1; /* FIXME */
KeInitializeEvent( /* Set the Flags */
&CreatedDeviceObject->DeviceLock, /* FIXME: After the Driver is Loaded, the flag below should be removed */
SynchronizationEvent, CreatedDeviceObject->Flags = DO_DEVICE_INITIALIZING;
TRUE); if (Exclusive) CreatedDeviceObject->Flags |= DO_EXCLUSIVE;
if (DeviceName) CreatedDeviceObject->Flags |= DO_DEVICE_HAS_NAME;
/* FIXME: Do we need to add network drives too?! */ /* Attach a Vpb for Disks and Tapes, and create the Device Lock */
if (CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK || if (CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK ||
CreatedDeviceObject->DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM || CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM ||
CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE) CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE)
{ {
IoAttachVpb(CreatedDeviceObject); /* Create Vpb */
IopAttachVpb(CreatedDeviceObject);
/* Initialize Lock Event */
KeInitializeEvent(&CreatedDeviceObject->DeviceLock,
SynchronizationEvent,
TRUE);
} }
CreatedDeviceObject->SectorSize = 512; /* FIXME */
DeviceObjectExtension = /* Set the right Sector Size */
ExAllocatePoolWithTag( switch (DeviceType)
NonPagedPool, {
sizeof(DEVOBJ_EXTENSION), case FILE_DEVICE_DISK_FILE_SYSTEM:
TAG_DEVICE_EXTENSION); case FILE_DEVICE_DISK:
case FILE_DEVICE_VIRTUAL_DISK:
CreatedDeviceObject->SectorSize = 512;
break;
RtlZeroMemory(DeviceObjectExtension, sizeof(DEVOBJ_EXTENSION)); case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
DeviceObjectExtension->Type = 0 /* ?? */; CreatedDeviceObject->SectorSize = 2048;
DeviceObjectExtension->Size = sizeof(DEVOBJ_EXTENSION); break;
DeviceObjectExtension->DeviceObject = CreatedDeviceObject; }
DeviceObjectExtension->DeviceNode = NULL;
CreatedDeviceObject->DeviceObjectExtension = DeviceObjectExtension; /* Create the Device Queue */
KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue);
/* Insert the Object */
Status = ObInsertObject(CreatedDeviceObject,
NULL,
FILE_READ_DATA | FILE_WRITE_DATA,
0,
NULL,
&TempHandle);
if (!NT_SUCCESS(Status))
{
DPRINT1("Cannot insert Device Object into Handle Table\n");
*DeviceObject = NULL;
return Status;
}
/* Now do the final linking */
ObReferenceObject(DriverObject);
CreatedDeviceObject->DriverObject = DriverObject;
CreatedDeviceObject->NextDevice = DriverObject->DeviceObject;
DriverObject->DeviceObject = CreatedDeviceObject;
/* Close the temporary handle, but do an extra reference first so it doesn't die */
ObReferenceObject(CreatedDeviceObject);
NtClose(TempHandle);
/* Return to caller */
*DeviceObject = CreatedDeviceObject; *DeviceObject = CreatedDeviceObject;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View file

@ -30,35 +30,30 @@ IoInitVpbImplementation(VOID)
} }
NTSTATUS NTSTATUS
IoAttachVpb(PDEVICE_OBJECT DeviceObject) STDCALL
IopAttachVpb(PDEVICE_OBJECT DeviceObject)
{ {
PVPB Vpb; PVPB Vpb;
/* Allocate the Vpb */
Vpb = ExAllocatePoolWithTag(NonPagedPool, Vpb = ExAllocatePoolWithTag(NonPagedPool,
sizeof(VPB), sizeof(VPB),
TAG_VPB); TAG_VPB);
if (Vpb == NULL) if (Vpb == NULL) return(STATUS_UNSUCCESSFUL);
{
return(STATUS_UNSUCCESSFUL);
}
Vpb->Type = 0; /* Clear it so we don't waste time manually */
Vpb->Size = sizeof(VPB) / sizeof(DWORD); RtlZeroMemory(Vpb, sizeof(VPB));
Vpb->Flags = 0;
Vpb->VolumeLabelLength = 0; /* Set the Header and Device Field */
Vpb->DeviceObject = NULL; Vpb->Type = IO_TYPE_VPB;
Vpb->Size = sizeof(VPB);
Vpb->RealDevice = DeviceObject; Vpb->RealDevice = DeviceObject;
Vpb->SerialNumber = 0;
Vpb->ReferenceCount = 0;
RtlZeroMemory(Vpb->VolumeLabel,
sizeof(WCHAR) * MAXIMUM_VOLUME_LABEL_LENGTH);
/* link it to the Device Object */
DeviceObject->Vpb = Vpb; DeviceObject->Vpb = Vpb;
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
/* /*
* FUNCTION: Queries the volume information * FUNCTION: Queries the volume information
* ARGUMENTS: * ARGUMENTS: