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