:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / fs / ms / create.c
1 /* $Id$
2  *
3  * COPYRIGHT:  See COPYING in the top level directory
4  * PROJECT:    ReactOS kernel
5  * FILE:       services/fs/ms/create.c
6  * PURPOSE:    Mailslot filesystem
7  * PROGRAMMER: Eric Kohl <ekohl@rz-online.de>
8  */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ddk/ntddk.h>
13 #include "msfs.h"
14
15 #define NDEBUG
16 #include <debug.h>
17
18
19 /* FUNCTIONS *****************************************************************/
20
21 NTSTATUS STDCALL
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_MAILSLOT Mailslot;
29    PMSFS_FCB Fcb;
30    PMSFS_MAILSLOT current;
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    Fcb = ExAllocatePool(NonPagedPool, sizeof(MSFS_FCB));
43    if (Fcb == NULL)
44      {
45         Irp->IoStatus.Status = STATUS_NO_MEMORY;
46         Irp->IoStatus.Information = 0;
47
48         IoCompleteRequest(Irp, IO_NO_INCREMENT);
49
50         return(STATUS_NO_MEMORY);
51      }
52
53    KeLockMutex(&DeviceExtension->MailslotListLock);
54    current_entry = DeviceExtension->MailslotListHead.Flink;
55    while (current_entry != &DeviceExtension->MailslotListHead)
56      {
57         current = CONTAINING_RECORD(current_entry,
58                                     MSFS_MAILSLOT,
59                                     MailslotListEntry);
60
61         if (!RtlCompareUnicodeString(&FileObject->FileName, &current->Name, TRUE))
62           {
63              break;
64           }
65
66         current_entry = current_entry->Flink;
67      }
68
69    if (current_entry == &DeviceExtension->MailslotListHead)
70      {
71         ExFreePool(Fcb);
72         KeUnlockMutex(&DeviceExtension->MailslotListLock);
73
74         Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
75         Irp->IoStatus.Information = 0;
76
77         IoCompleteRequest(Irp, IO_NO_INCREMENT);
78
79         return(STATUS_UNSUCCESSFUL);
80      }
81
82    Mailslot = current;
83
84    KeAcquireSpinLock(&Mailslot->FcbListLock, &oldIrql);
85    InsertTailList(&Mailslot->FcbListHead, &Fcb->FcbListEntry);
86    KeReleaseSpinLock(&Mailslot->FcbListLock, oldIrql);
87
88    Mailslot->ReferenceCount++;
89
90    Fcb->Mailslot = Mailslot;
91
92    KeUnlockMutex(&DeviceExtension->MailslotListLock);
93
94    FileObject->FsContext = Fcb;
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 NTSTATUS STDCALL
106 MsfsCreateMailslot(PDEVICE_OBJECT DeviceObject,
107                    PIRP Irp)
108 {
109    PIO_STACK_LOCATION IoStack;
110    PFILE_OBJECT FileObject;
111    PMSFS_DEVICE_EXTENSION DeviceExtension;
112    PMSFS_MAILSLOT Mailslot;
113    PMSFS_FCB Fcb;
114    KIRQL oldIrql;
115    PLIST_ENTRY current_entry;
116    PMSFS_MAILSLOT current;
117    PIO_MAILSLOT_CREATE_BUFFER Buffer;
118
119    DPRINT("MsfsCreateMailslot(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
120
121    IoStack = IoGetCurrentIrpStackLocation(Irp);
122    DeviceExtension = DeviceObject->DeviceExtension;
123    FileObject = IoStack->FileObject;
124    Buffer = (PIO_MAILSLOT_CREATE_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer;
125
126    DPRINT("Mailslot name: %wZ\n", &FileObject->FileName);
127
128    Mailslot = ExAllocatePool(NonPagedPool, sizeof(MSFS_MAILSLOT));
129    if (Mailslot == 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    if (!RtlCreateUnicodeString(&Mailslot->Name, FileObject->FileName.Buffer))
140      {
141         ExFreePool(Mailslot);
142         ExFreePool(Fcb);
143
144         Irp->IoStatus.Status = STATUS_NO_MEMORY;
145         Irp->IoStatus.Information = 0;
146
147         IoCompleteRequest(Irp, IO_NO_INCREMENT);
148
149         return(STATUS_NO_MEMORY);
150      }
151
152    Fcb = ExAllocatePool(NonPagedPool, sizeof(MSFS_FCB));
153    if (Fcb == NULL)
154      {
155         ExFreePool(Mailslot);
156
157         Irp->IoStatus.Status = STATUS_NO_MEMORY;
158         Irp->IoStatus.Information = 0;
159
160         IoCompleteRequest(Irp, IO_NO_INCREMENT);
161
162         return(STATUS_NO_MEMORY);
163      }
164
165    Mailslot->ReferenceCount = 0;
166    InitializeListHead(&Mailslot->FcbListHead);
167    KeInitializeSpinLock(&Mailslot->FcbListLock);
168
169    Mailslot->MaxMessageSize = Buffer->MaxMessageSize;
170    Mailslot->MessageCount = 0;
171    Mailslot->TimeOut = Buffer->TimeOut;
172    KeInitializeEvent(&Mailslot->MessageEvent,
173                      NotificationEvent,
174                      FALSE);
175
176    InitializeListHead(&Mailslot->MessageListHead);
177    KeInitializeSpinLock(&Mailslot->MessageListLock);
178
179    KeLockMutex(&DeviceExtension->MailslotListLock);
180    current_entry = DeviceExtension->MailslotListHead.Flink;
181    while (current_entry != &DeviceExtension->MailslotListHead)
182      {
183         current = CONTAINING_RECORD(current_entry,
184                                     MSFS_MAILSLOT,
185                                     MailslotListEntry);
186
187         if (!RtlCompareUnicodeString(&Mailslot->Name, &current->Name, TRUE))
188           {
189              break;
190           }
191
192         current_entry = current_entry->Flink;
193      }
194
195    if (current_entry != &DeviceExtension->MailslotListHead)
196      {
197         RtlFreeUnicodeString(&Mailslot->Name);
198         ExFreePool(Mailslot);
199         
200         Mailslot = current;
201      }
202    else
203      {
204         InsertTailList(&DeviceExtension->MailslotListHead,
205                        &Mailslot->MailslotListEntry);
206      }
207
208    KeAcquireSpinLock(&Mailslot->FcbListLock, &oldIrql);
209    InsertTailList(&Mailslot->FcbListHead, &Fcb->FcbListEntry);
210    KeReleaseSpinLock(&Mailslot->FcbListLock, oldIrql);
211
212    Mailslot->ReferenceCount++;
213    Mailslot->ServerFcb = Fcb;
214    Fcb->Mailslot = Mailslot;
215
216    KeUnlockMutex(&DeviceExtension->MailslotListLock);
217
218    FileObject->FsContext = Fcb;
219
220    Irp->IoStatus.Status = STATUS_SUCCESS;
221    Irp->IoStatus.Information = 0;
222
223    IoCompleteRequest(Irp, IO_NO_INCREMENT);
224
225    return(STATUS_SUCCESS);
226 }
227
228
229 NTSTATUS STDCALL
230 MsfsClose(PDEVICE_OBJECT DeviceObject,
231           PIRP Irp)
232 {
233    PIO_STACK_LOCATION IoStack;
234    PFILE_OBJECT FileObject;
235    PMSFS_DEVICE_EXTENSION DeviceExtension;
236    PMSFS_MAILSLOT Mailslot;
237    PMSFS_FCB Fcb;
238    PMSFS_MESSAGE Message;
239    KIRQL oldIrql;
240    
241    DPRINT("MsfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
242    
243    IoStack = IoGetCurrentIrpStackLocation(Irp);
244    DeviceExtension = DeviceObject->DeviceExtension;
245    FileObject = IoStack->FileObject;
246    
247    KeLockMutex(&DeviceExtension->MailslotListLock);
248    
249    if (DeviceExtension->MailslotListHead.Flink == &DeviceExtension->MailslotListHead)
250      {
251         KeUnlockMutex(&DeviceExtension->MailslotListLock);
252         
253         Irp->IoStatus.Status = STATUS_SUCCESS;
254         Irp->IoStatus.Information = 0;
255         
256         IoCompleteRequest(Irp, IO_NO_INCREMENT);
257         
258         return(STATUS_SUCCESS);
259      }
260    
261    Fcb = FileObject->FsContext;
262    Mailslot = Fcb->Mailslot;
263    
264    DPRINT("Mailslot name: %wZ\n", &Mailslot->Name);
265    
266    Mailslot->ReferenceCount--;
267    if (Mailslot->ServerFcb == Fcb)
268      {
269         /* delete all messages from message-list */
270         KeAcquireSpinLock(&Mailslot->MessageListLock, &oldIrql);
271         
272         while (Mailslot->MessageListHead.Flink != &Mailslot->MessageListHead)
273           {
274              Message = CONTAINING_RECORD(Mailslot->MessageListHead.Flink,
275                                          MSFS_MESSAGE,
276                                          MessageListEntry);
277              RemoveEntryList(Mailslot->MessageListHead.Flink);
278              ExFreePool(Message);
279           }
280         Mailslot->MessageCount = 0;
281         
282         KeReleaseSpinLock(&Mailslot->MessageListLock, oldIrql);
283         Mailslot->ServerFcb = NULL;
284      }
285    
286    KeAcquireSpinLock(&Mailslot->FcbListLock, &oldIrql);
287    RemoveEntryList(&Fcb->FcbListEntry);
288    KeReleaseSpinLock(&Mailslot->FcbListLock, oldIrql);
289    ExFreePool(Fcb);
290    FileObject->FsContext = NULL;
291    
292    if (Mailslot->ReferenceCount == 0)
293      {
294         DPRINT1("ReferenceCount == 0: Deleting mailslot data\n");
295         RtlFreeUnicodeString(&Mailslot->Name);
296         RemoveEntryList(&Mailslot->MailslotListEntry);
297         ExFreePool(Mailslot);
298      }
299    
300    KeUnlockMutex(&DeviceExtension->MailslotListLock);
301    
302    Irp->IoStatus.Status = STATUS_SUCCESS;
303    Irp->IoStatus.Information = 0;
304    
305    IoCompleteRequest(Irp, IO_NO_INCREMENT);
306    
307    return(STATUS_SUCCESS);
308 }
309
310 /* EOF */