[NTOSKRNL]

- Reenable some dereferences of the driver object
- Fix return values in NtLoadDriver
- Split unloading into code for legacy drivers and non-legacy drivers

svn path=/trunk/; revision=56184
This commit is contained in:
Cameron Gutman 2012-03-18 22:11:46 +00:00
parent 295501f398
commit 326be77908
2 changed files with 59 additions and 93 deletions

View file

@ -364,22 +364,8 @@ VOID
NTAPI NTAPI
IopUnloadDevice(IN PDEVICE_OBJECT DeviceObject) IopUnloadDevice(IN PDEVICE_OBJECT DeviceObject)
{ {
#if 0
PDRIVER_OBJECT DriverObject = DeviceObject->DriverObject; PDRIVER_OBJECT DriverObject = DeviceObject->DriverObject;
PEXTENDED_DEVOBJ_EXTENSION ThisExtension = IoGetDevObjExtension(DeviceObject); PEXTENDED_DEVOBJ_EXTENSION ThisExtension = IoGetDevObjExtension(DeviceObject);
PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
/* Return if we've already called unload (maybe we're in it?) */
if (DriverObject->Flags & DRVO_UNLOAD_INVOKED) return;
/* We can't unload unless there's an unload handler */
if (!DriverObject->DriverUnload)
{
if (DeviceNode && !(DeviceNode->Flags & DNF_LEGACY_DRIVER))
DPRINT1("No DriverUnload function on PnP driver! '%wZ' will not be unloaded!\n", &DriverObject->DriverName);
return;
}
/* Check if deletion is pending */ /* Check if deletion is pending */
if (ThisExtension->ExtensionFlags & DOE_DELETE_PENDING) if (ThisExtension->ExtensionFlags & DOE_DELETE_PENDING)
@ -410,45 +396,28 @@ IopUnloadDevice(IN PDEVICE_OBJECT DeviceObject)
ObDereferenceObject(DeviceObject); ObDereferenceObject(DeviceObject);
} }
/* Loop all the device objects */ /* We can't unload a non-PnP driver here */
DeviceObject = DriverObject->DeviceObject; if (DriverObject->Flags & DRVO_LEGACY_DRIVER)
while (DeviceObject)
{ {
/* DPRINT("Not a PnP driver! '%wZ' will not be unloaded!\n", &DriverObject->DriverName);
* Make sure we're not attached, having a reference count return;
* or already deleting
*/
if (DeviceObject->ReferenceCount)
{
DPRINT("Device object still has %d references\n", DeviceObject->ReferenceCount);
return;
}
if (DeviceObject->AttachedDevice)
{
DPRINT("Device object is in the middle of a device stack\n");
return;
}
if (IoGetDevObjExtension(DeviceObject)->ExtensionFlags & (DOE_DELETE_PENDING | DOE_REMOVE_PENDING))
{
DPRINT("Device object has a pending destructive operation\n");
return;
}
/* Check the next device */
DeviceObject = DeviceObject->NextDevice;
} }
/* Loop all the device objects */ /* Return if we've already called unload (maybe we're in it?) */
DeviceObject = DriverObject->DeviceObject; if (DriverObject->Flags & DRVO_UNLOAD_INVOKED) return;
while (DeviceObject)
{
/* Set the unload pending flag */
IoGetDevObjExtension(DeviceObject)->ExtensionFlags |= DOE_UNLOAD_PENDING;
/* Go to the next device */ /* We can't unload unless there's an unload handler */
DeviceObject = DeviceObject->NextDevice; if (!DriverObject->DriverUnload)
{
DPRINT1("No DriverUnload function on PnP driver! '%wZ' will not be unloaded!\n", &DriverObject->DriverName);
return;
}
/* Bail if there are still devices present */
if (DriverObject->DeviceObject)
{
DPRINT("Devices still present! '%wZ' will not be unloaded!\n", &DriverObject->DriverName);
return;
} }
DPRINT1("Unloading driver '%wZ' (automatic)\n", &DriverObject->DriverName); DPRINT1("Unloading driver '%wZ' (automatic)\n", &DriverObject->DriverName);
@ -461,10 +430,6 @@ IopUnloadDevice(IN PDEVICE_OBJECT DeviceObject)
/* Make object temporary so it can be deleted */ /* Make object temporary so it can be deleted */
ObMakeTemporaryObject(DriverObject); ObMakeTemporaryObject(DriverObject);
/* Dereference once more, referenced at driver object creation */
ObDereferenceObject(DriverObject);
#endif
} }
VOID VOID

View file

