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>
19 /* FUNCTIONS *****************************************************************/
22 NpfsConnectPipe(PNPFS_FCB Fcb
)
25 PLIST_ENTRY current_entry
;
29 DPRINT("NpfsConnectPipe()\n");
31 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
33 KeResetEvent(&Fcb
->ConnectEvent
);
34 return STATUS_PIPE_CONNECTED
;
37 if (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
)
38 return STATUS_PIPE_CLOSING
;
40 DPRINT("Waiting for connection...\n");
44 /* search for a listening client fcb */
45 KeLockMutex(&Pipe
->FcbListLock
);
47 current_entry
= Pipe
->ClientFcbListHead
.Flink
;
48 while (current_entry
!= &Pipe
->ClientFcbListHead
)
50 ClientFcb
= CONTAINING_RECORD(current_entry
,
54 if (ClientFcb
->PipeState
== 0)
56 /* found a passive (waiting) client fcb */
57 DPRINT("Passive (waiting) client fcb found -- wake the client\n");
58 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
63 if (ClientFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
65 /* found a listening client fcb */
66 DPRINT("Listening client fcb found -- connecting\n");
68 /* connect client and server fcb's */
69 Fcb
->OtherSide
= ClientFcb
;
70 ClientFcb
->OtherSide
= Fcb
;
72 /* set connected state */
73 Fcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
74 ClientFcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
76 KeUnlockMutex(&Pipe
->FcbListLock
);
78 /* FIXME: create and initialize data queues */
80 /* signal client's connect event */
81 DPRINT("Setting the ConnectEvent for %x\n", ClientFcb
);
82 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
84 return STATUS_PIPE_CONNECTED
;
88 current_entry
= current_entry
->Flink
;
91 KeUnlockMutex(&Pipe
->FcbListLock
);
93 /* no listening client fcb found */
94 DPRINT("No listening client fcb found -- waiting for client\n");
96 Fcb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
98 Status
= KeWaitForSingleObject(&Fcb
->ConnectEvent
,
103 if (!NT_SUCCESS(Status
))
105 DPRINT("KeWaitForSingleObject() failed (Status %lx)\n", Status
);
109 Fcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
111 DPRINT("Client Fcb: %p\n", Fcb
->OtherSide
);
113 return STATUS_PIPE_CONNECTED
;
118 NpfsDisconnectPipe(PNPFS_FCB Fcb
)
120 DPRINT("NpfsDisconnectPipe()\n");
122 if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
123 return STATUS_SUCCESS
;
125 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
127 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
128 /* FIXME: Shouldn't this be FILE_PIPE_CLOSING_STATE? */
129 Fcb
->OtherSide
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
131 /* FIXME: remove data queue(s) */
133 Fcb
->OtherSide
->OtherSide
= NULL
;
134 Fcb
->OtherSide
= NULL
;
136 DPRINT("Pipe disconnected\n");
137 return STATUS_SUCCESS
;
140 if (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
)
142 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
143 Fcb
->OtherSide
= NULL
;
145 /* FIXME: remove data queue(s) */
147 DPRINT("Pipe disconnected\n");
148 return STATUS_SUCCESS
;
151 return STATUS_UNSUCCESSFUL
;
156 NpfsWaitPipe(PIRP Irp
,
160 PLIST_ENTRY current_entry
;
162 PNPFS_WAIT_PIPE WaitPipe
;
165 DPRINT("NpfsWaitPipe\n");
167 WaitPipe
= (PNPFS_WAIT_PIPE
)Irp
->AssociatedIrp
.SystemBuffer
;
170 if (Fcb
->PipeState
!= 0)
172 DPRINT("Pipe is not in passive (waiting) state!\n");
173 return STATUS_UNSUCCESSFUL
;
176 /* search for listening server */
177 current_entry
= Pipe
->ServerFcbListHead
.Flink
;
178 while (current_entry
!= &Pipe
->ServerFcbListHead
)
180 ServerFcb
= CONTAINING_RECORD(current_entry
,
184 if (ServerFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
186 /* found a listening server fcb */
187 DPRINT("Listening server fcb found -- connecting\n");
189 return STATUS_SUCCESS
;
192 current_entry
= current_entry
->Flink
;
195 /* no listening server fcb found -- wait for one */
196 Status
= KeWaitForSingleObject(&Fcb
->ConnectEvent
,
202 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status
);
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 NpfsGetState(PIRP Irp
,
218 PIO_STACK_LOCATION IrpSp
)
220 ULONG OutputBufferLength
;
221 PNPFS_GET_STATE Reply
;
226 OutputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
228 /* Validate parameters */
229 if (OutputBufferLength
>= sizeof(NPFS_GET_STATE
))
231 Fcb
= IrpSp
->FileObject
->FsContext
;
232 Reply
= (PNPFS_GET_STATE
)Irp
->AssociatedIrp
.SystemBuffer
;
235 if (Pipe
->PipeWriteMode
== FILE_PIPE_MESSAGE_MODE
)
237 Reply
->WriteModeMessage
= TRUE
;
241 Reply
->WriteModeMessage
= FALSE
;
244 if (Pipe
->PipeReadMode
== FILE_PIPE_MESSAGE_MODE
)
246 Reply
->ReadModeMessage
= TRUE
;
250 Reply
->ReadModeMessage
= FALSE
;
253 if (Pipe
->PipeBlockMode
== FILE_PIPE_QUEUE_OPERATION
)
255 Reply
->NonBlocking
= TRUE
;
259 Reply
->NonBlocking
= FALSE
;
262 Reply
->InBufferSize
= Pipe
->InboundQuota
;
264 Reply
->OutBufferSize
= Pipe
->OutboundQuota
;
266 Reply
->Timeout
= Pipe
->TimeOut
;
268 Status
= STATUS_SUCCESS
;
272 Status
= STATUS_INVALID_PARAMETER
;
275 DPRINT("Status (0x%X).\n", Status
);
282 * FUNCTION: Set state of a pipe
284 * Irp = Pointer to I/O request packet
285 * IrpSp = Pointer to current stack location of Irp
287 * Status of operation
290 NpfsSetState(PIRP Irp
,
291 PIO_STACK_LOCATION IrpSp
)
293 ULONG InputBufferLength
;
294 PNPFS_SET_STATE Request
;
299 InputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
301 /* Validate parameters */
302 if (InputBufferLength
>= sizeof(NPFS_SET_STATE
))
304 Fcb
= IrpSp
->FileObject
->FsContext
;
305 Request
= (PNPFS_SET_STATE
)Irp
->AssociatedIrp
.SystemBuffer
;
308 if (Request
->WriteModeMessage
)
310 Pipe
->PipeWriteMode
= FILE_PIPE_MESSAGE_MODE
;
314 Pipe
->PipeWriteMode
= FILE_PIPE_BYTE_STREAM_MODE
;
317 if (Request
->ReadModeMessage
)
319 Pipe
->PipeReadMode
= FILE_PIPE_MESSAGE_MODE
;
323 Pipe
->PipeReadMode
= FILE_PIPE_BYTE_STREAM_MODE
;
326 if (Request
->NonBlocking
)
328 Pipe
->PipeBlockMode
= FILE_PIPE_QUEUE_OPERATION
;
332 Pipe
->PipeBlockMode
= FILE_PIPE_COMPLETE_OPERATION
;
335 Pipe
->InboundQuota
= Request
->InBufferSize
;
337 Pipe
->OutboundQuota
= Request
->OutBufferSize
;
339 Pipe
->TimeOut
= Request
->Timeout
;
341 Status
= STATUS_SUCCESS
;
345 Status
= STATUS_INVALID_PARAMETER
;
348 DPRINT("Status (0x%X).\n", Status
);
355 * FUNCTION: Peek at a pipe (get information about messages)
357 * Irp = Pointer to I/O request packet
358 * IoStack = Pointer to current stack location of Irp
360 * Status of operation
363 NpfsPeekPipe(PIRP Irp
,
364 PIO_STACK_LOCATION IoStack
)
366 ULONG OutputBufferLength
;
368 PFILE_PIPE_PEEK_BUFFER Reply
;
372 DPRINT("NpfsPeekPipe\n");
374 OutputBufferLength
= IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
376 /* Validate parameters */
377 if (OutputBufferLength
< sizeof(FILE_PIPE_PEEK_BUFFER
))
379 DPRINT("Buffer too small\n");
380 return STATUS_INVALID_PARAMETER
;
383 Fcb
= IoStack
->FileObject
->FsContext
;
384 Reply
= (PFILE_PIPE_PEEK_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
387 Status
= STATUS_NOT_IMPLEMENTED
;
395 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject
,
398 PIO_STACK_LOCATION IoStack
;
399 PFILE_OBJECT FileObject
;
401 PNPFS_DEVICE_EXTENSION DeviceExt
;
405 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
407 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
408 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
409 DPRINT("IoStack: %p\n", IoStack
);
410 FileObject
= IoStack
->FileObject
;
411 DPRINT("FileObject: %p\n", FileObject
);
412 Fcb
= FileObject
->FsContext
;
413 DPRINT("Fcb: %p\n", Fcb
);
415 DPRINT("Pipe: %p\n", Pipe
);
416 DPRINT("PipeName: %wZ\n", &Pipe
->PipeName
);
418 switch (IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
420 case FSCTL_PIPE_ASSIGN_EVENT
:
421 DPRINT("Assign event\n");
422 Status
= STATUS_NOT_IMPLEMENTED
;
425 case FSCTL_PIPE_DISCONNECT
:
426 DPRINT("Disconnecting pipe %wZ\n", &Pipe
->PipeName
);
427 Status
= NpfsDisconnectPipe(Fcb
);
430 case FSCTL_PIPE_LISTEN
:
431 DPRINT("Connecting pipe %wZ\n", &Pipe
->PipeName
);
432 Status
= NpfsConnectPipe(Fcb
);
435 case FSCTL_PIPE_PEEK
:
436 DPRINT("Peeking pipe %wZ\n", &Pipe
->PipeName
);
437 Status
= NpfsPeekPipe(Irp
, (PIO_STACK_LOCATION
)IoStack
);
440 case FSCTL_PIPE_QUERY_EVENT
:
441 DPRINT("Query event\n");
442 Status
= STATUS_NOT_IMPLEMENTED
;
445 case FSCTL_PIPE_TRANSCEIVE
:
446 DPRINT("Transceive\n");
447 Status
= STATUS_NOT_IMPLEMENTED
;
450 case FSCTL_PIPE_WAIT
:
451 DPRINT("Waiting for pipe %wZ\n", &Pipe
->PipeName
);
452 Status
= NpfsWaitPipe(Irp
, Fcb
);
455 case FSCTL_PIPE_IMPERSONATE
:
456 DPRINT("Impersonate\n");
457 Status
= STATUS_NOT_IMPLEMENTED
;
460 case FSCTL_PIPE_SET_CLIENT_PROCESS
:
461 DPRINT("Set client process\n");
462 Status
= STATUS_NOT_IMPLEMENTED
;
465 case FSCTL_PIPE_QUERY_CLIENT_PROCESS
:
466 DPRINT("Query client process\n");
467 Status
= STATUS_NOT_IMPLEMENTED
;
470 case FSCTL_PIPE_GET_STATE
:
471 DPRINT("Get state\n");
472 Status
= NpfsGetState(Irp
, (PIO_STACK_LOCATION
)IoStack
);
475 case FSCTL_PIPE_SET_STATE
:
476 DPRINT("Set state\n");
477 Status
= NpfsSetState(Irp
, (PIO_STACK_LOCATION
)IoStack
);
480 case FSCTL_PIPE_INTERNAL_READ
:
481 DPRINT("Internal read\n");
482 Status
= STATUS_NOT_IMPLEMENTED
;
485 case FSCTL_PIPE_INTERNAL_WRITE
:
486 DPRINT("Internal write\n");
487 Status
= STATUS_NOT_IMPLEMENTED
;
490 case FSCTL_PIPE_INTERNAL_TRANSCEIVE
:
491 DPRINT("Internal transceive\n");
492 Status
= STATUS_NOT_IMPLEMENTED
;
495 case FSCTL_PIPE_INTERNAL_READ_OVFLOW
:
496 DPRINT("Internal read overflow\n");
497 Status
= STATUS_NOT_IMPLEMENTED
;
501 DPRINT("IoControlCode: %x\n", IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
502 Status
= STATUS_UNSUCCESSFUL
;
505 Irp
->IoStatus
.Status
= Status
;
506 Irp
->IoStatus
.Information
= 0;
508 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
515 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject
,
518 /* FIXME: Implement */
520 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
521 Irp
->IoStatus
.Information
= 0;
523 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
525 return STATUS_SUCCESS
;