migrate substitution keywords to SVN
[reactos.git] / reactos / ntoskrnl / io / shutdown.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/shutdown.c
6 * PURPOSE: Implements shutdown notification
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* LOCAL DATA ***************************************************************/
19
20 typedef struct _SHUTDOWN_ENTRY
21 {
22 LIST_ENTRY ShutdownList;
23 PDEVICE_OBJECT DeviceObject;
24 } SHUTDOWN_ENTRY, *PSHUTDOWN_ENTRY;
25
26 static LIST_ENTRY ShutdownListHead;
27 static KSPIN_LOCK ShutdownListLock;
28
29 #define TAG_SHUTDOWN_ENTRY TAG('S', 'H', 'U', 'T')
30
31 /* FUNCTIONS *****************************************************************/
32
33 VOID INIT_FUNCTION
34 IoInitShutdownNotification (VOID)
35 {
36 InitializeListHead(&ShutdownListHead);
37 KeInitializeSpinLock(&ShutdownListLock);
38 }
39
40 VOID IoShutdownRegisteredDevices(VOID)
41 {
42 PSHUTDOWN_ENTRY ShutdownEntry;
43 PLIST_ENTRY Entry;
44 IO_STATUS_BLOCK StatusBlock;
45 PIRP Irp;
46 KEVENT Event;
47 NTSTATUS Status;
48
49 Entry = ShutdownListHead.Flink;
50 while (Entry != &ShutdownListHead)
51 {
52 ShutdownEntry = CONTAINING_RECORD(Entry, SHUTDOWN_ENTRY, ShutdownList);
53
54 KeInitializeEvent (&Event,
55 NotificationEvent,
56 FALSE);
57
58 Irp = IoBuildSynchronousFsdRequest (IRP_MJ_SHUTDOWN,
59 ShutdownEntry->DeviceObject,
60 NULL,
61 0,
62 NULL,
63 &Event,
64 &StatusBlock);
65
66 Status = IoCallDriver (ShutdownEntry->DeviceObject,
67 Irp);
68 if (Status == STATUS_PENDING)
69 {
70 KeWaitForSingleObject (&Event,
71 Executive,
72 KernelMode,
73 FALSE,
74 NULL);
75 }
76
77 Entry = Entry->Flink;
78 }
79 }
80
81 /*
82 * @implemented
83 */
84 NTSTATUS STDCALL IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
85 {
86 PSHUTDOWN_ENTRY Entry;
87
88 Entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(SHUTDOWN_ENTRY),
89 TAG_SHUTDOWN_ENTRY);
90 if (Entry == NULL)
91 return STATUS_INSUFFICIENT_RESOURCES;
92
93 Entry->DeviceObject = DeviceObject;
94
95 ExInterlockedInsertHeadList(&ShutdownListHead,
96 &Entry->ShutdownList,
97 &ShutdownListLock);
98
99 DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED;
100
101 return STATUS_SUCCESS;
102 }
103
104 /*
105 * @implemented
106 */
107 VOID STDCALL IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
108 {
109 PSHUTDOWN_ENTRY ShutdownEntry;
110 PLIST_ENTRY Entry;
111 KIRQL oldlvl;
112
113 Entry = ShutdownListHead.Flink;
114 while (Entry != &ShutdownListHead)
115 {
116 ShutdownEntry = CONTAINING_RECORD(Entry, SHUTDOWN_ENTRY, ShutdownList);
117 if (ShutdownEntry->DeviceObject == DeviceObject)
118 {
119 DeviceObject->Flags &= ~DO_SHUTDOWN_REGISTERED;
120
121 KeAcquireSpinLock(&ShutdownListLock,&oldlvl);
122 RemoveEntryList(Entry);
123 KeReleaseSpinLock(&ShutdownListLock,oldlvl);
124
125 ExFreePool(Entry);
126 return;
127 }
128
129 Entry = Entry->Flink;
130 }
131 }
132
133 /* EOF */