1 /* $Id: fsctrl.c,v 1.15 2004/05/05 18:30:16 navaraf 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 */
46 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
)
59 current_entry
= current_entry
->Flink
;
62 if (current_entry
!= &Pipe
->ClientFcbListHead
)
64 /* found a listening client fcb */
65 DPRINT("Listening client fcb found -- connecting\n");
67 /* connect client and server fcb's */
68 Fcb
->OtherSide
= ClientFcb
;
69 ClientFcb
->OtherSide
= Fcb
;
71 /* set connected state */
72 Fcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
73 ClientFcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
75 KeUnlockMutex(&Pipe
->FcbListLock
);
77 /* FIXME: create and initialize data queues */
79 /* signal client's connect event */
80 DPRINT("Setting the ConnectEvent for %x\n", ClientFcb
);
81 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
83 Status
= STATUS_PIPE_CONNECTED
;
87 /* no listening client fcb found */
88 DPRINT("No listening client fcb found -- waiting for client\n");
90 KeUnlockMutex(&Pipe
->FcbListLock
);
92 Fcb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
94 Status
= KeWaitForSingleObject(&Fcb
->ConnectEvent
,
100 if (NT_SUCCESS(Status
))
102 Status
= STATUS_PIPE_CONNECTED
;
103 Fcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
106 DPRINT("Finished waiting! Status: %x\n", Status
);
109 DPRINT("Client Fcb: %p\n", Fcb
->OtherSide
);
116 NpfsDisconnectPipe(PNPFS_FCB Fcb
)
118 DPRINT("NpfsDisconnectPipe()\n");
120 if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
121 return(STATUS_SUCCESS
);
123 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
125 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
126 /* FIXME: Shouldn't this be FILE_PIPE_CLOSING_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
;
141 Fcb
->OtherSide
= NULL
;
143 /* FIXME: remove data queue(s) */
145 DPRINT("Pipe disconnected\n");
146 return(STATUS_SUCCESS
);
149 return(STATUS_UNSUCCESSFUL
);
154 NpfsWaitPipe(PIRP Irp
,
158 PLIST_ENTRY current_entry
;
160 PNPFS_WAIT_PIPE WaitPipe
;
163 DPRINT("NpfsWaitPipe\n");
165 WaitPipe
= (PNPFS_WAIT_PIPE
)Irp
->AssociatedIrp
.SystemBuffer
;
168 /* search for listening server */
169 current_entry
= Pipe
->ServerFcbListHead
.Flink
;
170 while (current_entry
!= &Pipe
->ServerFcbListHead
)
172 ServerFcb
= CONTAINING_RECORD(current_entry
,
176 if (ServerFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
179 current_entry
= current_entry
->Flink
;
182 if (current_entry
!= &Pipe
->ServerFcbListHead
)
184 /* found a listening server fcb */
185 DPRINT("Listening server fcb found -- connecting\n");
187 Status
= STATUS_SUCCESS
;
191 /* no listening server fcb found -- wait for one */
192 Fcb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
194 Status
= KeWaitForSingleObject(&Fcb
->ConnectEvent
,
208 PIO_STACK_LOCATION IrpSp
)
210 * FUNCTION: Return current state of a pipe
212 * Irp = Pointer to I/O request packet
213 * IrpSp = Pointer to current stack location of Irp
215 * Status of operation
218 ULONG OutputBufferLength
;
219 PNPFS_GET_STATE Reply
;
224 OutputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
226 /* Validate parameters */
227 if (OutputBufferLength
>= sizeof(NPFS_GET_STATE
))
229 Fcb
= IrpSp
->FileObject
->FsContext
;
230 Reply
= (PNPFS_GET_STATE
)Irp
->AssociatedIrp
.SystemBuffer
;
233 if (Pipe
->PipeWriteMode
== FILE_PIPE_MESSAGE_MODE
)
235 Reply
->WriteModeMessage
= TRUE
;
239 Reply
->WriteModeMessage
= FALSE
;
242 if (Pipe
->PipeReadMode
== FILE_PIPE_MESSAGE_MODE
)
244 Reply
->ReadModeMessage
= TRUE
;
248 Reply
->ReadModeMessage
= FALSE
;
251 if (Pipe
->PipeBlockMode
== FILE_PIPE_QUEUE_OPERATION
)
253 Reply
->NonBlocking
= TRUE
;
257 Reply
->NonBlocking
= FALSE
;
260 Reply
->InBufferSize
= Pipe
->InboundQuota
;
262 Reply
->OutBufferSize
= Pipe
->OutboundQuota
;
264 Reply
->Timeout
= Pipe
->TimeOut
;
266 Status
= STATUS_SUCCESS
;
270 Status
= STATUS_INVALID_PARAMETER
;
273 DPRINT("Status (0x%X).\n", Status
);
282 PIO_STACK_LOCATION IrpSp
)
284 * FUNCTION: Set state of a pipe
286 * Irp = Pointer to I/O request packet
287 * IrpSp = Pointer to current stack location of Irp
289 * Status of operation
292 ULONG InputBufferLength
;
293 PNPFS_SET_STATE Request
;
298 InputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
300 /* Validate parameters */
301 if (InputBufferLength
>= sizeof(NPFS_SET_STATE
))
303 Fcb
= IrpSp
->FileObject
->FsContext
;
304 Request
= (PNPFS_SET_STATE
)Irp
->AssociatedIrp
.SystemBuffer
;
307 if (Request
->WriteModeMessage
)
309 Pipe
->PipeWriteMode
= FILE_PIPE_MESSAGE_MODE
;
313 Pipe
->PipeWriteMode
= FILE_PIPE_BYTE_STREAM_MODE
;
316 if (Request
->ReadModeMessage
)
318 Pipe
->PipeReadMode
= FILE_PIPE_MESSAGE_MODE
;
322 Pipe
->PipeReadMode
= FILE_PIPE_BYTE_STREAM_MODE
;
325 if (Request
->NonBlocking
)
327 Pipe
->PipeBlockMode
= FILE_PIPE_QUEUE_OPERATION
;
331 Pipe
->PipeBlockMode
= FILE_PIPE_COMPLETE_OPERATION
;
334 Pipe
->InboundQuota
= Request
->InBufferSize
;
336 Pipe
->OutboundQuota
= Request
->OutBufferSize
;
338 Pipe
->TimeOut
= Request
->Timeout
;
340 Status
= STATUS_SUCCESS
;
344 Status
= STATUS_INVALID_PARAMETER
;
347 DPRINT("Status (0x%X).\n", Status
);
354 NpfsPeekPipe(PIRP Irp
,
355 PIO_STACK_LOCATION IoStack
)
357 * FUNCTION: Peek at a pipe (get information about messages)
359 * Irp = Pointer to I/O request packet
360 * IoStack = Pointer to current stack location of Irp
362 * Status of operation
365 ULONG OutputBufferLength
;
367 PFILE_PIPE_PEEK_BUFFER Reply
;
371 DPRINT("NpfsPeekPipe\n");
373 OutputBufferLength
= IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
375 /* Validate parameters */
376 if (OutputBufferLength
< sizeof(FILE_PIPE_PEEK_BUFFER
))
378 DPRINT("Buffer too small\n");
379 return(STATUS_INVALID_PARAMETER
);
382 Fcb
= IoStack
->FileObject
->FsContext
;
383 Reply
= (PFILE_PIPE_PEEK_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
386 Status
= STATUS_NOT_IMPLEMENTED
;
394 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject
,
397 PEXTENDED_IO_STACK_LOCATION IoStack
;
398 PFILE_OBJECT FileObject
;
400 PNPFS_DEVICE_EXTENSION DeviceExt
;
404 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
406 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
407 IoStack
= (PEXTENDED_IO_STACK_LOCATION
) IoGetCurrentIrpStackLocation(Irp
);
408 DPRINT("IoStack: %p\n", IoStack
);
409 FileObject
= IoStack
->FileObject
;
410 DPRINT("FileObject: %p\n", FileObject
);
411 Fcb
= FileObject
->FsContext
;
412 DPRINT("Fcb: %p\n", Fcb
);
414 DPRINT("Pipe: %p\n", Pipe
);
415 DPRINT("PipeName: %wZ\n", &Pipe
->PipeName
);
417 switch (IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
419 case FSCTL_PIPE_ASSIGN_EVENT
:
420 DPRINT("Assign event\n");
421 Status
= STATUS_NOT_IMPLEMENTED
;
424 case FSCTL_PIPE_DISCONNECT
:
425 DPRINT("Disconnecting pipe %wZ\n", &Pipe
->PipeName
);
426 Status
= NpfsDisconnectPipe(Fcb
);
429 case FSCTL_PIPE_LISTEN
:
430 DPRINT("Connecting pipe %wZ\n", &Pipe
->PipeName
);
431 Status
= NpfsConnectPipe(Fcb
);
434 case FSCTL_PIPE_PEEK
:
435 DPRINT("Peeking pipe %wZ\n", &Pipe
->PipeName
);
436 Status
= NpfsPeekPipe(Irp
, (PIO_STACK_LOCATION
)IoStack
);
439 case FSCTL_PIPE_QUERY_EVENT
:
440 DPRINT("Query event\n");
441 Status
= STATUS_NOT_IMPLEMENTED
;
444 case FSCTL_PIPE_TRANSCEIVE
:
445 DPRINT("Transceive\n");
446 Status
= STATUS_NOT_IMPLEMENTED
;
449 case FSCTL_PIPE_WAIT
:
450 DPRINT("Waiting for pipe %wZ\n", &Pipe
->PipeName
);
451 Status
= NpfsWaitPipe(Irp
, Fcb
);
454 case FSCTL_PIPE_IMPERSONATE
:
455 DPRINT("Impersonate\n");
456 Status
= STATUS_NOT_IMPLEMENTED
;
459 case FSCTL_PIPE_SET_CLIENT_PROCESS
:
460 DPRINT("Set client process\n");
461 Status
= STATUS_NOT_IMPLEMENTED
;
464 case FSCTL_PIPE_QUERY_CLIENT_PROCESS
:
465 DPRINT("Query client process\n");
466 Status
= STATUS_NOT_IMPLEMENTED
;
469 case FSCTL_PIPE_GET_STATE
:
470 DPRINT("Get state\n");
471 Status
= NpfsGetState(Irp
, (PIO_STACK_LOCATION
)IoStack
);
474 case FSCTL_PIPE_SET_STATE
:
475 DPRINT("Set state\n");
476 Status
= NpfsSetState(Irp
, (PIO_STACK_LOCATION
)IoStack
);
479 case FSCTL_PIPE_INTERNAL_READ
:
480 DPRINT("Internal read\n");
481 Status
= STATUS_NOT_IMPLEMENTED
;
484 case FSCTL_PIPE_INTERNAL_WRITE
:
485 DPRINT("Internal write\n");
486 Status
= STATUS_NOT_IMPLEMENTED
;
489 case FSCTL_PIPE_INTERNAL_TRANSCEIVE
:
490 DPRINT("Internal transceive\n");
491 Status
= STATUS_NOT_IMPLEMENTED
;
494 case FSCTL_PIPE_INTERNAL_READ_OVFLOW
:
495 DPRINT("Internal read overflow\n");
496 Status
= STATUS_NOT_IMPLEMENTED
;
500 DPRINT("IoControlCode: %x\n", IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
501 Status
= STATUS_UNSUCCESSFUL
;
504 Irp
->IoStatus
.Status
= Status
;
505 Irp
->IoStatus
.Information
= 0;
507 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
514 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject
,
517 /* FIXME: Implement */
519 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
520 Irp
->IoStatus
.Information
= 0;
522 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
524 return STATUS_SUCCESS
;