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 Waiter
= (PNPFS_WAITER_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
;
27 DPRINT1("NpfsListeningCancelRoutine() called for <%wZ>\n",
28 &Waiter
->Fcb
->Pipe
->PipeName
);
30 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
33 KeLockMutex(&Waiter
->Fcb
->Pipe
->FcbListLock
);
34 RemoveEntryList(&Waiter
->Entry
);
35 KeUnlockMutex(&Waiter
->Fcb
->Pipe
->FcbListLock
);
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
= (PNPFS_WAITER_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
;
54 KeLockMutex(&Fcb
->Pipe
->FcbListLock
);
56 IoMarkIrpPending(Irp
);
57 InsertTailList(&Fcb
->Pipe
->WaiterListHead
, &Entry
->Entry
);
59 IoAcquireCancelSpinLock(&oldIrql
);
62 IoSetCancelRoutine(Irp
, NpfsListeningCancelRoutine
);
63 IoReleaseCancelSpinLock(oldIrql
);
64 KeUnlockMutex(&Fcb
->Pipe
->FcbListLock
);
65 return STATUS_PENDING
;
67 IoReleaseCancelSpinLock(oldIrql
);
69 RemoveEntryList(&Entry
->Entry
);
71 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
72 Irp
->IoStatus
.Information
= 0;
73 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
74 KeUnlockMutex(&Fcb
->Pipe
->FcbListLock
);
76 return STATUS_CANCELLED
;
81 NpfsConnectPipe(PIRP Irp
,
85 PLIST_ENTRY current_entry
;
89 DPRINT("NpfsConnectPipe()\n");
91 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
93 KeResetEvent(&Fcb
->ConnectEvent
);
94 return STATUS_PIPE_CONNECTED
;
97 if (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
)
98 return STATUS_PIPE_CLOSING
;
100 DPRINT("Waiting for connection...\n");
104 /* search for a listening client fcb */
105 KeLockMutex(&Pipe
->FcbListLock
);
107 current_entry
= Pipe
->ClientFcbListHead
.Flink
;
108 while (current_entry
!= &Pipe
->ClientFcbListHead
)
110 ClientFcb
= CONTAINING_RECORD(current_entry
,
114 if (ClientFcb
->PipeState
== 0)
116 /* found a passive (waiting) client fcb */
117 DPRINT("Passive (waiting) client fcb found -- wake the client\n");
118 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
123 if (ClientFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
125 /* found a listening client fcb */
126 DPRINT("Listening client fcb found -- connecting\n");
128 /* connect client and server fcb's */
129 Fcb
->OtherSide
= ClientFcb
;
130 ClientFcb
->OtherSide
= Fcb
;
132 /* set connected state */
133 Fcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
134 ClientFcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
136 KeUnlockMutex(&Pipe
->FcbListLock
);
138 /* FIXME: create and initialize data queues */
140 /* signal client's connect event */
141 DPRINT("Setting the ConnectEvent for %x\n", ClientFcb
);
142 KeSetEvent(&ClientFcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
144 return STATUS_PIPE_CONNECTED
;
148 current_entry
= current_entry
->Flink
;
151 /* no listening client fcb found */
152 DPRINT("No listening client fcb found -- waiting for client\n");
154 Fcb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
156 Status
= NpfsAddListeningServerInstance(Irp
, Fcb
);
158 KeUnlockMutex(&Pipe
->FcbListLock
);
160 DPRINT("NpfsConnectPipe() done (Status %lx)\n", Status
);
167 NpfsDisconnectPipe(PNPFS_FCB Fcb
)
174 DPRINT("NpfsDisconnectPipe()\n");
177 KeLockMutex(&Pipe
->FcbListLock
);
179 if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
181 DPRINT("Pipe is already disconnected\n");
182 Status
= STATUS_SUCCESS
;
184 else if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
186 Server
= (Fcb
->PipeEnd
== FILE_PIPE_SERVER_END
);
187 OtherSide
= Fcb
->OtherSide
;
188 Fcb
->OtherSide
= NULL
;
189 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
190 /* Lock the server first */
193 ExAcquireFastMutex(&Fcb
->DataListLock
);
194 ExAcquireFastMutex(&OtherSide
->DataListLock
);
198 ExAcquireFastMutex(&OtherSide
->DataListLock
);
199 ExAcquireFastMutex(&Fcb
->DataListLock
);
201 OtherSide
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
202 OtherSide
->OtherSide
= NULL
;
204 * Signaling the write event. If is possible that an other
205 * thread waits for an empty buffer.
207 KeSetEvent(&OtherSide
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
208 KeSetEvent(&OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
211 ExReleaseFastMutex(&Fcb
->DataListLock
);
212 ExReleaseFastMutex(&OtherSide
->DataListLock
);
216 ExReleaseFastMutex(&OtherSide
->DataListLock
);
217 ExReleaseFastMutex(&OtherSide
->DataListLock
);
219 Status
= STATUS_SUCCESS
;
221 else if (Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
224 PNPFS_WAITER_ENTRY WaitEntry
= NULL
;
225 BOOLEAN Complete
= FALSE
;
228 Entry
= Fcb
->Pipe
->WaiterListHead
.Flink
;
229 while (Entry
!= &Fcb
->Pipe
->WaiterListHead
)
231 WaitEntry
= CONTAINING_RECORD(Entry
, NPFS_WAITER_ENTRY
, Entry
);
232 if (WaitEntry
->Fcb
== Fcb
)
234 RemoveEntryList(Entry
);
235 Irp
= CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.DriverContext
);
236 Complete
= (NULL
== IoSetCancelRoutine(Irp
, NULL
));
239 Entry
= Entry
->Flink
;
246 Irp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
247 Irp
->IoStatus
.Information
= 0;
248 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
251 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
252 Status
= STATUS_SUCCESS
;
254 else if (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
)
256 Status
= STATUS_PIPE_CLOSING
;
260 Status
= STATUS_UNSUCCESSFUL
;
262 KeUnlockMutex(&Pipe
->FcbListLock
);
268 NpfsWaitPipe(PIRP Irp
,
272 PLIST_ENTRY current_entry
;
274 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe
;
277 DPRINT("NpfsWaitPipe\n");
279 WaitPipe
= (PFILE_PIPE_WAIT_FOR_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
282 if (Fcb
->PipeState
!= 0)
284 DPRINT("Pipe is not in passive (waiting) state!\n");
285 return STATUS_UNSUCCESSFUL
;
288 /* search for listening server */
289 current_entry
= Pipe
->ServerFcbListHead
.Flink
;
290 while (current_entry
!= &Pipe
->ServerFcbListHead
)
292 ServerFcb
= CONTAINING_RECORD(current_entry
,
296 if (ServerFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
298 /* found a listening server fcb */
299 DPRINT("Listening server fcb found -- connecting\n");
301 return STATUS_SUCCESS
;
304 current_entry
= current_entry
->Flink
;
307 /* no listening server fcb found -- wait for one */
308 Status
= KeWaitForSingleObject(&Fcb
->ConnectEvent
,
314 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status
);
321 * FUNCTION: Return current state of a pipe
323 * Irp = Pointer to I/O request packet
324 * IrpSp = Pointer to current stack location of Irp
326 * Status of operation
330 * FUNCTION: Peek at a pipe (get information about messages)
332 * Irp = Pointer to I/O request packet
333 * IoStack = Pointer to current stack location of Irp
335 * Status of operation
338 NpfsPeekPipe(PIRP Irp
,
339 PIO_STACK_LOCATION IoStack
)
341 ULONG OutputBufferLength
;
343 PFILE_PIPE_PEEK_BUFFER Reply
;
347 DPRINT("NpfsPeekPipe\n");
349 OutputBufferLength
= IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
351 /* Validate parameters */
352 if (OutputBufferLength
< sizeof(FILE_PIPE_PEEK_BUFFER
))
354 DPRINT("Buffer too small\n");
355 return STATUS_INVALID_PARAMETER
;
358 Fcb
= IoStack
->FileObject
->FsContext
;
359 Reply
= (PFILE_PIPE_PEEK_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
362 Status
= STATUS_NOT_IMPLEMENTED
;
369 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject
,
372 PIO_STACK_LOCATION IoStack
;
373 PFILE_OBJECT FileObject
;
375 PNPFS_DEVICE_EXTENSION DeviceExt
;
379 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
381 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
382 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
383 DPRINT("IoStack: %p\n", IoStack
);
384 FileObject
= IoStack
->FileObject
;
385 DPRINT("FileObject: %p\n", FileObject
);
386 Fcb
= FileObject
->FsContext
;
387 DPRINT("Fcb: %p\n", Fcb
);
389 DPRINT("Pipe: %p\n", Pipe
);
390 DPRINT("PipeName: %wZ\n", &Pipe
->PipeName
);
392 Irp
->IoStatus
.Information
= 0;
394 switch (IoStack
->Parameters
.FileSystemControl
.FsControlCode
)
396 case FSCTL_PIPE_ASSIGN_EVENT
:
397 DPRINT("Assign event\n");
398 Status
= STATUS_NOT_IMPLEMENTED
;
401 case FSCTL_PIPE_DISCONNECT
:
402 DPRINT("Disconnecting pipe %wZ\n", &Pipe
->PipeName
);
403 Status
= NpfsDisconnectPipe(Fcb
);
406 case FSCTL_PIPE_LISTEN
:
407 DPRINT("Connecting pipe %wZ\n", &Pipe
->PipeName
);
408 Status
= NpfsConnectPipe(Irp
, Fcb
);
411 case FSCTL_PIPE_PEEK
:
412 DPRINT("Peeking pipe %wZ\n", &Pipe
->PipeName
);
413 Status
= NpfsPeekPipe(Irp
, (PIO_STACK_LOCATION
)IoStack
);
416 case FSCTL_PIPE_QUERY_EVENT
:
417 DPRINT("Query event\n");
418 Status
= STATUS_NOT_IMPLEMENTED
;
421 case FSCTL_PIPE_TRANSCEIVE
:
422 DPRINT("Transceive\n");
423 Status
= STATUS_NOT_IMPLEMENTED
;
426 case FSCTL_PIPE_WAIT
:
427 DPRINT("Waiting for pipe %wZ\n", &Pipe
->PipeName
);
428 Status
= NpfsWaitPipe(Irp
, Fcb
);
431 case FSCTL_PIPE_IMPERSONATE
:
432 DPRINT("Impersonate\n");
433 Status
= STATUS_NOT_IMPLEMENTED
;
436 case FSCTL_PIPE_SET_CLIENT_PROCESS
:
437 DPRINT("Set client process\n");
438 Status
= STATUS_NOT_IMPLEMENTED
;
441 case FSCTL_PIPE_QUERY_CLIENT_PROCESS
:
442 DPRINT("Query client process\n");
443 Status
= STATUS_NOT_IMPLEMENTED
;
446 case FSCTL_PIPE_INTERNAL_READ
:
447 DPRINT("Internal read\n");
448 Status
= STATUS_NOT_IMPLEMENTED
;
451 case FSCTL_PIPE_INTERNAL_WRITE
:
452 DPRINT("Internal write\n");
453 Status
= STATUS_NOT_IMPLEMENTED
;
456 case FSCTL_PIPE_INTERNAL_TRANSCEIVE
:
457 DPRINT("Internal transceive\n");
458 Status
= STATUS_NOT_IMPLEMENTED
;
461 case FSCTL_PIPE_INTERNAL_READ_OVFLOW
:
462 DPRINT("Internal read overflow\n");
463 Status
= STATUS_NOT_IMPLEMENTED
;
467 DPRINT("IoControlCode: %x\n", IoStack
->Parameters
.FileSystemControl
.FsControlCode
);
468 Status
= STATUS_UNSUCCESSFUL
;
471 if (Status
!= STATUS_PENDING
)
473 Irp
->IoStatus
.Status
= Status
;
475 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
483 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject
,
486 /* FIXME: Implement */
488 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
489 Irp
->IoStatus
.Information
= 0;
491 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
493 return STATUS_SUCCESS
;