@ -589,7 +589,7 @@ IopAttachFilterDriversCallback(
Status = IopInitializeDevice(DeviceNode, DriverObject); Status = IopInitializeDevice(DeviceNode, DriverObject);
/* Remove extra reference */ /* Remove extra reference */
//ObDereferenceObject(DriverObject); ObDereferenceObject(DriverObject);
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -885,7 +885,7 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
} }
/* Remove extra reference from IopInitializeDriverModule */ /* Remove extra reference from IopInitializeDriverModule */
//ObDereferenceObject(DriverObject); ObDereferenceObject(DriverObject);
return Status; return Status;
} }
@ -948,6 +948,7 @@ IopInitializeBootDrivers(VOID)
{ {
/* Fail */ /* Fail */
IopFreeDeviceNode(DeviceNode); IopFreeDeviceNode(DeviceNode);
ObDereferenceObject(DriverObject);
return; return;
} }
@ -957,6 +958,7 @@ IopInitializeBootDrivers(VOID)
{ {
/* Fail */ /* Fail */
IopFreeDeviceNode(DeviceNode); IopFreeDeviceNode(DeviceNode);
ObDereferenceObject(DriverObject);
return; return;
} }
@ -1268,7 +1270,8 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
*/ */
/* Call the load/unload routine, depending on current process */ /* Call the load/unload routine, depending on current process */
if (DriverObject->DriverUnload && DriverObject->DriverSection) if (DriverObject->DriverUnload && DriverObject->DriverSection &&
(UnloadPnpDrivers || (DriverObject->Flags & DRVO_LEGACY_DRIVER)))
{ {
/* Loop through each device object of the driver /* Loop through each device object of the driver
and set DOE_UNLOAD_PENDING flag */ and set DOE_UNLOAD_PENDING flag */
@ -1484,7 +1487,7 @@ try_again:
RtlZeroMemory(DriverObject, ObjectSize); RtlZeroMemory(DriverObject, ObjectSize);
DriverObject->Type = IO_TYPE_DRIVER; DriverObject->Type = IO_TYPE_DRIVER;
DriverObject->Size = sizeof(DRIVER_OBJECT); DriverObject->Size = sizeof(DRIVER_OBJECT);
DriverObject->Flags = DRVO_LEGACY_DRIVER;//DRVO_BUILTIN_DRIVER; DriverObject->Flags = DRVO_LEGACY_DRIVER;
DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1); DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1);
DriverObject->DriverExtension->DriverObject = DriverObject; DriverObject->DriverExtension->DriverObject = DriverObject;
DriverObject->DriverInit = InitializationFunction; DriverObject->DriverInit = InitializationFunction;
@ -1585,6 +1588,10 @@ try_again:
*pDriverObject = DriverObject; *pDriverObject = DriverObject;
} }
/* We're going to say if we don't have any DOs from DriverEntry, then we're not legacy.
* Other parts of the I/O manager depend on this behavior */
if (!DriverObject->DeviceObject) DriverObject->Flags &= ~DRVO_LEGACY_DRIVER;
/* Loop all Major Functions */ /* Loop all Major Functions */
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
{ {
@ -1920,7 +1927,7 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)
DPRINT("Loading module from %wZ\n", &ImagePath); DPRINT("Loading module from %wZ\n", &ImagePath);
Status = MmLoadSystemImage(&ImagePath, NULL, NULL, 0, (PVOID)&ModuleObject, &BaseAddress); Status = MmLoadSystemImage(&ImagePath, NULL, NULL, 0, (PVOID)&ModuleObject, &BaseAddress);
if (!NT_SUCCESS(Status) && Status != STATUS_IMAGE_ALREADY_LOADED) if (!NT_SUCCESS(Status))
{ {
DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status); DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status);
LoadParams->Status = Status; LoadParams->Status = Status;
@ -1931,43 +1938,37 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)
/* /*
* Initialize the driver module if it's loaded for the first time * Initialize the driver module if it's loaded for the first time
*/ */
if (Status != STATUS_IMAGE_ALREADY_LOADED) Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode);
if (!NT_SUCCESS(Status))
{ {
Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode); DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status);
MmUnloadSystemImage(ModuleObject);
if (!NT_SUCCESS(Status)) LoadParams->Status = Status;
{ (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status); return;
MmUnloadSystemImage(ModuleObject);
LoadParams->Status = Status;
(VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
return;
}
IopDisplayLoadingMessage(&DeviceNode->ServiceName);
Status = IopInitializeDriverModule(
DeviceNode,
ModuleObject,
&DeviceNode->ServiceName,
(Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
Type == 8 /* SERVICE_RECOGNIZER_DRIVER */),
&DriverObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("IopInitializeDriver() failed (Status %lx)\n", Status);
MmUnloadSystemImage(ModuleObject);
IopFreeDeviceNode(DeviceNode);
LoadParams->Status = Status;
(VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
return;
}
/* Initialize and start device */
IopInitializeDevice(DeviceNode, DriverObject);
Status = IopStartDevice(DeviceNode);
} }
IopDisplayLoadingMessage(&DeviceNode->ServiceName);
Status = IopInitializeDriverModule(DeviceNode,
ModuleObject,
&DeviceNode->ServiceName,
(Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
Type == 8 /* SERVICE_RECOGNIZER_DRIVER */),
&DriverObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("IopInitializeDriver() failed (Status %lx)\n", Status);
MmUnloadSystemImage(ModuleObject);
IopFreeDeviceNode(DeviceNode);
LoadParams->Status = Status;
(VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
return;
}
/* Initialize and start device */
IopInitializeDevice(DeviceNode, DriverObject);
Status = IopStartDevice(DeviceNode);
} }
else else
{ {