1023deb17dd280f0546bf7f8e32e0902a99339a3
[reactos.git] / 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 <ddk/ntddk.h>
15 #include <internal/pool.h>
16
17 #define NDEBUG
18 #include <internal/debug.h>
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 #ifndef LIBCAPTIVE
42
43 VOID IoShutdownRegisteredDevices(VOID)
44 {
45    PSHUTDOWN_ENTRY ShutdownEntry;
46    PLIST_ENTRY Entry;
47    IO_STATUS_BLOCK StatusBlock;
48    PIRP Irp;
49    KEVENT Event;
50    NTSTATUS Status;
51
52    Entry = ShutdownListHead.Flink;
53    while (Entry != &ShutdownListHead)
54      {
55         ShutdownEntry = CONTAINING_RECORD(Entry, SHUTDOWN_ENTRY, ShutdownList);
56
57         KeInitializeEvent (&Event,
58                            NotificationEvent,
59                            FALSE);
60
61         Irp = IoBuildSynchronousFsdRequest (IRP_MJ_SHUTDOWN,
62                                             ShutdownEntry->DeviceObject,
63                                             NULL,
64                                             0,
65                                             NULL,
66                                             &Event,
67                                             &StatusBlock);
68
69         Status = IoCallDriver (ShutdownEntry->DeviceObject,
70                                Irp);
71         if (Status == STATUS_PENDING)
72         {
73                 KeWaitForSingleObject (&Event,
74                                        Executive,
75                                        KernelMode,
76                                        FALSE,
77                                        NULL);
78         }
79
80         Entry = Entry->Flink;
81      }
82 }
83
84 #endif /* LIBCAPTIVE */
85
86 NTSTATUS STDCALL IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
87 {
88    PSHUTDOWN_ENTRY Entry;
89
90    Entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(SHUTDOWN_ENTRY),
91                                  TAG_SHUTDOWN_ENTRY);
92    if (Entry == NULL)
93      return STATUS_INSUFFICIENT_RESOURCES;
94
95    Entry->DeviceObject = DeviceObject;
96
97    ExInterlockedInsertHeadList(&ShutdownListHead,
98                                &Entry->ShutdownList,
99                                &ShutdownListLock);
100
101    DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED;
102
103    return STATUS_SUCCESS;
104 }
105
106 VOID STDCALL IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
107 {
108    PSHUTDOWN_ENTRY ShutdownEntry;
109    PLIST_ENTRY Entry;
110    KIRQL oldlvl;
111
112    Entry = ShutdownListHead.Flink;
113    while (Entry != &ShutdownListHead)
114      {
115         ShutdownEntry = CONTAINING_RECORD(Entry, SHUTDOWN_ENTRY, ShutdownList);
116         if (ShutdownEntry->DeviceObject == DeviceObject)
117           {
118             DeviceObject->Flags &= ~DO_SHUTDOWN_REGISTERED;
119
120             KeAcquireSpinLock(&ShutdownListLock,&oldlvl);
121             RemoveEntryList(Entry);
122             KeReleaseSpinLock(&ShutdownListLock,oldlvl);
123
124             ExFreePool(Entry);
125             return;
126           }
127
128         Entry = Entry->Flink;
129      }
130 }
131
132 /* EOF */