8aaec240974c24503cb7cffc0af6c70df728fab6
[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 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 /*
83  * @implemented
84  */
85 NTSTATUS STDCALL IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
86 {
87    PSHUTDOWN_ENTRY Entry;
88
89    Entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(SHUTDOWN_ENTRY),
90                                  TAG_SHUTDOWN_ENTRY);
91    if (Entry == NULL)
92      return STATUS_INSUFFICIENT_RESOURCES;
93
94    Entry->DeviceObject = DeviceObject;
95
96    ExInterlockedInsertHeadList(&ShutdownListHead,
97                                &Entry->ShutdownList,
98                                &ShutdownListLock);
99
100    DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED;
101
102    return STATUS_SUCCESS;
103 }
104
105 /*
106  * @implemented
107  */
108 VOID STDCALL IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
109 {
110    PSHUTDOWN_ENTRY ShutdownEntry;
111    PLIST_ENTRY Entry;
112    KIRQL oldlvl;
113
114    Entry = ShutdownListHead.Flink;
115    while (Entry != &ShutdownListHead)
116      {
117         ShutdownEntry = CONTAINING_RECORD(Entry, SHUTDOWN_ENTRY, ShutdownList);
118         if (ShutdownEntry->DeviceObject == DeviceObject)
119           {
120             DeviceObject->Flags &= ~DO_SHUTDOWN_REGISTERED;
121
122             KeAcquireSpinLock(&ShutdownListLock,&oldlvl);
123             RemoveEntryList(Entry);
124             KeReleaseSpinLock(&ShutdownListLock,oldlvl);
125
126             ExFreePool(Entry);
127             return;
128           }
129
130         Entry = Entry->Flink;
131      }
132 }
133
134 /* EOF */