xref: /reactos/drivers/filesystems/msfs/create.c (revision 50cf16b3)
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     PIO_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 = 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 
181     InitializeListHead(&Fcb->MessageListHead);
182     KeInitializeSpinLock(&Fcb->MessageListLock);
183 
184     KeInitializeSpinLock(&Fcb->QueueLock);
185     InitializeListHead(&Fcb->PendingIrpQueue);
186     IoCsqInitialize(&Fcb->CancelSafeQueue,
187                     MsfsInsertIrp,
188                     MsfsRemoveIrp,
189                     MsfsPeekNextIrp,
190                     MsfsAcquireLock,
191                     MsfsReleaseLock,
192                     MsfsCompleteCanceledIrp);
193 
194     KeLockMutex(&DeviceExtension->FcbListLock);
195     current_entry = DeviceExtension->FcbListHead.Flink;
196     while (current_entry != &DeviceExtension->FcbListHead)
197     {
198         current = CONTAINING_RECORD(current_entry,
199                                     MSFS_FCB,
200                                     FcbListEntry);
201 
202         if (!RtlCompareUnicodeString(&Fcb->Name, &current->Name, TRUE))
203             break;
204 
205         current_entry = current_entry->Flink;
206     }
207 
208     if (current_entry != &DeviceExtension->FcbListHead)
209     {
210         ExFreePoolWithTag(Fcb->Name.Buffer, 'NFsM');
211         ExFreePoolWithTag(Fcb, 'fFsM');
212         ExFreePoolWithTag(Ccb, 'cFsM');
213 
214         KeUnlockMutex(&DeviceExtension->FcbListLock);
215 
216         Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
217         Irp->IoStatus.Information = 0;
218 
219         IoCompleteRequest(Irp, IO_NO_INCREMENT);
220 
221         return STATUS_UNSUCCESSFUL;
222     }
223     else
224     {
225         InsertTailList(&DeviceExtension->FcbListHead,
226                        &Fcb->FcbListEntry);
227     }
228 
229     KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
230     InsertTailList(&Fcb->CcbListHead, &Ccb->CcbListEntry);
231     KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
232 
233     Fcb->ReferenceCount++;
234     Fcb->ServerCcb = Ccb;
235     Ccb->Fcb = Fcb;
236 
237     KeUnlockMutex(&DeviceExtension->FcbListLock);
238 
239     FileObject->FsContext = Fcb;
240     FileObject->FsContext2 = Ccb;
241     FileObject->Flags |= FO_MAILSLOT;
242 
243     Irp->IoStatus.Status = STATUS_SUCCESS;
244     Irp->IoStatus.Information = 0;
245 
246     IoCompleteRequest(Irp, IO_NO_INCREMENT);
247 
248     return STATUS_SUCCESS;
249 }
250 
251 
252 NTSTATUS DEFAULTAPI
253 MsfsClose(PDEVICE_OBJECT DeviceObject,
254           PIRP Irp)
255 {
256     PIO_STACK_LOCATION IoStack;
257     PFILE_OBJECT FileObject;
258     PMSFS_DEVICE_EXTENSION DeviceExtension;
259     PMSFS_FCB Fcb;
260     PMSFS_CCB Ccb;
261     PMSFS_MESSAGE Message;
262     KIRQL oldIrql;
263 
264     DPRINT("MsfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
265 
266     IoStack = IoGetCurrentIrpStackLocation(Irp);
267     DeviceExtension = DeviceObject->DeviceExtension;
268     FileObject = IoStack->FileObject;
269 
270     KeLockMutex(&DeviceExtension->FcbListLock);
271 
272     if (DeviceExtension->FcbListHead.Flink == &DeviceExtension->FcbListHead)
273     {
274         KeUnlockMutex(&DeviceExtension->FcbListLock);
275 
276         Irp->IoStatus.Status = STATUS_SUCCESS;
277         Irp->IoStatus.Information = 0;
278 
279         IoCompleteRequest(Irp, IO_NO_INCREMENT);
280 
281         return STATUS_SUCCESS;
282     }
283 
284     Fcb = FileObject->FsContext;
285     Ccb = FileObject->FsContext2;
286 
287     DPRINT("Mailslot name: %wZ\n", &Fcb->Name);
288 
289     Fcb->ReferenceCount--;
290     if (Fcb->ServerCcb == Ccb)
291     {
292         /* delete all messages from message-list */
293         KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
294 
295         while (Fcb->MessageListHead.Flink != &Fcb->MessageListHead)
296         {
297             Message = CONTAINING_RECORD(Fcb->MessageListHead.Flink,
298                                         MSFS_MESSAGE,
299                                         MessageListEntry);
300             RemoveEntryList(Fcb->MessageListHead.Flink);
301             ExFreePoolWithTag(Message, 'rFsM');
302         }
303 
304         Fcb->MessageCount = 0;
305 
306         KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
307         Fcb->ServerCcb = NULL;
308     }
309 
310     KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
311     RemoveEntryList(&Ccb->CcbListEntry);
312     KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
313     ExFreePoolWithTag(Ccb, 'cFsM');
314     FileObject->FsContext2 = NULL;
315 
316     if (Fcb->ReferenceCount == 0)
317     {
318         DPRINT("ReferenceCount == 0: Deleting mailslot data\n");
319         RemoveEntryList(&Fcb->FcbListEntry);
320         ExFreePoolWithTag(Fcb->Name.Buffer, 'NFsM');
321         ExFreePoolWithTag(Fcb, 'fFsM');
322     }
323 
324     KeUnlockMutex(&DeviceExtension->FcbListLock);
325 
326     Irp->IoStatus.Status = STATUS_SUCCESS;
327     Irp->IoStatus.Information = 0;
328 
329     IoCompleteRequest(Irp, IO_NO_INCREMENT);
330 
331     return STATUS_SUCCESS;
332 }
333 
334 /* EOF */
335