Set file object flag FO_MAILSLOT upon mailslot creation.
[reactos.git] / reactos / drivers / filesystems / ms / create.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/fs/ms/create.c
6 * PURPOSE: Mailslot filesystem
7 * PROGRAMMER: Eric Kohl <ekohl@rz-online.de>
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include "msfs.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17
18 /* FUNCTIONS *****************************************************************/
19
20 NTSTATUS DEFAULTAPI
21 MsfsCreate(PDEVICE_OBJECT DeviceObject,
22 PIRP Irp)
23 {
24 PIO_STACK_LOCATION IoStack;
25 PFILE_OBJECT FileObject;
26 PMSFS_DEVICE_EXTENSION DeviceExtension;
27 PMSFS_MAILSLOT Mailslot;
28 PMSFS_FCB Fcb;
29 PMSFS_MAILSLOT current = NULL;
30 PLIST_ENTRY current_entry;
31 KIRQL oldIrql;
32
33 DPRINT("MsfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
34
35 IoStack = IoGetCurrentIrpStackLocation(Irp);
36 DeviceExtension = DeviceObject->DeviceExtension;
37 FileObject = IoStack->FileObject;
38
39 DPRINT("Mailslot name: %wZ\n", &FileObject->FileName);
40
41 Fcb = ExAllocatePool(NonPagedPool, sizeof(MSFS_FCB));
42 if (Fcb == NULL)
43 {
44 Irp->IoStatus.Status = STATUS_NO_MEMORY;
45 Irp->IoStatus.Information = 0;
46
47 IoCompleteRequest(Irp, IO_NO_INCREMENT);
48
49 return(STATUS_NO_MEMORY);
50 }
51
52 KeLockMutex(&DeviceExtension->MailslotListLock);
53 current_entry = DeviceExtension->MailslotListHead.Flink;
54 while (current_entry != &DeviceExtension->MailslotListHead)
55 {
56 current = CONTAINING_RECORD(current_entry,
57 MSFS_MAILSLOT,
58 MailslotListEntry);
59
60 if (!RtlCompareUnicodeString(&FileObject->FileName, &current->Name, TRUE))
61 {
62 break;
63 }
64
65 current_entry = current_entry->Flink;
66 }
67
68 if (current_entry == &DeviceExtension->MailslotListHead)
69 {
70 ExFreePool(Fcb);
71 KeUnlockMutex(&DeviceExtension->MailslotListLock);
72
73 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
74 Irp->IoStatus.Information = 0;
75
76 IoCompleteRequest(Irp, IO_NO_INCREMENT);
77
78 return(STATUS_UNSUCCESSFUL);
79 }
80
81 Mailslot = current;
82
83 KeAcquireSpinLock(&Mailslot->FcbListLock, &oldIrql);
84 InsertTailList(&Mailslot->FcbListHead, &Fcb->FcbListEntry);
85 KeReleaseSpinLock(&Mailslot->FcbListLock, oldIrql);
86
87 Mailslot->ReferenceCount++;
88
89 Fcb->Mailslot = Mailslot;
90
91 KeUnlockMutex(&DeviceExtension->MailslotListLock);
92
93 FileObject->FsContext = Fcb;
94 FileObject->Flags |= FO_MAILSLOT;
95
96 Irp->IoStatus.Status = STATUS_SUCCESS;
97 Irp->IoStatus.Information = 0;
98
99 IoCompleteRequest(Irp, IO_NO_INCREMENT);
100
101 return(STATUS_SUCCESS);
102 }
103
104
105 NTSTATUS DEFAULTAPI
106 MsfsCreateMailslot(PDEVICE_OBJECT DeviceObject,
107 PIRP Irp)
108 {
109 PEXTENDED_IO_STACK_LOCATION IoStack;
110 PFILE_OBJECT FileObject;
111 PMSFS_DEVICE_EXTENSION DeviceExtension;
112 PMSFS_MAILSLOT Mailslot;
113 PMSFS_FCB Fcb;
114 KIRQL oldIrql;
115 PLIST_ENTRY current_entry;
116 PMSFS_MAILSLOT current;
117 PMAILSLOT_CREATE_PARAMETERS Buffer;
118
119 DPRINT("MsfsCreateMailslot(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
120
121 IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
122 DeviceExtension = DeviceObject->DeviceExtension;
123 FileObject = IoStack->FileObject;
124 Buffer = IoStack->Parameters.CreateMailslot.Parameters;
125
126 DPRINT("Mailslot name: %wZ\n", &FileObject->FileName);
127
128 Mailslot = ExAllocatePool(NonPagedPool, sizeof(MSFS_MAILSLOT));
129 if (Mailslot == NULL)
130 {
131 Irp->IoStatus.Status = STATUS_NO_MEMORY;
132 Irp->IoStatus.Information = 0;
133
134 IoCompleteRequest(Irp, IO_NO_INCREMENT);
135
136 return(STATUS_NO_MEMORY);
137 }
138
139 Mailslot->Name.Length = FileObject->FileName.Length;
140 Mailslot->Name.MaximumLength = Mailslot->Name.Length + sizeof(UNICODE_NULL);
141 Mailslot->Name.Buffer = ExAllocatePool(NonPagedPool, Mailslot->Name.MaximumLength);
142 if (Mailslot->Name.Buffer == NULL)
143 {
144 ExFreePool(Mailslot);
145
146 Irp->IoStatus.Status = STATUS_NO_MEMORY;
147 Irp->IoStatus.Information = 0;
148
149 IoCompleteRequest(Irp, IO_NO_INCREMENT);
150
151 return(STATUS_NO_MEMORY);
152 }
153
154 RtlCopyUnicodeString(&Mailslot->Name, &FileObject->FileName);
155
156 Fcb = ExAllocatePool(NonPagedPool, sizeof(MSFS_FCB));
157 if (Fcb == NULL)
158 {
159 ExFreePool(Mailslot);
160
161 Irp->IoStatus.Status = STATUS_NO_MEMORY;
162 Irp->IoStatus.Information = 0;
163
164 IoCompleteRequest(Irp, IO_NO_INCREMENT);
165
166 return(STATUS_NO_MEMORY);
167 }
168
169 Mailslot->ReferenceCount = 0;
170 InitializeListHead(&Mailslot->FcbListHead);
171 KeInitializeSpinLock(&Mailslot->FcbListLock);
172
173 Mailslot->MaxMessageSize = Buffer->MaximumMessageSize;
174 Mailslot->MessageCount = 0;
175 Mailslot->TimeOut = Buffer->ReadTimeout;
176 KeInitializeEvent(&Mailslot->MessageEvent,
177 NotificationEvent,
178 FALSE);
179
180 InitializeListHead(&Mailslot->MessageListHead);
181 KeInitializeSpinLock(&Mailslot->MessageListLock);
182
183 KeLockMutex(&DeviceExtension->MailslotListLock);
184 current_entry = DeviceExtension->MailslotListHead.Flink;
185 while (current_entry != &DeviceExtension->MailslotListHead)
186 {
187 current = CONTAINING_RECORD(current_entry,
188 MSFS_MAILSLOT,
189 MailslotListEntry);
190
191 if (!RtlCompareUnicodeString(&Mailslot->Name, &current->Name, TRUE))
192 {
193 break;
194 }
195
196 current_entry = current_entry->Flink;
197 }
198
199 if (current_entry != &DeviceExtension->MailslotListHead)
200 {
201 RtlFreeUnicodeString(&Mailslot->Name);
202 ExFreePool(Mailslot);
203
204 Mailslot = current;
205 }
206 else
207 {
208 InsertTailList(&DeviceExtension->MailslotListHead,
209 &Mailslot->MailslotListEntry);
210 }
211
212 KeAcquireSpinLock(&Mailslot->FcbListLock, &oldIrql);
213 InsertTailList(&Mailslot->FcbListHead, &Fcb->FcbListEntry);
214 KeReleaseSpinLock(&Mailslot->FcbListLock, oldIrql);
215
216 Mailslot->ReferenceCount++;
217 Mailslot->ServerFcb = Fcb;
218 Fcb->Mailslot = Mailslot;
219
220 KeUnlockMutex(&DeviceExtension->MailslotListLock);
221
222 FileObject->FsContext = Fcb;
223 FileObject->Flags |= FO_MAILSLOT;
224
225 Irp->IoStatus.Status = STATUS_SUCCESS;
226 Irp->IoStatus.Information = 0;
227
228 IoCompleteRequest(Irp, IO_NO_INCREMENT);
229
230 return(STATUS_SUCCESS);
231 }
232
233
234 NTSTATUS DEFAULTAPI
235 MsfsClose(PDEVICE_OBJECT DeviceObject,
236 PIRP Irp)
237 {
238 PIO_STACK_LOCATION IoStack;
239 PFILE_OBJECT FileObject;
240 PMSFS_DEVICE_EXTENSION DeviceExtension;
241 PMSFS_MAILSLOT Mailslot;
242 PMSFS_FCB Fcb;
243 PMSFS_MESSAGE Message;
244 KIRQL oldIrql;
245
246 DPRINT("MsfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
247
248 IoStack = IoGetCurrentIrpStackLocation(Irp);
249 DeviceExtension = DeviceObject->DeviceExtension;
250 FileObject = IoStack->FileObject;
251
252 KeLockMutex(&DeviceExtension->MailslotListLock);
253
254 if (DeviceExtension->MailslotListHead.Flink == &DeviceExtension->MailslotListHead)
255 {
256 KeUnlockMutex(&DeviceExtension->MailslotListLock);
257
258 Irp->IoStatus.Status = STATUS_SUCCESS;
259 Irp->IoStatus.Information = 0;
260
261 IoCompleteRequest(Irp, IO_NO_INCREMENT);
262
263 return(STATUS_SUCCESS);
264 }
265
266 Fcb = FileObject->FsContext;
267 Mailslot = Fcb->Mailslot;
268
269 DPRINT("Mailslot name: %wZ\n", &Mailslot->Name);
270
271 Mailslot->ReferenceCount--;
272 if (Mailslot->ServerFcb == Fcb)
273 {
274 /* delete all messages from message-list */
275 KeAcquireSpinLock(&Mailslot->MessageListLock, &oldIrql);
276
277 while (Mailslot->MessageListHead.Flink != &Mailslot->MessageListHead)
278 {
279 Message = CONTAINING_RECORD(Mailslot->MessageListHead.Flink,
280 MSFS_MESSAGE,
281 MessageListEntry);
282 RemoveEntryList(Mailslot->MessageListHead.Flink);
283 ExFreePool(Message);
284 }
285 Mailslot->MessageCount = 0;
286
287 KeReleaseSpinLock(&Mailslot->MessageListLock, oldIrql);
288 Mailslot->ServerFcb = NULL;
289 }
290
291 KeAcquireSpinLock(&Mailslot->FcbListLock, &oldIrql);
292 RemoveEntryList(&Fcb->FcbListEntry);
293 KeReleaseSpinLock(&Mailslot->FcbListLock, oldIrql);
294 ExFreePool(Fcb);
295 FileObject->FsContext = NULL;
296
297 if (Mailslot->ReferenceCount == 0)
298 {
299 DPRINT1("ReferenceCount == 0: Deleting mailslot data\n");
300 RtlFreeUnicodeString(&Mailslot->Name);
301 RemoveEntryList(&Mailslot->MailslotListEntry);
302 ExFreePool(Mailslot);
303 }
304
305 KeUnlockMutex(&DeviceExtension->MailslotListLock);
306
307 Irp->IoStatus.Status = STATUS_SUCCESS;
308 Irp->IoStatus.Information = 0;
309
310 IoCompleteRequest(Irp, IO_NO_INCREMENT);
311
312 return(STATUS_SUCCESS);
313 }
314
315 /* EOF */