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 ******************************************************************/
19 /* FUNCTIONS *****************************************************************/
22 NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject
,
25 PNPFS_WAITER_ENTRY Waiter
;
27 DPRINT1("NpfsListeningCancelRoutine() called\n");
29 Waiter
= (PNPFS_WAITER_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
;
31 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
34 KeLockMutex(&Waiter
->Fcb
->Pipe
->FcbListLock
);
35 RemoveEntryList(&Waiter
->Entry
);
36 KeUnlockMutex(&Waiter
->Fcb
->Pipe
->FcbListLock
);
38 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
39 Irp
->IoStatus
.Information
= 0;
40 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
45 NpfsAddListeningServerInstance(PIRP Irp
,
48 PNPFS_WAITER_ENTRY Entry
;
51 Entry
= (PNPFS_WAITER_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
;
55 KeLockMutex(&Fcb
->Pipe
->FcbListLock
);
57 IoMarkIrpPending(Irp
);
58 InsertTailList(&Fcb
->Pipe
->WaiterListHead
, &Entry
->Entry
);
60 IoAcquireCancelSpinLock(&oldIrql
);
63 IoSetCancelRoutine(Irp
, NpfsListeningCancelRoutine
);
64 IoReleaseCancelSpinLock(oldIrql
);
65 KeUnlockMutex(&Fcb
->Pipe
->FcbListLock
);
66 return STATUS_PENDING
;
68 IoReleaseCancelSpinLock(oldIrql
);
70 RemoveEntryList(&Entry
->Entry
);
72 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
73 Irp
->IoStatus
.Information
= 0;
74 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
75 KeUnlockMutex(&Fcb
->Pipe
->FcbListLock
);
77 return STATUS_CANCELLED
;
82 NpfsConnectPipe(PIRP Irp
,
86 PLIST_ENTRY current_entry
;
90 DPRINT("NpfsConnectPipe()\n");
92 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
94 KeResetEvent(&Fcb
->ConnectEvent
);
95 return STATUS_PIPE_CONNECTED
;
98 if (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
)
99 return STATUS_PIPE_CLOSING
;
101 DPRINT("Waiting for connection...\n");
105 /* search for a listening client fcb */
106 KeLockMutex(&Pipe
->FcbListLock
);
108 current_entry
= Pipe
->ClientFcbListHead
.Flink
;
109 while (current_entry
!= &Pipe
->ClientFcbListHead
)
111 ClientFcb
= CONTAINING_RECORD(current_entry
,
115 if (ClientFcb
->PipeState
== 0)
117 /* found a passive (waiting) client fcb */
118 DPRINT("Passive (waiting) client fcb found -- wake the client\n");
119 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
124 if (ClientFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
126 /* found a listening client fcb */
127 DPRINT("Listening client fcb found -- connecting\n");
129 /* connect client and server fcb's */
130 Fcb
->OtherSide
= ClientFcb
;
131 ClientFcb
->OtherSide
= Fcb
;
133 /* set connected state */
134 Fcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
135 ClientFcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
137 KeUnlockMutex(&Pipe
->FcbListLock
);
139 /* FIXME: create and initialize data queues */
141 /* signal client's connect event */
142 DPRINT("Setting the ConnectEvent for %x\n", ClientFcb
);
143 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
145 return STATUS_PIPE_CONNECTED
;
149 current_entry
= current_entry
->Flink
;
152 /* no listening client fcb found */
153 DPRINT("No listening client fcb found -- waiting for client\n");
155 Fcb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
157 Status
= NpfsAddListeningServerInstance(Irp
, Fcb
);
159 KeUnlockMutex(&Pipe
->FcbListLock
);
161 DPRINT("NpfsConnectPipe() done (Status %lx)\n", Status
);
168 NpfsDisconnectPipe(PNPFS_FCB Fcb
)
175 DPRINT("NpfsDisconnectPipe()\n");
178 KeLockMutex(&Pipe
->FcbListLock
);
180 if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
182 DPRINT("Pipe is already disconnected\n");
183 Status
= STATUS_SUCCESS
;
185 else if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
187 Server
= (Fcb
->PipeEnd
== FILE_PIPE_SERVER_END
);
188 OtherSide
= Fcb
->OtherSide
;
189 Fcb
->OtherSide
= NULL
;
190 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
191 /* Lock the server first */
194 ExAcquireFastMutex(&Fcb
->DataListLock
);
195 ExAcquireFastMutex(&OtherSide
->DataListLock
);
199 ExAcquireFastMutex(&OtherSide
->DataListLock
);
200 ExAcquireFastMutex(&Fcb
->DataListLock
);
202 OtherSide
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
203 OtherSide
->OtherSide
= NULL
;
205 * Signaling the write event. If is possible that an other
206 * thread waits for an empty buffer.
208 KeSetEvent(&OtherSide
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
209 KeSetEvent(&OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
212 ExReleaseFastMutex(&Fcb
->DataListLock
);
213 ExReleaseFastMutex(&OtherSide
->DataListLock
);
217 ExReleaseFastMutex(&OtherSide
->DataListLock
);
218 ExReleaseFastMutex(&OtherSide
->DataListLock
);
220 Status
= STATUS_SUCCESS
;
222 else if (Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
225 PNPFS_WAITER_ENTRY WaitEntry
= NULL
;
226 BOOLEAN Complete
= FALSE
;
229 Entry
= Fcb
->Pipe
->WaiterListHead
.Flink
;
230 while (Entry
!= &Fcb
->Pipe
->WaiterListHead
)
232 WaitEntry
= CONTAINING_RECORD(Entry
, NPFS_WAITER_ENTRY
, Entry
);
233 if (WaitEntry
->Fcb
== Fcb
)
235 RemoveEntryList(Entry
);
236 Irp
= CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.DriverContext
);
237 Complete
= (NULL
== IoSetCancelRoutine(Irp
, NULL
));
240 Entry
= Entry
->Flink
;
247 Irp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
248 Irp
->IoStatus
.Information
= 0;
249 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
252 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
253 Status
= STATUS_SUCCESS
;
255 else if (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
)
257 Status
= STATUS_PIPE_CLOSING
;
261 Status
= STATUS_UNSUCCESSFUL
;
263 KeUnlockMutex(&Pipe
->FcbListLock
);
269 NpfsWaitPipe(PIRP Irp
,
273 PLIST_ENTRY current_entry
;
275 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe
;
278 DPRINT("NpfsWaitPipe\n");
280 WaitPipe
= (PFILE_PIPE_WAIT_FOR_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
283 if (Fcb
->PipeState
!= 0)
285 DPRINT("Pipe is not in passive (waiting) state!\n");
286 return STATUS_UNSUCCESSFUL
;
289 /* search for listening server */
290 current_entry
= Pipe
->ServerFcbListHead
.Flink
;
291 while (current_entry
!= &Pipe
->ServerFcbListHead
)
293 ServerFcb
= CONTAINING_RECORD(current_entry
,
297 if (ServerFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
299 /* found a listening server fcb */
300 DPRINT("Listening server fcb found -- connecting\n");
302 return STATUS_SUCCESS
;
305 current_entry
= current_entry
->Flink
;
308 /* no listening server fcb found -- wait for one */
309 Status
= KeWaitForSingleObject(&Fcb
->ConnectEvent
,
315 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status
);
322 * FUNCTION: Return current state of a pipe
324 * Irp = Pointer to I/O request packet
325 * IrpSp = Pointer to current stack location of Irp
327 * Status of operation
331 * FUNCTION: Peek at a pipe (get information about messages)
333 * Irp = Pointer to I/O request packet
334 * IoStack = Pointer to current stack location of Irp
336 * Status of operation
339 NpfsPeekPipe(PIRP Irp
,
340 PIO_STACK_LOCATION IoStack
)
342 ULONG OutputBufferLength
;
344 PFILE_PIPE_PEEK_BUFFER Reply
;
348 DPRINT("NpfsPeekPipe\n");
350 OutputBufferLength
= IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
352 /* Validate parameters */
353 if (OutputBufferLength
< sizeof(FILE_PIPE_PEEK_BUFFER
))
355 DPRINT("Buffer too small\n");
356 return STATUS_INVALID_PARAMETER
;
359 Fcb
= IoStack
->FileObject
->FsContext
;
360 Reply
= (PFILE_PIPE_PEEK_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
363 Status
= STATUS_NOT_IMPLEMENTED
;
370 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject
,
373 PIO_STACK_LOCATION IoStack
;
374 PFILE_OBJECT FileObject
;
376 PNPFS_DEVICE_EXTENSION DeviceExt
;
380 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
382 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
383 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
384 DPRINT("IoStack: %p\n", IoStack
);
385 FileObject
= IoStack
->FileObject
;
386 DPRINT("FileObject: %p\n", FileObject
);
387 Fcb
= FileObject
->FsContext
;
388 DPRINT("Fcb: %p\n", Fcb
);
390 DPRINT("Pipe: %p\n", Pipe
);
391 DPRINT("PipeName: %wZ\n", &Pipe
->PipeName
);
393 Irp
->IoStatus
.Information
= 0;
395 switch (IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
397 case FSCTL_PIPE_ASSIGN_EVENT
:
398 DPRINT("Assign event\n");
399 Status
= STATUS_NOT_IMPLEMENTED
;
402 case FSCTL_PIPE_DISCONNECT
:
403 DPRINT("Disconnecting pipe %wZ\n", &Pipe
->PipeName
);
404 Status
= NpfsDisconnectPipe(Fcb
);
407 case FSCTL_PIPE_LISTEN
:
408 DPRINT("Connecting pipe %wZ\n", &Pipe
->PipeName
);
409 Status
= NpfsConnectPipe(Irp
, Fcb
);
412 case FSCTL_PIPE_PEEK
:
413 DPRINT("Peeking pipe %wZ\n", &Pipe
->PipeName
);
414 Status
= NpfsPeekPipe(Irp
, (PIO_STACK_LOCATION
)IoStack
);
417 case FSCTL_PIPE_QUERY_EVENT
:
418 DPRINT("Query event\n");
419 Status
= STATUS_NOT_IMPLEMENTED
;
422 case FSCTL_PIPE_TRANSCEIVE
:
423 DPRINT("Transceive\n");
424 Status
= STATUS_NOT_IMPLEMENTED
;
427 case FSCTL_PIPE_WAIT
:
428 DPRINT("Waiting for pipe %wZ\n", &Pipe
->PipeName
);
429 Status
= NpfsWaitPipe(Irp
, Fcb
);
432 case FSCTL_PIPE_IMPERSONATE
:
433 DPRINT("Impersonate\n");
434 Status
= STATUS_NOT_IMPLEMENTED
;
437 case FSCTL_PIPE_SET_CLIENT_PROCESS
:
438 DPRINT("Set client process\n");
439 Status
= STATUS_NOT_IMPLEMENTED
;
442 case FSCTL_PIPE_QUERY_CLIENT_PROCESS
:
443 DPRINT("Query client process\n");
444 Status
= STATUS_NOT_IMPLEMENTED
;
447 case FSCTL_PIPE_INTERNAL_READ
:
448 DPRINT("Internal read\n");
449 Status
= STATUS_NOT_IMPLEMENTED
;
452 case FSCTL_PIPE_INTERNAL_WRITE
:
453 DPRINT("Internal write\n");
454 Status
= STATUS_NOT_IMPLEMENTED
;
457 case FSCTL_PIPE_INTERNAL_TRANSCEIVE
:
458 DPRINT("Internal transceive\n");
459 Status
= STATUS_NOT_IMPLEMENTED
;
462 case FSCTL_PIPE_INTERNAL_READ_OVFLOW
:
463 DPRINT("Internal read overflow\n");
464 Status
= STATUS_NOT_IMPLEMENTED
;
468 DPRINT("IoControlCode: %x\n", IoStack
->Parameters
.FileSystemControl
.FsControlCode
);
469 Status
= STATUS_UNSUCCESSFUL
;
472 if (Status
!= STATUS_PENDING
)
474 Irp
->IoStatus
.Status
= Status
;
476 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
484 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject
,
487 /* FIXME: Implement */
489 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
490 Irp
->IoStatus
.Information
= 0;
492 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
494 return STATUS_SUCCESS
;