[FS_REC]
[reactos.git] / reactos / 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 #include <ndk/iotypes.h>
14
15 #define NDEBUG
16 #include <debug.h>
17
18 /* FUNCTIONS *****************************************************************/
19
20 /* Creates the client side */
21 NTSTATUS DEFAULTAPI
22 MsfsCreate(PDEVICE_OBJECT DeviceObject,
23 PIRP Irp)
24 {
25 PIO_STACK_LOCATION IoStack;
26 PFILE_OBJECT FileObject;
27 PMSFS_DEVICE_EXTENSION DeviceExtension;
28 PMSFS_FCB Fcb;
29 PMSFS_CCB Ccb;
30 PMSFS_FCB current = NULL;
31 PLIST_ENTRY current_entry;
32 KIRQL oldIrql;
33
34 DPRINT("MsfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
35
36 IoStack = IoGetCurrentIrpStackLocation(Irp);
37 DeviceExtension = DeviceObject->DeviceExtension;
38 FileObject = IoStack->FileObject;
39
40 DPRINT("Mailslot name: %wZ\n", &FileObject->FileName);
41
42 Ccb = ExAllocatePool(NonPagedPool, sizeof(MSFS_CCB));
43 if (Ccb == NULL)
44 {
45 Irp->IoStatus.Status = STATUS_NO_MEMORY;
46 Irp->IoStatus.Information = 0;
47
48 IoCompleteRequest(Irp, IO_NO_INCREMENT);
49 return STATUS_NO_MEMORY;
50 }
51
52 KeLockMutex(&DeviceExtension->FcbListLock);
53 current_entry = DeviceExtension->FcbListHead.Flink;
54 while (current_entry != &DeviceExtension->FcbListHead)
55 {
56 current = CONTAINING_RECORD(current_entry,
57 MSFS_FCB,
58 FcbListEntry);
59
60 if (!RtlCompareUnicodeString(&FileObject->FileName, &current->Name, TRUE))
61 break;
62
63 current_entry = current_entry->Flink;
64 }
65
66 if (current_entry == &DeviceExtension->FcbListHead)
67 {
68 ExFreePool(Ccb);
69 KeUnlockMutex(&DeviceExtension->FcbListLock);
70
71 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
72 Irp->IoStatus.Information = 0;
73
74 IoCompleteRequest(Irp, IO_NO_INCREMENT);
75
76 return STATUS_UNSUCCESSFUL;
77 }
78
79 Fcb = current;
80
81 KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
82 InsertTailList(&Fcb->CcbListHead, &Ccb->CcbListEntry);
83 KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
84
85 Fcb->ReferenceCount++;
86
87 Ccb->Fcb = Fcb;
88
89 KeUnlockMutex(&DeviceExtension->FcbListLock);
90
91 FileObject->FsContext = Fcb;
92 FileObject->FsContext2 = Ccb;
93 FileObject->Flags |= FO_MAILSLOT;
94
95 Irp->IoStatus.Status = STATUS_SUCCESS;
96 Irp->IoStatus.Information = 0;
97
98 IoCompleteRequest(Irp, IO_NO_INCREMENT);
99
100 return STATUS_SUCCESS;
101 }
102
103
104 /* Creates the server side */
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_FCB Fcb;
113 PMSFS_CCB Ccb;
114 KIRQL oldIrql;
115 PLIST_ENTRY current_entry;
116 PMSFS_FCB current = NULL;
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 Fcb = ExAllocatePool(NonPagedPool, sizeof(MSFS_FCB));
129 if (Fcb == 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 Fcb->Name.Length = FileObject->FileName.Length;
140 Fcb->Name.MaximumLength = Fcb->Name.Length + sizeof(UNICODE_NULL);
141 Fcb->Name.Buffer = ExAllocatePool(NonPagedPool, Fcb->Name.MaximumLength);
142 if (Fcb->Name.Buffer == NULL)
143 {
144 ExFreePool(Fcb);
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(&Fcb->Name, &FileObject->FileName);
155
156 Ccb = ExAllocatePool(NonPagedPool, sizeof(MSFS_CCB));
157 if (Ccb == NULL)
158 {
159 ExFreePool(Fcb->Name.Buffer);
160 ExFreePool(Fcb);
161
162 Irp->IoStatus.Status = STATUS_NO_MEMORY;
163 Irp->IoStatus.Information = 0;
164
165 IoCompleteRequest(Irp, IO_NO_INCREMENT);
166
167 return STATUS_NO_MEMORY;
168 }
169
170 Fcb->ReferenceCount = 0;
171 InitializeListHead(&Fcb->CcbListHead);
172 KeInitializeSpinLock(&Fcb->CcbListLock);
173
174 Fcb->MaxMessageSize = Buffer->MaximumMessageSize;
175 Fcb->MessageCount = 0;
176 Fcb->TimeOut = Buffer->ReadTimeout;
177 KeInitializeEvent(&Fcb->MessageEvent,
178 NotificationEvent,
179 FALSE);
180
181 InitializeListHead(&Fcb->MessageListHead);
182 KeInitializeSpinLock(&Fcb->MessageListLock);
183
184 KeLockMutex(&DeviceExtension->FcbListLock);
185 current_entry = DeviceExtension->FcbListHead.Flink;
186 while (current_entry != &DeviceExtension->FcbListHead)
187 {
188 current = CONTAINING_RECORD(current_entry,
189 MSFS_FCB,
190 FcbListEntry);
191
192 if (!RtlCompareUnicodeString(&Fcb->Name, &current->Name, TRUE))
193 break;
194
195 current_entry = current_entry->Flink;
196 }
197
198 if (current_entry != &DeviceExtension->FcbListHead)
199 {
200 ExFreePool(Fcb->Name.Buffer);
201 ExFreePool(Fcb);
202 ExFreePool(Ccb);
203
204 KeUnlockMutex(&DeviceExtension->FcbListLock);
205
206 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
207 Irp->IoStatus.Information = 0;
208
209 IoCompleteRequest(Irp, IO_NO_INCREMENT);
210
211 return STATUS_UNSUCCESSFUL;
212 }
213 else
214 {
215 InsertTailList(&DeviceExtension->FcbListHead,
216 &Fcb->FcbListEntry);
217 }
218
219 KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
220 InsertTailList(&Fcb->CcbListHead, &Ccb->CcbListEntry);
221 KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
222
223 Fcb->ReferenceCount++;
224 Fcb->ServerCcb = Ccb;
225 Ccb->Fcb = Fcb;
226
227 KeUnlockMutex(&DeviceExtension->FcbListLock);
228
229 FileObject->FsContext = Fcb;
230 FileObject->FsContext2 = Ccb;
231 FileObject->Flags |= FO_MAILSLOT;
232
233 Irp->IoStatus.Status = STATUS_SUCCESS;
234 Irp->IoStatus.Information = 0;
235
236 IoCompleteRequest(Irp, IO_NO_INCREMENT);
237
238 return STATUS_SUCCESS;
239 }
240
241
242 NTSTATUS DEFAULTAPI
243 MsfsClose(PDEVICE_OBJECT DeviceObject,
244 PIRP Irp)
245 {
246 PIO_STACK_LOCATION IoStack;
247 PFILE_OBJECT FileObject;
248 PMSFS_DEVICE_EXTENSION DeviceExtension;
249 PMSFS_FCB Fcb;
250 PMSFS_CCB Ccb;
251 PMSFS_MESSAGE Message;
252 KIRQL oldIrql;
253
254 DPRINT("MsfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
255
256 IoStack = IoGetCurrentIrpStackLocation(Irp);
257 DeviceExtension = DeviceObject->DeviceExtension;
258 FileObject = IoStack->FileObject;
259
260 KeLockMutex(&DeviceExtension->FcbListLock);
261
262 if (DeviceExtension->FcbListHead.Flink == &DeviceExtension->FcbListHead)
263 {
264 KeUnlockMutex(&DeviceExtension->FcbListLock);
265
266 Irp->IoStatus.Status = STATUS_SUCCESS;
267 Irp->IoStatus.Information = 0;
268
269 IoCompleteRequest(Irp, IO_NO_INCREMENT);
270
271 return STATUS_SUCCESS;
272 }
273
274 Fcb = FileObject->FsContext;
275 Ccb = FileObject->FsContext2;
276
277 DPRINT("Mailslot name: %wZ\n", &Fcb->Name);
278
279 Fcb->ReferenceCount--;
280 if (Fcb->ServerCcb == Ccb)
281 {
282 /* delete all messages from message-list */
283 KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
284
285 while (Fcb->MessageListHead.Flink != &Fcb->MessageListHead)
286 {
287 Message = CONTAINING_RECORD(Fcb->MessageListHead.Flink,
288 MSFS_MESSAGE,
289 MessageListEntry);
290 RemoveEntryList(Fcb->MessageListHead.Flink);
291 ExFreePool(Message);
292 }
293
294 Fcb->MessageCount = 0;
295
296 KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
297 Fcb->ServerCcb = NULL;
298 }
299
300 KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
301 RemoveEntryList(&Ccb->CcbListEntry);
302 KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
303 ExFreePool(Ccb);
304 FileObject->FsContext2 = NULL;
305
306 if (Fcb->ReferenceCount == 0)
307 {
308 DPRINT("ReferenceCount == 0: Deleting mailslot data\n");
309 RemoveEntryList(&Fcb->FcbListEntry);
310 ExFreePool(Fcb->Name.Buffer);
311 ExFreePool(Fcb);
312 }
313
314 KeUnlockMutex(&DeviceExtension->FcbListLock);
315
316 Irp->IoStatus.Status = STATUS_SUCCESS;
317 Irp->IoStatus.Information = 0;
318
319 IoCompleteRequest(Irp, IO_NO_INCREMENT);
320
321 return STATUS_SUCCESS;
322 }
323
324 /* EOF */