3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: drivers/fs/np/fsctrl.c
6 * PURPOSE: Named pipe filesystem
7 * PROGRAMMER: David Welch <welch@cwcom.net>
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 PNPFS_GET_STATE Reply
;
224 /* Validate parameters */
225 if (IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(NPFS_GET_STATE
))
227 DPRINT("Status (0x%X).\n", STATUS_INVALID_PARAMETER
);
228 return STATUS_INVALID_PARAMETER
;
231 Fcb
= IrpSp
->FileObject
->FsContext
;
232 Reply
= (PNPFS_GET_STATE
)Irp
->AssociatedIrp
.SystemBuffer
;
235 Reply
->WriteModeMessage
= (Pipe
->WriteMode
== FILE_PIPE_MESSAGE_MODE
);
236 Reply
->ReadModeMessage
= (Pipe
->ReadMode
== FILE_PIPE_MESSAGE_MODE
);
237 Reply
->NonBlocking
= (Pipe
->CompletionMode
== FILE_PIPE_QUEUE_OPERATION
);
238 Reply
->InBufferSize
= Pipe
->InboundQuota
;
239 Reply
->OutBufferSize
= Pipe
->OutboundQuota
;
240 Reply
->Timeout
= Pipe
->TimeOut
;
242 DPRINT("Status (0x%X).\n", STATUS_SUCCESS
);
244 return STATUS_SUCCESS
;
249 * FUNCTION: Set state of a pipe
251 * Irp = Pointer to I/O request packet
252 * IrpSp = Pointer to current stack location of Irp
254 * Status of operation
257 NpfsSetState(PIRP Irp
,
258 PIO_STACK_LOCATION IrpSp
)
260 PNPFS_SET_STATE Request
;
264 /* Validate parameters */
265 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(NPFS_SET_STATE
))
267 DPRINT("Status (0x%X).\n", STATUS_INVALID_PARAMETER
);
268 return STATUS_INVALID_PARAMETER
;
271 Fcb
= IrpSp
->FileObject
->FsContext
;
272 Request
= (PNPFS_SET_STATE
)Irp
->AssociatedIrp
.SystemBuffer
;
276 Request
->WriteModeMessage
? FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
278 Request
->WriteModeMessage
? FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
279 Pipe
->CompletionMode
=
280 Request
->NonBlocking
? FILE_PIPE_QUEUE_OPERATION
: FILE_PIPE_COMPLETE_OPERATION
;
281 Pipe
->InboundQuota
= Request
->InBufferSize
;
282 Pipe
->OutboundQuota
= Request
->OutBufferSize
;
283 Pipe
->TimeOut
= Request
->Timeout
;
285 DPRINT("Status (0x%X).\n", STATUS_SUCCESS
);
287 return STATUS_SUCCESS
;
292 * FUNCTION: Peek at a pipe (get information about messages)
294 * Irp = Pointer to I/O request packet
295 * IoStack = Pointer to current stack location of Irp
297 * Status of operation
300 NpfsPeekPipe(PIRP Irp
,
301 PIO_STACK_LOCATION IoStack
)
303 ULONG OutputBufferLength
;
305 PFILE_PIPE_PEEK_BUFFER Reply
;
309 DPRINT("NpfsPeekPipe\n");
311 OutputBufferLength
= IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
313 /* Validate parameters */
314 if (OutputBufferLength
< sizeof(FILE_PIPE_PEEK_BUFFER
))
316 DPRINT("Buffer too small\n");
317 return STATUS_INVALID_PARAMETER
;
320 Fcb
= IoStack
->FileObject
->FsContext
;
321 Reply
= (PFILE_PIPE_PEEK_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
324 Status
= STATUS_NOT_IMPLEMENTED
;
332 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject
,
335 PIO_STACK_LOCATION IoStack
;
336 PFILE_OBJECT FileObject
;
338 PNPFS_DEVICE_EXTENSION DeviceExt
;
342 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
344 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
345 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
346 DPRINT("IoStack: %p\n", IoStack
);
347 FileObject
= IoStack
->FileObject
;
348 DPRINT("FileObject: %p\n", FileObject
);
349 Fcb
= FileObject
->FsContext
;
350 DPRINT("Fcb: %p\n", Fcb
);
352 DPRINT("Pipe: %p\n", Pipe
);
353 DPRINT("PipeName: %wZ\n", &Pipe
->PipeName
);
355 switch (IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
357 case FSCTL_PIPE_ASSIGN_EVENT
:
358 DPRINT("Assign event\n");
359 Status
= STATUS_NOT_IMPLEMENTED
;
362 case FSCTL_PIPE_DISCONNECT
:
363 DPRINT("Disconnecting pipe %wZ\n", &Pipe
->PipeName
);
364 Status
= NpfsDisconnectPipe(Fcb
);
367 case FSCTL_PIPE_LISTEN
:
368 DPRINT("Connecting pipe %wZ\n", &Pipe
->PipeName
);
369 Status
= NpfsConnectPipe(Fcb
);
372 case FSCTL_PIPE_PEEK
:
373 DPRINT("Peeking pipe %wZ\n", &Pipe
->PipeName
);
374 Status
= NpfsPeekPipe(Irp
, (PIO_STACK_LOCATION
)IoStack
);
377 case FSCTL_PIPE_QUERY_EVENT
:
378 DPRINT("Query event\n");
379 Status
= STATUS_NOT_IMPLEMENTED
;
382 case FSCTL_PIPE_TRANSCEIVE
:
383 DPRINT("Transceive\n");
384 Status
= STATUS_NOT_IMPLEMENTED
;
387 case FSCTL_PIPE_WAIT
:
388 DPRINT("Waiting for pipe %wZ\n", &Pipe
->PipeName
);
389 Status
= NpfsWaitPipe(Irp
, Fcb
);
392 case FSCTL_PIPE_IMPERSONATE
:
393 DPRINT("Impersonate\n");
394 Status
= STATUS_NOT_IMPLEMENTED
;
397 case FSCTL_PIPE_SET_CLIENT_PROCESS
:
398 DPRINT("Set client process\n");
399 Status
= STATUS_NOT_IMPLEMENTED
;
402 case FSCTL_PIPE_QUERY_CLIENT_PROCESS
:
403 DPRINT("Query client process\n");
404 Status
= STATUS_NOT_IMPLEMENTED
;
407 case FSCTL_PIPE_GET_STATE
:
408 DPRINT("Get state\n");
409 Status
= NpfsGetState(Irp
, (PIO_STACK_LOCATION
)IoStack
);
412 case FSCTL_PIPE_SET_STATE
:
413 DPRINT("Set state\n");
414 Status
= NpfsSetState(Irp
, (PIO_STACK_LOCATION
)IoStack
);
417 case FSCTL_PIPE_INTERNAL_READ
:
418 DPRINT("Internal read\n");
419 Status
= STATUS_NOT_IMPLEMENTED
;
422 case FSCTL_PIPE_INTERNAL_WRITE
:
423 DPRINT("Internal write\n");
424 Status
= STATUS_NOT_IMPLEMENTED
;
427 case FSCTL_PIPE_INTERNAL_TRANSCEIVE
:
428 DPRINT("Internal transceive\n");
429 Status
= STATUS_NOT_IMPLEMENTED
;
432 case FSCTL_PIPE_INTERNAL_READ_OVFLOW
:
433 DPRINT("Internal read overflow\n");
434 Status
= STATUS_NOT_IMPLEMENTED
;
438 DPRINT("IoControlCode: %x\n", IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
439 Status
= STATUS_UNSUCCESSFUL
;
442 Irp
->IoStatus
.Status
= Status
;
443 Irp
->IoStatus
.Information
= 0;
445 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
452 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject
,
455 /* FIXME: Implement */
457 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
458 Irp
->IoStatus
.Information
= 0;
460 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
462 return STATUS_SUCCESS
;