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 NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject
,
25 PNPFS_WAITER_ENTRY Waiter
;
27 DPRINT1("NpfsListeningCancelRoutine() called\n");
28 /* FIXME: Not tested. */
30 Waiter
= Irp
->Tail
.Overlay
.DriverContext
[0];
32 RemoveEntryList(&Waiter
->Entry
);
35 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
37 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
38 Irp
->IoStatus
.Information
= 0;
39 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
44 NpfsAddListeningServerInstance(PIRP Irp
,
47 PNPFS_WAITER_ENTRY Entry
;
50 Entry
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_WAITER_ENTRY
));
52 return STATUS_INSUFFICIENT_RESOURCES
;
56 InsertTailList(&Fcb
->Pipe
->WaiterListHead
, &Entry
->Entry
);
58 IoAcquireCancelSpinLock(&OldIrql
);
61 Irp
->Tail
.Overlay
.DriverContext
[0] = Entry
;
62 IoMarkIrpPending(Irp
);
63 IoSetCancelRoutine(Irp
, NpfsListeningCancelRoutine
);
64 IoReleaseCancelSpinLock(OldIrql
);
65 return STATUS_PENDING
;
67 /* IRP has already been cancelled */
68 IoReleaseCancelSpinLock(OldIrql
);
70 DPRINT1("FIXME: Remove waiter entry!\n");
71 RemoveEntryList(&Entry
->Entry
);
74 return STATUS_CANCELLED
;
79 NpfsConnectPipe(PIRP Irp
,
83 PLIST_ENTRY current_entry
;
87 DPRINT("NpfsConnectPipe()\n");
89 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
91 KeResetEvent(&Fcb
->ConnectEvent
);
92 return STATUS_PIPE_CONNECTED
;
95 if (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
)
96 return STATUS_PIPE_CLOSING
;
98 DPRINT("Waiting for connection...\n");
102 /* search for a listening client fcb */
103 KeLockMutex(&Pipe
->FcbListLock
);
105 current_entry
= Pipe
->ClientFcbListHead
.Flink
;
106 while (current_entry
!= &Pipe
->ClientFcbListHead
)
108 ClientFcb
= CONTAINING_RECORD(current_entry
,
112 if (ClientFcb
->PipeState
== 0)
114 /* found a passive (waiting) client fcb */
115 DPRINT("Passive (waiting) client fcb found -- wake the client\n");
116 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
121 if (ClientFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
123 /* found a listening client fcb */
124 DPRINT("Listening client fcb found -- connecting\n");
126 /* connect client and server fcb's */
127 Fcb
->OtherSide
= ClientFcb
;
128 ClientFcb
->OtherSide
= Fcb
;
130 /* set connected state */
131 Fcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
132 ClientFcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
134 KeUnlockMutex(&Pipe
->FcbListLock
);
136 /* FIXME: create and initialize data queues */
138 /* signal client's connect event */
139 DPRINT("Setting the ConnectEvent for %x\n", ClientFcb
);
140 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
142 return STATUS_PIPE_CONNECTED
;
146 current_entry
= current_entry
->Flink
;
149 /* no listening client fcb found */
150 DPRINT("No listening client fcb found -- waiting for client\n");
152 Fcb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
154 Status
= NpfsAddListeningServerInstance(Irp
, Fcb
);
156 KeUnlockMutex(&Pipe
->FcbListLock
);
158 DPRINT("NpfsConnectPipe() done (Status %lx)\n", Status
);
165 NpfsDisconnectPipe(PNPFS_FCB Fcb
)
167 DPRINT("NpfsDisconnectPipe()\n");
169 if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
170 return STATUS_SUCCESS
;
172 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
174 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
175 /* FIXME: Shouldn't this be FILE_PIPE_CLOSING_STATE? */
176 Fcb
->OtherSide
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
178 /* FIXME: remove data queue(s) */
180 Fcb
->OtherSide
->OtherSide
= NULL
;
181 Fcb
->OtherSide
= NULL
;
183 DPRINT("Pipe disconnected\n");
184 return STATUS_SUCCESS
;
187 if (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
)
189 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
190 Fcb
->OtherSide
= NULL
;
192 /* FIXME: remove data queue(s) */
194 DPRINT("Pipe disconnected\n");
195 return STATUS_SUCCESS
;
198 return STATUS_UNSUCCESSFUL
;
203 NpfsWaitPipe(PIRP Irp
,
207 PLIST_ENTRY current_entry
;
209 PNPFS_WAIT_PIPE WaitPipe
;
212 DPRINT("NpfsWaitPipe\n");
214 WaitPipe
= (PNPFS_WAIT_PIPE
)Irp
->AssociatedIrp
.SystemBuffer
;
217 if (Fcb
->PipeState
!= 0)
219 DPRINT("Pipe is not in passive (waiting) state!\n");
220 return STATUS_UNSUCCESSFUL
;
223 /* search for listening server */
224 current_entry
= Pipe
->ServerFcbListHead
.Flink
;
225 while (current_entry
!= &Pipe
->ServerFcbListHead
)
227 ServerFcb
= CONTAINING_RECORD(current_entry
,
231 if (ServerFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
233 /* found a listening server fcb */
234 DPRINT("Listening server fcb found -- connecting\n");
236 return STATUS_SUCCESS
;
239 current_entry
= current_entry
->Flink
;
242 /* no listening server fcb found -- wait for one */
243 Status
= KeWaitForSingleObject(&Fcb
->ConnectEvent
,
249 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status
);
256 * FUNCTION: Return current state of a pipe
258 * Irp = Pointer to I/O request packet
259 * IrpSp = Pointer to current stack location of Irp
261 * Status of operation
264 NpfsGetState(PIRP Irp
,
265 PIO_STACK_LOCATION IrpSp
)
267 PNPFS_GET_STATE Reply
;
271 /* Validate parameters */
272 if (IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(NPFS_GET_STATE
))
274 DPRINT("Status (0x%X).\n", STATUS_INVALID_PARAMETER
);
275 return STATUS_INVALID_PARAMETER
;
278 Fcb
= IrpSp
->FileObject
->FsContext
;
279 Reply
= (PNPFS_GET_STATE
)Irp
->AssociatedIrp
.SystemBuffer
;
282 Reply
->WriteModeMessage
= (Pipe
->WriteMode
== FILE_PIPE_MESSAGE_MODE
);
283 Reply
->ReadModeMessage
= (Pipe
->ReadMode
== FILE_PIPE_MESSAGE_MODE
);
284 Reply
->NonBlocking
= (Pipe
->CompletionMode
== FILE_PIPE_QUEUE_OPERATION
);
285 Reply
->InBufferSize
= Pipe
->InboundQuota
;
286 Reply
->OutBufferSize
= Pipe
->OutboundQuota
;
287 Reply
->Timeout
= Pipe
->TimeOut
;
289 DPRINT("Status (0x%X).\n", STATUS_SUCCESS
);
291 return STATUS_SUCCESS
;
296 * FUNCTION: Set state of a pipe
298 * Irp = Pointer to I/O request packet
299 * IrpSp = Pointer to current stack location of Irp
301 * Status of operation
304 NpfsSetState(PIRP Irp
,
305 PIO_STACK_LOCATION IrpSp
)
307 PNPFS_SET_STATE Request
;
311 /* Validate parameters */
312 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(NPFS_SET_STATE
))
314 DPRINT("Status (0x%X).\n", STATUS_INVALID_PARAMETER
);
315 return STATUS_INVALID_PARAMETER
;
318 Fcb
= IrpSp
->FileObject
->FsContext
;
319 Request
= (PNPFS_SET_STATE
)Irp
->AssociatedIrp
.SystemBuffer
;
323 Request
->WriteModeMessage
? FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
325 Request
->WriteModeMessage
? FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
326 Pipe
->CompletionMode
=
327 Request
->NonBlocking
? FILE_PIPE_QUEUE_OPERATION
: FILE_PIPE_COMPLETE_OPERATION
;
328 Pipe
->InboundQuota
= Request
->InBufferSize
;
329 Pipe
->OutboundQuota
= Request
->OutBufferSize
;
330 Pipe
->TimeOut
= Request
->Timeout
;
332 DPRINT("Status (0x%X).\n", STATUS_SUCCESS
);
334 return STATUS_SUCCESS
;
339 * FUNCTION: Peek at a pipe (get information about messages)
341 * Irp = Pointer to I/O request packet
342 * IoStack = Pointer to current stack location of Irp
344 * Status of operation
347 NpfsPeekPipe(PIRP Irp
,
348 PIO_STACK_LOCATION IoStack
)
350 ULONG OutputBufferLength
;
352 PFILE_PIPE_PEEK_BUFFER Reply
;
356 DPRINT("NpfsPeekPipe\n");
358 OutputBufferLength
= IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
360 /* Validate parameters */
361 if (OutputBufferLength
< sizeof(FILE_PIPE_PEEK_BUFFER
))
363 DPRINT("Buffer too small\n");
364 return STATUS_INVALID_PARAMETER
;
367 Fcb
= IoStack
->FileObject
->FsContext
;
368 Reply
= (PFILE_PIPE_PEEK_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
371 Status
= STATUS_NOT_IMPLEMENTED
;
378 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject
,
381 PIO_STACK_LOCATION IoStack
;
382 PFILE_OBJECT FileObject
;
384 PNPFS_DEVICE_EXTENSION DeviceExt
;
388 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
390 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
391 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
392 DPRINT("IoStack: %p\n", IoStack
);
393 FileObject
= IoStack
->FileObject
;
394 DPRINT("FileObject: %p\n", FileObject
);
395 Fcb
= FileObject
->FsContext
;
396 DPRINT("Fcb: %p\n", Fcb
);
398 DPRINT("Pipe: %p\n", Pipe
);
399 DPRINT("PipeName: %wZ\n", &Pipe
->PipeName
);
401 switch (IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
403 case FSCTL_PIPE_ASSIGN_EVENT
:
404 DPRINT("Assign event\n");
405 Status
= STATUS_NOT_IMPLEMENTED
;
408 case FSCTL_PIPE_DISCONNECT
:
409 DPRINT("Disconnecting pipe %wZ\n", &Pipe
->PipeName
);
410 Status
= NpfsDisconnectPipe(Fcb
);
413 case FSCTL_PIPE_LISTEN
:
414 DPRINT("Connecting pipe %wZ\n", &Pipe
->PipeName
);
415 Status
= NpfsConnectPipe(Irp
, Fcb
);
418 case FSCTL_PIPE_PEEK
:
419 DPRINT("Peeking pipe %wZ\n", &Pipe
->PipeName
);
420 Status
= NpfsPeekPipe(Irp
, (PIO_STACK_LOCATION
)IoStack
);
423 case FSCTL_PIPE_QUERY_EVENT
:
424 DPRINT("Query event\n");
425 Status
= STATUS_NOT_IMPLEMENTED
;
428 case FSCTL_PIPE_TRANSCEIVE
:
429 DPRINT("Transceive\n");
430 Status
= STATUS_NOT_IMPLEMENTED
;
433 case FSCTL_PIPE_WAIT
:
434 DPRINT("Waiting for pipe %wZ\n", &Pipe
->PipeName
);
435 Status
= NpfsWaitPipe(Irp
, Fcb
);
438 case FSCTL_PIPE_IMPERSONATE
:
439 DPRINT("Impersonate\n");
440 Status
= STATUS_NOT_IMPLEMENTED
;
443 case FSCTL_PIPE_SET_CLIENT_PROCESS
:
444 DPRINT("Set client process\n");
445 Status
= STATUS_NOT_IMPLEMENTED
;
448 case FSCTL_PIPE_QUERY_CLIENT_PROCESS
:
449 DPRINT("Query client process\n");
450 Status
= STATUS_NOT_IMPLEMENTED
;
453 case FSCTL_PIPE_GET_STATE
:
454 DPRINT("Get state\n");
455 Status
= NpfsGetState(Irp
, (PIO_STACK_LOCATION
)IoStack
);
458 case FSCTL_PIPE_SET_STATE
:
459 DPRINT("Set state\n");
460 Status
= NpfsSetState(Irp
, (PIO_STACK_LOCATION
)IoStack
);
463 case FSCTL_PIPE_INTERNAL_READ
:
464 DPRINT("Internal read\n");
465 Status
= STATUS_NOT_IMPLEMENTED
;
468 case FSCTL_PIPE_INTERNAL_WRITE
:
469 DPRINT("Internal write\n");
470 Status
= STATUS_NOT_IMPLEMENTED
;
473 case FSCTL_PIPE_INTERNAL_TRANSCEIVE
:
474 DPRINT("Internal transceive\n");
475 Status
= STATUS_NOT_IMPLEMENTED
;
478 case FSCTL_PIPE_INTERNAL_READ_OVFLOW
:
479 DPRINT("Internal read overflow\n");
480 Status
= STATUS_NOT_IMPLEMENTED
;
484 DPRINT("IoControlCode: %x\n", IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
485 Status
= STATUS_UNSUCCESSFUL
;
488 if (Status
!= STATUS_PENDING
)
490 Irp
->IoStatus
.Status
= Status
;
491 Irp
->IoStatus
.Information
= 0;
493 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
;