1 /* $Id: fsctrl.c,v 1.17 2004/12/23 12:38:16 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>
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
== FILE_PIPE_LISTENING_STATE
)
56 /* found a listening client fcb */
57 DPRINT("Listening client fcb found -- connecting\n");
59 /* connect client and server fcb's */
60 Fcb
->OtherSide
= ClientFcb
;
61 ClientFcb
->OtherSide
= Fcb
;
63 /* set connected state */
64 Fcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
65 ClientFcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
67 KeUnlockMutex(&Pipe
->FcbListLock
);
69 /* FIXME: create and initialize data queues */
71 /* signal client's connect event */
72 DPRINT("Setting the ConnectEvent for %x\n", ClientFcb
);
73 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
75 return STATUS_PIPE_CONNECTED
;
78 current_entry
= current_entry
->Flink
;
81 KeUnlockMutex(&Pipe
->FcbListLock
);
83 /* no listening client fcb found */
84 DPRINT("No listening client fcb found -- waiting for client\n");
86 Fcb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
88 Status
= KeWaitForSingleObject(&Fcb
->ConnectEvent
,
93 if (!NT_SUCCESS(Status
))
95 DPRINT("KeWaitForSingleObject() failed (Status %lx)\n", Status
);
99 Fcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
101 DPRINT("Client Fcb: %p\n", Fcb
->OtherSide
);
103 return STATUS_PIPE_CONNECTED
;
108 NpfsDisconnectPipe(PNPFS_FCB Fcb
)
110 DPRINT("NpfsDisconnectPipe()\n");
112 if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
113 return STATUS_SUCCESS
;
115 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
117 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
118 /* FIXME: Shouldn't this be FILE_PIPE_CLOSING_STATE? */
119 Fcb
->OtherSide
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
121 /* FIXME: remove data queue(s) */
123 Fcb
->OtherSide
->OtherSide
= NULL
;
124 Fcb
->OtherSide
= NULL
;
126 DPRINT("Pipe disconnected\n");
127 return STATUS_SUCCESS
;
130 if (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
)
132 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
133 Fcb
->OtherSide
= NULL
;
135 /* FIXME: remove data queue(s) */
137 DPRINT("Pipe disconnected\n");
138 return STATUS_SUCCESS
;
141 return STATUS_UNSUCCESSFUL
;
146 NpfsWaitPipe(PIRP Irp
,
150 PLIST_ENTRY current_entry
;
152 PNPFS_WAIT_PIPE WaitPipe
;
155 DPRINT("NpfsWaitPipe\n");
157 WaitPipe
= (PNPFS_WAIT_PIPE
)Irp
->AssociatedIrp
.SystemBuffer
;
160 /* search for listening server */
161 current_entry
= Pipe
->ServerFcbListHead
.Flink
;
162 while (current_entry
!= &Pipe
->ServerFcbListHead
)
164 ServerFcb
= CONTAINING_RECORD(current_entry
,
168 if (ServerFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
170 /* found a listening server fcb */
171 DPRINT("Listening server fcb found -- connecting\n");
173 return STATUS_SUCCESS
;
176 current_entry
= current_entry
->Flink
;
179 /* no listening server fcb found -- wait for one */
180 Fcb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
182 Status
= KeWaitForSingleObject(&Fcb
->ConnectEvent
,
188 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status
);
195 * FUNCTION: Return current state of a pipe
197 * Irp = Pointer to I/O request packet
198 * IrpSp = Pointer to current stack location of Irp
200 * Status of operation
203 NpfsGetState(PIRP Irp
,
204 PIO_STACK_LOCATION IrpSp
)
206 ULONG OutputBufferLength
;
207 PNPFS_GET_STATE Reply
;
212 OutputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
214 /* Validate parameters */
215 if (OutputBufferLength
>= sizeof(NPFS_GET_STATE
))
217 Fcb
= IrpSp
->FileObject
->FsContext
;
218 Reply
= (PNPFS_GET_STATE
)Irp
->AssociatedIrp
.SystemBuffer
;
221 if (Pipe
->PipeWriteMode
== FILE_PIPE_MESSAGE_MODE
)
223 Reply
->WriteModeMessage
= TRUE
;
227 Reply
->WriteModeMessage
= FALSE
;
230 if (Pipe
->PipeReadMode
== FILE_PIPE_MESSAGE_MODE
)
232 Reply
->ReadModeMessage
= TRUE
;
236 Reply
->ReadModeMessage
= FALSE
;
239 if (Pipe
->PipeBlockMode
== FILE_PIPE_QUEUE_OPERATION
)
241 Reply
->NonBlocking
= TRUE
;
245 Reply
->NonBlocking
= FALSE
;
248 Reply
->InBufferSize
= Pipe
->InboundQuota
;
250 Reply
->OutBufferSize
= Pipe
->OutboundQuota
;
252 Reply
->Timeout
= Pipe
->TimeOut
;
254 Status
= STATUS_SUCCESS
;
258 Status
= STATUS_INVALID_PARAMETER
;
261 DPRINT("Status (0x%X).\n", Status
);
268 * FUNCTION: Set state of a pipe
270 * Irp = Pointer to I/O request packet
271 * IrpSp = Pointer to current stack location of Irp
273 * Status of operation
276 NpfsSetState(PIRP Irp
,
277 PIO_STACK_LOCATION IrpSp
)
279 ULONG InputBufferLength
;
280 PNPFS_SET_STATE Request
;
285 InputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
287 /* Validate parameters */
288 if (InputBufferLength
>= sizeof(NPFS_SET_STATE
))
290 Fcb
= IrpSp
->FileObject
->FsContext
;
291 Request
= (PNPFS_SET_STATE
)Irp
->AssociatedIrp
.SystemBuffer
;
294 if (Request
->WriteModeMessage
)
296 Pipe
->PipeWriteMode
= FILE_PIPE_MESSAGE_MODE
;
300 Pipe
->PipeWriteMode
= FILE_PIPE_BYTE_STREAM_MODE
;
303 if (Request
->ReadModeMessage
)
305 Pipe
->PipeReadMode
= FILE_PIPE_MESSAGE_MODE
;
309 Pipe
->PipeReadMode
= FILE_PIPE_BYTE_STREAM_MODE
;
312 if (Request
->NonBlocking
)
314 Pipe
->PipeBlockMode
= FILE_PIPE_QUEUE_OPERATION
;
318 Pipe
->PipeBlockMode
= FILE_PIPE_COMPLETE_OPERATION
;
321 Pipe
->InboundQuota
= Request
->InBufferSize
;
323 Pipe
->OutboundQuota
= Request
->OutBufferSize
;
325 Pipe
->TimeOut
= Request
->Timeout
;
327 Status
= STATUS_SUCCESS
;
331 Status
= STATUS_INVALID_PARAMETER
;
334 DPRINT("Status (0x%X).\n", Status
);
341 * FUNCTION: Peek at a pipe (get information about messages)
343 * Irp = Pointer to I/O request packet
344 * IoStack = Pointer to current stack location of Irp
346 * Status of operation
349 NpfsPeekPipe(PIRP Irp
,
350 PIO_STACK_LOCATION IoStack
)
352 ULONG OutputBufferLength
;
354 PFILE_PIPE_PEEK_BUFFER Reply
;
358 DPRINT("NpfsPeekPipe\n");
360 OutputBufferLength
= IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
362 /* Validate parameters */
363 if (OutputBufferLength
< sizeof(FILE_PIPE_PEEK_BUFFER
))
365 DPRINT("Buffer too small\n");
366 return STATUS_INVALID_PARAMETER
;
369 Fcb
= IoStack
->FileObject
->FsContext
;
370 Reply
= (PFILE_PIPE_PEEK_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
373 Status
= STATUS_NOT_IMPLEMENTED
;
381 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject
,
384 PIO_STACK_LOCATION IoStack
;
385 PFILE_OBJECT FileObject
;
387 PNPFS_DEVICE_EXTENSION DeviceExt
;
391 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
393 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
394 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
395 DPRINT("IoStack: %p\n", IoStack
);
396 FileObject
= IoStack
->FileObject
;
397 DPRINT("FileObject: %p\n", FileObject
);
398 Fcb
= FileObject
->FsContext
;
399 DPRINT("Fcb: %p\n", Fcb
);
401 DPRINT("Pipe: %p\n", Pipe
);
402 DPRINT("PipeName: %wZ\n", &Pipe
->PipeName
);
404 switch (IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
406 case FSCTL_PIPE_ASSIGN_EVENT
:
407 DPRINT("Assign event\n");
408 Status
= STATUS_NOT_IMPLEMENTED
;
411 case FSCTL_PIPE_DISCONNECT
:
412 DPRINT("Disconnecting pipe %wZ\n", &Pipe
->PipeName
);
413 Status
= NpfsDisconnectPipe(Fcb
);
416 case FSCTL_PIPE_LISTEN
:
417 DPRINT("Connecting pipe %wZ\n", &Pipe
->PipeName
);
418 Status
= NpfsConnectPipe(Fcb
);
421 case FSCTL_PIPE_PEEK
:
422 DPRINT("Peeking pipe %wZ\n", &Pipe
->PipeName
);
423 Status
= NpfsPeekPipe(Irp
, (PIO_STACK_LOCATION
)IoStack
);
426 case FSCTL_PIPE_QUERY_EVENT
:
427 DPRINT("Query event\n");
428 Status
= STATUS_NOT_IMPLEMENTED
;
431 case FSCTL_PIPE_TRANSCEIVE
:
432 DPRINT("Transceive\n");
433 Status
= STATUS_NOT_IMPLEMENTED
;
436 case FSCTL_PIPE_WAIT
:
437 DPRINT("Waiting for pipe %wZ\n", &Pipe
->PipeName
);
438 Status
= NpfsWaitPipe(Irp
, Fcb
);
441 case FSCTL_PIPE_IMPERSONATE
:
442 DPRINT("Impersonate\n");
443 Status
= STATUS_NOT_IMPLEMENTED
;
446 case FSCTL_PIPE_SET_CLIENT_PROCESS
:
447 DPRINT("Set client process\n");
448 Status
= STATUS_NOT_IMPLEMENTED
;
451 case FSCTL_PIPE_QUERY_CLIENT_PROCESS
:
452 DPRINT("Query client process\n");
453 Status
= STATUS_NOT_IMPLEMENTED
;
456 case FSCTL_PIPE_GET_STATE
:
457 DPRINT("Get state\n");
458 Status
= NpfsGetState(Irp
, (PIO_STACK_LOCATION
)IoStack
);
461 case FSCTL_PIPE_SET_STATE
:
462 DPRINT("Set state\n");
463 Status
= NpfsSetState(Irp
, (PIO_STACK_LOCATION
)IoStack
);
466 case FSCTL_PIPE_INTERNAL_READ
:
467 DPRINT("Internal read\n");
468 Status
= STATUS_NOT_IMPLEMENTED
;
471 case FSCTL_PIPE_INTERNAL_WRITE
:
472 DPRINT("Internal write\n");
473 Status
= STATUS_NOT_IMPLEMENTED
;
476 case FSCTL_PIPE_INTERNAL_TRANSCEIVE
:
477 DPRINT("Internal transceive\n");
478 Status
= STATUS_NOT_IMPLEMENTED
;
481 case FSCTL_PIPE_INTERNAL_READ_OVFLOW
:
482 DPRINT("Internal read overflow\n");
483 Status
= STATUS_NOT_IMPLEMENTED
;
487 DPRINT("IoControlCode: %x\n", IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
488 Status
= STATUS_UNSUCCESSFUL
;
491 Irp
->IoStatus
.Status
= Status
;
492 Irp
->IoStatus
.Information
= 0;
494 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
501 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject
,
504 /* FIXME: Implement */
506 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
507 Irp
->IoStatus
.Information
= 0;
509 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
511 return STATUS_SUCCESS
;