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