- Data is now written to the readers data buffer and the reader reads from his own...
[reactos.git] / reactos / drivers / fs / np / fsctrl.c
1 /* $Id$
2 *
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>
8 * Eric Kohl
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include "npfs.h"
15
16 #define NDEBUG
17 #include <debug.h>
18
19 /* FUNCTIONS *****************************************************************/
20
21 static NTSTATUS
22 NpfsConnectPipe(PNPFS_FCB Fcb)
23 {
24 PNPFS_PIPE Pipe;
25 PLIST_ENTRY current_entry;
26 PNPFS_FCB ClientFcb;
27 NTSTATUS Status;
28
29 DPRINT("NpfsConnectPipe()\n");
30
31 if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
32 {
33 KeResetEvent(&Fcb->ConnectEvent);
34 return STATUS_PIPE_CONNECTED;
35 }
36
37 if (Fcb->PipeState == FILE_PIPE_CLOSING_STATE)
38 return STATUS_PIPE_CLOSING;
39
40 DPRINT("Waiting for connection...\n");
41
42 Pipe = Fcb->Pipe;
43
44 /* search for a listening client fcb */
45 KeLockMutex(&Pipe->FcbListLock);
46
47 current_entry = Pipe->ClientFcbListHead.Flink;
48 while (current_entry != &Pipe->ClientFcbListHead)
49 {
50 ClientFcb = CONTAINING_RECORD(current_entry,
51 NPFS_FCB,
52 FcbListEntry);
53
54 if (ClientFcb->PipeState == 0)
55 {
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);
59 break;
60 }
61
62 #if 0
63 if (ClientFcb->PipeState == FILE_PIPE_LISTENING_STATE)
64 {
65 /* found a listening client fcb */
66 DPRINT("Listening client fcb found -- connecting\n");
67
68 /* connect client and server fcb's */
69 Fcb->OtherSide = ClientFcb;
70 ClientFcb->OtherSide = Fcb;
71
72 /* set connected state */
73 Fcb->PipeState = FILE_PIPE_CONNECTED_STATE;
74 ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
75
76 KeUnlockMutex(&Pipe->FcbListLock);
77
78 /* FIXME: create and initialize data queues */
79
80 /* signal client's connect event */
81 DPRINT("Setting the ConnectEvent for %x\n", ClientFcb);
82 KeSetEvent(&ClientFcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
83
84 return STATUS_PIPE_CONNECTED;
85 }
86 #endif
87
88 current_entry = current_entry->Flink;
89 }
90
91 KeUnlockMutex(&Pipe->FcbListLock);
92
93 /* no listening client fcb found */
94 DPRINT("No listening client fcb found -- waiting for client\n");
95
96 Fcb->PipeState = FILE_PIPE_LISTENING_STATE;
97
98 Status = KeWaitForSingleObject(&Fcb->ConnectEvent,
99 UserRequest,
100 KernelMode,
101 FALSE,
102 NULL);
103 if (!NT_SUCCESS(Status))
104 {
105 DPRINT("KeWaitForSingleObject() failed (Status %lx)\n", Status);
106 return Status;
107 }
108
109 Fcb->PipeState = FILE_PIPE_CONNECTED_STATE;
110
111 DPRINT("Client Fcb: %p\n", Fcb->OtherSide);
112
113 return STATUS_PIPE_CONNECTED;
114 }
115
116
117 static NTSTATUS
118 NpfsDisconnectPipe(PNPFS_FCB Fcb)
119 {
120 DPRINT("NpfsDisconnectPipe()\n");
121
122 if (Fcb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
123 return STATUS_SUCCESS;
124
125 if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
126 {
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;
130
131 /* FIXME: remove data queue(s) */
132
133 Fcb->OtherSide->OtherSide = NULL;
134 Fcb->OtherSide = NULL;
135
136 DPRINT("Pipe disconnected\n");
137 return STATUS_SUCCESS;
138 }
139
140 if (Fcb->PipeState == FILE_PIPE_CLOSING_STATE)
141 {
142 Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
143 Fcb->OtherSide = NULL;
144
145 /* FIXME: remove data queue(s) */
146
147 DPRINT("Pipe disconnected\n");
148 return STATUS_SUCCESS;
149 }
150
151 return STATUS_UNSUCCESSFUL;
152 }
153
154
155 static NTSTATUS
156 NpfsWaitPipe(PIRP Irp,
157 PNPFS_FCB Fcb)
158 {
159 PNPFS_PIPE Pipe;
160 PLIST_ENTRY current_entry;
161 PNPFS_FCB ServerFcb;
162 PNPFS_WAIT_PIPE WaitPipe;
163 NTSTATUS Status;
164
165 DPRINT("NpfsWaitPipe\n");
166
167 WaitPipe = (PNPFS_WAIT_PIPE)Irp->AssociatedIrp.SystemBuffer;
168 Pipe = Fcb->Pipe;
169
170 if (Fcb->PipeState != 0)
171 {
172 DPRINT("Pipe is not in passive (waiting) state!\n");
173 return STATUS_UNSUCCESSFUL;
174 }
175
176 /* search for listening server */
177 current_entry = Pipe->ServerFcbListHead.Flink;
178 while (current_entry != &Pipe->ServerFcbListHead)
179 {
180 ServerFcb = CONTAINING_RECORD(current_entry,
181 NPFS_FCB,
182 FcbListEntry);
183
184 if (ServerFcb->PipeState == FILE_PIPE_LISTENING_STATE)
185 {
186 /* found a listening server fcb */
187 DPRINT("Listening server fcb found -- connecting\n");
188
189 return STATUS_SUCCESS;
190 }
191
192 current_entry = current_entry->Flink;
193 }
194
195 /* no listening server fcb found -- wait for one */
196 Status = KeWaitForSingleObject(&Fcb->ConnectEvent,
197 UserRequest,
198 KernelMode,
199 FALSE,
200 &WaitPipe->Timeout);
201
202 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status);
203
204 return Status;
205 }
206
207
208 /*
209 * FUNCTION: Return current state of a pipe
210 * ARGUMENTS:
211 * Irp = Pointer to I/O request packet
212 * IrpSp = Pointer to current stack location of Irp
213 * RETURNS:
214 * Status of operation
215 */
216 static NTSTATUS
217 NpfsGetState(PIRP Irp,
218 PIO_STACK_LOCATION IrpSp)
219 {
220 PNPFS_GET_STATE Reply;
221 PNPFS_PIPE Pipe;
222 PNPFS_FCB Fcb;
223
224 /* Validate parameters */
225 if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(NPFS_GET_STATE))
226 {
227 DPRINT("Status (0x%X).\n", STATUS_INVALID_PARAMETER);
228 return STATUS_INVALID_PARAMETER;
229 }
230
231 Fcb = IrpSp->FileObject->FsContext;
232 Reply = (PNPFS_GET_STATE)Irp->AssociatedIrp.SystemBuffer;
233 Pipe = Fcb->Pipe;
234
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;
241
242 DPRINT("Status (0x%X).\n", STATUS_SUCCESS);
243
244 return STATUS_SUCCESS;
245 }
246
247
248 /*
249 * FUNCTION: Set state of a pipe
250 * ARGUMENTS:
251 * Irp = Pointer to I/O request packet
252 * IrpSp = Pointer to current stack location of Irp
253 * RETURNS:
254 * Status of operation
255 */
256 static NTSTATUS
257 NpfsSetState(PIRP Irp,
258 PIO_STACK_LOCATION IrpSp)
259 {
260 PNPFS_SET_STATE Request;
261 PNPFS_PIPE Pipe;
262 PNPFS_FCB Fcb;
263
264 /* Validate parameters */
265 if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(NPFS_SET_STATE))
266 {
267 DPRINT("Status (0x%X).\n", STATUS_INVALID_PARAMETER);
268 return STATUS_INVALID_PARAMETER;
269 }
270
271 Fcb = IrpSp->FileObject->FsContext;
272 Request = (PNPFS_SET_STATE)Irp->AssociatedIrp.SystemBuffer;
273 Pipe = Fcb->Pipe;
274
275 Pipe->WriteMode =
276 Request->WriteModeMessage ? FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE;
277 Pipe->ReadMode =
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;
284
285 DPRINT("Status (0x%X).\n", STATUS_SUCCESS);
286
287 return STATUS_SUCCESS;
288 }
289
290
291 /*
292 * FUNCTION: Peek at a pipe (get information about messages)
293 * ARGUMENTS:
294 * Irp = Pointer to I/O request packet
295 * IoStack = Pointer to current stack location of Irp
296 * RETURNS:
297 * Status of operation
298 */
299 static NTSTATUS
300 NpfsPeekPipe(PIRP Irp,
301 PIO_STACK_LOCATION IoStack)
302 {
303 ULONG OutputBufferLength;
304 PNPFS_PIPE Pipe;
305 PFILE_PIPE_PEEK_BUFFER Reply;
306 PNPFS_FCB Fcb;
307 NTSTATUS Status;
308
309 DPRINT("NpfsPeekPipe\n");
310
311 OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
312
313 /* Validate parameters */
314 if (OutputBufferLength < sizeof(FILE_PIPE_PEEK_BUFFER))
315 {
316 DPRINT("Buffer too small\n");
317 return STATUS_INVALID_PARAMETER;
318 }
319
320 Fcb = IoStack->FileObject->FsContext;
321 Reply = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer;
322 Pipe = Fcb->Pipe;
323
324 Status = STATUS_NOT_IMPLEMENTED;
325
326 return Status;
327 }
328
329
330
331 NTSTATUS STDCALL
332 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
333 PIRP Irp)
334 {
335 PIO_STACK_LOCATION IoStack;
336 PFILE_OBJECT FileObject;
337 NTSTATUS Status;
338 PNPFS_DEVICE_EXTENSION DeviceExt;
339 PNPFS_PIPE Pipe;
340 PNPFS_FCB Fcb;
341
342 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
343
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);
351 Pipe = Fcb->Pipe;
352 DPRINT("Pipe: %p\n", Pipe);
353 DPRINT("PipeName: %wZ\n", &Pipe->PipeName);
354
355 switch (IoStack->Parameters.FileSystemControl.FsControlCode)
356 {
357 case FSCTL_PIPE_ASSIGN_EVENT:
358 DPRINT("Assign event\n");
359 Status = STATUS_NOT_IMPLEMENTED;
360 break;
361
362 case FSCTL_PIPE_DISCONNECT:
363 DPRINT("Disconnecting pipe %wZ\n", &Pipe->PipeName);
364 Status = NpfsDisconnectPipe(Fcb);
365 break;
366
367 case FSCTL_PIPE_LISTEN:
368 DPRINT("Connecting pipe %wZ\n", &Pipe->PipeName);
369 Status = NpfsConnectPipe(Fcb);
370 break;
371
372 case FSCTL_PIPE_PEEK:
373 DPRINT("Peeking pipe %wZ\n", &Pipe->PipeName);
374 Status = NpfsPeekPipe(Irp, (PIO_STACK_LOCATION)IoStack);
375 break;
376
377 case FSCTL_PIPE_QUERY_EVENT:
378 DPRINT("Query event\n");
379 Status = STATUS_NOT_IMPLEMENTED;
380 break;
381
382 case FSCTL_PIPE_TRANSCEIVE:
383 DPRINT("Transceive\n");
384 Status = STATUS_NOT_IMPLEMENTED;
385 break;
386
387 case FSCTL_PIPE_WAIT:
388 DPRINT("Waiting for pipe %wZ\n", &Pipe->PipeName);
389 Status = NpfsWaitPipe(Irp, Fcb);
390 break;
391
392 case FSCTL_PIPE_IMPERSONATE:
393 DPRINT("Impersonate\n");
394 Status = STATUS_NOT_IMPLEMENTED;
395 break;
396
397 case FSCTL_PIPE_SET_CLIENT_PROCESS:
398 DPRINT("Set client process\n");
399 Status = STATUS_NOT_IMPLEMENTED;
400 break;
401
402 case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
403 DPRINT("Query client process\n");
404 Status = STATUS_NOT_IMPLEMENTED;
405 break;
406
407 case FSCTL_PIPE_GET_STATE:
408 DPRINT("Get state\n");
409 Status = NpfsGetState(Irp, (PIO_STACK_LOCATION)IoStack);
410 break;
411
412 case FSCTL_PIPE_SET_STATE:
413 DPRINT("Set state\n");
414 Status = NpfsSetState(Irp, (PIO_STACK_LOCATION)IoStack);
415 break;
416
417 case FSCTL_PIPE_INTERNAL_READ:
418 DPRINT("Internal read\n");
419 Status = STATUS_NOT_IMPLEMENTED;
420 break;
421
422 case FSCTL_PIPE_INTERNAL_WRITE:
423 DPRINT("Internal write\n");
424 Status = STATUS_NOT_IMPLEMENTED;
425 break;
426
427 case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
428 DPRINT("Internal transceive\n");
429 Status = STATUS_NOT_IMPLEMENTED;
430 break;
431
432 case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
433 DPRINT("Internal read overflow\n");
434 Status = STATUS_NOT_IMPLEMENTED;
435 break;
436
437 default:
438 DPRINT("IoControlCode: %x\n", IoStack->Parameters.FileSystemControl.FsControlCode)
439 Status = STATUS_UNSUCCESSFUL;
440 }
441
442 Irp->IoStatus.Status = Status;
443 Irp->IoStatus.Information = 0;
444
445 IoCompleteRequest(Irp, IO_NO_INCREMENT);
446
447 return(Status);
448 }
449
450
451 NTSTATUS STDCALL
452 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject,
453 PIRP Irp)
454 {
455 /* FIXME: Implement */
456
457 Irp->IoStatus.Status = STATUS_SUCCESS;
458 Irp->IoStatus.Information = 0;
459
460 IoCompleteRequest(Irp, IO_NO_INCREMENT);
461
462 return STATUS_SUCCESS;
463 }
464
465 /* EOF */