merge ROS Shell without integrated explorer part into trunk
[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 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_PIPE_CONNECTED;
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 if (RtlCreateUnicodeString(&Pipe->PipeName, FileObject->FileName.Buffer) == FALSE)
391 {
392 KeUnlockMutex(&DeviceExt->PipeListLock);
393 ExFreePool(Pipe);
394 ExFreePool(Fcb);
395 Irp->IoStatus.Status = STATUS_NO_MEMORY;
396 Irp->IoStatus.Information = 0;
397 IoCompleteRequest(Irp, IO_NO_INCREMENT);
398 return STATUS_NO_MEMORY;
399 }
400
401 InitializeListHead(&Pipe->ServerFcbListHead);
402 InitializeListHead(&Pipe->ClientFcbListHead);
403 InitializeListHead(&Pipe->WaiterListHead);
404 KeInitializeMutex(&Pipe->FcbListLock, 0);
405
406 Pipe->PipeType = Buffer->NamedPipeType;
407 Pipe->WriteMode = Buffer->ReadMode;
408 Pipe->ReadMode = Buffer->ReadMode;
409 Pipe->CompletionMode = Buffer->CompletionMode;
410 Pipe->PipeConfiguration = IoStack->Parameters.CreatePipe.Options & 0x3;
411 Pipe->MaximumInstances = Buffer->MaximumInstances;
412 Pipe->CurrentInstances = 0;
413 Pipe->TimeOut = Buffer->DefaultTimeout;
414 if (!(IoStack->Parameters.Create.Options & FILE_PIPE_OUTBOUND) ||
415 IoStack->Parameters.Create.Options & FILE_PIPE_FULL_DUPLEX)
416 {
417 if (Buffer->InboundQuota == 0)
418 {
419 Pipe->InboundQuota = DeviceExt->DefaultQuota;
420 }
421 else
422 {
423 Pipe->InboundQuota = PAGE_ROUND_UP(Buffer->InboundQuota);
424 if (Pipe->InboundQuota < DeviceExt->MinQuota)
425 {
426 Pipe->InboundQuota = DeviceExt->MinQuota;
427 }
428 else if (Pipe->InboundQuota > DeviceExt->MaxQuota)
429 {
430 Pipe->InboundQuota = DeviceExt->MaxQuota;
431 }
432 }
433 }
434 else
435 {
436 Pipe->InboundQuota = 0;
437 }
438
439 if (IoStack->Parameters.Create.Options & (FILE_PIPE_FULL_DUPLEX|FILE_PIPE_OUTBOUND))
440 {
441 if (Buffer->OutboundQuota == 0)
442 {
443 Pipe->OutboundQuota = DeviceExt->DefaultQuota;
444 }
445 else
446 {
447 Pipe->OutboundQuota = PAGE_ROUND_UP(Buffer->OutboundQuota);
448 if (Pipe->OutboundQuota < DeviceExt->MinQuota)
449 {
450 Pipe->OutboundQuota = DeviceExt->MinQuota;
451 }
452 else if (Pipe->OutboundQuota > DeviceExt->MaxQuota)
453 {
454 Pipe->OutboundQuota = DeviceExt->MaxQuota;
455 }
456 }
457 }
458 else
459 {
460 Pipe->OutboundQuota = 0;
461 }
462
463 InsertTailList(&DeviceExt->PipeListHead, &Pipe->PipeListEntry);
464 KeUnlockMutex(&DeviceExt->PipeListLock);
465 }
466
467 if (Pipe->InboundQuota)
468 {
469 Fcb->Data = ExAllocatePool(PagedPool, Pipe->InboundQuota);
470 if (Fcb->Data == NULL)
471 {
472 ExFreePool(Fcb);
473
474 if (NewPipe)
475 {
476 KeLockMutex(&DeviceExt->PipeListLock);
477 RemoveEntryList(&Pipe->PipeListEntry);
478 KeUnlockMutex(&DeviceExt->PipeListLock);
479 RtlFreeUnicodeString(&Pipe->PipeName);
480 ExFreePool(Pipe);
481 }
482
483 Irp->IoStatus.Status = STATUS_NO_MEMORY;
484 IoCompleteRequest(Irp, IO_NO_INCREMENT);
485 return STATUS_NO_MEMORY;
486 }
487 }
488 else
489 {
490 Fcb->Data = NULL;
491 }
492
493 Fcb->ReadPtr = Fcb->Data;
494 Fcb->WritePtr = Fcb->Data;
495 Fcb->ReadDataAvailable = 0;
496 Fcb->WriteQuotaAvailable = Pipe->InboundQuota;
497 Fcb->MaxDataLength = Pipe->InboundQuota;
498 InitializeListHead(&Fcb->ReadRequestListHead);
499 ExInitializeFastMutex(&Fcb->DataListLock);
500
501 Pipe->CurrentInstances++;
502
503 Fcb->Pipe = Pipe;
504 Fcb->PipeEnd = FILE_PIPE_SERVER_END;
505 Fcb->PipeState = FILE_PIPE_LISTENING_STATE;
506 Fcb->OtherSide = NULL;
507
508 DPRINT("Fcb: %x\n", Fcb);
509
510 KeInitializeEvent(&Fcb->ConnectEvent, SynchronizationEvent, FALSE);
511 KeInitializeEvent(&Fcb->ReadEvent, SynchronizationEvent, FALSE);
512 KeInitializeEvent(&Fcb->WriteEvent, SynchronizationEvent, FALSE);
513
514 KeLockMutex(&Pipe->FcbListLock);
515 InsertTailList(&Pipe->ServerFcbListHead, &Fcb->FcbListEntry);
516 KeUnlockMutex(&Pipe->FcbListLock);
517
518 FileObject->FsContext = Fcb;
519
520 Irp->IoStatus.Status = STATUS_SUCCESS;
521 IoCompleteRequest(Irp, IO_NO_INCREMENT);
522
523 DPRINT("Success!\n");
524
525 return STATUS_SUCCESS;
526 }
527
528
529 NTSTATUS STDCALL
530 NpfsCleanup(PDEVICE_OBJECT DeviceObject,
531 PIRP Irp)
532 {
533 PNPFS_DEVICE_EXTENSION DeviceExt;
534 PIO_STACK_LOCATION IoStack;
535 PFILE_OBJECT FileObject;
536 PNPFS_FCB Fcb, OtherSide;
537 PNPFS_PIPE Pipe;
538 BOOL Server;
539
540 DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
541
542 IoStack = IoGetCurrentIrpStackLocation(Irp);
543 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
544 FileObject = IoStack->FileObject;
545 Fcb = FileObject->FsContext;
546
547 if (Fcb == NULL)
548 {
549 DPRINT("Success!\n");
550 Irp->IoStatus.Status = STATUS_SUCCESS;
551 Irp->IoStatus.Information = 0;
552 IoCompleteRequest(Irp, IO_NO_INCREMENT);
553 return STATUS_SUCCESS;
554 }
555
556 DPRINT("Fcb %x\n", Fcb);
557 Pipe = Fcb->Pipe;
558
559 DPRINT("Cleaning pipe %wZ\n", &Pipe->PipeName);
560
561 KeLockMutex(&Pipe->FcbListLock);
562
563 Server = (Fcb->PipeEnd == FILE_PIPE_SERVER_END);
564
565 if (Server)
566 {
567 /* FIXME: Clean up existing connections here ?? */
568 DPRINT("Server\n");
569 }
570 else
571 {
572 DPRINT("Client\n");
573 }
574 if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
575 {
576 OtherSide = Fcb->OtherSide;
577 /* Lock the server first */
578 if (Server)
579 {
580 ExAcquireFastMutex(&Fcb->DataListLock);
581 ExAcquireFastMutex(&OtherSide->DataListLock);
582 }
583 else
584 {
585 ExAcquireFastMutex(&OtherSide->DataListLock);
586 ExAcquireFastMutex(&Fcb->DataListLock);
587 }
588 OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
589 OtherSide->OtherSide = NULL;
590 /*
591 * Signaling the write event. If is possible that an other
592 * thread waits for an empty buffer.
593 */
594 KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
595 KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
596 if (Server)
597 {
598 ExReleaseFastMutex(&Fcb->DataListLock);
599 ExReleaseFastMutex(&OtherSide->DataListLock);
600 }
601 else
602 {
603 ExReleaseFastMutex(&OtherSide->DataListLock);
604 ExReleaseFastMutex(&Fcb->DataListLock);
605 }
606 }
607 else if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
608 {
609 PLIST_ENTRY Entry;
610 PNPFS_WAITER_ENTRY WaitEntry = NULL;
611 BOOLEAN Complete = FALSE;
612 KIRQL oldIrql;
613 PIRP tmpIrp;
614
615 Entry = Fcb->Pipe->WaiterListHead.Flink;
616 while (Entry != &Fcb->Pipe->WaiterListHead)
617 {
618 WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry);
619 if (WaitEntry->Fcb == Fcb)
620 {
621 RemoveEntryList(Entry);
622 tmpIrp = CONTAINING_RECORD(WaitEntry, IRP, Tail.Overlay.DriverContext);
623 IoAcquireCancelSpinLock(&oldIrql);
624 if (!tmpIrp->Cancel)
625 {
626 IoSetCancelRoutine(tmpIrp, NULL);
627 Complete = TRUE;
628 }
629 IoReleaseCancelSpinLock(oldIrql);
630 if (Complete)
631 {
632 tmpIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
633 tmpIrp->IoStatus.Information = 0;
634 IoCompleteRequest(tmpIrp, IO_NO_INCREMENT);
635 }
636 break;
637 }
638 Entry = Entry->Flink;
639 }
640
641 }
642 Fcb->PipeState = FILE_PIPE_CLOSING_STATE;
643
644 KeUnlockMutex(&Pipe->FcbListLock);
645
646 ExAcquireFastMutex(&Fcb->DataListLock);
647 if (Fcb->Data)
648 {
649 ExFreePool(Fcb->Data);
650 Fcb->Data = NULL;
651 Fcb->ReadPtr = NULL;
652 Fcb->WritePtr = NULL;
653 }
654 ExReleaseFastMutex(&Fcb->DataListLock);
655
656 Irp->IoStatus.Status = STATUS_SUCCESS;
657 Irp->IoStatus.Information = 0;
658 IoCompleteRequest(Irp, IO_NO_INCREMENT);
659
660 DPRINT("Success!\n");
661
662 return STATUS_SUCCESS;
663 }
664
665 NTSTATUS STDCALL
666 NpfsClose(PDEVICE_OBJECT DeviceObject,
667 PIRP Irp)
668 {
669 PNPFS_DEVICE_EXTENSION DeviceExt;
670 PIO_STACK_LOCATION IoStack;
671 PFILE_OBJECT FileObject;
672 PNPFS_FCB Fcb;
673 PNPFS_PIPE Pipe;
674 BOOL Server;
675
676 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
677
678 IoStack = IoGetCurrentIrpStackLocation(Irp);
679 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
680 FileObject = IoStack->FileObject;
681 Fcb = FileObject->FsContext;
682
683 if (Fcb == NULL)
684 {
685 DPRINT("Success!\n");
686 Irp->IoStatus.Status = STATUS_SUCCESS;
687 Irp->IoStatus.Information = 0;
688 IoCompleteRequest(Irp, IO_NO_INCREMENT);
689 return STATUS_SUCCESS;
690 }
691
692 DPRINT("Fcb %x\n", Fcb);
693 Pipe = Fcb->Pipe;
694
695 DPRINT("Closing pipe %wZ\n", &Pipe->PipeName);
696
697 KeLockMutex(&Pipe->FcbListLock);
698
699 Server = (Fcb->PipeEnd == FILE_PIPE_SERVER_END);
700
701 if (Server)
702 {
703 DPRINT("Server\n");
704 Pipe->CurrentInstances--;
705 }
706 else
707 {
708 DPRINT("Client\n");
709 }
710
711 ASSERT (Fcb->PipeState == FILE_PIPE_CLOSING_STATE);
712
713 FileObject->FsContext = NULL;
714
715 RemoveEntryList(&Fcb->FcbListEntry);
716
717 ExFreePool(Fcb);
718
719 KeUnlockMutex(&Pipe->FcbListLock);
720
721 if (IsListEmpty(&Pipe->ServerFcbListHead) &&
722 IsListEmpty(&Pipe->ClientFcbListHead))
723 {
724 RtlFreeUnicodeString(&Pipe->PipeName);
725 KeLockMutex(&DeviceExt->PipeListLock);
726 RemoveEntryList(&Pipe->PipeListEntry);
727 KeUnlockMutex(&DeviceExt->PipeListLock);
728 ExFreePool(Pipe);
729 }
730
731 Irp->IoStatus.Status = STATUS_SUCCESS;
732 Irp->IoStatus.Information = 0;
733 IoCompleteRequest(Irp, IO_NO_INCREMENT);
734
735 DPRINT("Success!\n");
736
737 return STATUS_SUCCESS;
738 }
739
740 /* EOF */