#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
/* GLOBALS ********************************************************************/
ULONG IopDeviceObjectNumber = 0;
-
LIST_ENTRY ShutdownListHead, LastChanceShutdownListHead;
KSPIN_LOCK ShutdownListLock;
+extern LIST_ENTRY IopDiskFsListHead;
+extern LIST_ENTRY IopCdRomFsListHead;
+extern LIST_ENTRY IopTapeFsListHead;
/* PRIVATE FUNCTIONS **********************************************************/
+VOID
+NTAPI
+IopReadyDeviceObjects(IN PDRIVER_OBJECT Driver)
+{
+ PDEVICE_OBJECT DeviceObject;
+ PAGED_CODE();
+
+ /* Set the driver as initialized */
+ Driver->Flags |= DRVO_INITIALIZED;
+ DeviceObject = Driver->DeviceObject;
+ while (DeviceObject)
+ {
+ /* Set every device as initialized too */
+ DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+ DeviceObject = DeviceObject->NextDevice;
+ }
+}
+
+VOID
+NTAPI
+IopDeleteDevice(IN PVOID ObjectBody)
+{
+ PDEVICE_OBJECT DeviceObject = ObjectBody;
+ PAGED_CODE();
+
+ /* TODO: Delete Device Node */
+
+ /* Dereference the driver object, referenced in IoCreateDevice */
+ if (DeviceObject->DriverObject)
+ ObDereferenceObject(DeviceObject->DriverObject);
+}
+
+
PDEVICE_OBJECT
NTAPI
IopAttachDeviceToDeviceStackSafe(IN PDEVICE_OBJECT SourceDevice,
VOID
NTAPI
-IoShutdownRegisteredDevices(VOID)
+IoShutdownPnpDevices(VOID)
+{
+ /* This routine is only used by Driver Verifier to validate shutdown */
+ return;
+}
+
+VOID
+NTAPI
+IoShutdownSystem(IN ULONG Phase)
{
PLIST_ENTRY ListEntry;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
KEVENT Event;
NTSTATUS Status;
-
+
/* Initialize an event to wait on */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
-
- /* Get the first entry and start looping */
- ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
- &ShutdownListLock);
- while (ListEntry)
+
+ /* What phase? */
+ if (Phase == 0)
{
- /* Get the shutdown entry */
- ShutdownEntry = CONTAINING_RECORD(ListEntry,
- SHUTDOWN_ENTRY,
- ShutdownList);
+ /* Shutdown PnP */
+ IoShutdownPnpDevices();
- /* Get the attached device */
- DeviceObject = IoGetAttachedDevice(ShutdownEntry->DeviceObject);
-
- /* Build the shutdown IRP and call the driver */
- Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
- DeviceObject,
- NULL,
- 0,
- NULL,
- &Event,
- &StatusBlock);
- Status = IoCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING)
+ /* Loop first-chance shutdown notifications */
+ ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
+ &ShutdownListLock);
+ while (ListEntry)
{
- /* Wait on the driver */
- KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
- }
+ /* Get the shutdown entry */
+ ShutdownEntry = CONTAINING_RECORD(ListEntry,
+ SHUTDOWN_ENTRY,
+ ShutdownList);
+
+ /* Get the attached device */
+ DeviceObject = IoGetAttachedDevice(ShutdownEntry->DeviceObject);
+
+ /* Build the shutdown IRP and call the driver */
+ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
+ DeviceObject,
+ NULL,
+ 0,
+ NULL,
+ &Event,
+ &StatusBlock);
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ /* Wait on the driver */
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ }
- /* Free the shutdown entry and reset the event */
- ExFreePool(ShutdownEntry);
- KeClearEvent(&Event);
+ /* Get rid of our reference to it */
+ ObDereferenceObject(DeviceObject);
+
+ /* Free the shutdown entry and reset the event */
+ ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+ KeClearEvent(&Event);
+
+ /* Go to the next entry */
+ ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
+ &ShutdownListLock);
+ }
+ }
+ else if (Phase == 1)
+ {
+ /* Shutdown disk file systems */
+ IopShutdownBaseFileSystems(&IopDiskFsListHead);
- /* Go to the next entry */
- ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
+ /* Shutdown cdrom file systems */
+ IopShutdownBaseFileSystems(&IopCdRomFsListHead);
+
+ /* Shutdown tape filesystems */
+ IopShutdownBaseFileSystems(&IopTapeFsListHead);
+
+ /* Loop last-chance shutdown notifications */
+ ListEntry = ExInterlockedRemoveHeadList(&LastChanceShutdownListHead,
&ShutdownListLock);
- }
+ while (ListEntry)
+ {
+ /* Get the shutdown entry */
+ ShutdownEntry = CONTAINING_RECORD(ListEntry,
+ SHUTDOWN_ENTRY,
+ ShutdownList);
+
+ /* Get the attached device */
+ DeviceObject = IoGetAttachedDevice(ShutdownEntry->DeviceObject);
+
+ /* Build the shutdown IRP and call the driver */
+ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
+ DeviceObject,
+ NULL,
+ 0,
+ NULL,
+ &Event,
+ &StatusBlock);
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ /* Wait on the driver */
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ }
+
+ /* Get rid of our reference to it */
+ ObDereferenceObject(DeviceObject);
+
+ /* Free the shutdown entry and reset the event */
+ ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+ KeClearEvent(&Event);
+
+ /* Go to the next entry */
+ ListEntry = ExInterlockedRemoveHeadList(&LastChanceShutdownListHead,
+ &ShutdownListLock);
+ }
+
+ }
}
NTSTATUS
/* Return the requested data */
*DeviceObject = IoGetRelatedDeviceObject(LocalFileObject);
*FileObject = LocalFileObject;
- ZwClose(FileHandle);
}
/* Close the handle */
+ ZwClose(FileHandle);
+
return Status;
}
if (DeviceObject->SecurityDescriptor)
{
/* Free it */
- ExFreePool(DeviceObject->SecurityDescriptor);
+ ExFreePoolWithTag(DeviceObject->SecurityDescriptor, TAG_SD);
}
/* Remove the device from the list */
/* Unload it */
if (DriverObject->DriverUnload) DriverObject->DriverUnload(DriverObject);
+
+ /* Make object temporary so it can be deleted */
+ ObMakeTemporaryObject(DriverObject);
+
+ /* Dereference once more, referenced at driver object creation */
+ ObDereferenceObject(DriverObject);
+
}
VOID
}
}
+NTSTATUS
+NTAPI
+IopGetRelatedTargetDevice(IN PFILE_OBJECT FileObject,
+ OUT PDEVICE_NODE *DeviceNode)
+{
+ NTSTATUS Status;
+ IO_STACK_LOCATION Stack = {0};
+ PDEVICE_RELATIONS DeviceRelations;
+ PDEVICE_OBJECT DeviceObject = NULL;
+
+ ASSERT(FileObject);
+
+ /* Get DeviceObject related to given FileObject */
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ if (!DeviceObject) return STATUS_NO_SUCH_DEVICE;
+
+ /* Define input parameters */
+ Stack.MajorFunction = IRP_MJ_PNP;
+ Stack.MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
+ Stack.Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
+ Stack.FileObject = FileObject;
+
+ /* Call the driver to query all relations (IRP_MJ_PNP) */
+ Status = IopSynchronousCall(DeviceObject,
+ &Stack,
+ (PVOID)&DeviceRelations);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Make sure it's not NULL and contains only one object */
+ ASSERT(DeviceRelations);
+ ASSERT(DeviceRelations->Count == 1);
+
+ /* Finally get the device node */
+ *DeviceNode = IopGetDeviceNode(DeviceRelations->Objects[0]);
+ if (!*DeviceNode) Status = STATUS_NO_SUCH_DEVICE;
+
+ /* Free the DEVICE_RELATIONS structure, it's not needed anymore */
+ ExFreePool(DeviceRelations);
+
+ return Status;
+}
+
/* PUBLIC FUNCTIONS ***********************************************************/
/*
* because that's only padding for the DevObjExt and not part of the Object.
*/
CreatedDeviceObject->Type = IO_TYPE_DEVICE;
- CreatedDeviceObject->Size = sizeof(DEVICE_OBJECT) + DeviceExtensionSize;
+ CreatedDeviceObject->Size = sizeof(DEVICE_OBJECT) + (USHORT)DeviceExtensionSize;
/* The kernel extension is after the driver internal extension */
DeviceObjectExtension = (PDEVOBJ_EXTENSION)
/* Set the Type and Size. Question: why is Size 0 on Windows? */
DeviceObjectExtension->Type = IO_TYPE_DEVICE_OBJECT_EXTENSION;
DeviceObjectExtension->Size = 0;
+
+ /* Initialize with Power Manager */
+ PoInitializeDeviceObject(DeviceObjectExtension);
/* Link the Object and Extension */
DeviceObjectExtension->DeviceObject = CreatedDeviceObject;
ASSERT((DriverObject->Flags & DRVO_UNLOAD_INVOKED) == 0);
CreatedDeviceObject->DriverObject = DriverObject;
IopEditDeviceList(DriverObject, CreatedDeviceObject, IopAdd);
+
+ /* Link with the power manager */
+ if (CreatedDeviceObject->Vpb) PoVolumeDevice(CreatedDeviceObject);
/* Close the temporary handle and return to caller */
ObCloseHandle(TempHandle, KernelMode);
/* Make sure it's not getting deleted */
DeviceExtension = IoGetDevObjExtension(DeviceObject);
- if (DeviceExtension->ExtensionFlags & (DOE_UNLOAD_PENDING |
+ if (!(DeviceExtension->ExtensionFlags & (DOE_UNLOAD_PENDING |
DOE_DELETE_PENDING |
DOE_REMOVE_PENDING |
- DOE_REMOVE_PROCESSED))
+ DOE_REMOVE_PROCESSED)))
{
/* Get the Lower Device Object */
LowerDeviceObject = DeviceExtension->AttachedTo;
- /* Reference it */
- ObReferenceObject(LowerDeviceObject);
+ /* Check that we got a valid device object */
+ if (LowerDeviceObject)
+ {
+ /* We did so let's reference it */
+ ObReferenceObject(LowerDeviceObject);
+ }
}
/* Return it */
{
/* FIXME: Unhandled yet */
DPRINT1("FOEs not supported\n");
- KEBUGCHECK(0);
+ ASSERT(FALSE);
}
}
return DeviceObject;
}
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IoGetRelatedTargetDevice(IN PFILE_OBJECT FileObject,
+ OUT PDEVICE_OBJECT *DeviceObject)
+{
+ NTSTATUS Status;
+ PDEVICE_NODE DeviceNode = NULL;
+
+ /* Call the internal helper function */
+ Status = IopGetRelatedTargetDevice(FileObject, &DeviceNode);
+ if (NT_SUCCESS(Status) && DeviceNode)
+ {
+ *DeviceObject = DeviceNode->PhysicalDeviceObject;
+ }
+ return Status;
+}
+
/*
* @implemented
*/
/* Set the DO */
Entry->DeviceObject = DeviceObject;
+
+ /* Reference it so it doesn't go away */
+ ObReferenceObject(DeviceObject);
/* Insert it into the list */
ExInterlockedInsertHeadList(&LastChanceShutdownListHead,
/* Set the DO */
Entry->DeviceObject = DeviceObject;
+
+ /* Reference it so it doesn't go away */
+ ObReferenceObject(DeviceObject);
/* Insert it into the list */
ExInterlockedInsertHeadList(&ShutdownListHead,
NextEntry = NextEntry->Blink;
/* Free the entry */
- ExFreePool(ShutdownEntry);
+ ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+
+ /* Get rid of our reference to it */
+ ObDereferenceObject(DeviceObject);
}
/* Go to the next entry */
NextEntry = NextEntry->Blink;
/* Free the entry */
- ExFreePool(ShutdownEntry);
+ ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+
+ /* Get rid of our reference to it */
+ ObDereferenceObject(DeviceObject);
}
/* Go to the next entry */
NextEntry = NextEntry->Flink;
}
+ /* Release the shutdown lock */
+ KeReleaseSpinLock(&ShutdownListLock, OldIrql);
+
/* Now remove the flag */
DeviceObject->Flags &= ~DO_SHUTDOWN_REGISTERED;
}
IopStartNextPacketByKeyEx(DeviceObject,
Key,
DOE_SIO_WITH_KEY |
- (Cancelable) ? DOE_SIO_CANCELABLE : 0);
+ (Cancelable ? DOE_SIO_CANCELABLE : 0));
}
else
{
IopStartNextPacketByKeyEx(DeviceObject,
0,
DOE_SIO_NO_KEY |
- (Cancelable) ? DOE_SIO_CANCELABLE : 0);
+ (Cancelable ? DOE_SIO_CANCELABLE : 0));
}
else
{
}
/* Release the cancel lock */
- IoReleaseCancelSpinLock(OldIrql);
+ IoReleaseCancelSpinLock(CancelIrql);
}
/* Call the Start I/O function */