/* 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)
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 */
- ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
- 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,
+ /* Go to the next entry */
+ ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
+ &ShutdownListLock);
+ }
+ }
+ else if (Phase == 1)
+ {
+ /* Shutdown disk file systems */
+ IopShutdownBaseFileSystems(&IopDiskFsListHead);
+
+ /* 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
{
NTSTATUS Status;
IO_STACK_LOCATION Stack = {0};
- IO_STATUS_BLOCK IoStatusBlock;
PDEVICE_RELATIONS DeviceRelations;
PDEVICE_OBJECT DeviceObject = NULL;
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 = IopInitiatePnpIrp(DeviceObject,
- &IoStatusBlock,
- IRP_MN_QUERY_DEVICE_RELATIONS,
- &Stack);
+ Status = IopSynchronousCall(DeviceObject,
+ &Stack,
+ (PVOID)&DeviceRelations);
if (!NT_SUCCESS(Status)) return Status;
- /* Get returned pointer to DEVICE_RELATIONS */
- DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
-
/* Make sure it's not NULL and contains only one object */
ASSERT(DeviceRelations);
ASSERT(DeviceRelations->Count == 1);
/* 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);
/* 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,
/* Free the entry */
ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+
+ /* Get rid of our reference to it */
+ ObDereferenceObject(DeviceObject);
}
/* Go to the next entry */
/* Free the entry */
ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+
+ /* Get rid of our reference to it */
+ ObDereferenceObject(DeviceObject);
}
/* Go to the next entry */