reactos/reactos/ntoskrnl/io/device.c
Filip Navara bb917ce975 - Support for upper level filter drivers.
NOTE: Although the support for lower level filter driver is very similar, it's practically impossible to incorporate it with the current design without avoiding bugs such as #262 or #263. I don't want to extend the current mess beyond it's borders, so I ommited the call for initializing lower level filter drivers. The code needs a major cleanup and simplification on some places to make this support possible while maintaining a reasonable stable system.

svn path=/trunk/; revision=8830
2004-03-21 18:58:53 +00:00

906 lines
22 KiB
C

/* $Id: device.c,v 1.68 2004/03/21 18:58:53 navaraf Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/io/device.c
* PURPOSE: Manage devices
* PROGRAMMER: David Welch (welch@cwcom.net)
* UPDATE HISTORY:
* 15/05/98: Created
*/
/* INCLUDES ****************************************************************/
#define NTOS_MODE_KERNEL
#include <ntos.h>
#include <internal/io.h>
#include <internal/po.h>
#include <internal/ldr.h>
#include <internal/id.h>
#include <internal/pool.h>
#include <roscfg.h>
#define NDEBUG
//#define DBG
#include <internal/debug.h>
/* GLOBALS *******************************************************************/
#define TAG_DRIVER TAG('D', 'R', 'V', 'R')
#define TAG_DRIVER_EXTENSION TAG('D', 'R', 'V', 'E')
#define TAG_DEVICE_EXTENSION TAG('D', 'E', 'X', 'T')
#define DRIVER_REGISTRY_KEY_BASENAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
/* FUNCTIONS ***************************************************************/
/*
* @implemented
*/
NTSTATUS STDCALL
IoAttachDeviceByPointer(IN PDEVICE_OBJECT SourceDevice,
IN PDEVICE_OBJECT TargetDevice)
{
PDEVICE_OBJECT AttachedDevice;
DPRINT("IoAttachDeviceByPointer(SourceDevice %x, TargetDevice %x)\n",
SourceDevice,
TargetDevice);
AttachedDevice = IoAttachDeviceToDeviceStack (SourceDevice,
TargetDevice);
if (AttachedDevice == NULL)
return STATUS_NO_SUCH_DEVICE;
return STATUS_SUCCESS;
}
/*
* @implemented
*/
VOID STDCALL
IoDeleteDevice(PDEVICE_OBJECT DeviceObject)
{
PDEVICE_OBJECT Previous;
if (DeviceObject->Flags & DO_SHUTDOWN_REGISTERED)
IoUnregisterShutdownNotification(DeviceObject);
/* remove the timer if it exists */
if (DeviceObject->Timer)
{
IoStopTimer(DeviceObject);
ExFreePool(DeviceObject->Timer);
}
/* free device extension */
if (DeviceObject->DeviceObjectExtension)
ExFreePool (DeviceObject->DeviceObjectExtension);
/* remove device from driver device list */
Previous = DeviceObject->DriverObject->DeviceObject;
if (Previous == DeviceObject)
{
DeviceObject->DriverObject->DeviceObject = DeviceObject->NextDevice;
}
else
{
while (Previous->NextDevice != DeviceObject)
Previous = Previous->NextDevice;
Previous->NextDevice = DeviceObject->NextDevice;
}
ObDereferenceObject (DeviceObject);
}
/*
* @implemented
*/
PDEVICE_OBJECT
STDCALL
IoGetRelatedDeviceObject (
IN PFILE_OBJECT FileObject
)
{
/*Win NT File System Internals, page 633-634*/
/*get logical volume mounted on a physical/virtual/logical device*/
if (FileObject->Vpb && FileObject->Vpb->DeviceObject)
{
return IoGetAttachedDevice(FileObject->Vpb->DeviceObject);
}
/*check if fileobject has an associated device object mounted by some other file system*/
if (FileObject->DeviceObject->Vpb && FileObject->DeviceObject->Vpb->DeviceObject)
{
return IoGetAttachedDevice(FileObject->DeviceObject->Vpb->DeviceObject);
}
return IoGetAttachedDevice(FileObject->DeviceObject);
}
/*
* @implemented
*/
NTSTATUS
STDCALL
IoGetDeviceObjectPointer (
IN PUNICODE_STRING ObjectName,
IN ACCESS_MASK DesiredAccess,
OUT PFILE_OBJECT * FileObject,
OUT PDEVICE_OBJECT * DeviceObject)
{
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK StatusBlock;
PFILE_OBJECT LocalFileObject;
HANDLE FileHandle;
NTSTATUS Status;
DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x, FileObject %p DeviceObject %p)\n",
ObjectName,
DesiredAccess,
FileObject,
DeviceObject);
InitializeObjectAttributes (&ObjectAttributes,
ObjectName,
0,
NULL,
NULL);
Status = NtOpenFile (&FileHandle,
DesiredAccess,
&ObjectAttributes,
&StatusBlock,
0,
FILE_NON_DIRECTORY_FILE);
if (!NT_SUCCESS(Status))
return Status;
Status = ObReferenceObjectByHandle (FileHandle,
0,
IoFileObjectType,
KernelMode,
(PVOID*)&LocalFileObject,
NULL);
if (NT_SUCCESS(Status))
{
*DeviceObject = IoGetRelatedDeviceObject (LocalFileObject);
*FileObject = LocalFileObject;
}
NtClose (FileHandle);
return Status;
}
/*
* @unimplemented
*/
VOID
STDCALL
IoDetachDevice(PDEVICE_OBJECT TargetDevice)
{
// UNIMPLEMENTED;
DPRINT("IoDetachDevice(TargetDevice %x) - UNIMPLEMENTED\n", TargetDevice);
}
/*
* @implemented
*/
PDEVICE_OBJECT
STDCALL
IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject)
{
PDEVICE_OBJECT Current = DeviceObject;
// DPRINT("IoGetAttachedDevice(DeviceObject %x)\n",DeviceObject);
while (Current->AttachedDevice!=NULL)
{
Current = Current->AttachedDevice;
// DPRINT("Current %x\n",Current);
}
// DPRINT("IoGetAttachedDevice() = %x\n",DeviceObject);
return(Current);
}
/*
* @implemented
*/
PDEVICE_OBJECT
STDCALL
IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
{
PDEVICE_OBJECT Current = DeviceObject;
while (Current->AttachedDevice!=NULL)
{
Current = Current->AttachedDevice;
}
ObReferenceObject(Current);
return(Current);
}
/*
* @implemented
*/
PDEVICE_OBJECT STDCALL
IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice,
PDEVICE_OBJECT TargetDevice)
{
PDEVICE_OBJECT AttachedDevice;
DPRINT("IoAttachDeviceToDeviceStack(SourceDevice %x, TargetDevice %x)\n",
SourceDevice,TargetDevice);
AttachedDevice = IoGetAttachedDevice(TargetDevice);
AttachedDevice->AttachedDevice = SourceDevice;
SourceDevice->AttachedDevice = NULL;
SourceDevice->StackSize = AttachedDevice->StackSize + 1;
SourceDevice->Vpb = AttachedDevice->Vpb;
return(AttachedDevice);
}
NTSTATUS STDCALL
IopDefaultDispatchFunction(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_NOT_IMPLEMENTED);
}
NTSTATUS
IopCreateDriverObject(PDRIVER_OBJECT *DriverObject,
PUNICODE_STRING ServiceName,
BOOLEAN FileSystem,
PVOID DriverImageStart,
ULONG DriverImageSize)
{
PDRIVER_OBJECT Object;
ULONG i;
WCHAR NameBuffer[MAX_PATH];
UNICODE_STRING DriverName;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
DPRINT("IopCreateDriverObject(%p '%wZ' %x %p %x)\n", DriverObject, ServiceName, FileSystem,
DriverImageStart, DriverImageSize);
*DriverObject = NULL;
/* Create ModuleName string */
if ((ServiceName != NULL) && (ServiceName->Buffer != NULL))
{
if (FileSystem == TRUE)
wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME);
else
wcscpy(NameBuffer, DRIVER_ROOT_NAME);
wcscat(NameBuffer, ServiceName->Buffer);
RtlInitUnicodeString(&DriverName,
NameBuffer);
DPRINT("Driver name: '%wZ'\n", &DriverName);
}
/* Initialize ObjectAttributes for driver object */
InitializeObjectAttributes(&ObjectAttributes,
((ServiceName != NULL) && (ServiceName->Buffer != NULL))? &DriverName : NULL,
OBJ_PERMANENT,
NULL,
NULL);
/* Create driver object */
Status = ObCreateObject(KernelMode,
IoDriverObjectType,
&ObjectAttributes,
KernelMode,
NULL,
sizeof(DRIVER_OBJECT),
0,
0,
(PVOID*)&Object);
if (!NT_SUCCESS(Status))
{
return(Status);
}
/* Create driver extension */
Object->DriverExtension = (PDRIVER_EXTENSION)
ExAllocatePoolWithTag(NonPagedPool,
sizeof(DRIVER_EXTENSION),
TAG_DRIVER_EXTENSION);
if (Object->DriverExtension == NULL)
{
ExFreePool(Object);
return(STATUS_INSUFFICIENT_RESOURCES);
}
RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
Object->Type = InternalDriverType;
Object->DriverStart = DriverImageStart;
Object->DriverSize = DriverImageSize;
for (i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
{
Object->MajorFunction[i] = (PDRIVER_DISPATCH) IopDefaultDispatchFunction;
}
*DriverObject = Object;
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
IopAttachFilterDriversCallback(
PWSTR ValueName,
ULONG ValueType,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext)
{
PDEVICE_NODE DeviceNode = Context;
UNICODE_STRING ServiceName;
PWCHAR Filters;
Filters = ValueData;
while (((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength &&
*Filters != 0)
{
DPRINT1("Filter Driver: %S (%wZ)\n", Filters, &DeviceNode->InstancePath);
ServiceName.Buffer = Filters;
ServiceName.MaximumLength =
ServiceName.Length = wcslen(Filters) * sizeof(WCHAR);
IopInitializeDeviceNodeService(
DeviceNode,
&ServiceName,
FALSE);
Filters += (ServiceName.Length / sizeof(WCHAR)) + 1;
}
return STATUS_SUCCESS;
}
NTSTATUS
IopAttachFilterDrivers(
PDEVICE_NODE DeviceNode,
BOOLEAN Lower)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
PWCHAR KeyBuffer;
UNICODE_STRING Class;
WCHAR ClassBuffer[40];
NTSTATUS Status;
/*
* First load the device filters
*/
QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback;
if (Lower)
QueryTable[0].Name = L"LowerFilters";
else
QueryTable[0].Name = L"UpperFilters";
QueryTable[0].EntryContext = NULL;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[1].QueryRoutine = NULL;
QueryTable[1].Name = NULL;
KeyBuffer = ExAllocatePool(
PagedPool,
(49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer);
RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
KeyBuffer,
QueryTable,
DeviceNode,
NULL);
/*
* Now get the class GUID
*/
Class.Length = 0;
Class.MaximumLength = 40 * sizeof(WCHAR);
Class.Buffer = ClassBuffer;
QueryTable[0].QueryRoutine = NULL;
QueryTable[0].Name = L"ClassGUID";
QueryTable[0].EntryContext = &Class;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
Status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
KeyBuffer,
QueryTable,
DeviceNode,
NULL);
ExFreePool(KeyBuffer);
/*
* Load the class filter driver
*/
if (NT_SUCCESS(Status))
{
QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback;
if (Lower)
QueryTable[0].Name = L"LowerFilters";
else
QueryTable[0].Name = L"UpperFilters";
QueryTable[0].EntryContext = NULL;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
KeyBuffer = ExAllocatePool(PagedPool, (58 * sizeof(WCHAR)) + Class.Length);
wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\");
wcscat(KeyBuffer, ClassBuffer);
RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
KeyBuffer,
QueryTable,
DeviceNode,
NULL);
ExFreePool(KeyBuffer);
}
return STATUS_SUCCESS;
}
NTSTATUS
IopInitializeDevice(PDEVICE_NODE DeviceNode,
BOOLEAN BootDriver)
{
IO_STATUS_BLOCK IoStatusBlock;
PDRIVER_OBJECT DriverObject;
IO_STACK_LOCATION Stack;
PDEVICE_OBJECT Fdo;
NTSTATUS Status;
DriverObject = DeviceNode->DriverObject;
if (DriverObject->DriverExtension->AddDevice)
{
/* This is a Plug and Play driver */
DPRINT("Plug and Play driver found\n");
assert(DeviceNode->Pdo);
DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
DriverObject->DriverExtension->AddDevice);
Status = DriverObject->DriverExtension->AddDevice(
DriverObject, DeviceNode->Pdo);
if (!NT_SUCCESS(Status))
{
return(Status);
}
IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
Fdo = IoGetAttachedDeviceReference(DeviceNode->Pdo);
if (Fdo == DeviceNode->Pdo)
{
/* FIXME: What do we do? Unload the driver or just disable the device? */
DbgPrint("An FDO was not attached\n");
KEBUGCHECK(0);
}
/* FIXME: Put some resources in the IRP for the device */
Stack.Parameters.StartDevice.AllocatedResources = NULL;
Stack.Parameters.StartDevice.AllocatedResourcesTranslated = NULL;
Status = IopInitiatePnpIrp(
Fdo,
&IoStatusBlock,
IRP_MN_START_DEVICE,
&Stack);
if (!NT_SUCCESS(Status))
{
DPRINT("IopInitiatePnpIrp() failed\n");
ObDereferenceObject(Fdo);
return(Status);
}
if (Fdo->DeviceType == FILE_DEVICE_BUS_EXTENDER)
{
DPRINT("Bus extender found\n");
Status = IopInvalidateDeviceRelations(
DeviceNode, BusRelations, BootDriver);
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(Fdo);
return(Status);
}
}
else if (Fdo->DeviceType == FILE_DEVICE_ACPI)
{
#ifdef ACPI
static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
/* There can be only one system power device */
if (!SystemPowerDeviceNodeCreated)
{
PopSystemPowerDeviceNode = DeviceNode;
SystemPowerDeviceNodeCreated = TRUE;
}
#endif /* ACPI */
}
ObDereferenceObject(Fdo);
}
return STATUS_SUCCESS;
}
NTSTATUS
IopInitializeService(
PDEVICE_NODE DeviceNode,
PUNICODE_STRING ServiceName,
PUNICODE_STRING ImagePath)
{
PMODULE_OBJECT ModuleObject;
NTSTATUS Status;
ModuleObject = LdrGetModuleObject(ServiceName);
if (ModuleObject == NULL)
{
/* The module is currently not loaded, so load it now */
Status = LdrLoadModule(ImagePath, &ModuleObject);
if (!NT_SUCCESS(Status))
{
/* FIXME: Log the error */
CPRINT("Driver load failed\n");
return(Status);
}
Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode, FALSE,
ModuleObject->Base, ModuleObject->Length,
FALSE);
if (!NT_SUCCESS(Status))
{
LdrUnloadModule(ModuleObject);
/* FIXME: Log the error */
CPRINT("A driver failed to initialize\n");
return(Status);
}
} else
{
/* FIXME: This doesn't work for two devices with the same driver */
Status = IopInitializeDevice(DeviceNode, FALSE);
}
return(Status);
}
NTSTATUS
IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry,
PDEVICE_NODE DeviceNode,
BOOLEAN FileSystemDriver,
PVOID DriverImageStart,
ULONG DriverImageSize,
BOOLEAN BootDriver)
/*
* FUNCTION: Called to initalize a loaded driver
* ARGUMENTS:
* DriverEntry = Pointer to driver entry routine
* DeviceNode = Pointer to device node
*/
{
WCHAR RegistryKeyBuffer[MAX_PATH];
PDRIVER_OBJECT DriverObject;
UNICODE_STRING RegistryKey;
NTSTATUS Status;
DPRINT("IopInitializeDriver(DriverEntry %08lx, DeviceNode %08lx)\n",
DriverEntry, DeviceNode);
Status = IopCreateDriverObject(&DriverObject,
&DeviceNode->ServiceName,
FileSystemDriver,
DriverImageStart,
DriverImageSize);
if (!NT_SUCCESS(Status))
{
return(Status);
}
DeviceNode->DriverObject = DriverObject;
if (DeviceNode->ServiceName.Buffer)
{
wcscpy(RegistryKeyBuffer, DRIVER_REGISTRY_KEY_BASENAME);
wcscat(RegistryKeyBuffer, DeviceNode->ServiceName.Buffer);
RtlInitUnicodeString(&RegistryKey, RegistryKeyBuffer);
}
else
{
RtlInitUnicodeString(&RegistryKey, NULL);
}
DPRINT("RegistryKey: %wZ\n", &RegistryKey);
DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry);
IopMarkLastReinitializeDriver();
Status = DriverEntry(DriverObject, &RegistryKey);
if (!NT_SUCCESS(Status))
{
DeviceNode->DriverObject = NULL;
ExFreePool(DriverObject->DriverExtension);
ObMakeTemporaryObject(DriverObject);
ObDereferenceObject(DriverObject);
return(Status);
}
IopReinitializeDrivers();
Status = IopInitializeDevice(DeviceNode, BootDriver);
return(Status);
}
/*
* @implemented
*/
NTSTATUS STDCALL
IoAttachDevice(PDEVICE_OBJECT SourceDevice,
PUNICODE_STRING TargetDeviceName,
PDEVICE_OBJECT* AttachedDevice)
/*
* FUNCTION: Layers a device over the highest device in a device stack
* ARGUMENTS:
* SourceDevice = Device to attached
* TargetDevice = Name of the target device
* AttachedDevice (OUT) = Caller storage for the device attached to
*/
{
NTSTATUS Status;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT TargetDevice;
Status = IoGetDeviceObjectPointer(TargetDeviceName,
FILE_READ_ATTRIBUTES,
&FileObject,
&TargetDevice);
if (!NT_SUCCESS(Status))
{
return Status;
}
*AttachedDevice = IoAttachDeviceToDeviceStack(SourceDevice,
TargetDevice);
ObDereferenceObject(FileObject);
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
IopCreateDevice(PVOID ObjectBody,
PVOID Parent,
PWSTR RemainingPath,
POBJECT_ATTRIBUTES ObjectAttributes)
{
DPRINT("IopCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
ObjectBody, Parent, RemainingPath);
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
{
return(STATUS_UNSUCCESSFUL);
}
return(STATUS_SUCCESS);
}
/*
* @implemented
*/
NTSTATUS STDCALL
IoCreateDevice(PDRIVER_OBJECT DriverObject,
ULONG DeviceExtensionSize,
PUNICODE_STRING DeviceName,
DEVICE_TYPE DeviceType,
ULONG DeviceCharacteristics,
BOOLEAN Exclusive,
PDEVICE_OBJECT* DeviceObject)
/*
* FUNCTION: Allocates memory for and intializes a device object for use for
* a driver
* ARGUMENTS:
* DriverObject : Driver object passed by iomgr when the driver was
* loaded
* DeviceExtensionSize : Number of bytes for the device extension
* DeviceName : Unicode name of device
* DeviceType : Device type
* DeviceCharacteristics : Bit mask of device characteristics
* Exclusive : True if only one thread can access the device at a
* time
* RETURNS:
* Success or failure
* DeviceObject : Contains a pointer to allocated device object
* if the call succeeded
* NOTES: See the DDK documentation for more information
*/
{
PDEVICE_OBJECT CreatedDeviceObject;
PDEVOBJ_EXTENSION DeviceObjectExtension;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
assert_irql(PASSIVE_LEVEL);
if (DeviceName != NULL)
{
DPRINT("IoCreateDevice(DriverObject %x, DeviceName %S)\n",DriverObject,
DeviceName->Buffer);
}
else
{
DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject);
}
if (DeviceName != NULL)
{
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;
if (!NT_SUCCESS(Status))
{
DPRINT("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status);
return(Status);
}
if (DriverObject->DeviceObject == NULL)
{
DriverObject->DeviceObject = 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);
}
CreatedDeviceObject->Size = sizeof(DEVICE_OBJECT) + DeviceExtensionSize;
CreatedDeviceObject->ReferenceCount = 1;
CreatedDeviceObject->AttachedDevice = NULL;
CreatedDeviceObject->DeviceType = DeviceType;
CreatedDeviceObject->StackSize = 1;
CreatedDeviceObject->AlignmentRequirement = 1;
CreatedDeviceObject->Characteristics = DeviceCharacteristics;
CreatedDeviceObject->Timer = NULL;
CreatedDeviceObject->Vpb = NULL;
KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue);
KeInitializeEvent(&CreatedDeviceObject->DeviceLock,
SynchronizationEvent,
TRUE);
/* FIXME: Do we need to add network drives too?! */
if (CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK ||
CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM ||
CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE)
{
IoAttachVpb(CreatedDeviceObject);
}
DeviceObjectExtension =
ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVOBJ_EXTENSION),
TAG_DEVICE_EXTENSION);
DeviceObjectExtension->Type = 0 /* ?? */;
DeviceObjectExtension->Size = sizeof(DEVOBJ_EXTENSION);
DeviceObjectExtension->DeviceObject = CreatedDeviceObject;
DeviceObjectExtension->DeviceNode = NULL;
CreatedDeviceObject->DeviceObjectExtension = DeviceObjectExtension;
*DeviceObject = CreatedDeviceObject;
return(STATUS_SUCCESS);
}
NTSTATUS
STDCALL
IoOpenDeviceInstanceKey (
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3,
DWORD Unknown4
)
{
UNIMPLEMENTED;
return(STATUS_NOT_IMPLEMENTED);
}
DWORD
STDCALL
IoQueryDeviceEnumInfo (
DWORD Unknown0,
DWORD Unknown1
)
{
UNIMPLEMENTED;
return 0;
}
/* EOF */