09870e98966ff66f005b1a6092832f7d6c251ed9
[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/filesystems/npfs/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 /* FUNCTIONS *****************************************************************/
19
20 static DRIVER_CANCEL NpfsListeningCancelRoutine;
21 static VOID NTAPI
22 NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
23 IN PIRP Irp)
24 {
25 PNPFS_WAITER_ENTRY Waiter;
26
27 UNREFERENCED_PARAMETER(DeviceObject);
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 IoAcquireCancelSpinLock(&oldIrql);
61 if (!Irp->Cancel)
62 {
63 Ccb->PipeState = FILE_PIPE_LISTENING_STATE;
64 IoMarkIrpPending(Irp);
65 InsertTailList(&Ccb->Fcb->WaiterListHead, &Entry->Entry);
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 KPROCESSOR_MODE WaitMode;
96
97 DPRINT("NpfsConnectPipe()\n");
98
99 /* Fail, if the CCB is not a pipe CCB */
100 if (Ccb->Type != CCB_PIPE)
101 {
102 DPRINT("Not a pipe\n");
103 return STATUS_ILLEGAL_FUNCTION;
104 }
105
106 /* Fail, if the CCB is not a server end CCB */
107 if (Ccb->PipeEnd != FILE_PIPE_SERVER_END)
108 {
109 DPRINT("Not the server end\n");
110 return STATUS_ILLEGAL_FUNCTION;
111 }
112
113 if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE)
114 {
115 KeResetEvent(&Ccb->ConnectEvent);
116 return STATUS_PIPE_CONNECTED;
117 }
118
119 if (Ccb->PipeState == FILE_PIPE_CLOSING_STATE)
120 return STATUS_PIPE_CLOSING;
121
122 DPRINT("Waiting for connection...\n");
123
124 Fcb = Ccb->Fcb;
125 IoStack = IoGetCurrentIrpStackLocation(Irp);
126 FileObject = IoStack->FileObject;
127 Flags = FileObject->Flags;
128 WaitMode = Irp->RequestorMode;
129
130 /* search for a listening client fcb */
131 KeLockMutex(&Fcb->CcbListLock);
132
133 current_entry = Fcb->ClientCcbListHead.Flink;
134 while (current_entry != &Fcb->ClientCcbListHead)
135 {
136 ClientCcb = CONTAINING_RECORD(current_entry,
137 NPFS_CCB,
138 CcbListEntry);
139
140 if (ClientCcb->PipeState == 0)
141 {
142 /* found a passive (waiting) client CCB */
143 DPRINT("Passive (waiting) client CCB found -- wake the client\n");
144 KeSetEvent(&ClientCcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
145 break;
146 }
147
148 #if 0
149 if (ClientCcb->PipeState == FILE_PIPE_LISTENING_STATE)
150 {
151 /* found a listening client CCB */
152 DPRINT("Listening client CCB found -- connecting\n");
153
154 /* connect client and server CCBs */
155 Ccb->OtherSide = ClientCcb;
156 ClientCcb->OtherSide = Ccb;
157
158 /* set connected state */
159 Ccb->PipeState = FILE_PIPE_CONNECTED_STATE;
160 ClientCcb->PipeState = FILE_PIPE_CONNECTED_STATE;
161
162 KeUnlockMutex(&Fcb->CcbListLock);
163
164 /* FIXME: create and initialize data queues */
165
166 /* signal client's connect event */
167 DPRINT("Setting the ConnectEvent for %x\n", ClientCcb);
168 KeSetEvent(&ClientCcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
169
170 return STATUS_PIPE_CONNECTED;
171 }
172 #endif
173
174 current_entry = current_entry->Flink;
175 }
176
177 /* no listening client fcb found */
178 DPRINT("No listening client fcb found -- waiting for client\n");
179
180 Status = NpfsAddListeningServerInstance(Irp, Ccb);
181
182 KeUnlockMutex(&Fcb->CcbListLock);
183
184 if ((Status == STATUS_PENDING) && (Flags & FO_SYNCHRONOUS_IO))
185 {
186 KeWaitForSingleObject(&Ccb->ConnectEvent,
187 UserRequest,
188 WaitMode,
189 (Flags & FO_ALERTABLE_IO) != 0,
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 DPRINT("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 DPRINT("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 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 LARGE_INTEGER TimeOut;
329 NTSTATUS Status;
330 PNPFS_VCB Vcb;
331 UNICODE_STRING PipeName;
332 DPRINT("NpfsWaitPipe\n");
333
334 WaitPipe = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
335
336 /* Fail, if the CCB does not represent the root directory */
337 if (Ccb->Type != CCB_DIRECTORY)
338 return STATUS_ILLEGAL_FUNCTION;
339
340 /* Calculate the pipe name length and allocate the buffer */
341 PipeName.Length = WaitPipe->NameLength + sizeof(WCHAR);
342 PipeName.MaximumLength = PipeName.Length + sizeof(WCHAR);
343 PipeName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
344 PipeName.MaximumLength,
345 TAG_NPFS_NAMEBLOCK);
346 if (PipeName.Buffer == NULL)
347 {
348 DPRINT1("Could not allocate memory for the pipe name!\n");
349 return STATUS_NO_MEMORY;
350 }
351
352 /* Copy the pipe name into the buffer, prepend a backslash and append a 0 character */
353 PipeName.Buffer[0] = L'\\';
354 RtlCopyMemory(&PipeName.Buffer[1],
355 &WaitPipe->Name[0],
356 WaitPipe->NameLength);
357 PipeName.Buffer[PipeName.Length / sizeof(WCHAR)] = 0;
358
359 DPRINT("Waiting for Pipe %wZ\n", &PipeName);
360
361 /* Get the VCB */
362 Vcb = Ccb->Fcb->Vcb;
363
364 /* Lock the pipe list */
365 KeLockMutex(&Vcb->PipeListLock);
366
367 /* File a pipe with the given name */
368 Fcb = NpfsFindPipe(Vcb,
369 &PipeName);
370
371 /* Unlock the pipe list */
372 KeUnlockMutex(&Vcb->PipeListLock);
373
374 /* Release the pipe name buffer */
375 ExFreePoolWithTag(PipeName.Buffer, TAG_NPFS_NAMEBLOCK);
376
377 /* Fail if not pipe was found */
378 if (Fcb == NULL)
379 {
380 DPRINT("No pipe found!\n");
381 return STATUS_OBJECT_NAME_NOT_FOUND;
382 }
383
384 DPRINT("Fcb %p\n", Fcb);
385
386 /* search for listening server */
387 current_entry = Fcb->ServerCcbListHead.Flink;
388 while (current_entry != &Fcb->ServerCcbListHead)
389 {
390 ServerCcb = CONTAINING_RECORD(current_entry,
391 NPFS_CCB,
392 CcbListEntry);
393
394 if (ServerCcb->PipeState == FILE_PIPE_LISTENING_STATE)
395 {
396 /* found a listening server CCB */
397 DPRINT("Listening server CCB found -- connecting\n");
398 NpfsDereferenceFcb(Fcb);
399 return STATUS_SUCCESS;
400 }
401
402 current_entry = current_entry->Flink;
403 }
404
405 /* No listening server fcb found */
406
407 /* If no timeout specified, use the default one */
408 if (WaitPipe->TimeoutSpecified)
409 TimeOut = WaitPipe->Timeout;
410 else
411 TimeOut = Fcb->TimeOut;
412
413 NpfsDereferenceFcb(Fcb);
414
415 /* Wait for one */
416 Status = KeWaitForSingleObject(&Ccb->ConnectEvent,
417 UserRequest,
418 Irp->RequestorMode,
419 (Ccb->FileObject->Flags & FO_ALERTABLE_IO) != 0,
420 &TimeOut);
421 if ((Status == STATUS_USER_APC) || (Status == STATUS_KERNEL_APC) || (Status == STATUS_ALERTED))
422 Status = STATUS_CANCELLED;
423
424 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status);
425
426 return Status;
427 }
428
429
430 /*
431 * FUNCTION: Return current state of a pipe
432 * ARGUMENTS:
433 * Irp = Pointer to I/O request packet
434 * IrpSp = Pointer to current stack location of Irp
435 * RETURNS:
436 * Status of operation
437 */
438
439 /*
440 * FUNCTION: Peek at a pipe (get information about messages)
441 * ARGUMENTS:
442 * Irp = Pointer to I/O request packet
443 * IoStack = Pointer to current stack location of Irp
444 * RETURNS:
445 * Status of operation
446 */
447 static NTSTATUS
448 NpfsPeekPipe(PIRP Irp,
449 PIO_STACK_LOCATION IoStack)
450 {
451 ULONG OutputBufferLength;
452 ULONG ReturnLength = 0;
453 PFILE_PIPE_PEEK_BUFFER Reply;
454 //PNPFS_FCB Fcb;
455 PNPFS_CCB Ccb;
456 NTSTATUS Status;
457 ULONG MessageCount = 0;
458 ULONG MessageLength;
459 ULONG ReadDataAvailable;
460 PVOID BufferPtr;
461
462 DPRINT("NpfsPeekPipe\n");
463
464 OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
465 DPRINT("OutputBufferLength: %lu\n", OutputBufferLength);
466
467 /* Validate parameters */
468 if (OutputBufferLength < (ULONG)FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]))
469 {
470 DPRINT1("Buffer too small\n");
471 return STATUS_INVALID_PARAMETER;
472 }
473
474 Ccb = IoStack->FileObject->FsContext2;
475 Reply = Irp->AssociatedIrp.SystemBuffer;
476 //Fcb = Ccb->Fcb;
477
478
479 Reply->NamedPipeState = Ccb->PipeState;
480
481 Reply->ReadDataAvailable = Ccb->ReadDataAvailable;
482 DPRINT("ReadDataAvailable: %lu\n", Ccb->ReadDataAvailable);
483
484 ExAcquireFastMutex(&Ccb->DataListLock);
485 BufferPtr = Ccb->ReadPtr;
486 DPRINT("BufferPtr = %p\n", BufferPtr);
487 if (Ccb->Fcb->PipeType == FILE_PIPE_BYTE_STREAM_TYPE)
488 {
489 DPRINT("Byte Stream Mode\n");
490 Reply->MessageLength = Ccb->ReadDataAvailable;
491 DPRINT("Reply->MessageLength %lu\n", Reply->MessageLength);
492 MessageCount = 1;
493
494 if (OutputBufferLength >= (ULONG)FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[Ccb->ReadDataAvailable]))
495 {
496 RtlCopyMemory(Reply->Data, BufferPtr, Ccb->ReadDataAvailable);
497 ReturnLength = Ccb->ReadDataAvailable;
498 }
499 }
500 else
501 {
502 DPRINT("Message Mode\n");
503 ReadDataAvailable = Ccb->ReadDataAvailable;
504
505 if (ReadDataAvailable > 0)
506 {
507 RtlCopyMemory(&Reply->MessageLength,
508 BufferPtr,
509 sizeof(Reply->MessageLength));
510
511 while ((ReadDataAvailable > 0) && (BufferPtr < Ccb->WritePtr))
512 {
513 RtlCopyMemory(&MessageLength, BufferPtr, sizeof(MessageLength));
514
515 ASSERT(MessageLength > 0);
516
517 DPRINT("MessageLength = %lu\n", MessageLength);
518 ReadDataAvailable -= MessageLength;
519 MessageCount++;
520
521 /* If its the first message, copy the Message if the size of buffer is large enough */
522 if (MessageCount == 1)
523 {
524 if (OutputBufferLength >= (ULONG)FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[MessageLength]))
525 {
526 RtlCopyMemory(Reply->Data,
527 (PVOID)((ULONG_PTR)BufferPtr + sizeof(MessageLength)),
528 MessageLength);
529 ReturnLength = MessageLength;
530 }
531 }
532
533 BufferPtr = (PVOID)((ULONG_PTR)BufferPtr + sizeof(MessageLength) + MessageLength);
534 DPRINT("BufferPtr = %p\n", BufferPtr);
535 DPRINT("ReadDataAvailable: %lu\n", ReadDataAvailable);
536 }
537
538 if (ReadDataAvailable != 0)
539 {
540 DPRINT1("Possible memory corruption.\n");
541 ASSERT(FALSE);
542 }
543 }
544 }
545 ExReleaseFastMutex(&Ccb->DataListLock);
546
547 Reply->NumberOfMessages = MessageCount;
548
549 Irp->IoStatus.Information = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[ReturnLength]);
550 Irp->IoStatus.Status = STATUS_SUCCESS;
551
552 Status = STATUS_SUCCESS;
553
554 DPRINT("NpfsPeekPipe done\n");
555
556 return Status;
557 }
558
559
560 NTSTATUS NTAPI
561 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
562 PIRP Irp)
563 {
564 PIO_STACK_LOCATION IoStack;
565 PFILE_OBJECT FileObject;
566 NTSTATUS Status;
567 //PNPFS_VCB Vcb;
568 PNPFS_FCB Fcb;
569 PNPFS_CCB Ccb;
570
571 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
572
573 //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
574 IoStack = IoGetCurrentIrpStackLocation(Irp);
575 DPRINT("IoStack: %p\n", IoStack);
576 FileObject = IoStack->FileObject;
577 DPRINT("FileObject: %p\n", FileObject);
578 Ccb = FileObject->FsContext2;
579 DPRINT("CCB: %p\n", Ccb);
580 Fcb = Ccb->Fcb;
581 DPRINT("Pipe: %p\n", Fcb);
582 DPRINT("PipeName: %wZ\n", &Fcb->PipeName);
583
584 Irp->IoStatus.Information = 0;
585
586 switch (IoStack->Parameters.FileSystemControl.FsControlCode)
587 {
588 case FSCTL_PIPE_ASSIGN_EVENT:
589 DPRINT1("Assign event not implemented\n");
590 Status = STATUS_NOT_IMPLEMENTED;
591 break;
592
593 case FSCTL_PIPE_DISCONNECT:
594 DPRINT("Disconnecting pipe %wZ\n", &Fcb->PipeName);
595 Status = NpfsDisconnectPipe(Ccb);
596 break;
597
598 case FSCTL_PIPE_LISTEN:
599 DPRINT("Connecting pipe %wZ\n", &Fcb->PipeName);
600 Status = NpfsConnectPipe(Irp, Ccb);
601 break;
602
603 case FSCTL_PIPE_PEEK:
604 DPRINT("Peeking pipe %wZ\n", &Fcb->PipeName);
605 Status = NpfsPeekPipe(Irp, (PIO_STACK_LOCATION)IoStack);
606 break;
607
608 case FSCTL_PIPE_QUERY_EVENT:
609 DPRINT1("Query event not implemented\n");
610 Status = STATUS_NOT_IMPLEMENTED;
611 break;
612
613 case FSCTL_PIPE_TRANSCEIVE:
614 /* If you implement this, please remove the workaround in
615 lib/kernel32/file/npipe.c function TransactNamedPipe() */
616 DPRINT1("Transceive not implemented\n");
617 Status = STATUS_NOT_IMPLEMENTED;
618 break;
619
620 case FSCTL_PIPE_WAIT:
621 DPRINT("Waiting for pipe %wZ\n", &Fcb->PipeName);
622 Status = NpfsWaitPipe(Irp, Ccb);
623 break;
624
625 case FSCTL_PIPE_IMPERSONATE:
626 DPRINT1("Impersonate not implemented\n");
627 Status = STATUS_NOT_IMPLEMENTED;
628 break;
629
630 case FSCTL_PIPE_SET_CLIENT_PROCESS:
631 DPRINT1("Set client process not implemented\n");
632 Status = STATUS_NOT_IMPLEMENTED;
633 break;
634
635 case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
636 DPRINT1("Query client process not implemented\n");
637 Status = STATUS_NOT_IMPLEMENTED;
638 break;
639
640 case FSCTL_PIPE_INTERNAL_READ:
641 DPRINT1("Internal read not implemented\n");
642 Status = STATUS_NOT_IMPLEMENTED;
643 break;
644
645 case FSCTL_PIPE_INTERNAL_WRITE:
646 DPRINT1("Internal write not implemented\n");
647 Status = STATUS_NOT_IMPLEMENTED;
648 break;
649
650 case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
651 DPRINT1("Internal transceive not implemented\n");
652 Status = STATUS_NOT_IMPLEMENTED;
653 break;
654
655 case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
656 DPRINT1("Internal read overflow not implemented\n");
657 Status = STATUS_NOT_IMPLEMENTED;
658 break;
659
660 default:
661 DPRINT1("Unrecognized IoControlCode: %x\n",
662 IoStack->Parameters.FileSystemControl.FsControlCode);
663 Status = STATUS_UNSUCCESSFUL;
664 }
665
666 if (Status != STATUS_PENDING)
667 {
668 Irp->IoStatus.Status = Status;
669
670 IoCompleteRequest(Irp, IO_NO_INCREMENT);
671 }
672
673 return Status;
674 }
675
676
677 NTSTATUS NTAPI
678 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject,
679 PIRP Irp)
680 {
681 /* FIXME: Implement */
682 UNREFERENCED_PARAMETER(DeviceObject);
683
684 Irp->IoStatus.Status = STATUS_SUCCESS;
685 Irp->IoStatus.Information = 0;
686
687 IoCompleteRequest(Irp, IO_NO_INCREMENT);
688
689 return STATUS_SUCCESS;
690 }
691
692 /* EOF */