2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/fs/np/fsctrl.c
5 * PURPOSE: Named pipe filesystem
6 * PROGRAMMER: David Welch <welch@cwcom.net>
10 /* INCLUDES ******************************************************************/
17 /* FUNCTIONS *****************************************************************/
20 NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject
,
23 PNPFS_WAITER_ENTRY Waiter
;
25 DPRINT1("NpfsListeningCancelRoutine() called\n");
27 Waiter
= (PNPFS_WAITER_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
;
29 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
32 KeLockMutex(&Waiter
->Fcb
->Pipe
->FcbListLock
);
33 RemoveEntryList(&Waiter
->Entry
);
34 KeUnlockMutex(&Waiter
->Fcb
->Pipe
->FcbListLock
);
36 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
37 Irp
->IoStatus
.Information
= 0;
38 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
43 NpfsAddListeningServerInstance(PIRP Irp
,
46 PNPFS_WAITER_ENTRY Entry
;
49 Entry
= (PNPFS_WAITER_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
;
53 KeLockMutex(&Fcb
->Pipe
->FcbListLock
);
55 IoMarkIrpPending(Irp
);
56 InsertTailList(&Fcb
->Pipe
->WaiterListHead
, &Entry
->Entry
);
58 IoAcquireCancelSpinLock(&oldIrql
);
61 IoSetCancelRoutine(Irp
, NpfsListeningCancelRoutine
);
62 IoReleaseCancelSpinLock(oldIrql
);
63 KeUnlockMutex(&Fcb
->Pipe
->FcbListLock
);
64 return STATUS_PENDING
;
66 IoReleaseCancelSpinLock(oldIrql
);
68 RemoveEntryList(&Entry
->Entry
);
70 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
71 Irp
->IoStatus
.Information
= 0;
72 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
73 KeUnlockMutex(&Fcb
->Pipe
->FcbListLock
);
75 return STATUS_CANCELLED
;
80 NpfsConnectPipe(PIRP Irp
,
84 PLIST_ENTRY current_entry
;
88 DPRINT("NpfsConnectPipe()\n");
90 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
92 KeResetEvent(&Fcb
->ConnectEvent
);
93 return STATUS_PIPE_CONNECTED
;
96 if (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
)
97 return STATUS_PIPE_CLOSING
;
99 DPRINT("Waiting for connection...\n");
103 /* search for a listening client fcb */
104 KeLockMutex(&Pipe
->FcbListLock
);
106 current_entry
= Pipe
->ClientFcbListHead
.Flink
;
107 while (current_entry
!= &Pipe
->ClientFcbListHead
)
109 ClientFcb
= CONTAINING_RECORD(current_entry
,
113 if (ClientFcb
->PipeState
== 0)
115 /* found a passive (waiting) client fcb */
116 DPRINT("Passive (waiting) client fcb found -- wake the client\n");
117 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
122 if (ClientFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
124 /* found a listening client fcb */
125 DPRINT("Listening client fcb found -- connecting\n");
127 /* connect client and server fcb's */
128 Fcb
->OtherSide
= ClientFcb
;
129 ClientFcb
->OtherSide
= Fcb
;
131 /* set connected state */
132 Fcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
133 ClientFcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
135 KeUnlockMutex(&Pipe
->FcbListLock
);
137 /* FIXME: create and initialize data queues */
139 /* signal client's connect event */
140 DPRINT("Setting the ConnectEvent for %x\n", ClientFcb
);
141 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
143 return STATUS_PIPE_CONNECTED
;
147 current_entry
= current_entry
->Flink
;
150 /* no listening client fcb found */
151 DPRINT("No listening client fcb found -- waiting for client\n");
153 Fcb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
155 Status
= NpfsAddListeningServerInstance(Irp
, Fcb
);
157 KeUnlockMutex(&Pipe
->FcbListLock
);
159 DPRINT("NpfsConnectPipe() done (Status %lx)\n", Status
);
166 NpfsDisconnectPipe(PNPFS_FCB Fcb
)
173 DPRINT("NpfsDisconnectPipe()\n");
176 KeLockMutex(&Pipe
->FcbListLock
);
178 if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
180 DPRINT("Pipe is already disconnected\n");
181 Status
= STATUS_SUCCESS
;
183 else if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
185 Server
= (Fcb
->PipeEnd
== FILE_PIPE_SERVER_END
);
186 OtherSide
= Fcb
->OtherSide
;
187 Fcb
->OtherSide
= NULL
;
188 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
189 /* Lock the server first */
192 ExAcquireFastMutex(&Fcb
->DataListLock
);
193 ExAcquireFastMutex(&OtherSide
->DataListLock
);
197 ExAcquireFastMutex(&OtherSide
->DataListLock
);
198 ExAcquireFastMutex(&Fcb
->DataListLock
);
200 OtherSide
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
201 OtherSide
->OtherSide
= NULL
;
203 * Signaling the write event. If is possible that an other
204 * thread waits for an empty buffer.
206 KeSetEvent(&OtherSide
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
207 KeSetEvent(&OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
210 ExReleaseFastMutex(&Fcb
->DataListLock
);
211 ExReleaseFastMutex(&OtherSide
->DataListLock
);
215 ExReleaseFastMutex(&OtherSide
->DataListLock
);
216 ExReleaseFastMutex(&OtherSide
->DataListLock
);
218 Status
= STATUS_SUCCESS
;
220 else if (Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
223 PNPFS_WAITER_ENTRY WaitEntry
= NULL
;
224 BOOLEAN Complete
= FALSE
;
227 Entry
= Fcb
->Pipe
->WaiterListHead
.Flink
;
228 while (Entry
!= &Fcb
->Pipe
->WaiterListHead
)
230 WaitEntry
= CONTAINING_RECORD(Entry
, NPFS_WAITER_ENTRY
, Entry
);
231 if (WaitEntry
->Fcb
== Fcb
)
233 RemoveEntryList(Entry
);
234 Irp
= CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.DriverContext
);
235 Complete
= (NULL
== IoSetCancelRoutine(Irp
, NULL
));
238 Entry
= Entry
->Flink
;
245 Irp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
246 Irp
->IoStatus
.Information
= 0;
247 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
250 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
251 Status
= STATUS_SUCCESS
;
253 else if (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
)
255 Status
= STATUS_PIPE_CLOSING
;
259 Status
= STATUS_UNSUCCESSFUL
;
261 KeUnlockMutex(&Pipe
->FcbListLock
);
267 NpfsWaitPipe(PIRP Irp
,
271 PLIST_ENTRY current_entry
;
273 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe
;
276 DPRINT("NpfsWaitPipe\n");
278 WaitPipe
= (PFILE_PIPE_WAIT_FOR_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
281 if (Fcb
->PipeState
!= 0)
283 DPRINT("Pipe is not in passive (waiting) state!\n");
284 return STATUS_UNSUCCESSFUL
;
287 /* search for listening server */
288 current_entry
= Pipe
->ServerFcbListHead
.Flink
;
289 while (current_entry
!= &Pipe
->ServerFcbListHead
)
291 ServerFcb
= CONTAINING_RECORD(current_entry
,
295 if (ServerFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
297 /* found a listening server fcb */
298 DPRINT("Listening server fcb found -- connecting\n");
300 return STATUS_SUCCESS
;
303 current_entry
= current_entry
->Flink
;
306 /* no listening server fcb found -- wait for one */
307 Status
= KeWaitForSingleObject(&Fcb
->ConnectEvent
,
313 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status
);
320 * FUNCTION: Return current state of a pipe
322 * Irp = Pointer to I/O request packet
323 * IrpSp = Pointer to current stack location of Irp
325 * Status of operation
329 * FUNCTION: Peek at a pipe (get information about messages)
331 * Irp = Pointer to I/O request packet
332 * IoStack = Pointer to current stack location of Irp
334 * Status of operation
337 NpfsPeekPipe(PIRP Irp
,
338 PIO_STACK_LOCATION IoStack
)
340 ULONG OutputBufferLength
;
342 PFILE_PIPE_PEEK_BUFFER Reply
;
346 DPRINT("NpfsPeekPipe\n");
348 OutputBufferLength
= IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
350 /* Validate parameters */
351 if (OutputBufferLength
< sizeof(FILE_PIPE_PEEK_BUFFER
))
353 DPRINT("Buffer too small\n");
354 return STATUS_INVALID_PARAMETER
;
357 Fcb
= IoStack
->FileObject
->FsContext
;
358 Reply
= (PFILE_PIPE_PEEK_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
361 Status
= STATUS_NOT_IMPLEMENTED
;
368 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject
,
371 PIO_STACK_LOCATION IoStack
;
372 PFILE_OBJECT FileObject
;
374 PNPFS_DEVICE_EXTENSION DeviceExt
;
378 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
380 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
381 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
382 DPRINT("IoStack: %p\n", IoStack
);
383 FileObject
= IoStack
->FileObject
;
384 DPRINT("FileObject: %p\n", FileObject
);
385 Fcb
= FileObject
->FsContext
;
386 DPRINT("Fcb: %p\n", Fcb
);
388 DPRINT("Pipe: %p\n", Pipe
);
389 DPRINT("PipeName: %wZ\n", &Pipe
->PipeName
);
391 Irp
->IoStatus
.Information
= 0;
393 switch (IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
395 case FSCTL_PIPE_ASSIGN_EVENT
:
396 DPRINT("Assign event\n");
397 Status
= STATUS_NOT_IMPLEMENTED
;
400 case FSCTL_PIPE_DISCONNECT
:
401 DPRINT("Disconnecting pipe %wZ\n", &Pipe
->PipeName
);
402 Status
= NpfsDisconnectPipe(Fcb
);
405 case FSCTL_PIPE_LISTEN
:
406 DPRINT("Connecting pipe %wZ\n", &Pipe
->PipeName
);
407 Status
= NpfsConnectPipe(Irp
, Fcb
);
410 case FSCTL_PIPE_PEEK
:
411 DPRINT("Peeking pipe %wZ\n", &Pipe
->PipeName
);
412 Status
= NpfsPeekPipe(Irp
, (PIO_STACK_LOCATION
)IoStack
);
415 case FSCTL_PIPE_QUERY_EVENT
:
416 DPRINT("Query event\n");
417 Status
= STATUS_NOT_IMPLEMENTED
;
420 case FSCTL_PIPE_TRANSCEIVE
:
421 DPRINT("Transceive\n");
422 Status
= STATUS_NOT_IMPLEMENTED
;
425 case FSCTL_PIPE_WAIT
:
426 DPRINT("Waiting for pipe %wZ\n", &Pipe
->PipeName
);
427 Status
= NpfsWaitPipe(Irp
, Fcb
);
430 case FSCTL_PIPE_IMPERSONATE
:
431 DPRINT("Impersonate\n");
432 Status
= STATUS_NOT_IMPLEMENTED
;
435 case FSCTL_PIPE_SET_CLIENT_PROCESS
:
436 DPRINT("Set client process\n");
437 Status
= STATUS_NOT_IMPLEMENTED
;
440 case FSCTL_PIPE_QUERY_CLIENT_PROCESS
:
441 DPRINT("Query client process\n");
442 Status
= STATUS_NOT_IMPLEMENTED
;
445 case FSCTL_PIPE_INTERNAL_READ
:
446 DPRINT("Internal read\n");
447 Status
= STATUS_NOT_IMPLEMENTED
;
450 case FSCTL_PIPE_INTERNAL_WRITE
:
451 DPRINT("Internal write\n");
452 Status
= STATUS_NOT_IMPLEMENTED
;
455 case FSCTL_PIPE_INTERNAL_TRANSCEIVE
:
456 DPRINT("Internal transceive\n");
457 Status
= STATUS_NOT_IMPLEMENTED
;
460 case FSCTL_PIPE_INTERNAL_READ_OVFLOW
:
461 DPRINT("Internal read overflow\n");
462 Status
= STATUS_NOT_IMPLEMENTED
;
466 DPRINT("IoControlCode: %x\n", IoStack
->Parameters
.FileSystemControl
.FsControlCode
);
467 Status
= STATUS_UNSUCCESSFUL
;
470 if (Status
!= STATUS_PENDING
)
472 Irp
->IoStatus
.Status
= Status
;
474 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
482 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject
,
485 /* FIXME: Implement */
487 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
488 Irp
->IoStatus
.Information
= 0;
490 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
492 return STATUS_SUCCESS
;