Use free Windows DDK and compile with latest MinGW releases.
[reactos.git] / reactos / ntoskrnl / io / shutdown.c
1 /* $Id: shutdown.c,v 1.6 2002/09/07 15:12:53 chorns Exp $
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
16 #define NDEBUG
17 #include <internal/debug.h>
18
19
20 /* LOCAL DATA ***************************************************************/
21
22 typedef struct _SHUTDOWN_ENTRY
23 {
24 LIST_ENTRY ShutdownList;
25 PDEVICE_OBJECT DeviceObject;
26 } SHUTDOWN_ENTRY, *PSHUTDOWN_ENTRY;
27
28 static LIST_ENTRY ShutdownListHead;
29 static KSPIN_LOCK ShutdownListLock;
30
31 #define TAG_SHUTDOWN_ENTRY TAG('S', 'H', 'U', 'T')
32
33 /* FUNCTIONS *****************************************************************/
34
35 VOID IoInitShutdownNotification (VOID)
36 {
37 InitializeListHead(&ShutdownListHead);
38 KeInitializeSpinLock(&ShutdownListLock);
39 }
40
41 VOID IoShutdownRegisteredDevices(VOID)
42 {
43 PSHUTDOWN_ENTRY ShutdownEntry;
44 PLIST_ENTRY Entry;
45 IO_STATUS_BLOCK StatusBlock;
46 PIRP Irp;
47 KEVENT Event;
48 NTSTATUS Status;
49
50 Entry = ShutdownListHead.Flink;
51 while (Entry != &ShutdownListHead)
52 {
53 ShutdownEntry = CONTAINING_RECORD(Entry, SHUTDOWN_ENTRY, ShutdownList);
54
55 KeInitializeEvent (&Event,
56 NotificationEvent,
57 FALSE);
58
59 Irp = IoBuildSynchronousFsdRequest (IRP_MJ_SHUTDOWN,
60 ShutdownEntry->DeviceObject,
61 NULL,
62 0,
63 NULL,
64 &Event,
65 &StatusBlock);
66
67 Status = IoCallDriver (ShutdownEntry->DeviceObject,
68 Irp);
69 if (Status == STATUS_PENDING)
70 {
71 KeWaitForSingleObject (&Event,
72 Executive,
73 KernelMode,
74 FALSE,
75 NULL);
76 }
77
78 Entry = Entry->Flink;
79 }
80 }
81
82 NTSTATUS STDCALL IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
83 {
84 PSHUTDOWN_ENTRY Entry;
85
86 Entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(SHUTDOWN_ENTRY),
87 TAG_SHUTDOWN_ENTRY);
88 if (Entry == NULL)
89 return STATUS_INSUFFICIENT_RESOURCES;
90
91 Entry->DeviceObject = DeviceObject;
92
93 ExInterlockedInsertHeadList(&ShutdownListHead,
94 &Entry->ShutdownList,
95 &ShutdownListLock);
96
97 DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED;
98
99 return STATUS_SUCCESS;
100 }
101
102 VOID STDCALL IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
103 {
104 PSHUTDOWN_ENTRY ShutdownEntry;
105 PLIST_ENTRY Entry;
106 KIRQL oldlvl;
107
108 Entry = ShutdownListHead.Flink;
109 while (Entry != &ShutdownListHead)
110 {
111 ShutdownEntry = CONTAINING_RECORD(Entry, SHUTDOWN_ENTRY, ShutdownList);
112 if (ShutdownEntry->DeviceObject == DeviceObject)
113 {
114 DeviceObject->Flags &= ~DO_SHUTDOWN_REGISTERED;
115
116 KeAcquireSpinLock(&ShutdownListLock,&oldlvl);
117 RemoveEntryList(Entry);
118 KeReleaseSpinLock(&ShutdownListLock,oldlvl);
119
120 ExFreePool(Entry);
121 return;
122 }
123
124 Entry = Entry->Flink;
125 }
126 }
127
128 /* EOF */