Kill NTOS headers. So long, and thanks for all the fish
[reactos.git] / reactos / drivers / fs / np / create.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: drivers/fs/np/create.c
6 * PURPOSE: Named pipe filesystem
7 * PROGRAMMER: David Welch <welch@cwcom.net>
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntifs.h>
13 #include <ndk/iotypes.h>
14 #include "npfs.h"
15
16 #define NDEBUG
17 #include <debug.h>
18
19 /* FUNCTIONS *****************************************************************/
20
21 static PNPFS_PIPE
22 NpfsFindPipe(PNPFS_DEVICE_EXTENSION DeviceExt,
23 PUNICODE_STRING PipeName)
24 {
25 PLIST_ENTRY CurrentEntry;
26 PNPFS_PIPE Pipe;
27
28 CurrentEntry = DeviceExt->PipeListHead.Flink;
29 while (CurrentEntry != &DeviceExt->PipeListHead)
30 {
31 Pipe = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE, PipeListEntry);
32 if (RtlCompareUnicodeString(PipeName,
33 &Pipe->PipeName,
34 TRUE) == 0)
35 {
36 DPRINT("<%wZ> = <%wZ>\n", PipeName, &Pipe->PipeName);
37 return Pipe;
38 }
39
40 CurrentEntry = CurrentEntry->Flink;
41 }
42
43 return NULL;
44 }
45
46
47 static PNPFS_FCB
48 NpfsFindListeningServerInstance(PNPFS_PIPE Pipe)
49 {
50 PLIST_ENTRY CurrentEntry;
51 PNPFS_WAITER_ENTRY Waiter;
52 KIRQL oldIrql;
53 PIRP Irp;
54
55 CurrentEntry = Pipe->WaiterListHead.Flink;
56 while (CurrentEntry != &Pipe->WaiterListHead)
57 {
58 Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
59 Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
60 if (Waiter->Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
61 {
62 DPRINT("Server found! Fcb %p\n", Waiter->Fcb);
63
64 IoAcquireCancelSpinLock(&oldIrql);
65 if (!Irp->Cancel)
66 {
67 IoSetCancelRoutine(Irp, NULL);
68 IoReleaseCancelSpinLock(oldIrql);
69 return Waiter->Fcb;
70 }
71 IoReleaseCancelSpinLock(oldIrql);
72 }
73
74 CurrentEntry = CurrentEntry->Flink;
75 }
76
77 return NULL;
78 }
79
80
81 static VOID
82 NpfsSignalAndRemoveListeningServerInstance(PNPFS_PIPE Pipe,
83 PNPFS_FCB Fcb)
84 {
85 PLIST_ENTRY CurrentEntry;
86 PNPFS_WAITER_ENTRY Waiter;
87 PIRP Irp;
88
89 CurrentEntry = Pipe->WaiterListHead.Flink;
90 while (CurrentEntry != &Pipe->WaiterListHead)
91 {
92 Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
93 if (Waiter->Fcb == Fcb)
94 {
95 DPRINT("Server found! Fcb %p\n", Waiter->Fcb);
96
97 RemoveEntryList(&Waiter->Entry);
98 Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
99 Irp->IoStatus.Status = STATUS_SUCCESS;
100 Irp->IoStatus.Information = 0;
101 IoCompleteRequest(Irp, IO_NO_INCREMENT);
102 break;
103 }
104 CurrentEntry = CurrentEntry->Flink;
105 }
106 }
107
108
109 NTSTATUS STDCALL
110 NpfsCreate(PDEVICE_OBJECT DeviceObject,
111 PIRP Irp)
112 {
113 PIO_STACK_LOCATION IoStack;
114 PFILE_OBJECT FileObject;
115 PNPFS_PIPE Pipe;
116 PNPFS_FCB ClientFcb;
117 PNPFS_FCB ServerFcb = NULL;
118 PNPFS_DEVICE_EXTENSION DeviceExt;
119 BOOLEAN SpecialAccess;
120
121 DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
122
123 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
124 IoStack = IoGetCurrentIrpStackLocation(Irp);
125 FileObject = IoStack->FileObject;
126 DPRINT("FileObject %p\n", FileObject);
127 DPRINT("FileName %wZ\n", &FileObject->FileName);
128
129 Irp->IoStatus.Information = 0;
130
131 SpecialAccess = ((IoStack->Parameters.Create.ShareAccess & 3) == 3);
132 if (SpecialAccess)
133 {
134 DPRINT("NpfsCreate() open client end for special use!\n");
135 }
136
137 /*
138 * Step 1. Find the pipe we're trying to open.
139 */
140 KeLockMutex(&DeviceExt->PipeListLock);
141 Pipe = NpfsFindPipe(DeviceExt,
142 &FileObject->FileName);
143 if (Pipe == NULL)
144 {
145 /* Not found, bail out with error. */
146 DPRINT("No pipe found!\n");
147 KeUnlockMutex(&DeviceExt->PipeListLock);
148 Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
149 IoCompleteRequest(Irp, IO_NO_INCREMENT);
150 return STATUS_OBJECT_NAME_NOT_FOUND;
151 }
152
153 KeUnlockMutex(&DeviceExt->PipeListLock);
154
155 /*
156 * Acquire the lock for FCB lists. From now on no modifications to the
157 * FCB lists are allowed, because it can cause various misconsistencies.
158 */
159 KeLockMutex(&Pipe->FcbListLock);
160
161 /*
162 * Step 2. Create the client FCB.
163 */
164 ClientFcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
165 if (ClientFcb == NULL)
166 {
167 DPRINT("No memory!\n");
168 KeUnlockMutex(&Pipe->FcbListLock);
169 Irp->IoStatus.Status = STATUS_NO_MEMORY;
170 IoCompleteRequest(Irp, IO_NO_INCREMENT);
171 return STATUS_NO_MEMORY;
172 }
173
174 ClientFcb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
175 ClientFcb->Pipe = Pipe;
176 ClientFcb->PipeEnd = FILE_PIPE_CLIENT_END;
177 ClientFcb->OtherSide = NULL;
178 ClientFcb->PipeState = SpecialAccess ? 0 : FILE_PIPE_DISCONNECTED_STATE;
179 InitializeListHead(&ClientFcb->ReadRequestListHead);
180
181 DPRINT("Fcb: %x\n", ClientFcb);
182
183 /* Initialize data list. */
184 if (Pipe->OutboundQuota)
185 {
186 ClientFcb->Data = ExAllocatePool(PagedPool, Pipe->OutboundQuota);
187 if (ClientFcb->Data == NULL)
188 {
189 DPRINT("No memory!\n");
190 ExFreePool(ClientFcb);
191 KeUnlockMutex(&Pipe->FcbListLock);
192 Irp->IoStatus.Status = STATUS_NO_MEMORY;
193 IoCompleteRequest(Irp, IO_NO_INCREMENT);
194 return STATUS_NO_MEMORY;
195 }
196 }
197 else
198 {
199 ClientFcb->Data = NULL;
200 }
201
202 ClientFcb->ReadPtr = ClientFcb->Data;
203 ClientFcb->WritePtr = ClientFcb->Data;
204 ClientFcb->ReadDataAvailable = 0;
205 ClientFcb->WriteQuotaAvailable = Pipe->OutboundQuota;
206 ClientFcb->MaxDataLength = Pipe->OutboundQuota;
207 ExInitializeFastMutex(&ClientFcb->DataListLock);
208 KeInitializeEvent(&ClientFcb->ConnectEvent, SynchronizationEvent, FALSE);
209 KeInitializeEvent(&ClientFcb->ReadEvent, SynchronizationEvent, FALSE);
210 KeInitializeEvent(&ClientFcb->WriteEvent, SynchronizationEvent, FALSE);
211
212
213 /*
214 * Step 3. Search for listening server FCB.
215 */
216
217 if (!SpecialAccess)
218 {
219 /*
220 * WARNING: Point of no return! Once we get the server FCB it's
221 * possible that we completed a wait request and so we have to
222 * complete even this request.
223 */
224
225 ServerFcb = NpfsFindListeningServerInstance(Pipe);
226 if (ServerFcb == NULL)
227 {
228 PLIST_ENTRY CurrentEntry;
229 PNPFS_FCB Fcb;
230
231 /*
232 * If no waiting server FCB was found then try to pick
233 * one of the listing server FCB on the pipe.
234 */
235
236 CurrentEntry = Pipe->ServerFcbListHead.Flink;
237 while (CurrentEntry != &Pipe->ServerFcbListHead)
238 {
239 Fcb = CONTAINING_RECORD(CurrentEntry, NPFS_FCB, FcbListEntry);
240 if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
241 {
242 ServerFcb = Fcb;
243 break;
244 }
245 CurrentEntry = CurrentEntry->Flink;
246 }
247
248 /*
249 * No one is listening to me?! I'm so lonely... :(
250 */
251
252 if (ServerFcb == NULL)
253 {
254 /* Not found, bail out with error for FILE_OPEN requests. */
255 DPRINT("No listening server fcb found!\n");
256 if (ClientFcb->Data)
257 ExFreePool(ClientFcb->Data);
258 KeUnlockMutex(&Pipe->FcbListLock);
259 Irp->IoStatus.Status = STATUS_PIPE_BUSY;
260 IoCompleteRequest(Irp, IO_NO_INCREMENT);
261 return STATUS_PIPE_BUSY;
262 }
263 }
264 else
265 {
266 /* Signal the server thread and remove it from the waiter list */
267 /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
268 NpfsSignalAndRemoveListeningServerInstance(Pipe, ServerFcb);
269 }
270 }
271 else if (IsListEmpty(&Pipe->ServerFcbListHead))
272 {
273 DPRINT("No server fcb found!\n");
274 KeUnlockMutex(&Pipe->FcbListLock);
275 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
276 IoCompleteRequest(Irp, IO_NO_INCREMENT);
277 return STATUS_UNSUCCESSFUL;
278 }
279
280 /*
281 * Step 4. Add the client FCB to a list and connect it if possible.
282 */
283
284 /* Add the client FCB to the pipe FCB list. */
285 InsertTailList(&Pipe->ClientFcbListHead, &ClientFcb->FcbListEntry);
286
287 /* Connect to listening server side */
288 if (ServerFcb)
289 {
290 ClientFcb->OtherSide = ServerFcb;
291 ServerFcb->OtherSide = ClientFcb;
292 ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
293 ServerFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
294 }
295
296 KeUnlockMutex(&Pipe->FcbListLock);
297
298 FileObject->FsContext = ClientFcb;
299
300 Irp->IoStatus.Status = STATUS_SUCCESS;
301 IoCompleteRequest(Irp, IO_NO_INCREMENT);
302
303 DPRINT("Success!\n");
304
305 return STATUS_SUCCESS;
306 }
307
308
309 NTSTATUS STDCALL
310 NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
311 PIRP Irp)
312 {
313 PIO_STACK_LOCATION IoStack;
314 PFILE_OBJECT FileObject;
315 PNPFS_DEVICE_EXTENSION DeviceExt;
316 PNPFS_PIPE Pipe;
317 PNPFS_FCB Fcb;
318 PNAMED_PIPE_CREATE_PARAMETERS Buffer;
319 BOOLEAN NewPipe = FALSE;
320
321 DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
322
323 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
324 IoStack = IoGetCurrentIrpStackLocation(Irp);
325 FileObject = IoStack->FileObject;
326 DPRINT("FileObject %p\n", FileObject);
327 DPRINT("Pipe name %wZ\n", &FileObject->FileName);
328
329 Buffer = IoStack->Parameters.CreatePipe.Parameters;
330
331 Irp->IoStatus.Information = 0;
332
333 Fcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
334 if (Fcb == NULL)
335 {
336 Irp->IoStatus.Status = STATUS_NO_MEMORY;
337 IoCompleteRequest(Irp, IO_NO_INCREMENT);
338 return STATUS_NO_MEMORY;
339 }
340
341 Fcb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
342 KeLockMutex(&DeviceExt->PipeListLock);
343
344 /*
345 * First search for existing Pipe with the same name.
346 */
347 Pipe = NpfsFindPipe(DeviceExt,
348 &FileObject->FileName);
349 if (Pipe != NULL)
350 {
351 /*
352 * Found Pipe with the same name. Check if we are
353 * allowed to use it.
354 */
355 KeUnlockMutex(&DeviceExt->PipeListLock);
356
357 if (Pipe->CurrentInstances >= Pipe->MaximumInstances)
358 {
359 DPRINT("Out of instances.\n");
360 ExFreePool(Fcb);
361 Irp->IoStatus.Status = STATUS_PIPE_BUSY;
362 IoCompleteRequest(Irp, IO_NO_INCREMENT);
363 return STATUS_PIPE_BUSY;
364 }
365
366 /* FIXME: Check pipe modes also! */
367 if (Pipe->MaximumInstances != Buffer->MaximumInstances ||
368 Pipe->TimeOut.QuadPart != Buffer->DefaultTimeout.QuadPart)
369 {
370 DPRINT("Asked for invalid pipe mode.\n");
371 ExFreePool(Fcb);
372 Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
373 IoCompleteRequest(Irp, IO_NO_INCREMENT);
374 return STATUS_ACCESS_DENIED;
375 }
376 }
377 else
378 {
379 NewPipe = TRUE;
380 Pipe = ExAllocatePool(NonPagedPool, sizeof(NPFS_PIPE));
381 if (Pipe == NULL)
382 {
383 KeUnlockMutex(&DeviceExt->PipeListLock);
384 Irp->IoStatus.Status = STATUS_NO_MEMORY;
385 Irp->IoStatus.Information = 0;
386 IoCompleteRequest(Irp, IO_NO_INCREMENT);
387 return STATUS_NO_MEMORY;
388 }
389
390 Pipe->PipeName.Length = FileObject->FileName.Length;
391 Pipe->PipeName.MaximumLength = Pipe->PipeName.Length + sizeof(UNICODE_NULL);
392 Pipe->PipeName.Buffer = ExAllocatePool(NonPagedPool, Pipe->PipeName.MaximumLength);
393 if (Pipe->PipeName.Buffer == NULL)
394 {
395 KeUnlockMutex(&DeviceExt->PipeListLock);
396 ExFreePool(Pipe);
397 ExFreePool(Fcb);
398 Irp->IoStatus.Status = STATUS_NO_MEMORY;
399 Irp->IoStatus.Information = 0;
400 IoCompleteRequest(Irp, IO_NO_INCREMENT);
401 return STATUS_NO_MEMORY;
402 }
403
404 RtlCopyUnicodeString(&Pipe->PipeName, &FileObject->FileName);
405
406 InitializeListHead(&Pipe->ServerFcbListHead);
407 InitializeListHead(&Pipe->ClientFcbListHead);
408 InitializeListHead(&Pipe->WaiterListHead);
409 KeInitializeMutex(&Pipe->FcbListLock, 0);
410
411 Pipe->PipeType = Buffer->NamedPipeType;
412 Pipe->WriteMode = Buffer->ReadMode;
413 Pipe->ReadMode = Buffer->ReadMode;
414 Pipe->CompletionMode = Buffer->CompletionMode;
415 Pipe->PipeConfiguration = IoStack->Parameters.CreatePipe.Options & 0x3;
416 Pipe->MaximumInstances = Buffer->MaximumInstances;
417 Pipe->CurrentInstances = 0;
418 Pipe->TimeOut = Buffer->DefaultTimeout;
419 if (!(IoStack->Parameters.Create.Options & FILE_PIPE_OUTBOUND) ||
420 IoStack->Parameters.Create.Options & FILE_PIPE_FULL_DUPLEX)
421 {
422 if (Buffer->InboundQuota == 0)
423 {
424 Pipe->InboundQuota = DeviceExt->DefaultQuota;
425 }
426 else
427 {
428 Pipe->InboundQuota = PAGE_ROUND_UP(Buffer->InboundQuota);
429 if (Pipe->InboundQuota < DeviceExt->MinQuota)
430 {
431 Pipe->InboundQuota = DeviceExt->MinQuota;
432 }
433 else if (Pipe->InboundQuota > DeviceExt->MaxQuota)
434 {
435 Pipe->InboundQuota = DeviceExt->MaxQuota;
436 }
437 }
438 }
439 else
440 {
441 Pipe->InboundQuota = 0;
442 }
443
444 if (IoStack->Parameters.Create.Options & (FILE_PIPE_FULL_DUPLEX|FILE_PIPE_OUTBOUND))
445 {
446 if (Buffer->OutboundQuota == 0)
447 {
448 Pipe->OutboundQuota = DeviceExt->DefaultQuota;
449 }
450 else
451 {
452 Pipe->OutboundQuota = PAGE_ROUND_UP(Buffer->OutboundQuota);
453 if (Pipe->OutboundQuota < DeviceExt->MinQuota)
454 {
455 Pipe->OutboundQuota = DeviceExt->MinQuota;
456 }
457 else if (Pipe->OutboundQuota > DeviceExt->MaxQuota)
458 {
459 Pipe->OutboundQuota = DeviceExt->MaxQuota;
460 }
461 }
462 }
463 else
464 {
465 Pipe->OutboundQuota = 0;
466 }
467
468 InsertTailList(&DeviceExt->PipeListHead, &Pipe->PipeListEntry);
469 KeUnlockMutex(&DeviceExt->PipeListLock);
470 }
471
472 if (Pipe->InboundQuota)
473 {
474 Fcb->Data = ExAllocatePool(PagedPool, Pipe->InboundQuota);
475 if (Fcb->Data == NULL)
476 {
477 ExFreePool(Fcb);
478
479 if (NewPipe)
480 {
481 KeLockMutex(&DeviceExt->PipeListLock);
482 RemoveEntryList(&Pipe->PipeListEntry);
483 KeUnlockMutex(&DeviceExt->PipeListLock);
484 RtlFreeUnicodeString(&Pipe->PipeName);
485 ExFreePool(Pipe);
486 }
487
488 Irp->IoStatus.Status = STATUS_NO_MEMORY;
489 IoCompleteRequest(Irp, IO_NO_INCREMENT);
490 return STATUS_NO_MEMORY;
491 }
492 }
493 else
494 {
495 Fcb->Data = NULL;
496 }
497
498 Fcb->ReadPtr = Fcb->Data;
499 Fcb->WritePtr = Fcb->Data;
500 Fcb->ReadDataAvailable = 0;
501 Fcb->WriteQuotaAvailable = Pipe->InboundQuota;
502 Fcb->MaxDataLength = Pipe->InboundQuota;
503 InitializeListHead(&Fcb->ReadRequestListHead);
504 ExInitializeFastMutex(&Fcb->DataListLock);
505
506 Pipe->CurrentInstances++;
507
508 Fcb->Pipe = Pipe;
509 Fcb->PipeEnd = FILE_PIPE_SERVER_END;
510 Fcb->PipeState = FILE_PIPE_LISTENING_STATE;
511 Fcb->OtherSide = NULL;
512
513 DPRINT("Fcb: %x\n", Fcb);
514
515 KeInitializeEvent(&Fcb->ConnectEvent, SynchronizationEvent, FALSE);
516 KeInitializeEvent(&Fcb->ReadEvent, SynchronizationEvent, FALSE);
517 KeInitializeEvent(&Fcb->WriteEvent, SynchronizationEvent, FALSE);
518
519 KeLockMutex(&Pipe->FcbListLock);
520 InsertTailList(&Pipe->ServerFcbListHead, &Fcb->FcbListEntry);
521 KeUnlockMutex(&Pipe->FcbListLock);
522
523 FileObject->FsContext = Fcb;
524
525 Irp->IoStatus.Status = STATUS_SUCCESS;
526 IoCompleteRequest(Irp, IO_NO_INCREMENT);
527
528 DPRINT("Success!\n");
529
530 return STATUS_SUCCESS;
531 }
532
533
534 NTSTATUS STDCALL
535 NpfsCleanup(PDEVICE_OBJECT DeviceObject,
536 PIRP Irp)
537 {
538 PNPFS_DEVICE_EXTENSION DeviceExt;
539 PIO_STACK_LOCATION IoStack;
540 PFILE_OBJECT FileObject;
541 PNPFS_FCB Fcb, OtherSide;
542 PNPFS_PIPE Pipe;
543 BOOL Server;
544
545 DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
546
547 IoStack = IoGetCurrentIrpStackLocation(Irp);
548 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
549 FileObject = IoStack->FileObject;
550 Fcb = FileObject->FsContext;
551
552 if (Fcb == NULL)
553 {
554 DPRINT("Success!\n");
555 Irp->IoStatus.Status = STATUS_SUCCESS;
556 Irp->IoStatus.Information = 0;
557 IoCompleteRequest(Irp, IO_NO_INCREMENT);
558 return STATUS_SUCCESS;
559 }
560
561 DPRINT("Fcb %x\n", Fcb);
562 Pipe = Fcb->Pipe;
563
564 DPRINT("Cleaning pipe %wZ\n", &Pipe->PipeName);
565
566 KeLockMutex(&Pipe->FcbListLock);
567
568 Server = (Fcb->PipeEnd == FILE_PIPE_SERVER_END);
569
570 if (Server)
571 {
572 /* FIXME: Clean up existing connections here ?? */
573 DPRINT("Server\n");
574 }
575 else
576 {
577 DPRINT("Client\n");
578 }
579 if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
580 {
581 OtherSide = Fcb->OtherSide;
582 /* Lock the server first */
583 if (Server)
584 {
585 ExAcquireFastMutex(&Fcb->DataListLock);
586 ExAcquireFastMutex(&OtherSide->DataListLock);
587 }
588 else
589 {
590 ExAcquireFastMutex(&OtherSide->DataListLock);
591 ExAcquireFastMutex(&Fcb->DataListLock);
592 }
593 OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
594 OtherSide->OtherSide = NULL;
595 /*
596 * Signaling the write event. If is possible that an other
597 * thread waits for an empty buffer.
598 */
599 KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
600 KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
601 if (Server)
602 {
603 ExReleaseFastMutex(&Fcb->DataListLock);
604 ExReleaseFastMutex(&OtherSide->DataListLock);
605 }
606 else
607 {
608 ExReleaseFastMutex(&OtherSide->DataListLock);
609 ExReleaseFastMutex(&Fcb->DataListLock);
610 }
611 }
612 else if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
613 {
614 PLIST_ENTRY Entry;
615 PNPFS_WAITER_ENTRY WaitEntry = NULL;
616 BOOLEAN Complete = FALSE;
617 KIRQL oldIrql;
618 PIRP tmpIrp;
619
620 Entry = Fcb->Pipe->WaiterListHead.Flink;
621 while (Entry != &Fcb->Pipe->WaiterListHead)
622 {
623 WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry);
624 if (WaitEntry->Fcb == Fcb)
625 {
626 RemoveEntryList(Entry);
627 tmpIrp = CONTAINING_RECORD(WaitEntry, IRP, Tail.Overlay.DriverContext);
628 IoAcquireCancelSpinLock(&oldIrql);
629 if (!tmpIrp->Cancel)
630 {
631 IoSetCancelRoutine(tmpIrp, NULL);
632 Complete = TRUE;
633 }
634 IoReleaseCancelSpinLock(oldIrql);
635 if (Complete)
636 {
637 tmpIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
638 tmpIrp->IoStatus.Information = 0;
639 IoCompleteRequest(tmpIrp, IO_NO_INCREMENT);
640 }
641 break;
642 }
643 Entry = Entry->Flink;
644 }
645
646 }
647 Fcb->PipeState = FILE_PIPE_CLOSING_STATE;
648
649 KeUnlockMutex(&Pipe->FcbListLock);
650
651 ExAcquireFastMutex(&Fcb->DataListLock);
652 if (Fcb->Data)
653 {
654 ExFreePool(Fcb->Data);
655 Fcb->Data = NULL;
656 Fcb->ReadPtr = NULL;
657 Fcb->WritePtr = NULL;
658 }
659 ExReleaseFastMutex(&Fcb->DataListLock);
660
661 Irp->IoStatus.Status = STATUS_SUCCESS;
662 Irp->IoStatus.Information = 0;
663 IoCompleteRequest(Irp, IO_NO_INCREMENT);
664
665 DPRINT("Success!\n");
666
667 return STATUS_SUCCESS;
668 }
669
670 NTSTATUS STDCALL
671 NpfsClose(PDEVICE_OBJECT DeviceObject,
672 PIRP Irp)
673 {
674 PNPFS_DEVICE_EXTENSION DeviceExt;
675 PIO_STACK_LOCATION IoStack;
676 PFILE_OBJECT FileObject;
677 PNPFS_FCB Fcb;
678 PNPFS_PIPE Pipe;
679 BOOL Server;
680
681 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
682
683 IoStack = IoGetCurrentIrpStackLocation(Irp);
684 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
685 FileObject = IoStack->FileObject;
686 Fcb = FileObject->FsContext;
687
688 if (Fcb == NULL)
689 {
690 DPRINT("Success!\n");
691 Irp->IoStatus.Status = STATUS_SUCCESS;
692 Irp->IoStatus.Information = 0;
693 IoCompleteRequest(Irp, IO_NO_INCREMENT);
694 return STATUS_SUCCESS;
695 }
696
697 DPRINT("Fcb %x\n", Fcb);
698 Pipe = Fcb->Pipe;
699
700 DPRINT("Closing pipe %wZ\n", &Pipe->PipeName);
701
702 KeLockMutex(&Pipe->FcbListLock);
703
704 Server = (Fcb->PipeEnd == FILE_PIPE_SERVER_END);
705
706 if (Server)
707 {
708 DPRINT("Server\n");
709 Pipe->CurrentInstances--;
710 }
711 else
712 {
713 DPRINT("Client\n");
714 }
715
716 ASSERT (Fcb->PipeState == FILE_PIPE_CLOSING_STATE);
717
718 FileObject->FsContext = NULL;
719
720 RemoveEntryList(&Fcb->FcbListEntry);
721
722 ExFreePool(Fcb);
723
724 KeUnlockMutex(&Pipe->FcbListLock);
725
726 if (IsListEmpty(&Pipe->ServerFcbListHead) &&
727 IsListEmpty(&Pipe->ClientFcbListHead))
728 {
729 RtlFreeUnicodeString(&Pipe->PipeName);
730 KeLockMutex(&DeviceExt->PipeListLock);
731 RemoveEntryList(&Pipe->PipeListEntry);
732 KeUnlockMutex(&DeviceExt->PipeListLock);
733 ExFreePool(Pipe);
734 }
735
736 Irp->IoStatus.Status = STATUS_SUCCESS;
737 Irp->IoStatus.Information = 0;
738 IoCompleteRequest(Irp, IO_NO_INCREMENT);
739
740 DPRINT("Success!\n");
741
742 return STATUS_SUCCESS;
743 }
744
745 /* EOF */