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