Merge r51043 and r51044
[reactos.git] / reactos / drivers / filesystems / npfs / fsctrl.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/fs/np/fsctrl.c
5 * PURPOSE: Named pipe filesystem
6 * PROGRAMMER: David Welch <welch@cwcom.net>
7 * Eric Kohl
8 * Michael Martin
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include "npfs.h"
14
15 #define NDEBUG
16 #include <debug.h>
17
18 //#define USING_PROPER_NPFS_WAIT_SEMANTICS
19
20 /* FUNCTIONS *****************************************************************/
21
22 static DRIVER_CANCEL NpfsListeningCancelRoutine;
23 static VOID NTAPI
24 NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
25 IN PIRP Irp)
26 {
27 PNPFS_WAITER_ENTRY Waiter;
28
29 Waiter = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext;
30
31 DPRINT("NpfsListeningCancelRoutine() called for <%wZ>\n",
32 &Waiter->Ccb->Fcb->PipeName);
33
34 IoReleaseCancelSpinLock(Irp->CancelIrql);
35
36
37 KeLockMutex(&Waiter->Ccb->Fcb->CcbListLock);
38 RemoveEntryList(&Waiter->Entry);
39 KeUnlockMutex(&Waiter->Ccb->Fcb->CcbListLock);
40
41 Irp->IoStatus.Status = STATUS_CANCELLED;
42 Irp->IoStatus.Information = 0;
43 IoCompleteRequest(Irp, IO_NO_INCREMENT);
44 }
45
46
47 static NTSTATUS
48 NpfsAddListeningServerInstance(PIRP Irp,
49 PNPFS_CCB Ccb)
50 {
51 PNPFS_WAITER_ENTRY Entry;
52 KIRQL oldIrql;
53
54 Entry = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext;
55
56 Entry->Ccb = Ccb;
57
58 KeLockMutex(&Ccb->Fcb->CcbListLock);
59
60 IoMarkIrpPending(Irp);
61 InsertTailList(&Ccb->Fcb->WaiterListHead, &Entry->Entry);
62
63 IoAcquireCancelSpinLock(&oldIrql);
64 if (!Irp->Cancel)
65 {
66 (void)IoSetCancelRoutine(Irp, NpfsListeningCancelRoutine);
67 IoReleaseCancelSpinLock(oldIrql);
68 KeUnlockMutex(&Ccb->Fcb->CcbListLock);
69 return STATUS_PENDING;
70 }
71 IoReleaseCancelSpinLock(oldIrql);
72
73 RemoveEntryList(&Entry->Entry);
74
75 Irp->IoStatus.Status = STATUS_CANCELLED;
76 Irp->IoStatus.Information = 0;
77 IoCompleteRequest(Irp, IO_NO_INCREMENT);
78 KeUnlockMutex(&Ccb->Fcb->CcbListLock);
79
80 return STATUS_CANCELLED;
81 }
82
83
84 static NTSTATUS
85 NpfsConnectPipe(PIRP Irp,
86 PNPFS_CCB Ccb)
87 {
88 PIO_STACK_LOCATION IoStack;
89 PFILE_OBJECT FileObject;
90 ULONG Flags;
91 PLIST_ENTRY current_entry;
92 PNPFS_FCB Fcb;
93 PNPFS_CCB ClientCcb;
94 NTSTATUS Status;
95
96 DPRINT("NpfsConnectPipe()\n");
97
98 /* Fail, if the CCB is not a pipe CCB */
99 if (Ccb->Type != CCB_PIPE)
100 {
101 DPRINT1("Not a pipe\n");
102 return STATUS_ILLEGAL_FUNCTION;
103 }
104
105 /* Fail, if the CCB is not a server end CCB */
106 if (Ccb->PipeEnd != FILE_PIPE_SERVER_END)
107 {
108 DPRINT1("Not the server end\n");
109 return STATUS_ILLEGAL_FUNCTION;
110 }
111
112 if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE)
113 {
114 KeResetEvent(&Ccb->ConnectEvent);
115 return STATUS_PIPE_CONNECTED;
116 }
117
118 if (Ccb->PipeState == FILE_PIPE_CLOSING_STATE)
119 return STATUS_PIPE_CLOSING;
120
121 DPRINT("Waiting for connection...\n");
122
123 Fcb = Ccb->Fcb;
124 IoStack = IoGetCurrentIrpStackLocation(Irp);
125 FileObject = IoStack->FileObject;
126 Flags = FileObject->Flags;
127
128 /* search for a listening client fcb */
129 KeLockMutex(&Fcb->CcbListLock);
130
131 current_entry = Fcb->ClientCcbListHead.Flink;
132 while (current_entry != &Fcb->ClientCcbListHead)
133 {
134 ClientCcb = CONTAINING_RECORD(current_entry,
135 NPFS_CCB,
136 CcbListEntry);
137
138 if (ClientCcb->PipeState == 0)
139 {
140 /* found a passive (waiting) client CCB */
141 DPRINT("Passive (waiting) client CCB found -- wake the client\n");
142 KeSetEvent(&ClientCcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
143 break;
144 }
145
146 #if 0
147 if (ClientCcb->PipeState == FILE_PIPE_LISTENING_STATE)
148 {
149 /* found a listening client CCB */
150 DPRINT("Listening client CCB found -- connecting\n");
151
152 /* connect client and server CCBs */
153 Ccb->OtherSide = ClientCcb;
154 ClientCcb->OtherSide = Ccb;
155
156 /* set connected state */
157 Ccb->PipeState = FILE_PIPE_CONNECTED_STATE;
158 ClientCcb->PipeState = FILE_PIPE_CONNECTED_STATE;
159
160 KeUnlockMutex(&Fcb->CcbListLock);
161
162 /* FIXME: create and initialize data queues */
163
164 /* signal client's connect event */
165 DPRINT("Setting the ConnectEvent for %x\n", ClientCcb);
166 KeSetEvent(&ClientCcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
167
168 return STATUS_PIPE_CONNECTED;
169 }
170 #endif
171
172 current_entry = current_entry->Flink;
173 }
174
175 /* no listening client fcb found */
176 DPRINT("No listening client fcb found -- waiting for client\n");
177
178 Ccb->PipeState = FILE_PIPE_LISTENING_STATE;
179
180 Status = NpfsAddListeningServerInstance(Irp, Ccb);
181
182 KeUnlockMutex(&Fcb->CcbListLock);
183
184 if (Flags & FO_SYNCHRONOUS_IO)
185 {
186 KeWaitForSingleObject(&Ccb->ConnectEvent,
187 UserRequest,
188 Irp->RequestorMode,
189 FALSE,
190 NULL);
191 }
192
193 DPRINT("NpfsConnectPipe() done (Status %lx)\n", Status);
194
195 return Status;
196 }
197
198
199 static NTSTATUS
200 NpfsDisconnectPipe(PNPFS_CCB Ccb)
201 {
202 NTSTATUS Status;
203 PNPFS_FCB Fcb;
204 PNPFS_CCB OtherSide;
205 BOOLEAN Server;
206
207 DPRINT("NpfsDisconnectPipe()\n");
208
209 /* Fail, if the CCB is not a pipe CCB */
210 if (Ccb->Type != CCB_PIPE)
211 {
212 DPRINT1("Not a pipe\n");
213 return STATUS_ILLEGAL_FUNCTION;
214 }
215
216 /* Fail, if the CCB is not a server end CCB */
217 if (Ccb->PipeEnd != FILE_PIPE_SERVER_END)
218 {
219 DPRINT1("Not the server end\n");
220 return STATUS_ILLEGAL_FUNCTION;
221 }
222
223 Fcb = Ccb->Fcb;
224 KeLockMutex(&Fcb->CcbListLock);
225
226 if (Ccb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
227 {
228 DPRINT("Pipe is already disconnected\n");
229 Status = STATUS_PIPE_DISCONNECTED;
230 }
231 else if ((!Ccb->OtherSide) && (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE))
232 {
233 ExAcquireFastMutex(&Ccb->DataListLock);
234 Ccb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
235 ExReleaseFastMutex(&Ccb->DataListLock);
236 Status = STATUS_SUCCESS;
237 }
238 else if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE)
239 {
240 Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END);
241 OtherSide = Ccb->OtherSide;
242 //Ccb->OtherSide = NULL;
243 Ccb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
244 /* Lock the server first */
245 if (Server)
246 {
247 ExAcquireFastMutex(&Ccb->DataListLock);
248 ExAcquireFastMutex(&OtherSide->DataListLock);
249 }
250 else
251 {
252 ExAcquireFastMutex(&OtherSide->DataListLock);
253 ExAcquireFastMutex(&Ccb->DataListLock);
254 }
255 OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
256 //OtherSide->OtherSide = NULL;
257 /*
258 * Signaling the write event. If is possible that an other
259 * thread waits for an empty buffer.
260 */
261 KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
262 KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
263 if (Server)
264 {
265 ExReleaseFastMutex(&OtherSide->DataListLock);
266 ExReleaseFastMutex(&Ccb->DataListLock);
267 }
268 else
269 {
270 ExReleaseFastMutex(&Ccb->DataListLock);
271 ExReleaseFastMutex(&OtherSide->DataListLock);
272 }
273 Status = STATUS_SUCCESS;
274 }
275 else if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
276 {
277 PLIST_ENTRY Entry;
278 PNPFS_WAITER_ENTRY WaitEntry = NULL;
279 BOOLEAN Complete = FALSE;
280 PIRP Irp = NULL;
281
282 Entry = Ccb->Fcb->WaiterListHead.Flink;
283 while (Entry != &Ccb->Fcb->WaiterListHead)
284 {
285 WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry);
286 if (WaitEntry->Ccb == Ccb)
287 {
288 RemoveEntryList(Entry);
289 Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DriverContext);
290 Complete = (NULL == IoSetCancelRoutine(Irp, NULL));
291 break;
292 }
293 Entry = Entry->Flink;
294 }
295
296 if (Irp)
297 {
298 if (Complete)
299 {
300 Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
301 Irp->IoStatus.Information = 0;
302 IoCompleteRequest(Irp, IO_NO_INCREMENT);
303 }
304 }
305 Ccb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
306 Status = STATUS_SUCCESS;
307 }
308 else if (Ccb->PipeState == FILE_PIPE_CLOSING_STATE)
309 {
310 Status = STATUS_PIPE_CLOSING;
311 }
312 else
313 {
314 Status = STATUS_UNSUCCESSFUL;
315 }
316 KeUnlockMutex(&Fcb->CcbListLock);
317 return Status;
318 }
319
320 static NTSTATUS
321 NpfsWaitPipe(PIRP Irp,
322 PNPFS_CCB Ccb)
323 {
324 PLIST_ENTRY current_entry;
325 PNPFS_FCB Fcb;
326 PNPFS_CCB ServerCcb;
327 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe;
328 PLARGE_INTEGER TimeOut;
329 NTSTATUS Status;
330 PEXTENDED_IO_STACK_LOCATION IoStack;
331 PFILE_OBJECT FileObject;
332 PNPFS_VCB Vcb;
333
334 IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
335 ASSERT(IoStack);
336 FileObject = IoStack->FileObject;
337 ASSERT(FileObject);
338
339 DPRINT1("Waiting on Pipe %wZ\n", &FileObject->FileName);
340
341 WaitPipe = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
342
343 ASSERT(Ccb->Fcb);
344 ASSERT(Ccb->Fcb->Vcb);
345
346 /* Get the VCB */
347 Vcb = Ccb->Fcb->Vcb;
348
349 /* Lock the pipe list */
350 KeLockMutex(&Vcb->PipeListLock);
351
352 /* File a pipe with the given name */
353 Fcb = NpfsFindPipe(Vcb,
354 &FileObject->FileName);
355
356 /* Unlock the pipe list */
357 KeUnlockMutex(&Vcb->PipeListLock);
358
359 /* Fail if not pipe was found */
360 if (Fcb == NULL)
361 {
362 DPRINT1("No pipe found!\n", Fcb);
363 return STATUS_OBJECT_NAME_NOT_FOUND;
364 }
365
366 /* search for listening server */
367 current_entry = Fcb->ServerCcbListHead.Flink;
368 while (current_entry != &Fcb->ServerCcbListHead)
369 {
370 ServerCcb = CONTAINING_RECORD(current_entry,
371 NPFS_CCB,
372 CcbListEntry);
373
374 if (ServerCcb->PipeState == FILE_PIPE_LISTENING_STATE)
375 {
376 /* found a listening server CCB */
377 DPRINT("Listening server CCB found -- connecting\n");
378
379 return STATUS_SUCCESS;
380 }
381
382 current_entry = current_entry->Flink;
383 }
384
385 /* No listening server fcb found, so wait for one */
386
387 /* If a timeout specified */
388 if (WaitPipe->TimeoutSpecified)
389 {
390 /* NMPWAIT_USE_DEFAULT_WAIT = 0 */
391 if (WaitPipe->Timeout.QuadPart == 0)
392 {
393 TimeOut = &Fcb->TimeOut;
394 }
395 else
396 {
397 TimeOut = &WaitPipe->Timeout;
398 }
399 }
400 else
401 {
402 /* Wait forever */
403 TimeOut = NULL;
404 }
405
406 Status = KeWaitForSingleObject(&Ccb->ConnectEvent,
407 UserRequest,
408 KernelMode,
409 TRUE,
410 TimeOut);
411
412 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status);
413
414 return Status;
415 }
416
417 NTSTATUS
418 NpfsWaitPipe2(PIRP Irp,
419 PNPFS_CCB Ccb)
420 {
421 PLIST_ENTRY current_entry;
422 PNPFS_FCB Fcb;
423 PNPFS_CCB ServerCcb;
424 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe;
425 LARGE_INTEGER TimeOut;
426 NTSTATUS Status;
427 #ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
428 PNPFS_VCB Vcb;
429 UNICODE_STRING PipeName;
430 #endif
431
432 DPRINT("NpfsWaitPipe\n");
433
434 WaitPipe = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
435
436 #ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
437 /* Fail, if the CCB does not represent the root directory */
438 if (Ccb->Type != CCB_DIRECTORY)
439 return STATUS_ILLEGAL_FUNCTION;
440
441 /* Calculate the pipe name length and allocate the buffer */
442 PipeName.Length = WaitPipe->NameLength + sizeof(WCHAR);
443 PipeName.MaximumLength = PipeName.Length + sizeof(WCHAR);
444 PipeName.Buffer = ExAllocatePool(NonPagedPool, PipeName.MaximumLength);
445 if (PipeName.Buffer == NULL)
446 {
447 DPRINT1("Could not allocate memory for the pipe name!\n");
448 return STATUS_NO_MEMORY;
449 }
450
451 /* Copy the pipe name into the buffer, prepend a backslash and append a 0 character */
452 PipeName.Buffer[0] = L'\\';
453 RtlCopyMemory(&PipeName.Buffer[1],
454 &WaitPipe->Name[0],
455 WaitPipe->NameLength);
456 PipeName.Buffer[PipeName.Length / sizeof(WCHAR)] = 0;
457
458 DPRINT("Waiting for Pipe %wZ\n", &PipeName);
459
460 /* Get the VCB */
461 Vcb = Ccb->Fcb->Vcb;
462
463 /* Lock the pipe list */
464 KeLockMutex(&Vcb->PipeListLock);
465
466 /* File a pipe with the given name */
467 Fcb = NpfsFindPipe(Vcb,
468 &PipeName);
469
470 /* Unlock the pipe list */
471 KeUnlockMutex(&Vcb->PipeListLock);
472
473 /* Release the pipe name buffer */
474 ExFreePool(PipeName.Buffer);
475
476 /* Fail if not pipe was found */
477 if (Fcb == NULL)
478 {
479 DPRINT("No pipe found!\n", Fcb);
480 return STATUS_OBJECT_NAME_NOT_FOUND;
481 }
482
483 DPRINT("Fcb %p\n", Fcb);
484 #else
485 Fcb = Ccb->Fcb;
486
487 if (Ccb->PipeState != 0)
488 {
489 DPRINT("Pipe is not in passive (waiting) state!\n");
490 return STATUS_UNSUCCESSFUL;
491 }
492 #endif
493
494 /* search for listening server */
495 current_entry = Fcb->ServerCcbListHead.Flink;
496 while (current_entry != &Fcb->ServerCcbListHead)
497 {
498 ServerCcb = CONTAINING_RECORD(current_entry,
499 NPFS_CCB,
500 CcbListEntry);
501
502 if (ServerCcb->PipeState == FILE_PIPE_LISTENING_STATE)
503 {
504 /* found a listening server CCB */
505 DPRINT("Listening server CCB found -- connecting\n");
506
507 return STATUS_SUCCESS;
508 }
509
510 current_entry = current_entry->Flink;
511 }
512
513 /* No listening server fcb found */
514
515 /* If no timeout specified, use the default one */
516 if (WaitPipe->TimeoutSpecified)
517 TimeOut = WaitPipe->Timeout;
518 else
519 TimeOut = Fcb->TimeOut;
520
521 /* Wait for one */
522 Status = KeWaitForSingleObject(&Ccb->ConnectEvent,
523 UserRequest,
524 KernelMode,
525 FALSE,
526 &TimeOut);
527
528 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status);
529
530 return Status;
531 }
532
533
534 /*
535 * FUNCTION: Return current state of a pipe
536 * ARGUMENTS:
537 * Irp = Pointer to I/O request packet
538 * IrpSp = Pointer to current stack location of Irp
539 * RETURNS:
540 * Status of operation
541 */
542
543 /*
544 * FUNCTION: Peek at a pipe (get information about messages)
545 * ARGUMENTS:
546 * Irp = Pointer to I/O request packet
547 * IoStack = Pointer to current stack location of Irp
548 * RETURNS:
549 * Status of operation
550 */
551 static NTSTATUS
552 NpfsPeekPipe(PIRP Irp,
553 PIO_STACK_LOCATION IoStack)
554 {
555 ULONG OutputBufferLength;
556 ULONG ReturnLength = 0;
557 PFILE_PIPE_PEEK_BUFFER Reply;
558 PNPFS_FCB Fcb;
559 PNPFS_CCB Ccb;
560 NTSTATUS Status;
561 ULONG MessageCount = 0;
562 ULONG MessageLength;
563 ULONG ReadDataAvailable;
564 PVOID BufferPtr;
565
566 DPRINT("NpfsPeekPipe\n");
567
568 OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
569 DPRINT("OutputBufferLength: %lu\n", OutputBufferLength);
570
571 /* Validate parameters */
572 if (OutputBufferLength < sizeof(FILE_PIPE_PEEK_BUFFER))
573 {
574 DPRINT1("Buffer too small\n");
575 return STATUS_INVALID_PARAMETER;
576 }
577
578 Ccb = IoStack->FileObject->FsContext2;
579 Reply = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer;
580 Fcb = Ccb->Fcb;
581
582
583 Reply->NamedPipeState = Ccb->PipeState;
584
585 Reply->ReadDataAvailable = Ccb->ReadDataAvailable;
586 DPRINT("ReadDataAvailable: %lu\n", Ccb->ReadDataAvailable);
587
588 ExAcquireFastMutex(&Ccb->DataListLock);
589 BufferPtr = Ccb->ReadPtr;
590 DPRINT("BufferPtr = %x\n", BufferPtr);
591 if (Ccb->Fcb->PipeType == FILE_PIPE_BYTE_STREAM_TYPE)
592 {
593 DPRINT("Byte Stream Mode\n");
594 Reply->MessageLength = Ccb->ReadDataAvailable;
595 DPRINT("Reply->MessageLength %lu\n",Reply->MessageLength );
596 MessageCount = 1;
597
598 if (Reply->Data[0] && (OutputBufferLength >= Ccb->ReadDataAvailable + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0])))
599 {
600 ReturnLength = Ccb->ReadDataAvailable;
601 memcpy(&Reply->Data[0], (PVOID)BufferPtr, Ccb->ReadDataAvailable);
602 }
603 }
604 else
605 {
606 DPRINT("Message Mode\n");
607 ReadDataAvailable=Ccb->ReadDataAvailable;
608
609 if (ReadDataAvailable > 0)
610 {
611 memcpy(&Reply->MessageLength, BufferPtr, sizeof(ULONG));
612
613 while ((ReadDataAvailable > 0) && (BufferPtr < Ccb->WritePtr))
614 {
615 memcpy(&MessageLength, BufferPtr, sizeof(MessageLength));
616
617 ASSERT(MessageLength > 0);
618
619 DPRINT("MessageLength = %lu\n",MessageLength);
620 ReadDataAvailable -= MessageLength;
621 MessageCount++;
622
623 /* If its the first message, copy the Message if the size of buffer is large enough */
624 if (MessageCount==1)
625 {
626 if ((Reply->Data[0])
627 && (OutputBufferLength >= (MessageLength + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]))))
628 {
629 memcpy(&Reply->Data[0], (PVOID)((ULONG_PTR)BufferPtr + sizeof(MessageLength)), MessageLength);
630 ReturnLength = MessageLength;
631 }
632 }
633
634 BufferPtr =(PVOID)((ULONG_PTR)BufferPtr + MessageLength + sizeof(MessageLength));
635 DPRINT("BufferPtr = %x\n", BufferPtr);
636 DPRINT("ReadDataAvailable: %lu\n", ReadDataAvailable);
637 }
638
639 if (ReadDataAvailable != 0)
640 {
641 DPRINT1("Possible memory corruption.\n");
642 ASSERT(FALSE);
643 }
644 }
645 }
646 ExReleaseFastMutex(&Ccb->DataListLock);
647
648 Reply->NumberOfMessages = MessageCount;
649
650 Irp->IoStatus.Information = ReturnLength + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]);
651 Irp->IoStatus.Status = STATUS_SUCCESS;
652
653 Status = STATUS_SUCCESS;
654
655 DPRINT("NpfsPeekPipe done\n");
656
657 return Status;
658 }
659
660
661 NTSTATUS NTAPI
662 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
663 PIRP Irp)
664 {
665 PIO_STACK_LOCATION IoStack;
666 PFILE_OBJECT FileObject;
667 NTSTATUS Status;
668 PNPFS_VCB Vcb;
669 PNPFS_FCB Fcb;
670 PNPFS_CCB Ccb;
671
672 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
673
674 Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
675 IoStack = IoGetCurrentIrpStackLocation(Irp);
676 DPRINT("IoStack: %p\n", IoStack);
677 FileObject = IoStack->FileObject;
678 DPRINT("FileObject: %p\n", FileObject);
679 Ccb = FileObject->FsContext2;
680 DPRINT("CCB: %p\n", Ccb);
681 Fcb = Ccb->Fcb;
682 DPRINT("Pipe: %p\n", Fcb);
683 DPRINT("PipeName: %wZ\n", &Fcb->PipeName);
684
685 Irp->IoStatus.Information = 0;
686
687 switch (IoStack->Parameters.FileSystemControl.FsControlCode)
688 {
689 case FSCTL_PIPE_ASSIGN_EVENT:
690 DPRINT1("Assign event not implemented\n");
691 Status = STATUS_NOT_IMPLEMENTED;
692 break;
693
694 case FSCTL_PIPE_DISCONNECT:
695 DPRINT("Disconnecting pipe %wZ\n", &Fcb->PipeName);
696 Status = NpfsDisconnectPipe(Ccb);
697 break;
698
699 case FSCTL_PIPE_LISTEN:
700 DPRINT("Connecting pipe %wZ\n", &Fcb->PipeName);
701 Status = NpfsConnectPipe(Irp, Ccb);
702 break;
703
704 case FSCTL_PIPE_PEEK:
705 DPRINT("Peeking pipe %wZ\n", &Fcb->PipeName);
706 Status = NpfsPeekPipe(Irp, (PIO_STACK_LOCATION)IoStack);
707 break;
708
709 case FSCTL_PIPE_QUERY_EVENT:
710 DPRINT1("Query event not implemented\n");
711 Status = STATUS_NOT_IMPLEMENTED;
712 break;
713
714 case FSCTL_PIPE_TRANSCEIVE:
715 /* If you implement this, please remove the workaround in
716 lib/kernel32/file/npipe.c function TransactNamedPipe() */
717 DPRINT1("Transceive not implemented\n");
718 Status = STATUS_NOT_IMPLEMENTED;
719 break;
720
721 case FSCTL_PIPE_WAIT:
722 DPRINT("Waiting for pipe %wZ\n", &Fcb->PipeName);
723 Status = NpfsWaitPipe(Irp, Ccb);
724 break;
725
726 case FSCTL_PIPE_IMPERSONATE:
727 DPRINT1("Impersonate not implemented\n");
728 Status = STATUS_NOT_IMPLEMENTED;
729 break;
730
731 case FSCTL_PIPE_SET_CLIENT_PROCESS:
732 DPRINT1("Set client process not implemented\n");
733 Status = STATUS_NOT_IMPLEMENTED;
734 break;
735
736 case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
737 DPRINT1("Query client process not implemented\n");
738 Status = STATUS_NOT_IMPLEMENTED;
739 break;
740
741 case FSCTL_PIPE_INTERNAL_READ:
742 DPRINT1("Internal read not implemented\n");
743 Status = STATUS_NOT_IMPLEMENTED;
744 break;
745
746 case FSCTL_PIPE_INTERNAL_WRITE:
747 DPRINT1("Internal write not implemented\n");
748 Status = STATUS_NOT_IMPLEMENTED;
749 break;
750
751 case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
752 DPRINT1("Internal transceive not implemented\n");
753 Status = STATUS_NOT_IMPLEMENTED;
754 break;
755
756 case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
757 DPRINT1("Internal read overflow not implemented\n");
758 Status = STATUS_NOT_IMPLEMENTED;
759 break;
760
761 default:
762 DPRINT1("Unrecognized IoControlCode: %x\n",
763 IoStack->Parameters.FileSystemControl.FsControlCode);
764 Status = STATUS_UNSUCCESSFUL;
765 }
766
767 if (Status != STATUS_PENDING)
768 {
769 Irp->IoStatus.Status = Status;
770
771 IoCompleteRequest(Irp, IO_NO_INCREMENT);
772 }
773
774 return Status;
775 }
776
777
778 NTSTATUS NTAPI
779 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject,
780 PIRP Irp)
781 {
782 /* FIXME: Implement */
783
784 Irp->IoStatus.Status = STATUS_SUCCESS;
785 Irp->IoStatus.Information = 0;
786
787 IoCompleteRequest(Irp, IO_NO_INCREMENT);
788
789 return STATUS_SUCCESS;
790 }
791
792 /* EOF */