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