[FASTFAT] Start implementing FAT32 statistics support
[reactos.git] / 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
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 */