[KS]
[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 #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
202 KeUnlockMutex(&DeviceExtension->FcbListLock);
203
204 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
205 Irp->IoStatus.Information = 0;
206
207 IoCompleteRequest(Irp, IO_NO_INCREMENT);
208
209 return STATUS_UNSUCCESSFUL;
210 }
211 else
212 {
213 InsertTailList(&DeviceExtension->FcbListHead,
214 &Fcb->FcbListEntry);
215 }
216
217 KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
218 InsertTailList(&Fcb->CcbListHead, &Ccb->CcbListEntry);
219 KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
220
221 Fcb->ReferenceCount++;
222 Fcb->ServerCcb = Ccb;
223 Ccb->Fcb = Fcb;
224
225 KeUnlockMutex(&DeviceExtension->FcbListLock);
226
227 FileObject->FsContext = Fcb;
228 FileObject->FsContext2 = Ccb;
229 FileObject->Flags |= FO_MAILSLOT;
230
231 Irp->IoStatus.Status = STATUS_SUCCESS;
232 Irp->IoStatus.Information = 0;
233
234 IoCompleteRequest(Irp, IO_NO_INCREMENT);
235
236 return STATUS_SUCCESS;
237 }
238
239
240 NTSTATUS DEFAULTAPI
241 MsfsClose(PDEVICE_OBJECT DeviceObject,
242 PIRP Irp)
243 {
244 PIO_STACK_LOCATION IoStack;
245 PFILE_OBJECT FileObject;
246 PMSFS_DEVICE_EXTENSION DeviceExtension;
247 PMSFS_FCB Fcb;
248 PMSFS_CCB Ccb;
249 PMSFS_MESSAGE Message;
250 KIRQL oldIrql;
251
252 DPRINT("MsfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
253
254 IoStack = IoGetCurrentIrpStackLocation(Irp);
255 DeviceExtension = DeviceObject->DeviceExtension;
256 FileObject = IoStack->FileObject;
257
258 KeLockMutex(&DeviceExtension->FcbListLock);
259
260 if (DeviceExtension->FcbListHead.Flink == &DeviceExtension->FcbListHead)
261 {
262 KeUnlockMutex(&DeviceExtension->FcbListLock);
263
264 Irp->IoStatus.Status = STATUS_SUCCESS;
265 Irp->IoStatus.Information = 0;
266
267 IoCompleteRequest(Irp, IO_NO_INCREMENT);
268
269 return STATUS_SUCCESS;
270 }
271
272 Fcb = FileObject->FsContext;
273 Ccb = FileObject->FsContext2;
274
275 DPRINT("Mailslot name: %wZ\n", &Fcb->Name);
276
277 Fcb->ReferenceCount--;
278 if (Fcb->ServerCcb == Ccb)
279 {
280 /* delete all messages from message-list */
281 KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
282
283 while (Fcb->MessageListHead.Flink != &Fcb->MessageListHead)
284 {
285 Message = CONTAINING_RECORD(Fcb->MessageListHead.Flink,
286 MSFS_MESSAGE,
287 MessageListEntry);
288 RemoveEntryList(Fcb->MessageListHead.Flink);
289 ExFreePool(Message);
290 }
291
292 Fcb->MessageCount = 0;
293
294 KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
295 Fcb->ServerCcb = NULL;
296 }
297
298 KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
299 RemoveEntryList(&Ccb->CcbListEntry);
300 KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
301 ExFreePool(Ccb);
302 FileObject->FsContext2 = NULL;
303
304 if (Fcb->ReferenceCount == 0)
305 {
306 DPRINT("ReferenceCount == 0: Deleting mailslot data\n");
307 RemoveEntryList(&Fcb->FcbListEntry);
308 ExFreePool(Fcb->Name.Buffer);
309 ExFreePool(Fcb);
310 }
311
312 KeUnlockMutex(&DeviceExtension->FcbListLock);
313
314 Irp->IoStatus.Status = STATUS_SUCCESS;
315 Irp->IoStatus.Information = 0;
316
317 IoCompleteRequest(Irp, IO_NO_INCREMENT);
318
319 return STATUS_SUCCESS;
320 }
321
322 /* EOF */