[MSFS]
[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 * Nikita Pechenkin (n.pechenkin@mail.ru)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include "msfs.h"
13
14 #include <ndk/iotypes.h>
15
16 #define NDEBUG
17 #include <debug.h>
18
19 /* FUNCTIONS *****************************************************************/
20
21 /* Creates the client side */
22 NTSTATUS DEFAULTAPI
23 MsfsCreate(PDEVICE_OBJECT DeviceObject,
24 PIRP Irp)
25 {
26 PIO_STACK_LOCATION IoStack;
27 PFILE_OBJECT FileObject;
28 PMSFS_DEVICE_EXTENSION DeviceExtension;
29 PMSFS_FCB Fcb;
30 PMSFS_CCB Ccb;
31 PMSFS_FCB current = NULL;
32 PLIST_ENTRY current_entry;
33 KIRQL oldIrql;
34
35 DPRINT("MsfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
36
37 IoStack = IoGetCurrentIrpStackLocation(Irp);
38 DeviceExtension = DeviceObject->DeviceExtension;
39 FileObject = IoStack->FileObject;
40
41 DPRINT("Mailslot name: %wZ\n", &FileObject->FileName);
42
43 Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(MSFS_CCB), 'cFsM');
44 if (Ccb == NULL)
45 {
46 Irp->IoStatus.Status = STATUS_NO_MEMORY;
47 Irp->IoStatus.Information = 0;
48
49 IoCompleteRequest(Irp, IO_NO_INCREMENT);
50 return STATUS_NO_MEMORY;
51 }
52
53 KeLockMutex(&DeviceExtension->FcbListLock);
54 current_entry = DeviceExtension->FcbListHead.Flink;
55 while (current_entry != &DeviceExtension->FcbListHead)
56 {
57 current = CONTAINING_RECORD(current_entry,
58 MSFS_FCB,
59 FcbListEntry);
60
61 if (!RtlCompareUnicodeString(&FileObject->FileName, &current->Name, TRUE))
62 break;
63
64 current_entry = current_entry->Flink;
65 }
66
67 if (current_entry == &DeviceExtension->FcbListHead)
68 {
69 ExFreePoolWithTag(Ccb, 'cFsM');
70 KeUnlockMutex(&DeviceExtension->FcbListLock);
71
72 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
73 Irp->IoStatus.Information = 0;
74
75 IoCompleteRequest(Irp, IO_NO_INCREMENT);
76
77 return STATUS_UNSUCCESSFUL;
78 }
79
80 Fcb = current;
81
82 KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
83 InsertTailList(&Fcb->CcbListHead, &Ccb->CcbListEntry);
84 KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
85
86 Fcb->ReferenceCount++;
87
88 Ccb->Fcb = Fcb;
89
90 KeUnlockMutex(&DeviceExtension->FcbListLock);
91
92 FileObject->FsContext = Fcb;
93 FileObject->FsContext2 = Ccb;
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 /* Creates the server side */
106 NTSTATUS DEFAULTAPI
107 MsfsCreateMailslot(PDEVICE_OBJECT DeviceObject,
108 PIRP Irp)
109 {
110 PEXTENDED_IO_STACK_LOCATION IoStack;
111 PFILE_OBJECT FileObject;
112 PMSFS_DEVICE_EXTENSION DeviceExtension;
113 PMSFS_FCB Fcb;
114 PMSFS_CCB Ccb;
115 KIRQL oldIrql;
116 PLIST_ENTRY current_entry;
117 PMSFS_FCB current = NULL;
118 PMAILSLOT_CREATE_PARAMETERS Buffer;
119
120 DPRINT("MsfsCreateMailslot(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
121
122 IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
123 DeviceExtension = DeviceObject->DeviceExtension;
124 FileObject = IoStack->FileObject;
125 Buffer = IoStack->Parameters.CreateMailslot.Parameters;
126
127 DPRINT("Mailslot name: %wZ\n", &FileObject->FileName);
128
129 Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(MSFS_FCB), 'fFsM');
130 if (Fcb == NULL)
131 {
132 Irp->IoStatus.Status = STATUS_NO_MEMORY;
133 Irp->IoStatus.Information = 0;
134
135 IoCompleteRequest(Irp, IO_NO_INCREMENT);
136
137 return STATUS_NO_MEMORY;
138 }
139
140 Fcb->Name.Length = FileObject->FileName.Length;
141 Fcb->Name.MaximumLength = Fcb->Name.Length + sizeof(UNICODE_NULL);
142 Fcb->Name.Buffer = ExAllocatePoolWithTag(NonPagedPool,
143 Fcb->Name.MaximumLength,
144 'NFsM');
145 if (Fcb->Name.Buffer == NULL)
146 {
147 ExFreePoolWithTag(Fcb, 'fFsM');
148
149 Irp->IoStatus.Status = STATUS_NO_MEMORY;
150 Irp->IoStatus.Information = 0;
151
152 IoCompleteRequest(Irp, IO_NO_INCREMENT);
153
154 return STATUS_NO_MEMORY;
155 }
156
157 RtlCopyUnicodeString(&Fcb->Name, &FileObject->FileName);
158
159 Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(MSFS_CCB), 'cFsM');
160 if (Ccb == NULL)
161 {
162 ExFreePoolWithTag(Fcb->Name.Buffer, 'NFsM');
163 ExFreePoolWithTag(Fcb, 'fFsM');
164
165 Irp->IoStatus.Status = STATUS_NO_MEMORY;
166 Irp->IoStatus.Information = 0;
167
168 IoCompleteRequest(Irp, IO_NO_INCREMENT);
169
170 return STATUS_NO_MEMORY;
171 }
172
173 Fcb->ReferenceCount = 0;
174 InitializeListHead(&Fcb->CcbListHead);
175 KeInitializeSpinLock(&Fcb->CcbListLock);
176
177 Fcb->MaxMessageSize = Buffer->MaximumMessageSize;
178 Fcb->MessageCount = 0;
179 Fcb->TimeOut = Buffer->ReadTimeout;
180 KeInitializeEvent(&Fcb->MessageEvent,
181 NotificationEvent,
182 FALSE);
183
184 InitializeListHead(&Fcb->MessageListHead);
185 KeInitializeSpinLock(&Fcb->MessageListLock);
186
187 Fcb->WaitCount = 0;
188 KeInitializeSpinLock(&Fcb->QueueLock);
189 InitializeListHead(&Fcb->PendingIrpQueue);
190 IoCsqInitialize(&Fcb->CancelSafeQueue,
191 MsfsInsertIrp,
192 MsfsRemoveIrp,
193 MsfsPeekNextIrp,
194 MsfsAcquireLock,
195 MsfsReleaseLock,
196 MsfsCompleteCanceledIrp);
197
198 KeLockMutex(&DeviceExtension->FcbListLock);
199 current_entry = DeviceExtension->FcbListHead.Flink;
200 while (current_entry != &DeviceExtension->FcbListHead)
201 {
202 current = CONTAINING_RECORD(current_entry,
203 MSFS_FCB,
204 FcbListEntry);
205
206 if (!RtlCompareUnicodeString(&Fcb->Name, &current->Name, TRUE))
207 break;
208
209 current_entry = current_entry->Flink;
210 }
211
212 if (current_entry != &DeviceExtension->FcbListHead)
213 {
214 ExFreePoolWithTag(Fcb->Name.Buffer, 'NFsM');
215 ExFreePoolWithTag(Fcb, 'fFsM');
216 ExFreePoolWithTag(Ccb, 'cFsM');
217
218 KeUnlockMutex(&DeviceExtension->FcbListLock);
219
220 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
221 Irp->IoStatus.Information = 0;
222
223 IoCompleteRequest(Irp, IO_NO_INCREMENT);
224
225 return STATUS_UNSUCCESSFUL;
226 }
227 else
228 {
229 InsertTailList(&DeviceExtension->FcbListHead,
230 &Fcb->FcbListEntry);
231 }
232
233 KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
234 InsertTailList(&Fcb->CcbListHead, &Ccb->CcbListEntry);
235 KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
236
237 Fcb->ReferenceCount++;
238 Fcb->ServerCcb = Ccb;
239 Ccb->Fcb = Fcb;
240
241 KeUnlockMutex(&DeviceExtension->FcbListLock);
242
243 FileObject->FsContext = Fcb;
244 FileObject->FsContext2 = Ccb;
245 FileObject->Flags |= FO_MAILSLOT;
246
247 Irp->IoStatus.Status = STATUS_SUCCESS;
248 Irp->IoStatus.Information = 0;
249
250 IoCompleteRequest(Irp, IO_NO_INCREMENT);
251
252 return STATUS_SUCCESS;
253 }
254
255
256 NTSTATUS DEFAULTAPI
257 MsfsClose(PDEVICE_OBJECT DeviceObject,
258 PIRP Irp)
259 {
260 PIO_STACK_LOCATION IoStack;
261 PFILE_OBJECT FileObject;
262 PMSFS_DEVICE_EXTENSION DeviceExtension;
263 PMSFS_FCB Fcb;
264 PMSFS_CCB Ccb;
265 PMSFS_MESSAGE Message;
266 KIRQL oldIrql;
267
268 DPRINT("MsfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
269
270 IoStack = IoGetCurrentIrpStackLocation(Irp);
271 DeviceExtension = DeviceObject->DeviceExtension;
272 FileObject = IoStack->FileObject;
273
274 KeLockMutex(&DeviceExtension->FcbListLock);
275
276 if (DeviceExtension->FcbListHead.Flink == &DeviceExtension->FcbListHead)
277 {
278 KeUnlockMutex(&DeviceExtension->FcbListLock);
279
280 Irp->IoStatus.Status = STATUS_SUCCESS;
281 Irp->IoStatus.Information = 0;
282
283 IoCompleteRequest(Irp, IO_NO_INCREMENT);
284
285 return STATUS_SUCCESS;
286 }
287
288 Fcb = FileObject->FsContext;
289 Ccb = FileObject->FsContext2;
290
291 DPRINT("Mailslot name: %wZ\n", &Fcb->Name);
292
293 Fcb->ReferenceCount--;
294 if (Fcb->ServerCcb == Ccb)
295 {
296 /* delete all messages from message-list */
297 KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
298
299 while (Fcb->MessageListHead.Flink != &Fcb->MessageListHead)
300 {
301 Message = CONTAINING_RECORD(Fcb->MessageListHead.Flink,
302 MSFS_MESSAGE,
303 MessageListEntry);
304 RemoveEntryList(Fcb->MessageListHead.Flink);
305 ExFreePoolWithTag(Message, 'rFsM');
306 }
307
308 Fcb->MessageCount = 0;
309
310 KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
311 Fcb->ServerCcb = NULL;
312 }
313
314 KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
315 RemoveEntryList(&Ccb->CcbListEntry);
316 KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
317 ExFreePoolWithTag(Ccb, 'cFsM');
318 FileObject->FsContext2 = NULL;
319
320 if (Fcb->ReferenceCount == 0)
321 {
322 DPRINT("ReferenceCount == 0: Deleting mailslot data\n");
323 RemoveEntryList(&Fcb->FcbListEntry);
324 ExFreePoolWithTag(Fcb->Name.Buffer, 'NFsM');
325 ExFreePoolWithTag(Fcb, 'fFsM');
326 }
327
328 KeUnlockMutex(&DeviceExtension->FcbListLock);
329
330 Irp->IoStatus.Status = STATUS_SUCCESS;
331 Irp->IoStatus.Information = 0;
332
333 IoCompleteRequest(Irp, IO_NO_INCREMENT);
334
335 return STATUS_SUCCESS;
336 }
337
338 /* EOF */