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,157 +647,169 @@ 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,
ULONG DeviceCharacteristics, ULONG DeviceCharacteristics,
BOOLEAN Exclusive, BOOLEAN Exclusive,
PDEVICE_OBJECT *DeviceObject) PDEVICE_OBJECT *DeviceObject)
{ {
WCHAR AutoNameBuffer[20]; WCHAR AutoNameBuffer[20];
UNICODE_STRING AutoName; UNICODE_STRING AutoName;
PDEVICE_OBJECT CreatedDeviceObject; PDEVICE_OBJECT CreatedDeviceObject;
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);
DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject);
if (DeviceName != NULL) /* Generate a name if we have to */
{ if (DeviceCharacteristics & FILE_AUTOGENERATED_DEVICE_NAME)
DPRINT("IoCreateDevice(DriverObject %x, DeviceName %S)\n", {
DriverObject, DeviceName->Buffer); swprintf(AutoNameBuffer,
} L"\\Device\\%08lx",
else InterlockedIncrementUL(&IopDeviceObjectNumber));
{ RtlInitUnicodeString(&AutoName, AutoNameBuffer);
DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject); DeviceName = &AutoName;
} }
if (DeviceCharacteristics & FILE_AUTOGENERATED_DEVICE_NAME) /* Initialize the Object Attributes */
{ InitializeObjectAttributes(&ObjectAttributes, DeviceName, 0, NULL, NULL);
swprintf(AutoNameBuffer,
L"\\Device\\%08lx",
InterlockedIncrementUL(&IopDeviceObjectNumber));
RtlInitUnicodeString(&AutoName,
AutoNameBuffer);
DeviceName = &AutoName;
}
if (DeviceName != NULL) /* Honour exclusive flag */
{ ObjectAttributes.Attributes |= OBJ_EXCLUSIVE;
InitializeObjectAttributes(&ObjectAttributes, DeviceName, 0, NULL, NULL);
Status = ObCreateObject(
KernelMode,
IoDeviceObjectType,
&ObjectAttributes,
KernelMode,
NULL,
sizeof(DEVICE_OBJECT),
0,
0,
(PVOID*)&CreatedDeviceObject);
}
else
{
Status = ObCreateObject(
KernelMode,
IoDeviceObjectType,
NULL,
KernelMode,
NULL,
sizeof(DEVICE_OBJECT),
0,
0,
(PVOID*)&CreatedDeviceObject);
}
*DeviceObject = NULL; /* Align the Extension Size to 8-bytes */
AlignedDeviceExtensionSize = (DeviceExtensionSize + 7) &~ 7;
DPRINT("AlignedDeviceExtensionSize %x\n", AlignedDeviceExtensionSize);
if (!NT_SUCCESS(Status)) /* Total Size */
{ TotalSize = AlignedDeviceExtensionSize +
DPRINT("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status); sizeof(DEVICE_OBJECT) + sizeof(DEVOBJ_EXTENSION);
return Status; DPRINT("TotalSize %x\n", TotalSize);
}
if (DriverObject->DeviceObject == NULL) /* Create the Device Object */
{ Status = ObCreateObject(KernelMode,
DriverObject->DeviceObject = CreatedDeviceObject; IoDeviceObjectType,
CreatedDeviceObject->NextDevice = NULL; &ObjectAttributes,
} KernelMode,
else NULL,
{ TotalSize,
CreatedDeviceObject->NextDevice = DriverObject->DeviceObject; 0,
DriverObject->DeviceObject = CreatedDeviceObject; 0,
} (PVOID*)&CreatedDeviceObject);
CreatedDeviceObject->Type = DeviceType; if (!NT_SUCCESS(Status))
CreatedDeviceObject->DriverObject = DriverObject; {
CreatedDeviceObject->CurrentIrp = NULL; DPRINT1("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status);
CreatedDeviceObject->Flags = 0; return Status;
}
CreatedDeviceObject->DeviceExtension = /* Clear the whole Object and extension so we don't null stuff manually */
ExAllocatePoolWithTag( RtlZeroMemory(CreatedDeviceObject, TotalSize);
NonPagedPool, DPRINT("CreatedDeviceObject %x\n", CreatedDeviceObject);
DeviceExtensionSize,
TAG_DEVICE_EXTENSION);
if (DeviceExtensionSize > 0 && CreatedDeviceObject->DeviceExtension == NULL) /*
{ * Setup the Type and Size. Note that we don't use the aligned size,
ExFreePool(CreatedDeviceObject); * because that's only padding for the DevObjExt and not part of the Object.
DPRINT("IoCreateDevice() ExAllocatePoolWithTag failed, returning: 0x%08X\n", STATUS_INSUFFICIENT_RESOURCES); */
return STATUS_INSUFFICIENT_RESOURCES; CreatedDeviceObject->Type = IO_TYPE_DEVICE;
} CreatedDeviceObject->Size = sizeof(DEVICE_OBJECT) + DeviceExtensionSize;
if (DeviceExtensionSize > 0) /* The kernel extension is after the driver internal extension */
{ DeviceObjectExtension = (PDEVOBJ_EXTENSION)
RtlZeroMemory(CreatedDeviceObject->DeviceExtension, DeviceExtensionSize); ((ULONG_PTR)(CreatedDeviceObject + 1) +
} AlignedDeviceExtensionSize);
CreatedDeviceObject->Size = sizeof(DEVICE_OBJECT) + DeviceExtensionSize; /* Set the Type and Size. Question: why is Size 0 on Windows? */
CreatedDeviceObject->ReferenceCount = 1; DPRINT("DeviceObjectExtension %x\n", DeviceObjectExtension);
CreatedDeviceObject->AttachedDevice = NULL; DeviceObjectExtension->Type = IO_TYPE_DEVICE_OBJECT_EXTENSION;
CreatedDeviceObject->DeviceType = DeviceType; DeviceObjectExtension->Size = 0;
CreatedDeviceObject->StackSize = 1;
CreatedDeviceObject->AlignmentRequirement = 1;
CreatedDeviceObject->Characteristics = DeviceCharacteristics;
CreatedDeviceObject->Timer = NULL;
CreatedDeviceObject->Vpb = NULL;
KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue);
KeInitializeEvent( /* Link the Object and Extension */
&CreatedDeviceObject->DeviceLock, DeviceObjectExtension->DeviceObject = CreatedDeviceObject;
SynchronizationEvent, CreatedDeviceObject->DeviceObjectExtension = DeviceObjectExtension;
TRUE);
/* FIXME: Do we need to add network drives too?! */ /* Set Device Object Data */
if (CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK || CreatedDeviceObject->DeviceType = DeviceType;
CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM || CreatedDeviceObject->Characteristics = DeviceCharacteristics;
CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE) CreatedDeviceObject->DeviceExtension = CreatedDeviceObject + 1;
{ CreatedDeviceObject->StackSize = 1;
IoAttachVpb(CreatedDeviceObject); CreatedDeviceObject->AlignmentRequirement = 1; /* FIXME */
}
CreatedDeviceObject->SectorSize = 512; /* FIXME */
DeviceObjectExtension = /* Set the Flags */
ExAllocatePoolWithTag( /* FIXME: After the Driver is Loaded, the flag below should be removed */
NonPagedPool, CreatedDeviceObject->Flags = DO_DEVICE_INITIALIZING;
sizeof(DEVOBJ_EXTENSION), if (Exclusive) CreatedDeviceObject->Flags |= DO_EXCLUSIVE;
TAG_DEVICE_EXTENSION); if (DeviceName) CreatedDeviceObject->Flags |= DO_DEVICE_HAS_NAME;
RtlZeroMemory(DeviceObjectExtension, sizeof(DEVOBJ_EXTENSION)); /* Attach a Vpb for Disks and Tapes, and create the Device Lock */
DeviceObjectExtension->Type = 0 /* ?? */; if (CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK ||
DeviceObjectExtension->Size = sizeof(DEVOBJ_EXTENSION); CreatedDeviceObject->DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
DeviceObjectExtension->DeviceObject = CreatedDeviceObject; CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM ||
DeviceObjectExtension->DeviceNode = NULL; CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE)
{
/* Create Vpb */
IopAttachVpb(CreatedDeviceObject);
CreatedDeviceObject->DeviceObjectExtension = DeviceObjectExtension; /* Initialize Lock Event */
KeInitializeEvent(&CreatedDeviceObject->DeviceLock,
SynchronizationEvent,
TRUE);
}
*DeviceObject = CreatedDeviceObject; /* Set the right Sector Size */
switch (DeviceType)
{
case FILE_DEVICE_DISK_FILE_SYSTEM:
case FILE_DEVICE_DISK:
case FILE_DEVICE_VIRTUAL_DISK:
CreatedDeviceObject->SectorSize = 512;
break;
return STATUS_SUCCESS; case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
CreatedDeviceObject->SectorSize = 2048;
break;
}
/* 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;
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;
Vpb = ExAllocatePoolWithTag(NonPagedPool, /* Allocate the Vpb */
sizeof(VPB), Vpb = ExAllocatePoolWithTag(NonPagedPool,
TAG_VPB); sizeof(VPB),
if (Vpb == NULL) TAG_VPB);
{ 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;
Vpb->DeviceObject = NULL;
Vpb->RealDevice = DeviceObject;
Vpb->SerialNumber = 0;
Vpb->ReferenceCount = 0;
RtlZeroMemory(Vpb->VolumeLabel,
sizeof(WCHAR) * MAXIMUM_VOLUME_LABEL_LENGTH);
DeviceObject->Vpb = Vpb; /* Set the Header and Device Field */
Vpb->Type = IO_TYPE_VPB;
Vpb->Size = sizeof(VPB);
Vpb->RealDevice = DeviceObject;
return(STATUS_SUCCESS); /* link it to the Device Object */
DeviceObject->Vpb = Vpb;
return(STATUS_SUCCESS);
} }
/* /*
* FUNCTION: Queries the volume information * FUNCTION: Queries the volume information
* ARGUMENTS: * ARGUMENTS: