* PROJECT: ReactOS kernel
* FILE: ntoskrnl/io/driver.c
* PURPOSE: Loading and unloading of drivers
- *
+ *
* PROGRAMMERS: David Welch (welch@cwcom.net)
* Filip Navara (xnavara@volny.cz)
*/
/* ke/main.c */
extern LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock;
extern ULONG KeTickCount;
+extern BOOLEAN SetupMode;
NTSTATUS
LdrProcessModule(PVOID ModuleLoadBase,
POBJECT_TYPE EXPORTED IoDriverObjectType = NULL;
-#define TAG_DRIVER TAG('D', 'R', 'V', 'R')
-#define TAG_DRIVER_EXTENSION TAG('D', 'R', 'V', 'E')
-
/* DECLARATIONS ***************************************************************/
-NTSTATUS STDCALL
-IopCreateDriver(
- PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- POBJECT_ATTRIBUTES ObjectAttributes);
-
VOID STDCALL
IopDeleteDriver(PVOID ObjectBody);
/* PRIVATE FUNCTIONS **********************************************************/
-VOID INIT_FUNCTION
+VOID
+INIT_FUNCTION
IopInitDriverImplementation(VOID)
{
- /* Register the process object type */
- IoDriverObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
- IoDriverObjectType->Tag = TAG('D', 'R', 'V', 'R');
- IoDriverObjectType->TotalObjects = 0;
- IoDriverObjectType->TotalHandles = 0;
- IoDriverObjectType->PeakObjects = 0;
- IoDriverObjectType->PeakHandles = 0;
- IoDriverObjectType->PagedPoolCharge = 0;
- IoDriverObjectType->NonpagedPoolCharge = sizeof(DRIVER_OBJECT);
- IoDriverObjectType->Dump = NULL;
- IoDriverObjectType->Open = NULL;
- IoDriverObjectType->Close = NULL;
- IoDriverObjectType->Delete = IopDeleteDriver;
- IoDriverObjectType->Parse = NULL;
- IoDriverObjectType->Security = NULL;
- IoDriverObjectType->QueryName = NULL;
- IoDriverObjectType->OkayToClose = NULL;
- IoDriverObjectType->Create = IopCreateDriver;
- IoDriverObjectType->DuplicationNotify = NULL;
- RtlInitUnicodeString(&IoDriverObjectType->TypeName, L"Driver");
-
- ObpCreateTypeObject(IoDriverObjectType);
+ OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+ UNICODE_STRING Name;
+
+ DPRINT1("Creating Registry Object Type\n");
+
+ /* Initialize the Driver object type */
+ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+ RtlInitUnicodeString(&Name, L"Driver");
+ ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+ ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DRIVER_OBJECT);
+ ObjectTypeInitializer.PoolType = NonPagedPool;
+ ObjectTypeInitializer.UseDefaultObject = TRUE;
+ ObjectTypeInitializer.DeleteProcedure = IopDeleteDriver;
+
+ ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoDriverObjectType);
InitializeListHead(&DriverReinitListHead);
KeInitializeSpinLock(&DriverReinitListLock);
DriverReinitTailEntry = NULL;
-
+
InitializeListHead(&DriverBootReinitListHead);
KeInitializeSpinLock(&DriverBootReinitListLock);
DriverBootReinitTailEntry = NULL;
return STATUS_INVALID_DEVICE_REQUEST;
}
-NTSTATUS STDCALL
-IopCreateDriver(
- PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- POBJECT_ATTRIBUTES ObjectAttributes)
-{
- PDRIVER_OBJECT Object = ObjectBody;
- ULONG i;
-
- DPRINT("IopCreateDriver(ObjectBody %x, Parent %x, RemainingPath %S)\n",
- ObjectBody, Parent, RemainingPath);
-
- if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
- return STATUS_UNSUCCESSFUL;
-
- /* Create driver extension */
- Object->DriverExtension = (PDRIVER_EXTENSION)
- ExAllocatePoolWithTag(
- NonPagedPool,
- sizeof(DRIVER_EXTENSION),
- TAG_DRIVER_EXTENSION);
-
- if (Object->DriverExtension == NULL)
- {
- return STATUS_NO_MEMORY;
- }
-
- RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
-
- Object->Type = IO_TYPE_DRIVER;
-
- for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
- Object->MajorFunction[i] = IopInvalidDeviceRequest;
-
- Object->HardwareDatabase = &IopHardwareDatabaseKey;
-
- return STATUS_SUCCESS;
-}
-
VOID STDCALL
IopDeleteDriver(PVOID ObjectBody)
{
KfLowerIrql(OldIrql);
}
+NTSTATUS FASTCALL
+IopGetDriverObject(
+ PDRIVER_OBJECT *DriverObject,
+ PUNICODE_STRING ServiceName,
+ BOOLEAN FileSystem)
+{
+ PDRIVER_OBJECT Object;
+ WCHAR NameBuffer[MAX_PATH];
+ UNICODE_STRING DriverName;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+
+ DPRINT("IopOpenDriverObject(%p '%wZ' %x)\n",
+ DriverObject, ServiceName, FileSystem);
+
+ *DriverObject = NULL;
+
+ /* Create ModuleName string */
+ if (ServiceName == NULL || ServiceName->Buffer == NULL)
+ /* We don't know which DriverObject we have to open */
+ return STATUS_INVALID_PARAMETER_2;
+
+ 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,
+ &DriverName,
+ OBJ_OPENIF | OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+
+ /* Open driver object */
+ Status = ObReferenceObjectByName(
+ &DriverName,
+ 0, /* Attributes */
+ NULL, /* PassedAccessState */
+ 0, /* DesiredAccess */
+ IoDriverObjectType,
+ KernelMode,
+ NULL, /* ParseContext */
+ (PVOID*)&Object);
+
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ *DriverObject = Object;
+
+ return STATUS_SUCCESS;
+}
+
NTSTATUS FASTCALL
IopCreateDriverObject(
PDRIVER_OBJECT *DriverObject,
UNICODE_STRING DriverName;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
+ ULONG i;
PWSTR Buffer = NULL;
DPRINT("IopCreateDriverObject(%p '%wZ' %x %p %x)\n",
RtlInitUnicodeString(&DriverName, NameBuffer);
DPRINT("Driver name: '%wZ'\n", &DriverName);
-
+
Buffer = (PWSTR)ExAllocatePool(NonPagedPool, DriverName.Length);
/* If we don't success, it is not a problem. Our driver
* object will not have associated driver name... */
return Status;
}
+ Status = ObInsertObject(Object,
+ NULL,
+ FILE_ALL_ACCESS,
+ 0,
+ NULL,
+ NULL);
+ 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)
+ {
+ return STATUS_NO_MEMORY;
+ }
+
+ RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
+
+ Object->Type = IO_TYPE_DRIVER;
+
+ for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
+ Object->MajorFunction[i] = IopInvalidDeviceRequest;
+
+ Object->HardwareDatabase = &IopHardwareDatabaseKey;
+
Object->DriverStart = DriverImageStart;
Object->DriverSize = DriverImageSize;
if (Buffer)
* Display 'Loading XXX...' message.
*/
-VOID FASTCALL
-IopDisplayLoadingMessage(PWCHAR ServiceName)
+VOID
+FASTCALL
+INIT_FUNCTION
+IopDisplayLoadingMessage(PVOID ServiceName,
+ BOOLEAN Unicode)
{
- CHAR TextBuffer[256];
- sprintf(TextBuffer, "Loading %S...\n", ServiceName);
- HalDisplayString(TextBuffer);
+ if (SetupMode) return;
+ CHAR TextBuffer[256];
+ if (Unicode)
+ {
+ sprintf(TextBuffer, "Loading %S...\n", (PWCHAR)ServiceName);
+ }
+ else
+ {
+ sprintf(TextBuffer, "Loading %s...\n", (PCHAR)ServiceName);
+ }
+ HalDisplayString(TextBuffer);
}
/*
DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status);
return Status;
}
-
- IopDisplayLoadingMessage(ServiceName->Buffer);
+
+ IopDisplayLoadingMessage(ServiceName->Buffer, TRUE);
/*
* Normalize the image path for all later processing.
UNICODE_STRING RegistryKey;
PDRIVER_INITIALIZE DriverEntry;
NTSTATUS Status;
-
+
DriverEntry = ModuleObject->EntryPoint;
-
+
if (ServiceName != NULL && ServiceName->Length != 0)
{
RegistryKey.Length = 0;
IopMarkLastReinitializeDriver();
Status = DriverEntry(*DriverObject, &RegistryKey);
-
+
RtlFreeUnicodeString(&RegistryKey);
-
+
if (!NT_SUCCESS(Status))
{
ObMakeTemporaryObject(*DriverObject);
PMODULE_OBJECT ModuleObject;
PDRIVER_OBJECT DriverObject;
NTSTATUS Status;
-
+
for (Filters = ValueData;
((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength &&
*Filters != 0;
{
DPRINT("Filter Driver: %S (%wZ)\n", Filters, &DeviceNode->InstancePath);
ServiceName.Buffer = Filters;
- ServiceName.MaximumLength =
+ ServiceName.MaximumLength =
ServiceName.Length = wcslen(Filters) * sizeof(WCHAR);
/* Load and initialize the filter driver */
else
{
/* get existing DriverObject pointer */
- Status = IopCreateDriverObject(
+ Status = IopGetDriverObject(
&DriverObject,
&ServiceName,
- OBJ_OPENIF,
- FALSE,
- ModuleObject->Base,
- ModuleObject->Length);
+ FALSE);
if (!NT_SUCCESS(Status))
continue;
}
/*
* First load the device filters
*/
-
+
QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback;
if (Lower)
QueryTable[0].Name = L"LowerFilters";
QueryTable[1].Name = NULL;
KeyBuffer = ExAllocatePool(
- PagedPool,
+ PagedPool,
(49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
- wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer);
+ wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer);
RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
ExFreePool(KeyBuffer);
}
-
+
return STATUS_SUCCESS;
}
-static NTSTATUS STDCALL
+static NTSTATUS STDCALL
IopGetGroupOrderList(PWSTR ValueName,
ULONG ValueType,
PVOID ValueData,
NULL);
if (!NT_SUCCESS(Status) || Service->Start > 1)
{
- ExFreePool(Service->ServiceGroup.Buffer);
- ExFreePool(Service->ImagePath.Buffer);
+ /*
+ * If something goes wrong during RtlQueryRegistryValues
+ * it'll just drop everything on the floor and return,
+ * so you have to check if the buffers were filled.
+ * Luckily we zerofilled the Service.
+ */
+ if (Service->ServiceGroup.Buffer)
+ {
+ ExFreePool(Service->ServiceGroup.Buffer);
+ }
+ if (Service->ImagePath.Buffer)
+ {
+ ExFreePool(Service->ImagePath.Buffer);
+ }
ExFreePool(Service);
return(Status);
}
PDEVICE_NODE DeviceNode;
PDRIVER_OBJECT DriverObject;
NTSTATUS Status;
- CHAR TextBuffer[256];
PCHAR FileNameWithoutPath;
LPWSTR FileExtension;
FileName, ModuleLoadBase, ModuleLength);
/*
- * Display 'Initializing XXX...' message
+ * Display 'Loading XXX...' message
*/
-
- sprintf(TextBuffer, "Initializing %s...\n", FileName);
- HalDisplayString(TextBuffer);
+ IopDisplayLoadingMessage(FileName, FALSE);
/*
* Determine the right device object
Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
&DeviceNode->ServiceName, FALSE, &DriverObject);
-
+
if (!NT_SUCCESS(Status))
{
if (ModuleDeviceNode == NULL)
}
Status = IopInitializeDevice(DeviceNode, DriverObject);
+ if (NT_SUCCESS(Status))
+ {
+ Status = IopStartDevice(DeviceNode);
+ }
return Status;
}
*
* Parameters
* None
- *
+ *
* Return Value
* None
*/
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
- IopDisplayLoadingMessage(Service->ServiceName.Buffer);
+ IopDisplayLoadingMessage(Service->ServiceName.Buffer, TRUE);
Status = ZwLoadDriver(&Service->RegistryPath);
IopBootLog(&Service->ImagePath, NT_SUCCESS(Status) ? TRUE : FALSE);
if (!NT_SUCCESS(Status))
if (Service->ErrorControl == 1)
{
/* Log error */
- }
+ }
else if (Service->ErrorControl == 2)
{
if (IsLastKnownGood == FALSE)
{
/* Boot last known good configuration */
}
- }
+ }
else if (Service->ErrorControl == 3)
{
if (IsLastKnownGood == FALSE)
{
/* Boot last known good configuration */
- }
+ }
else
{
/* BSOD! */
*
* Parameters
* None
- *
+ *
* Return Value
* None
*/
DPRINT("Group: %wZ\n", &CurrentGroup->GroupName);
- /* Load all drivers with a valid tag */
+ /* Load all drivers with a valid tag */
for (i = 0; i < CurrentGroup->TagCount; i++)
{
ServiceEntry = ServiceListHead.Flink;
* Whether to unload Plug & Plug or only legacy drivers. If this
* parameter is set to FALSE, the routine will unload only legacy
* drivers.
- *
+ *
* Return Value
* Status
*
UNICODE_STRING ServiceKeyName;
HANDLE hDriver;
ULONG i;
-
+
/* First, create a unique name for the driver if we don't have one */
if (!DriverName) {
-
+
/* Create a random name and set up the string*/
NameLength = swprintf(NameBuffer, L"\\Driver\\%08u", KeTickCount);
LocalDriverName.Length = NameLength * sizeof(WCHAR);
LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL);
LocalDriverName.Buffer = NameBuffer;
-
+
} else {
-
+
/* So we can avoid another code path, use a local var */
LocalDriverName = *DriverName;
}
-
+
/* Initialize the Attributes */
ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(DRIVER_EXTENSION);
InitializeObjectAttributes(&ObjectAttributes,
OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
NULL,
NULL);
-
+
/* Create the Object */
Status = ObCreateObject(KernelMode,
IoDriverObjectType,
0,
0,
(PVOID*)&DriverObject);
-
+
/* Return on failure */
if (!NT_SUCCESS(Status)) return Status;
-
+
/* Set up the Object */
RtlZeroMemory(DriverObject, ObjectSize);
DriverObject->Type = IO_TYPE_DRIVER;
DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1);
DriverObject->DriverExtension->DriverObject = DriverObject;
DriverObject->DriverInit = InitializationFunction;
-
+
/* Invalidate all Major Functions */
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
{
DriverObject->MajorFunction[i] = IopInvalidDeviceRequest;
}
-
+
/* Set up the Service Key Name */
ServiceKeyName.Buffer = ExAllocatePool(PagedPool, LocalDriverName.Length + sizeof(WCHAR));
ServiceKeyName.Length = LocalDriverName.Length;
RtlMoveMemory(ServiceKeyName.Buffer, LocalDriverName.Buffer, LocalDriverName.Length);
ServiceKeyName.Buffer[ServiceKeyName.Length / sizeof(WCHAR)] = L'\0';
DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName;
-
+
/* Also store it in the Driver Object. This is a bit of a hack. */
RtlMoveMemory(&DriverObject->DriverName, &ServiceKeyName, sizeof(UNICODE_STRING));
-
+
/* Add the Object and get its handle */
Status = ObInsertObject(DriverObject,
NULL,
0,
NULL,
&hDriver);
-
+
/* Return on Failure */
if (!NT_SUCCESS(Status)) return Status;
-
+
/* Now reference it */
Status = ObReferenceObjectByHandle(hDriver,
0,
(PVOID*)&DriverObject,
NULL);
ZwClose(hDriver);
-
+
/* Finally, call its init function */
Status = (*InitializationFunction)(DriverObject, NULL);
-
+
if (!NT_SUCCESS(Status)) {
/* If it didn't work, then kill the object */
ObMakeTemporaryObject(DriverObject);
ObDereferenceObject(DriverObject);
}
-
+
/* Return the Status */
return Status;
}
* Parameters
* DriverServiceName
* Name of the service to load (registry key).
- *
+ *
* Return Value
* Status
*
PMODULE_OBJECT ModuleObject;
PDRIVER_OBJECT DriverObject;
WCHAR *cur;
-
+
PAGED_CODE();
-
+
PreviousMode = KeGetPreviousMode();
/*
}
IopInitializeDevice(DeviceNode, DriverObject);
-
+ Status = IopStartDevice(DeviceNode);
+
ReleaseCapturedString:
RtlReleaseCapturedUnicodeString(&CapturedDriverServiceName,
PreviousMode,
* Parameters
* DriverServiceName
* Name of the service to unload (registry key).
- *
+ *
* Return Value
* Status
*
ReinitItem->DriverObject = DriverObject;
ReinitItem->ReinitRoutine = ReinitRoutine;
ReinitItem->Context = Context;
-
+
DriverObject->Flags |= DRVO_REINIT_REGISTERED;
ExInterlockedInsertTailList(
ReinitItem->DriverObject = DriverObject;
ReinitItem->ReinitRoutine = DriverReinitializationRoutine;
ReinitItem->Context = Context;
-
+
DriverObject->Flags |= DRVO_BOOTREINIT_REGISTERED;
ExInterlockedInsertTailList(
if (NewDriverExtension == NULL)
{
- return STATUS_INSUFFICIENT_RESOURCES;
+ return STATUS_INSUFFICIENT_RESOURCES;
}
-
+
OldIrql = KeRaiseIrqlToDpcLevel();
NewDriverExtension->Link = DriverObject->DriverSection;
*DriverObjectExtension = &NewDriverExtension->Extension;
- return STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
/*