[SHELL32]
[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 DPRINT("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 DPRINT("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 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 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 DPRINT("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 DPRINT("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 = ExAllocatePoolWithTag(NonPagedPool,
445 PipeName.MaximumLength,
446 TAG_NPFS_NAMEBLOCK);
447 if (PipeName.Buffer == NULL)
448 {
449 DPRINT1("Could not allocate memory for the pipe name!\n");
450 return STATUS_NO_MEMORY;
451 }
452
453 /* Copy the pipe name into the buffer, prepend a backslash and append a 0 character */
454 PipeName.Buffer[0] = L'\\';
455 RtlCopyMemory(&PipeName.Buffer[1],
456 &WaitPipe->Name[0],
457 WaitPipe->NameLength);
458 PipeName.Buffer[PipeName.Length / sizeof(WCHAR)] = 0;
459
460 DPRINT("Waiting for Pipe %wZ\n", &PipeName);
461
462 /* Get the VCB */
463 Vcb = Ccb->Fcb->Vcb;
464
465 /* Lock the pipe list */
466 KeLockMutex(&Vcb->PipeListLock);
467
468 /* File a pipe with the given name */
469 Fcb = NpfsFindPipe(Vcb,
470 &PipeName);
471
472 /* Unlock the pipe list */
473 KeUnlockMutex(&Vcb->PipeListLock);
474
475 /* Release the pipe name buffer */
476 ExFreePoolWithTag(PipeName.Buffer, TAG_NPFS_NAMEBLOCK);
477
478 /* Fail if not pipe was found */
479 if (Fcb == NULL)
480 {
481 DPRINT("No pipe found!\n", Fcb);
482 return STATUS_OBJECT_NAME_NOT_FOUND;
483 }
484
485 DPRINT("Fcb %p\n", Fcb);
486 #else
487 Fcb = Ccb->Fcb;
488
489 if (Ccb->PipeState != 0)
490 {
491 DPRINT("Pipe is not in passive (waiting) state!\n");
492 return STATUS_UNSUCCESSFUL;
493 }
494 #endif
495
496 /* search for listening server */
497 current_entry = Fcb->ServerCcbListHead.Flink;
498 while (current_entry != &Fcb->ServerCcbListHead)
499 {
500 ServerCcb = CONTAINING_RECORD(current_entry,
501 NPFS_CCB,
502 CcbListEntry);
503
504 if (ServerCcb->PipeState == FILE_PIPE_LISTENING_STATE)
505 {
506 /* found a listening server CCB */
507 DPRINT("Listening server CCB found -- connecting\n");
508
509 return STATUS_SUCCESS;
510 }
511
512 current_entry = current_entry->Flink;
513 }
514
515 /* No listening server fcb found */
516
517 /* If no timeout specified, use the default one */
518 if (WaitPipe->TimeoutSpecified)
519 TimeOut = WaitPipe->Timeout;
520 else
521 TimeOut = Fcb->TimeOut;
522
523 /* Wait for one */
524 Status = KeWaitForSingleObject(&Ccb->ConnectEvent,
525 UserRequest,
526 KernelMode,
527 FALSE,
528 &TimeOut);
529
530 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status);
531
532 return Status;
533 }
534
535
536 /*
537 * FUNCTION: Return current state of a pipe
538 * ARGUMENTS:
539 * Irp = Pointer to I/O request packet
540 * IrpSp = Pointer to current stack location of Irp
541 * RETURNS:
542 * Status of operation
543 */
544
545 /*
546 * FUNCTION: Peek at a pipe (get information about messages)
547 * ARGUMENTS:
548 * Irp = Pointer to I/O request packet
549 * IoStack = Pointer to current stack location of Irp
550 * RETURNS:
551 * Status of operation
552 */
553 static NTSTATUS
554 NpfsPeekPipe(PIRP Irp,
555 PIO_STACK_LOCATION IoStack)
556 {
557 ULONG OutputBufferLength;
558 ULONG ReturnLength = 0;
559 PFILE_PIPE_PEEK_BUFFER Reply;
560 PNPFS_FCB Fcb;
561 PNPFS_CCB Ccb;
562 NTSTATUS Status;
563 ULONG MessageCount = 0;
564 ULONG MessageLength;
565 ULONG ReadDataAvailable;
566 PVOID BufferPtr;
567
568 DPRINT("NpfsPeekPipe\n");
569
570 OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
571 DPRINT("OutputBufferLength: %lu\n", OutputBufferLength);
572
573 /* Validate parameters */
574 if (OutputBufferLength < sizeof(FILE_PIPE_PEEK_BUFFER))
575 {
576 DPRINT1("Buffer too small\n");
577 return STATUS_INVALID_PARAMETER;
578 }
579
580 Ccb = IoStack->FileObject->FsContext2;
581 Reply = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer;
582 Fcb = Ccb->Fcb;
583
584
585 Reply->NamedPipeState = Ccb->PipeState;
586
587 Reply->ReadDataAvailable = Ccb->ReadDataAvailable;
588 DPRINT("ReadDataAvailable: %lu\n", Ccb->ReadDataAvailable);
589
590 ExAcquireFastMutex(&Ccb->DataListLock);
591 BufferPtr = Ccb->ReadPtr;
592 DPRINT("BufferPtr = %x\n", BufferPtr);
593 if (Ccb->Fcb->PipeType == FILE_PIPE_BYTE_STREAM_TYPE)
594 {
595 DPRINT("Byte Stream Mode\n");
596 Reply->MessageLength = Ccb->ReadDataAvailable;
597 DPRINT("Reply->MessageLength %lu\n",Reply->MessageLength );
598 MessageCount = 1;
599
600 if (Reply->Data[0] && (OutputBufferLength >= Ccb->ReadDataAvailable + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0])))
601 {
602 ReturnLength = Ccb->ReadDataAvailable;
603 memcpy(&Reply->Data[0], (PVOID)BufferPtr, Ccb->ReadDataAvailable);
604 }
605 }
606 else
607 {
608 DPRINT("Message Mode\n");
609 ReadDataAvailable=Ccb->ReadDataAvailable;
610
611 if (ReadDataAvailable > 0)
612 {
613 memcpy(&Reply->MessageLength, BufferPtr, sizeof(ULONG));
614
615 while ((ReadDataAvailable > 0) && (BufferPtr < Ccb->WritePtr))
616 {
617 memcpy(&MessageLength, BufferPtr, sizeof(MessageLength));
618
619 ASSERT(MessageLength > 0);
620
621 DPRINT("MessageLength = %lu\n",MessageLength);
622 ReadDataAvailable -= MessageLength;
623 MessageCount++;
624
625 /* If its the first message, copy the Message if the size of buffer is large enough */
626 if (MessageCount==1)
627 {
628 if ((Reply->Data[0])
629 && (OutputBufferLength >= (MessageLength + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]))))
630 {
631 memcpy(&Reply->Data[0], (PVOID)((ULONG_PTR)BufferPtr + sizeof(MessageLength)), MessageLength);
632 ReturnLength = MessageLength;
633 }
634 }
635
636 BufferPtr =(PVOID)((ULONG_PTR)BufferPtr + MessageLength + sizeof(MessageLength));
637 DPRINT("BufferPtr = %x\n", BufferPtr);
638 DPRINT("ReadDataAvailable: %lu\n", ReadDataAvailable);
639 }
640
641 if (ReadDataAvailable != 0)
642 {
643 DPRINT1("Possible memory corruption.\n");
644 ASSERT(FALSE);
645 }
646 }
647 }
648 ExReleaseFastMutex(&Ccb->DataListLock);
649
650 Reply->NumberOfMessages = MessageCount;
651
652 Irp->IoStatus.Information = ReturnLength + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]);
653 Irp->IoStatus.Status = STATUS_SUCCESS;
654
655 Status = STATUS_SUCCESS;
656
657 DPRINT("NpfsPeekPipe done\n");
658
659 return Status;
660 }
661
662
663 NTSTATUS NTAPI
664 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
665 PIRP Irp)
666 {
667 PIO_STACK_LOCATION IoStack;
668 PFILE_OBJECT FileObject;
669 NTSTATUS Status;
670 PNPFS_VCB Vcb;
671 PNPFS_FCB Fcb;
672 PNPFS_CCB Ccb;
673
674 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
675
676 Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
677 IoStack = IoGetCurrentIrpStackLocation(Irp);
678 DPRINT("IoStack: %p\n", IoStack);
679 FileObject = IoStack->FileObject;
680 DPRINT("FileObject: %p\n", FileObject);
681 Ccb = FileObject->FsContext2;
682 DPRINT("CCB: %p\n", Ccb);
683 Fcb = Ccb->Fcb;
684 DPRINT("Pipe: %p\n", Fcb);
685 DPRINT("PipeName: %wZ\n", &Fcb->PipeName);
686
687 Irp->IoStatus.Information = 0;
688
689 switch (IoStack->Parameters.FileSystemControl.FsControlCode)
690 {
691 case FSCTL_PIPE_ASSIGN_EVENT:
692 DPRINT1("Assign event not implemented\n");
693 Status = STATUS_NOT_IMPLEMENTED;
694 break;
695
696 case FSCTL_PIPE_DISCONNECT:
697 DPRINT("Disconnecting pipe %wZ\n", &Fcb->PipeName);
698 Status = NpfsDisconnectPipe(Ccb);
699 break;
700
701 case FSCTL_PIPE_LISTEN:
702 DPRINT("Connecting pipe %wZ\n", &Fcb->PipeName);
703 Status = NpfsConnectPipe(Irp, Ccb);
704 break;
705
706 case FSCTL_PIPE_PEEK:
707 DPRINT("Peeking pipe %wZ\n", &Fcb->PipeName);
708 Status = NpfsPeekPipe(Irp, (PIO_STACK_LOCATION)IoStack);
709 break;
710
711 case FSCTL_PIPE_QUERY_EVENT:
712 DPRINT1("Query event not implemented\n");
713 Status = STATUS_NOT_IMPLEMENTED;
714 break;
715
716 case FSCTL_PIPE_TRANSCEIVE:
717 /* If you implement this, please remove the workaround in
718 lib/kernel32/file/npipe.c function TransactNamedPipe() */
719 DPRINT1("Transceive not implemented\n");
720 Status = STATUS_NOT_IMPLEMENTED;
721 break;
722
723 case FSCTL_PIPE_WAIT:
724 DPRINT("Waiting for pipe %wZ\n", &Fcb->PipeName);
725 Status = NpfsWaitPipe(Irp, Ccb);
726 break;
727
728 case FSCTL_PIPE_IMPERSONATE:
729 DPRINT1("Impersonate not implemented\n");
730 Status = STATUS_NOT_IMPLEMENTED;
731 break;
732
733 case FSCTL_PIPE_SET_CLIENT_PROCESS:
734 DPRINT1("Set client process not implemented\n");
735 Status = STATUS_NOT_IMPLEMENTED;
736 break;
737
738 case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
739 DPRINT1("Query client process not implemented\n");
740 Status = STATUS_NOT_IMPLEMENTED;
741 break;
742
743 case FSCTL_PIPE_INTERNAL_READ:
744 DPRINT1("Internal read not implemented\n");
745 Status = STATUS_NOT_IMPLEMENTED;
746 break;
747
748 case FSCTL_PIPE_INTERNAL_WRITE:
749 DPRINT1("Internal write not implemented\n");
750 Status = STATUS_NOT_IMPLEMENTED;
751 break;
752
753 case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
754 DPRINT1("Internal transceive not implemented\n");
755 Status = STATUS_NOT_IMPLEMENTED;
756 break;
757
758 case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
759 DPRINT1("Internal read overflow not implemented\n");
760 Status = STATUS_NOT_IMPLEMENTED;
761 break;
762
763 default:
764 DPRINT1("Unrecognized IoControlCode: %x\n",
765 IoStack->Parameters.FileSystemControl.FsControlCode);
766 Status = STATUS_UNSUCCESSFUL;
767 }
768
769 if (Status != STATUS_PENDING)
770 {
771 Irp->IoStatus.Status = Status;
772
773 IoCompleteRequest(Irp, IO_NO_INCREMENT);
774 }
775
776 return Status;
777 }
778
779
780 NTSTATUS NTAPI
781 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject,
782 PIRP Irp)
783 {
784 /* FIXME: Implement */
785
786 Irp->IoStatus.Status = STATUS_SUCCESS;
787 Irp->IoStatus.Information = 0;
788
789 IoCompleteRequest(Irp, IO_NO_INCREMENT);
790
791 return STATUS_SUCCESS;
792 }
793
794 /* EOF */