1 /* $Id: fsctrl.c,v 1.13 2003/11/13 15:26:07 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/fs/np/fsctrl.c
6 * PURPOSE: Named pipe filesystem
7 * PROGRAMMER: David Welch <welch@cwcom.net>
8 * Eric Kohl <ekohl@rz-online.de>
11 /* INCLUDES ******************************************************************/
13 #include <ddk/ntddk.h>
20 /* FUNCTIONS *****************************************************************/
23 NpfsConnectPipe(PNPFS_FCB Fcb
)
26 PLIST_ENTRY current_entry
;
30 DPRINT("NpfsConnectPipe()\n");
32 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
33 return STATUS_PIPE_CONNECTED
;
35 if (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
)
36 return STATUS_PIPE_CLOSING
;
39 * Acceptable states are: FILE_PIPE_DISCONNECTED_STATE and
40 * FILE_PIPE_LISTENING_STATE
43 DPRINT("Waiting for connection...\n");
47 Fcb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
49 /* search for a listening client fcb */
51 current_entry
= Pipe
->ClientFcbListHead
.Flink
;
52 while (current_entry
!= &Pipe
->ClientFcbListHead
)
54 ClientFcb
= CONTAINING_RECORD(current_entry
,
58 if ((ClientFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
59 || (ClientFcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
))
64 current_entry
= current_entry
->Flink
;
67 if ((current_entry
!= &Pipe
->ClientFcbListHead
)
68 && (ClientFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
))
70 /* found a listening client fcb */
71 DPRINT("Listening client fcb found -- connecting\n");
73 /* connect client and server fcb's */
74 Fcb
->OtherSide
= ClientFcb
;
75 ClientFcb
->OtherSide
= Fcb
;
77 /* set connected state */
78 Fcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
79 ClientFcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
81 /* FIXME: create and initialize data queues */
83 /* signal client's connect event */
84 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
87 else if ((current_entry
!= &Pipe
->ClientFcbListHead
)
88 && (ClientFcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
))
90 /* found a disconnected client fcb */
91 DPRINT("Disconnected client fcb found - notifying client\n");
93 /* signal client's connect event */
94 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
98 /* no listening client fcb found */
99 DPRINT("No listening client fcb found -- waiting for client\n");
100 Status
= KeWaitForSingleObject(&Fcb
->ConnectEvent
,
106 DPRINT("Finished waiting! Status: %x\n", Status
);
110 DPRINT("Client Fcb: %p\n", Fcb
->OtherSide
);
112 return STATUS_PIPE_CONNECTED
;
117 NpfsDisconnectPipe(PNPFS_FCB Fcb
)
119 DPRINT("NpfsDisconnectPipe()\n");
121 if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
122 return(STATUS_SUCCESS
);
124 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
126 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
127 Fcb
->OtherSide
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
129 /* FIXME: remove data queue(s) */
131 Fcb
->OtherSide
->OtherSide
= NULL
;
132 Fcb
->OtherSide
= NULL
;
134 DPRINT("Pipe disconnected\n");
135 return(STATUS_SUCCESS
);
138 if (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
)
140 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
142 /* FIXME: remove data queue(s) */
144 DPRINT("Pipe disconnected\n");
145 return(STATUS_SUCCESS
);
148 return(STATUS_UNSUCCESSFUL
);
153 NpfsWaitPipe(PIRP Irp
,
157 PLIST_ENTRY current_entry
;
159 PNPFS_WAIT_PIPE WaitPipe
;
162 DPRINT("NpfsWaitPipe\n");
164 WaitPipe
= (PNPFS_WAIT_PIPE
)Irp
->AssociatedIrp
.SystemBuffer
;
167 /* search for listening server */
168 current_entry
= Pipe
->ServerFcbListHead
.Flink
;
169 while (current_entry
!= &Pipe
->ServerFcbListHead
)
171 ServerFcb
= CONTAINING_RECORD(current_entry
,
175 if (ServerFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
178 current_entry
= current_entry
->Flink
;
181 if (current_entry
!= &Pipe
->ServerFcbListHead
)
183 /* found a listening server fcb */
184 DPRINT("Listening server fcb found -- connecting\n");
186 Status
= STATUS_SUCCESS
;
190 /* no listening server fcb found -- wait for one */
191 Fcb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
193 Status
= KeWaitForSingleObject(&Fcb
->ConnectEvent
,
207 PIO_STACK_LOCATION IrpSp
)
209 * FUNCTION: Return current state of a pipe
211 * Irp = Pointer to I/O request packet
212 * IrpSp = Pointer to current stack location of Irp
214 * Status of operation
217 ULONG OutputBufferLength
;
218 PNPFS_GET_STATE Reply
;
223 OutputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
225 /* Validate parameters */
226 if (OutputBufferLength
>= sizeof(NPFS_GET_STATE
))
228 Fcb
= IrpSp
->FileObject
->FsContext
;
229 Reply
= (PNPFS_GET_STATE
)Irp
->AssociatedIrp
.SystemBuffer
;
232 if (Pipe
->PipeWriteMode
== FILE_PIPE_MESSAGE_MODE
)
234 Reply
->WriteModeMessage
= TRUE
;
238 Reply
->WriteModeMessage
= FALSE
;
241 if (Pipe
->PipeReadMode
== FILE_PIPE_MESSAGE_MODE
)
243 Reply
->ReadModeMessage
= TRUE
;
247 Reply
->ReadModeMessage
= FALSE
;
250 if (Pipe
->PipeBlockMode
== FILE_PIPE_QUEUE_OPERATION
)
252 Reply
->NonBlocking
= TRUE
;
256 Reply
->NonBlocking
= FALSE
;
259 Reply
->InBufferSize
= Pipe
->InboundQuota
;
261 Reply
->OutBufferSize
= Pipe
->OutboundQuota
;
263 Reply
->Timeout
= Pipe
->TimeOut
;
265 Status
= STATUS_SUCCESS
;
269 Status
= STATUS_INVALID_PARAMETER
;
272 DPRINT("Status (0x%X).\n", Status
);
281 PIO_STACK_LOCATION IrpSp
)
283 * FUNCTION: Set state of a pipe
285 * Irp = Pointer to I/O request packet
286 * IrpSp = Pointer to current stack location of Irp
288 * Status of operation
291 ULONG InputBufferLength
;
292 PNPFS_SET_STATE Request
;
297 InputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
299 /* Validate parameters */
300 if (InputBufferLength
>= sizeof(NPFS_SET_STATE
))
302 Fcb
= IrpSp
->FileObject
->FsContext
;
303 Request
= (PNPFS_SET_STATE
)Irp
->AssociatedIrp
.SystemBuffer
;
306 if (Request
->WriteModeMessage
)
308 Pipe
->PipeWriteMode
= FILE_PIPE_MESSAGE_MODE
;
312 Pipe
->PipeWriteMode
= FILE_PIPE_BYTE_STREAM_MODE
;
315 if (Request
->ReadModeMessage
)
317 Pipe
->PipeReadMode
= FILE_PIPE_MESSAGE_MODE
;
321 Pipe
->PipeReadMode
= FILE_PIPE_BYTE_STREAM_MODE
;
324 if (Request
->NonBlocking
)
326 Pipe
->PipeBlockMode
= FILE_PIPE_QUEUE_OPERATION
;
330 Pipe
->PipeBlockMode
= FILE_PIPE_COMPLETE_OPERATION
;
333 Pipe
->InboundQuota
= Request
->InBufferSize
;
335 Pipe
->OutboundQuota
= Request
->OutBufferSize
;
337 Pipe
->TimeOut
= Request
->Timeout
;
339 Status
= STATUS_SUCCESS
;
343 Status
= STATUS_INVALID_PARAMETER
;
346 DPRINT("Status (0x%X).\n", Status
);
353 NpfsPeekPipe(PIRP Irp
,
354 PIO_STACK_LOCATION IoStack
)
356 * FUNCTION: Peek at a pipe (get information about messages)
358 * Irp = Pointer to I/O request packet
359 * IoStack = Pointer to current stack location of Irp
361 * Status of operation
364 ULONG OutputBufferLength
;
366 PFILE_PIPE_PEEK_BUFFER Reply
;
370 DPRINT("NpfsPeekPipe\n");
372 OutputBufferLength
= IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
374 /* Validate parameters */
375 if (OutputBufferLength
< sizeof(FILE_PIPE_PEEK_BUFFER
))
377 DPRINT("Buffer too small\n");
378 return(STATUS_INVALID_PARAMETER
);
381 Fcb
= IoStack
->FileObject
->FsContext
;
382 Reply
= (PFILE_PIPE_PEEK_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
385 Status
= STATUS_NOT_IMPLEMENTED
;
393 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject
,
396 PEXTENDED_IO_STACK_LOCATION IoStack
;
397 PFILE_OBJECT FileObject
;
399 PNPFS_DEVICE_EXTENSION DeviceExt
;
403 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
405 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
406 IoStack
= (PEXTENDED_IO_STACK_LOCATION
) IoGetCurrentIrpStackLocation(Irp
);
407 DPRINT("IoStack: %p\n", IoStack
);
408 FileObject
= IoStack
->FileObject
;
409 DPRINT("FileObject: %p\n", FileObject
);
410 Fcb
= FileObject
->FsContext
;
411 DPRINT("Fcb: %p\n", Fcb
);
413 DPRINT("Pipe: %p\n", Pipe
);
414 DPRINT("PipeName: %wZ\n", &Pipe
->PipeName
);
416 switch (IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
418 case FSCTL_PIPE_ASSIGN_EVENT
:
419 DPRINT("Assign event\n");
420 Status
= STATUS_NOT_IMPLEMENTED
;
423 case FSCTL_PIPE_DISCONNECT
:
424 DPRINT("Disconnecting pipe %wZ\n", &Pipe
->PipeName
);
425 Status
= NpfsDisconnectPipe(Fcb
);
428 case FSCTL_PIPE_LISTEN
:
429 DPRINT("Connecting pipe %wZ\n", &Pipe
->PipeName
);
430 Status
= NpfsConnectPipe(Fcb
);
433 case FSCTL_PIPE_PEEK
:
434 DPRINT("Peeking pipe %wZ\n", &Pipe
->PipeName
);
435 Status
= NpfsPeekPipe(Irp
, (PIO_STACK_LOCATION
)IoStack
);
438 case FSCTL_PIPE_QUERY_EVENT
:
439 DPRINT("Query event\n");
440 Status
= STATUS_NOT_IMPLEMENTED
;
443 case FSCTL_PIPE_TRANSCEIVE
:
444 DPRINT("Transceive\n");
445 Status
= STATUS_NOT_IMPLEMENTED
;
448 case FSCTL_PIPE_WAIT
:
449 DPRINT("Waiting for pipe %wZ\n", &Pipe
->PipeName
);
450 Status
= NpfsWaitPipe(Irp
, Fcb
);
453 case FSCTL_PIPE_IMPERSONATE
:
454 DPRINT("Impersonate\n");
455 Status
= STATUS_NOT_IMPLEMENTED
;
458 case FSCTL_PIPE_SET_CLIENT_PROCESS
:
459 DPRINT("Set client process\n");
460 Status
= STATUS_NOT_IMPLEMENTED
;
463 case FSCTL_PIPE_QUERY_CLIENT_PROCESS
:
464 DPRINT("Query client process\n");
465 Status
= STATUS_NOT_IMPLEMENTED
;
468 case FSCTL_PIPE_GET_STATE
:
469 DPRINT("Get state\n");
470 Status
= NpfsGetState(Irp
, (PIO_STACK_LOCATION
)IoStack
);
473 case FSCTL_PIPE_SET_STATE
:
474 DPRINT("Set state\n");
475 Status
= NpfsSetState(Irp
, (PIO_STACK_LOCATION
)IoStack
);
478 case FSCTL_PIPE_INTERNAL_READ
:
479 DPRINT("Internal read\n");
480 Status
= STATUS_NOT_IMPLEMENTED
;
483 case FSCTL_PIPE_INTERNAL_WRITE
:
484 DPRINT("Internal write\n");
485 Status
= STATUS_NOT_IMPLEMENTED
;
488 case FSCTL_PIPE_INTERNAL_TRANSCEIVE
:
489 DPRINT("Internal transceive\n");
490 Status
= STATUS_NOT_IMPLEMENTED
;
493 case FSCTL_PIPE_INTERNAL_READ_OVFLOW
:
494 DPRINT("Internal read overflow\n");
495 Status
= STATUS_NOT_IMPLEMENTED
;
499 DPRINT("IoControlCode: %x\n", IoStack
->Parameters
.FileSystemControl
.IoControlCode
)
500 Status
= STATUS_UNSUCCESSFUL
;
503 Irp
->IoStatus
.Status
= Status
;
504 Irp
->IoStatus
.Information
= 0;
506 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);