Author: sir_richard
Date: Mon Mar 8 21:47:10 2010
New Revision: 46004
URL:
http://svn.reactos.org/svn/reactos?rev=46004&view=rev
Log:
[NTOS]: Have I/O Manager Volume Device Objects register with the Power Manager so that
they can receive dope.
[NTOS]: Reimplement NtShutdownSystem.
[NTOS]: Implement NtSetSystemPowerState for the shutdown/reboot cases.
[NTOS]: Use the dope from the volume device objects to flush all writeable (non-floppy)
devices. Pending hard-disk changes are now flushed to disks before shutdown.
[NTOS]: Flush \\REGISTRY during shutdown. This flushes all pending changes.
[NTOS]: Call into Cc to flush lazy writer during shutdown.
[NTOS]: Stop killing processes on shutdown. The kernel should not be doing this.
[NTOS]: Don't only shutdown disk file systems, but also cdrom and tape.
[NTOS]: Don't only notify drivers of first-chance shutdown -- also parse the
last-change shutdown list.
[NTOS]: Reference drivers registering for shutdown notifications so that they remain
loaded for them to get the notification at shutdown.
[NTOS]: Notify drivers that have registered/opened the Power State callback.
[NTOS]: A lot of the Po* power state code is highly simplified, but provides a good
roadmap to anyone interested in this functionality long-term.
Added:
trunk/reactos/ntoskrnl/po/poshtdwn.c (with props)
trunk/reactos/ntoskrnl/po/povolume.c (with props)
Modified:
trunk/reactos/ntoskrnl/ex/shutdown.c
trunk/reactos/ntoskrnl/include/internal/io.h
trunk/reactos/ntoskrnl/include/internal/po.h
trunk/reactos/ntoskrnl/io/iomgr/device.c
trunk/reactos/ntoskrnl/io/iomgr/volume.c
trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
trunk/reactos/ntoskrnl/po/power.c
Modified: trunk/reactos/ntoskrnl/ex/shutdown.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/shutdown.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ex/shutdown.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ex/shutdown.c [iso-8859-1] Mon Mar 8 21:47:10 2010
@@ -14,123 +14,40 @@
/* FUNCTIONS *****************************************************************/
-VOID NTAPI
-ShutdownThreadMain(PVOID Context)
-{
- SHUTDOWN_ACTION Action = (SHUTDOWN_ACTION)Context;
- PUCHAR Logo1, Logo2;
- ULONG i;
-
- /* Run the thread on the boot processor */
- KeSetSystemAffinityThread(1);
-
- PspShutdownProcessManager();
-
- CmShutdownSystem();
- IoShutdownRegisteredFileSystems();
- IoShutdownRegisteredDevices();
-
- if (Action == ShutdownNoReboot)
- {
- /* Try the platform driver */
- PopSetSystemPowerState(PowerSystemShutdown);
-
- /* If that didn't work, try legacy switch off */
- //HalReturnToFirmware(HalPowerDownRoutine);
-
- /* If that still didn't work, stop all interrupts */
- KeRaiseIrqlToDpcLevel();
- _disable();
-
- /* Do we have boot video */
- if (InbvIsBootDriverInstalled())
- {
- /* Yes we do, cleanup for shutdown screen */
- if (!InbvCheckDisplayOwnership()) InbvAcquireDisplayOwnership();
- InbvResetDisplay();
- InbvSolidColorFill(0, 0, 639, 479, 0);
- InbvEnableDisplayString(TRUE);
- InbvSetScrollRegion(0, 0, 639, 479);
-
- /* Display shutdown logo and message */
- Logo1 = InbvGetResourceAddress(IDB_SHUTDOWN_LOGO);
- Logo2 = InbvGetResourceAddress(IDB_LOGO);
- if ((Logo1) && (Logo2))
- {
- InbvBitBlt(Logo1, 215, 352);
- InbvBitBlt(Logo2, 217, 111);
- }
- }
- else
- {
- /* Do it in text-mode */
- for (i = 0; i < 25; i++) InbvDisplayString("\n");
- InbvDisplayString(" ");
- InbvDisplayString("The system may be powered off now.\n");
- }
-
- /* Hang the system */
- for (;;) HalHaltSystem();
- }
- else if (Action == ShutdownReboot)
- {
- HalReturnToFirmware (HalRebootRoutine);
- }
- else
- {
- HalReturnToFirmware (HalHaltRoutine);
- }
-}
-
-
-NTSTATUS NTAPI
-NtSetSystemPowerState(IN POWER_ACTION SystemAction,
- IN SYSTEM_POWER_STATE MinSystemState,
- IN ULONG Flags)
-{
- /* Windows 2000 only */
- return(STATUS_NOT_IMPLEMENTED);
-}
-
/*
* @implemented
*/
-NTSTATUS NTAPI
+NTSTATUS
+NTAPI
NtShutdownSystem(IN SHUTDOWN_ACTION Action)
{
- NTSTATUS Status;
- HANDLE ThreadHandle;
- PETHREAD ShutdownThread;
-
- if (Action > ShutdownPowerOff)
- return STATUS_INVALID_PARAMETER;
- Status = PsCreateSystemThread(&ThreadHandle,
- THREAD_ALL_ACCESS,
- NULL,
- NULL,
- NULL,
- ShutdownThreadMain,
- (PVOID)Action);
- if (!NT_SUCCESS(Status))
- {
- ASSERT(FALSE);
- }
- Status = ObReferenceObjectByHandle(ThreadHandle,
- THREAD_ALL_ACCESS,
- PsThreadType,
- KernelMode,
- (PVOID*)&ShutdownThread,
- NULL);
- NtClose(ThreadHandle);
- if (!NT_SUCCESS(Status))
- {
- ASSERT(FALSE);
- }
-
- KeSetPriorityThread(&ShutdownThread->Tcb, LOW_REALTIME_PRIORITY + 1);
- ObDereferenceObject(ShutdownThread);
-
- return STATUS_SUCCESS;
+ POWER_ACTION PowerAction;
+
+ /* Convert to power action */
+ if (Action == ShutdownNoReboot)
+ {
+ PowerAction = PowerActionShutdown;
+ }
+ else if (Action == ShutdownReboot)
+ {
+ PowerAction = PowerActionShutdownReset;
+ }
+ else if (Action == ShutdownPowerOff)
+ {
+ PowerAction = PowerActionShutdownOff;
+ }
+ else
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Now call the power manager */
+ DPRINT1("Setting state to: %lx\n", PowerAction);
+ return NtSetSystemPowerState(PowerAction,
+ PowerSystemSleeping3,
+ POWER_ACTION_OVERRIDE_APPS |
+ POWER_ACTION_DISABLE_WAKES |
+ POWER_ACTION_CRITICAL);
}
/* EOF */
Modified: trunk/reactos/ntoskrnl/include/internal/io.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/io.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/io.h [iso-8859-1] Mon Mar 8 21:47:10 2010
@@ -743,14 +743,14 @@
VOID
NTAPI
-IoShutdownRegisteredDevices(
- VOID
-);
-
-VOID
-NTAPI
-IoShutdownRegisteredFileSystems(
- VOID
+IoShutdownSystem(
+ IN ULONG Phase
+);
+
+VOID
+NTAPI
+IopShutdownBaseFileSystems(
+ IN PLIST_ENTRY ListHead
);
//
Modified: trunk/reactos/ntoskrnl/include/internal/po.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/po.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/po.h [iso-8859-1] Mon Mar 8 21:47:10 2010
@@ -32,6 +32,228 @@
#define POTRACE(x, ...) DPRINT(__VA_ARGS__)
#endif
+typedef struct _PO_HIBER_PERF
+{
+ ULONGLONG IoTicks;
+ ULONGLONG InitTicks;
+ ULONGLONG CopyTicks;
+ ULONGLONG StartCount;
+ ULONG ElapsedTime;
+ ULONG IoTime;
+ ULONG CopyTime;
+ ULONG InitTime;
+ ULONG PagesWritten;
+ ULONG PagesProcessed;
+ ULONG BytesCopied;
+ ULONG DumpCount;
+ ULONG FileRuns;
+} PO_HIBER_PERF, *PPO_HIBER_PERF;
+
+typedef struct _PO_MEMORY_IMAGE
+{
+ ULONG Signature;
+ ULONG Version;
+ ULONG CheckSum;
+ ULONG LengthSelf;
+ PFN_NUMBER PageSelf;
+ ULONG PageSize;
+ ULONG ImageType;
+ LARGE_INTEGER SystemTime;
+ ULONGLONG InterruptTime;
+ ULONG FeatureFlags;
+ UCHAR HiberFlags;
+ UCHAR spare[3];
+ ULONG NoHiberPtes;
+ ULONG_PTR HiberVa;
+ PHYSICAL_ADDRESS HiberPte;
+ ULONG NoFreePages;
+ ULONG FreeMapCheck;
+ ULONG WakeCheck;
+ PFN_NUMBER TotalPages;
+ PFN_NUMBER FirstTablePage;
+ PFN_NUMBER LastFilePage;
+ PO_HIBER_PERF PerfInfo;
+} PO_MEMORY_IMAGE, *PPO_MEMORY_IMAGE;
+
+typedef struct _PO_MEMORY_RANGE_ARRAY_RANGE
+{
+ PFN_NUMBER PageNo;
+ PFN_NUMBER StartPage;
+ PFN_NUMBER EndPage;
+ ULONG CheckSum;
+} PO_MEMORY_RANGE_ARRAY_RANGE;
+
+typedef struct _PO_MEMORY_RANGE_ARRAY_LINK
+{
+ struct _PO_MEMORY_RANGE_ARRAY *Next;
+ PFN_NUMBER NextTable;
+ ULONG CheckSum;
+ ULONG EntryCount;
+} PO_MEMORY_RANGE_ARRAY_LINK;
+
+typedef struct _PO_MEMORY_RANGE_ARRAY
+{
+ union
+ {
+ PO_MEMORY_RANGE_ARRAY_RANGE Range;
+ PO_MEMORY_RANGE_ARRAY_LINK Link;
+ };
+} PO_MEMORY_RANGE_ARRAY, *PPO_MEMORY_RANGE_ARRAY;
+
+typedef struct _POP_HIBER_CONTEXT
+{
+ BOOLEAN WriteToFile;
+ BOOLEAN ReserveLoaderMemory;
+ BOOLEAN ReserveFreeMemory;
+ BOOLEAN VerifyOnWake;
+ BOOLEAN Reset;
+ UCHAR HiberFlags;
+ BOOLEAN LinkFile;
+ HANDLE LinkFileHandle;
+ PKSPIN_LOCK Lock;
+ BOOLEAN MapFrozen;
+ RTL_BITMAP MemoryMap;
+ LIST_ENTRY ClonedRanges;
+ ULONG ClonedRangeCount;
+ PLIST_ENTRY NextCloneRange;
+ PFN_NUMBER NextPreserve;
+ PMDL LoaderMdl;
+ PMDL Clones;
+ PUCHAR NextClone;
+ ULONG NoClones;
+ PMDL Spares;
+ ULONGLONG PagesOut;
+ PVOID IoPage;
+ PVOID CurrentMcb;
+ PVOID DumpStack;
+ PKPROCESSOR_STATE WakeState;
+ ULONG NoRanges;
+ ULONG_PTR HiberVa;
+ PHYSICAL_ADDRESS HiberPte;
+ NTSTATUS Status;
+ PPO_MEMORY_IMAGE MemoryImage;
+ PPO_MEMORY_RANGE_ARRAY TableHead;
+ PVOID CompressionWorkspace;
+ PUCHAR CompressedWriteBuffer;
+ PULONG PerformanceStats;
+ PVOID CompressionBlock;
+ PVOID DmaIO;
+ PVOID TemporaryHeap;
+ PO_HIBER_PERF PerfInfo;
+} POP_HIBER_CONTEXT, *PPOP_HIBER_CONTEXT;
+
+typedef struct _PO_NOTIFY_ORDER_LEVEL
+{
+ KEVENT LevelReady;
+ ULONG DeviceCount;
+ ULONG ActiveCount;
+ LIST_ENTRY WaitSleep;
+ LIST_ENTRY ReadySleep;
+ LIST_ENTRY Pending;
+ LIST_ENTRY Complete;
+ LIST_ENTRY ReadyS0;
+ LIST_ENTRY WaitS0;
+} PO_NOTIFY_ORDER_LEVEL, *PPO_NOTIFY_ORDER_LEVEL;
+
+typedef struct _POP_SHUTDOWN_BUG_CHECK
+{
+ HANDLE ThreadHandle;
+ HANDLE ThreadId;
+ HANDLE ProcessId;
+ ULONG Code;
+ ULONG_PTR Parameter1;
+ ULONG_PTR Parameter2;
+ ULONG_PTR Parameter3;
+ ULONG_PTR Parameter4;
+} POP_SHUTDOWN_BUG_CHECK, *PPOP_SHUTDOWN_BUG_CHECK;
+
+typedef struct _POP_DEVICE_POWER_IRP
+{
+ SINGLE_LIST_ENTRY Free;
+ PIRP Irp;
+ PPO_DEVICE_NOTIFY Notify;
+ LIST_ENTRY Pending;
+ LIST_ENTRY Complete;
+ LIST_ENTRY Abort;
+ LIST_ENTRY Failed;
+} POP_DEVICE_POWER_IRP, *PPOP_DEVICE_POWER_IRP;
+
+typedef struct _PO_DEVICE_NOTIFY_ORDER
+{
+ ULONG DevNodeSequence;
+ PDEVICE_OBJECT *WarmEjectPdoPointer;
+ PO_NOTIFY_ORDER_LEVEL OrderLevel[8];
+} PO_DEVICE_NOTIFY_ORDER, *PPO_DEVICE_NOTIFY_ORDER;
+
+typedef struct _POP_DEVICE_SYS_STATE
+{
+ UCHAR IrpMinor;
+ SYSTEM_POWER_STATE SystemState;
+ PKEVENT Event;
+ KSPIN_LOCK SpinLock;
+ PKTHREAD Thread;
+ BOOLEAN GetNewDeviceList;
+ PO_DEVICE_NOTIFY_ORDER Order;
+ NTSTATUS Status;
+ PDEVICE_OBJECT FailedDevice;
+ BOOLEAN Waking;
+ BOOLEAN Cancelled;
+ BOOLEAN IgnoreErrors;
+ BOOLEAN IgnoreNotImplemented;
+ BOOLEAN _WaitAny;
+ BOOLEAN _WaitAll;
+ LIST_ENTRY PresentIrpQueue;
+ POP_DEVICE_POWER_IRP Head;
+ POP_DEVICE_POWER_IRP PowerIrpState[20];
+} POP_DEVICE_SYS_STATE, *PPOP_DEVICE_SYS_STATE;
+
+typedef struct _POP_POWER_ACTION
+{
+ UCHAR Updates;
+ UCHAR State;
+ BOOLEAN Shutdown;
+ POWER_ACTION Action;
+ SYSTEM_POWER_STATE LightestState;
+ ULONG Flags;
+ NTSTATUS Status;
+ UCHAR IrpMinor;
+ SYSTEM_POWER_STATE SystemState;
+ SYSTEM_POWER_STATE NextSystemState;
+ PPOP_SHUTDOWN_BUG_CHECK ShutdownBugCode;
+ PPOP_DEVICE_SYS_STATE DevState;
+ PPOP_HIBER_CONTEXT HiberContext;
+ ULONGLONG WakeTime;
+ ULONGLONG SleepTime;
+} POP_POWER_ACTION, *PPOP_POWER_ACTION;
+
+typedef enum _POP_DEVICE_IDLE_TYPE
+{
+ DeviceIdleNormal,
+ DeviceIdleDisk,
+} POP_DEVICE_IDLE_TYPE, *PPOP_DEVICE_IDLE_TYPE;
+
+typedef struct _POWER_CHANNEL_SUMMARY
+{
+ ULONG Signature;
+ ULONG TotalCount;
+ ULONG D0Count;
+ LIST_ENTRY NotifyList;
+} POWER_CHANNEL_SUMMARY, *PPOWER_CHANNEL_SUMMARY;
+
+typedef struct _DEVICE_OBJECT_POWER_EXTENSION
+{
+ ULONG IdleCount;
+ ULONG ConservationIdleTime;
+ ULONG PerformanceIdleTime;
+ PDEVICE_OBJECT DeviceObject;
+ LIST_ENTRY IdleList;
+ DEVICE_POWER_STATE State;
+ LIST_ENTRY NotifySourceList;
+ LIST_ENTRY NotifyTargetList;
+ POWER_CHANNEL_SUMMARY PowerChannelSummary;
+ LIST_ENTRY Volume;
+} DEVICE_OBJECT_POWER_EXTENSION, *PDEVICE_OBJECT_POWER_EXTENSION;
+
//
// Initialization routines
//
@@ -45,6 +267,21 @@
NTAPI
PoInitializePrcb(
IN PKPRCB Prcb
+);
+
+//
+// I/O Routines
+//
+VOID
+NTAPI
+PoInitializeDeviceObject(
+ IN OUT PDEVOBJ_EXTENSION DeviceObjectExtension
+);
+
+VOID
+NTAPI
+PoVolumeDevice(
+ IN PDEVICE_OBJECT DeviceObject
);
//
@@ -79,6 +316,32 @@
);
//
+// Shutdown routines
+//
+VOID
+NTAPI
+PopReadShutdownPolicy(
+ VOID
+);
+
+VOID
+NTAPI
+PopGracefulShutdown(
+ IN PVOID Context
+);
+
+VOID
+NTAPI
+PopFlushVolumes(
+ IN BOOLEAN ShuttingDown
+);
+
+//
// Global data inside the Power Manager
//
extern PDEVICE_NODE PopSystemPowerDeviceNode;
+extern KGUARDED_MUTEX PopVolumeLock;
+extern LIST_ENTRY PopVolumeDevices;
+extern KSPIN_LOCK PopDopeGlobalLock;
+extern POP_POWER_ACTION PopAction;
+
Modified: trunk/reactos/ntoskrnl/io/iomgr/device.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/device.c…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/device.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/device.c [iso-8859-1] Mon Mar 8 21:47:10 2010
@@ -17,9 +17,11 @@
/* 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 **********************************************************/
@@ -95,7 +97,15 @@
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;
@@ -104,46 +114,108 @@
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)
- {
- /* 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);
-
- /* Go to the next entry */
+
+ /* What phase? */
+ if (Phase == 0)
+ {
+ /* Shutdown PnP */
+ IoShutdownPnpDevices();
+
+ /* Loop first-chance shutdown notifications */
ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
&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(&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
@@ -843,6 +915,9 @@
/* 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;
@@ -932,6 +1007,9 @@
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);
@@ -1351,6 +1429,9 @@
/* Set the DO */
Entry->DeviceObject = DeviceObject;
+
+ /* Reference it so it doesn't go away */
+ ObReferenceObject(DeviceObject);
/* Insert it into the list */
ExInterlockedInsertHeadList(&LastChanceShutdownListHead,
@@ -1379,6 +1460,9 @@
/* Set the DO */
Entry->DeviceObject = DeviceObject;
+
+ /* Reference it so it doesn't go away */
+ ObReferenceObject(DeviceObject);
/* Insert it into the list */
ExInterlockedInsertHeadList(&ShutdownListHead,
@@ -1420,6 +1504,9 @@
/* Free the entry */
ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+
+ /* Get rid of our reference to it */
+ ObDereferenceObject(DeviceObject);
}
/* Go to the next entry */
@@ -1444,6 +1531,9 @@
/* Free the entry */
ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+
+ /* Get rid of our reference to it */
+ ObDereferenceObject(DeviceObject);
}
/* Go to the next entry */
Modified: trunk/reactos/ntoskrnl/io/iomgr/volume.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/volume.c…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/volume.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/volume.c [iso-8859-1] Mon Mar 8 21:47:10 2010
@@ -245,7 +245,7 @@
VOID
NTAPI
-IoShutdownRegisteredFileSystems(VOID)
+IopShutdownBaseFileSystems(IN PLIST_ENTRY ListHead)
{
PLIST_ENTRY ListEntry;
PDEVICE_OBJECT DeviceObject;
@@ -260,8 +260,8 @@
KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* Get the first entry and start looping */
- ListEntry = IopDiskFsListHead.Flink;
- while (ListEntry != &IopDiskFsListHead)
+ ListEntry = ListHead->Flink;
+ while (ListEntry != ListHead)
{
/* Get the device object */
DeviceObject = CONTAINING_RECORD(ListEntry,
Modified: trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl-generic.…
==============================================================================
--- trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] Mon Mar 8 21:47:10 2010
@@ -438,8 +438,10 @@
<file>obwait.c</file>
</directory>
<directory name="po">
+ <file>events.c</file>
<file>power.c</file>
- <file>events.c</file>
+ <file>poshtdwn.c</file>
+ <file>povolume.c</file>
</directory>
<directory name="ps">
<if property="ARCH" value="i386">
Added: trunk/reactos/ntoskrnl/po/poshtdwn.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/po/poshtdwn.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/po/poshtdwn.c (added)
+++ trunk/reactos/ntoskrnl/po/poshtdwn.c [iso-8859-1] Mon Mar 8 21:47:10 2010
@@ -1,0 +1,196 @@
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: ntoskrnl/po/poshtdwn.c
+ * PURPOSE: Power Manager Shutdown Code
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+
+ULONG PopShutdownPowerOffPolicy;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+NTAPI
+PopShutdownHandler(VOID)
+{
+ PUCHAR Logo1, Logo2;
+ ULONG i;
+
+ /* Stop all interrupts */
+ KeRaiseIrqlToDpcLevel();
+ _disable();
+
+ /* Do we have boot video */
+ if (InbvIsBootDriverInstalled())
+ {
+ /* Yes we do, cleanup for shutdown screen */
+ if (!InbvCheckDisplayOwnership()) InbvAcquireDisplayOwnership();
+ InbvResetDisplay();
+ InbvSolidColorFill(0, 0, 639, 479, 0);
+ InbvEnableDisplayString(TRUE);
+ InbvSetScrollRegion(0, 0, 639, 479);
+
+ /* Display shutdown logo and message */
+ Logo1 = InbvGetResourceAddress(IDB_SHUTDOWN_LOGO);
+ Logo2 = InbvGetResourceAddress(IDB_LOGO);
+ if ((Logo1) && (Logo2))
+ {
+ InbvBitBlt(Logo1, 215, 352);
+ InbvBitBlt(Logo2, 217, 111);
+ }
+ }
+ else
+ {
+ /* Do it in text-mode */
+ for (i = 0; i < 25; i++) InbvDisplayString("\n");
+ InbvDisplayString(" ");
+ InbvDisplayString("The system may be powered off now.\n");
+ }
+
+ /* Hang the system */
+ for (;;) HalHaltSystem();
+}
+
+VOID
+NTAPI
+PopShutdownSystem(IN POWER_ACTION SystemAction)
+{
+ /* Note should notify caller of NtPowerInformation(PowerShutdownNotification) */
+
+ /* Unload symbols */
+ DPRINT1("It's the final countdown...%lx\n", SystemAction);
+ DbgUnLoadImageSymbols(NULL, (PVOID)-1, 0);
+
+ /* Run the thread on the boot processor */
+ KeSetSystemAffinityThread(1);
+
+ /* Now check what the caller wants */
+ switch (SystemAction)
+ {
+ /* Reset */
+ case PowerActionShutdownReset:
+
+ /* Try platform driver first, then legacy */
+ //PopInvokeSystemStateHandler(PowerStateShutdownReset, NULL);
+ HalReturnToFirmware(HalRebootRoutine);
+ break;
+
+ case PowerActionShutdown:
+
+ /* Check for group policy that says to use "it is now safe" screen
*/
+ if (PopShutdownPowerOffPolicy)
+ {
+ /* FIXFIX: Switch to legacy shutdown handler */
+ //PopPowerStateHandlers[PowerStateShutdownOff].Handler =
PopShutdownHandler;
+ }
+
+ case PowerActionShutdownOff:
+
+ /* Call shutdown handler */
+ //PopInvokeSystemStateHandler(PowerStateShutdownOff, NULL);
+
+ /* ReactOS Hack */
+ PopSetSystemPowerState(PowerSystemShutdown);
+ PopShutdownHandler();
+
+ /* If that didn't work, call the HAL */
+ HalReturnToFirmware(HalPowerDownRoutine);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Anything else should not happen */
+ KeBugCheckEx(INTERNAL_POWER_ERROR, 5, 0, 0, 0);
+}
+
+VOID
+NTAPI
+PopGracefulShutdown(IN PVOID Context)
+{
+ /* First, the HAL handles any "end of boot" special functionality */
+ DPRINT1("HAL shutting down\n");
+ HalEndOfBoot();
+
+ /* In this step, the I/O manager does first-chance shutdown notification */
+ DPRINT1("I/O manager shutting down in phase 0\n");
+ IoShutdownSystem(0);
+
+ /* In this step, all workers are killed and hives are flushed */
+ DPRINT1("Configuration Manager shutting down\n");
+ CmShutdownSystem();
+
+ /* Note that modified pages should be written here (MiShutdownSystem) */
+
+ /* In this step, the I/O manager does last-chance shutdown notification */
+ DPRINT1("I/O manager shutting down in phase 1\n");
+ IoShutdownSystem(1);
+ CcWaitForCurrentLazyWriterActivity();
+
+ /* Note that here, we should broadcast the power IRP to devices */
+
+ /* In this step, the HAL disables any wake timers */
+ DPRINT1("Disabling wake timers\n");
+ HalSetWakeEnable(FALSE);
+
+ /* And finally the power request is sent */
+ DPRINT1("Taking the system down\n");
+ PopShutdownSystem(PopAction.Action);
+}
+
+VOID
+NTAPI
+PopReadShutdownPolicy(VOID)
+{
+ UNICODE_STRING KeyString;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ HANDLE KeyHandle;
+ ULONG Length;
+ UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
+ PKEY_VALUE_PARTIAL_INFORMATION Info = (PVOID)Buffer;
+
+ /* Setup object attributes */
+ RtlInitUnicodeString(&KeyString,
+
L"\\Registry\\Machine\\Software\\Policies\\Microsoft\\Windows NT");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyString,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+
+ /* Open the key */
+ Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
+ if (NT_SUCCESS(Status))
+ {
+ /* Open the policy value and query it */
+ RtlInitUnicodeString(&KeyString, L"DontPowerOffAfterShutdown");
+ Status = ZwQueryValueKey(KeyHandle,
+ &KeyString,
+ KeyValuePartialInformation,
+ &Info,
+ sizeof(Info),
+ &Length);
+ if ((NT_SUCCESS(Status)) && (Info->Type == REG_DWORD))
+ {
+ /* Read the policy */
+ PopShutdownPowerOffPolicy = *Info->Data == 1;
+ }
+
+ /* Close the key */
+ ZwClose(KeyHandle);
+ }
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
Propchange: trunk/reactos/ntoskrnl/po/poshtdwn.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/ntoskrnl/po/povolume.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/po/povolume.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/po/povolume.c (added)
+++ trunk/reactos/ntoskrnl/po/povolume.c [iso-8859-1] Mon Mar 8 21:47:10 2010
@@ -1,0 +1,334 @@
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: ntoskrnl/po/povolume.c
+ * PURPOSE: Power Manager DOPE and Volume Management
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+
+typedef struct _POP_FLUSH_VOLUME
+{
+ LIST_ENTRY List;
+ LONG Count;
+ KEVENT Wait;
+} POP_FLUSH_VOLUME, *PPOP_FLUSH_VOLUME;
+
+ULONG PopFlushPolicy = 0;
+
+KGUARDED_MUTEX PopVolumeLock;
+LIST_ENTRY PopVolumeDevices;
+KSPIN_LOCK PopDopeGlobalLock;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+PDEVICE_OBJECT_POWER_EXTENSION
+NTAPI
+PopGetDope(IN PDEVICE_OBJECT DeviceObject)
+{
+ PEXTENDED_DEVOBJ_EXTENSION DeviceExtension;
+ PDEVICE_OBJECT_POWER_EXTENSION Dope;
+ KIRQL OldIrql;
+ PAGED_CODE();
+
+ /* If the device already has the dope, return it */
+ DeviceExtension = IoGetDevObjExtension(DeviceObject);
+ if (DeviceExtension->Dope) goto Return;
+
+ /* Allocate some dope for the device */
+ Dope = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(DEVICE_OBJECT_POWER_EXTENSION),
+ 'Dope');
+ if (!Dope) goto Return;
+
+ /* Initialize the initial contents of the dope */
+ RtlZeroMemory(Dope, sizeof(DEVICE_OBJECT_POWER_EXTENSION));
+ Dope->DeviceObject = DeviceObject;
+ Dope->State = PowerDeviceUnspecified;
+ InitializeListHead(&Dope->IdleList);
+
+ /* Make sure only one caller can assign dope to a device */
+ KeAcquireSpinLock(&PopDopeGlobalLock, &OldIrql);
+
+ /* Make sure the device still has no dope */
+ if (!DeviceExtension->Dope)
+ {
+ /* Give the local dope to this device, and remember we won the race */
+ DeviceExtension->Dope = (PVOID)Dope;
+ Dope = NULL;
+ }
+
+ /* Allow other dope transactions now */
+ KeReleaseSpinLock(&PopDopeGlobalLock, OldIrql);
+
+ /* Check if someone other than us already assigned the dope, so free ours */
+ if (Dope) ExFreePoolWithTag(Dope, 'Dope');
+
+ /* Return the dope to the caller */
+Return:
+ return (PDEVICE_OBJECT_POWER_EXTENSION)DeviceExtension->Dope;
+}
+
+VOID
+NTAPI
+PoVolumeDevice(IN PDEVICE_OBJECT DeviceObject)
+{
+ PDEVICE_OBJECT_POWER_EXTENSION Dope;
+ PAGED_CODE();
+
+ /* Get dope from the device (if the device has no dope, it will receive some) */
+ DPRINT1("New volume: %p\n", DeviceObject);
+ Dope = PopGetDope(DeviceObject);
+ if (Dope)
+ {
+ /* Make sure we can flush safely */
+ DPRINT1("Acquiring volume lock\n");
+ KeAcquireGuardedMutex(&PopVolumeLock);
+
+ /* Add this volume into the list of power-manager volumes */
+ DPRINT1("Got DOPE: %p\n", Dope);
+ if (!Dope->Volume.Flink) InsertTailList(&PopVolumeDevices,
&Dope->Volume);
+
+ /* Allow flushes to go through */
+ KeReleaseGuardedMutex(&PopVolumeLock);
+ }
+}
+
+VOID
+NTAPI
+PopFlushVolumeWorker(IN PVOID Context)
+{
+ PPOP_FLUSH_VOLUME FlushContext = (PPOP_FLUSH_VOLUME)Context;
+ PDEVICE_OBJECT_POWER_EXTENSION Dope;
+ PLIST_ENTRY NextEntry;
+ NTSTATUS Status;
+ UCHAR Buffer[sizeof(OBJECT_NAME_INFORMATION) + 512];
+ POBJECT_NAME_INFORMATION NameInfo = (PVOID)Buffer;
+ ULONG Length;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE VolumeHandle;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ /* Acquire the flush lock since we're messing with the list */
+ KeAcquireGuardedMutex(&PopVolumeLock);
+
+ /* Loop the flush list */
+ while (!IsListEmpty(&FlushContext->List))
+ {
+ /* Grab the next (ie: current) entry and remove it */
+ NextEntry = FlushContext->List.Flink;
+ RemoveEntryList(NextEntry);
+
+ /* Add it back on the volume list */
+ InsertTailList(&PopVolumeDevices, NextEntry);
+
+ /* Done touching the volume list */
+ KeReleaseGuardedMutex(&PopVolumeLock);
+
+ /* Get the dope from the volume link */
+ Dope = CONTAINING_RECORD(NextEntry, DEVICE_OBJECT_POWER_EXTENSION, Volume);
+
+ /* Get the name */
+ Status = ObQueryNameString(Dope->DeviceObject,
+ NameInfo,
+ sizeof(Buffer),
+ &Length);
+ if ((NT_SUCCESS(Status)) && (NameInfo->Name.Buffer))
+ {
+ /* Open the volume */
+ DPRINT1("Opening: %wZ\n", &NameInfo->Name);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &NameInfo->Name,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ 0,
+ 0);
+ Status = ZwCreateFile(&VolumeHandle,
+ SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0,
+ NULL,
+ 0);
+ if (NT_SUCCESS(Status))
+ {
+ /* Flush it and close it */
+ DPRINT1("Sending flush to: %lx\n", VolumeHandle);
+ ZwFlushBuffersFile(VolumeHandle, &IoStatusBlock);
+ ZwClose(VolumeHandle);
+ }
+ }
+
+ /* Acquire the flush lock again since we'll touch the list */
+ KeAcquireGuardedMutex(&PopVolumeLock);
+ }
+
+ /* One more flush completed... if it was the last, signal the caller */
+ if (!--FlushContext->Count) KeSetEvent(&FlushContext->Wait,
IO_NO_INCREMENT, FALSE);
+
+ /* Serialize with flushers */
+ KeReleaseGuardedMutex(&PopVolumeLock);
+}
+
+VOID
+NTAPI
+PopFlushVolumes(IN BOOLEAN ShuttingDown)
+{
+ POP_FLUSH_VOLUME FlushContext = {{0}};
+ ULONG FlushPolicy;
+ UNICODE_STRING RegistryName = RTL_CONSTANT_STRING(L"\\Registry");
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE RegistryHandle;
+ PLIST_ENTRY NextEntry;
+ PDEVICE_OBJECT_POWER_EXTENSION Dope;
+ ULONG VolumeCount = 0;
+ NTSTATUS Status;
+ HANDLE ThreadHandle;
+ ULONG ThreadCount;
+
+ /* Setup the flush context */
+ InitializeListHead(&FlushContext.List);
+ KeInitializeEvent(&FlushContext.Wait, NotificationEvent, FALSE);
+
+ /* What to flush */
+ FlushPolicy = ShuttingDown ? 1 | 2 : PopFlushPolicy;
+ if ((FlushPolicy & 1))
+ {
+ /* Registry flush requested, so open it */
+ DPRINT1("Opening registry\n");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &RegistryName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+ Status = ZwOpenKey(&RegistryHandle, KEY_READ, &ObjectAttributes);
+ if (NT_SUCCESS(Status))
+ {
+ /* Flush the registry */
+ DPRINT1("Flushing registry\n");
+ ZwFlushKey(RegistryHandle);
+ ZwClose(RegistryHandle);
+ }
+ }
+
+ /* Serialize with other flushes */
+ KeAcquireGuardedMutex(&PopVolumeLock);
+
+ /* Scan the volume list */
+ NextEntry = PopVolumeDevices.Flink;
+ while (NextEntry != &PopVolumeDevices)
+ {
+ /* Get the dope from the link */
+ Dope = CONTAINING_RECORD(NextEntry, DEVICE_OBJECT_POWER_EXTENSION, Volume);
+
+ /* Grab the next entry now, since we'll be modifying the list */
+ NextEntry = NextEntry->Flink;
+
+ /* Make sure the object is mounted, writable, exists, and is not a floppy */
+ if (!(Dope->DeviceObject->Vpb->Flags & VPB_MOUNTED) ||
+ (Dope->DeviceObject->Characteristics & FILE_FLOPPY_DISKETTE) ||
+ (Dope->DeviceObject->Characteristics & FILE_READ_ONLY_DEVICE) ||
+ ((Dope->DeviceObject->Vpb->RealDevice) &&
+ (Dope->DeviceObject->Vpb->RealDevice->Characteristics &
FILE_FLOPPY_DISKETTE)))
+ {
+ /* Not flushable */
+ continue;
+ }
+
+ /* Remove it from the dope and add it to the flush context list */
+ RemoveEntryList(&Dope->Volume);
+ InsertTailList(&FlushContext.List, &Dope->Volume);
+
+ /* Next */
+ VolumeCount++;
+ }
+
+ /* Check if we should skip non-removable devices */
+ if (!(FlushPolicy & 2))
+ {
+ /* ReactOS only implements this routine for shutdown, which requires it */
+ UNIMPLEMENTED;
+ while (TRUE);
+ }
+
+ /* Check if there were no volumes at all */
+ if (!VolumeCount)
+ {
+ /* Nothing to do */
+ KeReleaseGuardedMutex(&PopVolumeLock);
+ return;
+ }
+
+ /* Allocate up to 8 flusher threads */
+ ThreadCount = min(VolumeCount, 8);
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+
+ /* We will ourselves become a flusher thread */
+ FlushContext.Count = 1;
+ ThreadCount--;
+
+ /* Look for any extra ones we might need */
+ while (ThreadCount > 0)
+ {
+ /* Create a new one */
+ ThreadCount--;
+ DPRINT1("Creating flush thread\n");
+ Status = PsCreateSystemThread(&ThreadHandle,
+ THREAD_ALL_ACCESS,
+ &ObjectAttributes,
+ 0L,
+ NULL,
+ PopFlushVolumeWorker,
+ &FlushContext);
+ if (NT_SUCCESS(Status))
+ {
+ /* One more created... */
+ FlushContext.Count++;
+ ZwClose(ThreadHandle);
+ }
+ }
+
+ /* Allow flushes to go through */
+ KeReleaseGuardedMutex(&PopVolumeLock);
+
+ /* Enter the flush work */
+ DPRINT1("Local flush\n");
+ PopFlushVolumeWorker(&FlushContext);
+
+ /* Wait for all flushes to be over */
+ DPRINT1("Waiting for flushes\n");
+ KeWaitForSingleObject(&FlushContext.Wait, Executive, KernelMode, FALSE, NULL);
+ DPRINT1("Flushes have completed\n");
+}
+
+VOID
+NTAPI
+PoInitializeDeviceObject(IN OUT PDEVOBJ_EXTENSION DeviceObjectExtension)
+{
+ PEXTENDED_DEVOBJ_EXTENSION DeviceExtension = (PVOID)DeviceObjectExtension;
+ PAGED_CODE();
+
+ /* Initialize the power flags */
+ DeviceExtension->PowerFlags = PowerSystemUnspecified & 0xF;
+ DeviceExtension->PowerFlags |= ((PowerDeviceUnspecified << 4) & 0xF0);
+
+ /* The device object is not on drugs yet */
+ DeviceExtension->Dope = NULL;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
Propchange: trunk/reactos/ntoskrnl/po/povolume.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/ntoskrnl/po/power.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/po/power.c?rev=46…
==============================================================================
--- trunk/reactos/ntoskrnl/po/power.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/po/power.c [iso-8859-1] Mon Mar 8 21:47:10 2010
@@ -24,6 +24,8 @@
PDEVICE_NODE PopSystemPowerDeviceNode = NULL;
BOOLEAN PopAcpiPresent = FALSE;
+POP_POWER_ACTION PopAction;
+WORK_QUEUE_ITEM PopShutdownWorkItem;
/* PRIVATE FUNCTIONS *********************************************************/
@@ -165,6 +167,13 @@
PopAcpiPresent = KeLoaderBlock->Extension->AcpiTable != NULL ? TRUE :
FALSE;
}
+
+ /* Initialize volume support */
+ InitializeListHead(&PopVolumeDevices);
+ KeInitializeGuardedMutex(&PopVolumeLock);
+
+ /* Initialize support for dope */
+ KeInitializeSpinLock(&PopDopeGlobalLock);
return TRUE;
}
@@ -636,3 +645,138 @@
/* All is good */
return STATUS_SUCCESS;
}
+
+NTSTATUS
+NTAPI
+NtSetSystemPowerState(IN POWER_ACTION SystemAction,
+ IN SYSTEM_POWER_STATE MinSystemState,
+ IN ULONG Flags)
+{
+ KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+ POP_POWER_ACTION Action = {0};
+ NTSTATUS Status;
+
+ /* Check for invalid parameter combinations */
+ if ((MinSystemState >= PowerSystemMaximum) ||
+ (MinSystemState <= PowerSystemUnspecified) ||
+ (SystemAction > PowerActionWarmEject) ||
+ (SystemAction < PowerActionReserved) ||
+ (Flags & ~(POWER_ACTION_QUERY_ALLOWED |
+ POWER_ACTION_UI_ALLOWED |
+ POWER_ACTION_OVERRIDE_APPS |
+ POWER_ACTION_LIGHTEST_FIRST |
+ POWER_ACTION_LOCK_CONSOLE |
+ POWER_ACTION_DISABLE_WAKES |
+ POWER_ACTION_CRITICAL)))
+ {
+ DPRINT1("NtSetSystemPowerState: Bad parameters!\n");
+ DPRINT1(" SystemAction: 0x%x\n", SystemAction);
+ DPRINT1(" MinSystemState: 0x%x\n",
MinSystemState);
+ DPRINT1(" Flags: 0x%x\n", Flags);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Check for user caller */
+ if (PreviousMode != KernelMode)
+ {
+ /* Check for shutdown permission */
+ if (!SeSinglePrivilegeCheck(SeShutdownPrivilege, PreviousMode))
+ {
+ /* Not granted */
+ DPRINT1("ERROR: Privilege not held for shutdown\n");
+ //return STATUS_PRIVILEGE_NOT_HELD; HACK!
+ }
+
+ /* Do it as a kernel-mode caller for consistency with system state */
+ return ZwSetSystemPowerState (SystemAction, MinSystemState, Flags);
+ }
+
+ /* Read policy settings (partial shutdown vs. full shutdown) */
+ if (SystemAction == PowerActionShutdown) PopReadShutdownPolicy();
+
+ /* Disable lazy flushing of registry */
+ DPRINT1("Stopping lazy flush\n");
+ CmSetLazyFlushState(FALSE);
+
+ /* Setup the power action */
+ Action.Action = SystemAction;
+ Action.Flags = Flags;
+
+ /* Notify callbacks */
+ DPRINT1("Notifying callbacks\n");
+ ExNotifyCallback(PowerStateCallback, (PVOID)3, NULL);
+
+ /* Swap in any worker thread stacks */
+ DPRINT1("Swapping worker threads\n");
+ ExSwapinWorkerThreads(FALSE);
+
+ /* Make our action global */
+ PopAction = Action;
+
+ /* Start power loop */
+ Status = STATUS_CANCELLED;
+ while (TRUE)
+ {
+ /* Break out if there's nothing to do */
+ if (Action.Action == PowerActionNone) break;
+
+ /* Check for first-pass or restart */
+ if (Status == STATUS_CANCELLED)
+ {
+ /* Check for shutdown action */
+ if ((PopAction.Action == PowerActionShutdown) ||
+ (PopAction.Action == PowerActionShutdownReset) ||
+ (PopAction.Action == PowerActionShutdownOff))
+ {
+ /* Set the action */
+ PopAction.Shutdown = TRUE;
+ }
+
+ /* Now we are good to go */
+ Status = STATUS_SUCCESS;
+ }
+
+ /* Check if we're still in an invalid status */
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Flush all volumes and the registry */
+ DPRINT1("Flushing volumes\n");
+ PopFlushVolumes(PopAction.Shutdown);
+
+ /* Set IRP for drivers */
+ PopAction.IrpMinor = IRP_MN_SET_POWER;
+ if (PopAction.Shutdown)
+ {
+ DPRINT1("Queueing shutdown thread\n");
+ /* Check if we are running in the system context */
+ if (PsGetCurrentProcess() != PsInitialSystemProcess)
+ {
+ /* We're not, so use a worker thread for shutdown */
+ ExInitializeWorkItem(&PopShutdownWorkItem,
+ &PopGracefulShutdown,
+ NULL);
+
+ ExQueueWorkItem(&PopShutdownWorkItem, CriticalWorkQueue);
+
+ /* Spend us -- when we wake up, the system is good to go down */
+ KeSuspendThread(KeGetCurrentThread());
+ Status = STATUS_SYSTEM_SHUTDOWN;
+ goto Exit;
+
+ }
+ else
+ {
+ /* Do the shutdown inline */
+ PopGracefulShutdown(NULL);
+ }
+ }
+
+ /* You should not have made it this far */
+ ASSERT(FALSE && "System is still up and running?!");
+ break;
+ }
+
+Exit:
+ /* We're done, return */
+ return Status;
+}