[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
IopUnloadDevice(IN PDEVICE_OBJECT DeviceObject)
{
#if 0
PDRIVER_OBJECT DriverObject = DeviceObject->DriverObject;
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 */
if (ThisExtension->ExtensionFlags & DOE_DELETE_PENDING)
@ -410,45 +396,28 @@ IopUnloadDevice(IN PDEVICE_OBJECT DeviceObject)
ObDereferenceObject(DeviceObject);
}
/* Loop all the device objects */
DeviceObject = DriverObject->DeviceObject;
while (DeviceObject)
/* We can't unload a non-PnP driver here */
if (DriverObject->Flags & DRVO_LEGACY_DRIVER)
{
/*
* Make sure we're not attached, having a reference count
* 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;
DPRINT("Not a PnP driver! '%wZ' will not be unloaded!\n", &DriverObject->DriverName);
return;
}
/* Loop all the device objects */
DeviceObject = DriverObject->DeviceObject;
while (DeviceObject)
{
/* Set the unload pending flag */
IoGetDevObjExtension(DeviceObject)->ExtensionFlags |= DOE_UNLOAD_PENDING;
/* Return if we've already called unload (maybe we're in it?) */
if (DriverObject->Flags & DRVO_UNLOAD_INVOKED) return;
/* Go to the next device */
DeviceObject = DeviceObject->NextDevice;
/* We can't unload unless there's an unload handler */
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);
@ -461,10 +430,6 @@ IopUnloadDevice(IN PDEVICE_OBJECT DeviceObject)
/* Make object temporary so it can be deleted */
ObMakeTemporaryObject(DriverObject);
/* Dereference once more, referenced at driver object creation */
ObDereferenceObject(DriverObject);
#endif
}
VOID

View file

@ -589,7 +589,7 @@ IopAttachFilterDriversCallback(
Status = IopInitializeDevice(DeviceNode, DriverObject);
/* Remove extra reference */
//ObDereferenceObject(DriverObject);
ObDereferenceObject(DriverObject);
}
return STATUS_SUCCESS;
@ -885,7 +885,7 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
}
/* Remove extra reference from IopInitializeDriverModule */
//ObDereferenceObject(DriverObject);
ObDereferenceObject(DriverObject);
return Status;
}
@ -948,6 +948,7 @@ IopInitializeBootDrivers(VOID)
{
/* Fail */
IopFreeDeviceNode(DeviceNode);
ObDereferenceObject(DriverObject);
return;
}
@ -957,6 +958,7 @@ IopInitializeBootDrivers(VOID)
{
/* Fail */
IopFreeDeviceNode(DeviceNode);
ObDereferenceObject(DriverObject);
return;
}
@ -1268,7 +1270,8 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
*/
/* 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
and set DOE_UNLOAD_PENDING flag */
@ -1484,7 +1487,7 @@ try_again:
RtlZeroMemory(DriverObject, ObjectSize);
DriverObject->Type = IO_TYPE_DRIVER;
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->DriverObject = DriverObject;
DriverObject->DriverInit = InitializationFunction;
@ -1585,6 +1588,10 @@ try_again:
*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 */
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);
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);
LoadParams->Status = Status;
@ -1931,43 +1938,37 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)
/*
* 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);
if (!NT_SUCCESS(Status))
{
DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status);
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);
DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status);
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);
}
else
{