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