Connect client and server side upon client side creation only if both sides were...
[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: services/fs/np/fsctrl.c
6 * PURPOSE: Named pipe filesystem
7 * PROGRAMMER: David Welch <welch@cwcom.net>
8 * Eric Kohl <ekohl@rz-online.de>
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 ULONG OutputBufferLength;
221 PNPFS_GET_STATE Reply;
222 NTSTATUS Status;
223 PNPFS_PIPE Pipe;
224 PNPFS_FCB Fcb;
225
226 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
227
228 /* Validate parameters */
229 if (OutputBufferLength >= sizeof(NPFS_GET_STATE))
230 {
231 Fcb = IrpSp->FileObject->FsContext;
232 Reply = (PNPFS_GET_STATE)Irp->AssociatedIrp.SystemBuffer;
233 Pipe = Fcb->Pipe;
234
235 if (Pipe->PipeWriteMode == FILE_PIPE_MESSAGE_MODE)
236 {
237 Reply->WriteModeMessage = TRUE;
238 }
239 else
240 {
241 Reply->WriteModeMessage = FALSE;
242 }
243
244 if (Pipe->PipeReadMode == FILE_PIPE_MESSAGE_MODE)
245 {
246 Reply->ReadModeMessage = TRUE;
247 }
248 else
249 {
250 Reply->ReadModeMessage = FALSE;
251 }
252
253 if (Pipe->PipeBlockMode == FILE_PIPE_QUEUE_OPERATION)
254 {
255 Reply->NonBlocking = TRUE;
256 }
257 else
258 {
259 Reply->NonBlocking = FALSE;
260 }
261
262 Reply->InBufferSize = Pipe->InboundQuota;
263
264 Reply->OutBufferSize = Pipe->OutboundQuota;
265
266 Reply->Timeout = Pipe->TimeOut;
267
268 Status = STATUS_SUCCESS;
269 }
270 else
271 {
272 Status = STATUS_INVALID_PARAMETER;
273 }
274
275 DPRINT("Status (0x%X).\n", Status);
276
277 return Status;
278 }
279
280
281 /*
282 * FUNCTION: Set state of a pipe
283 * ARGUMENTS:
284 * Irp = Pointer to I/O request packet
285 * IrpSp = Pointer to current stack location of Irp
286 * RETURNS:
287 * Status of operation
288 */
289 static NTSTATUS
290 NpfsSetState(PIRP Irp,
291 PIO_STACK_LOCATION IrpSp)
292 {
293 ULONG InputBufferLength;
294 PNPFS_SET_STATE Request;
295 PNPFS_PIPE Pipe;
296 NTSTATUS Status;
297 PNPFS_FCB Fcb;
298
299 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
300
301 /* Validate parameters */
302 if (InputBufferLength >= sizeof(NPFS_SET_STATE))
303 {
304 Fcb = IrpSp->FileObject->FsContext;
305 Request = (PNPFS_SET_STATE)Irp->AssociatedIrp.SystemBuffer;
306 Pipe = Fcb->Pipe;
307
308 if (Request->WriteModeMessage)
309 {
310 Pipe->PipeWriteMode = FILE_PIPE_MESSAGE_MODE;
311 }
312 else
313 {
314 Pipe->PipeWriteMode = FILE_PIPE_BYTE_STREAM_MODE;
315 }
316
317 if (Request->ReadModeMessage)
318 {
319 Pipe->PipeReadMode = FILE_PIPE_MESSAGE_MODE;
320 }
321 else
322 {
323 Pipe->PipeReadMode = FILE_PIPE_BYTE_STREAM_MODE;
324 }
325
326 if (Request->NonBlocking)
327 {
328 Pipe->PipeBlockMode = FILE_PIPE_QUEUE_OPERATION;
329 }
330 else
331 {
332 Pipe->PipeBlockMode = FILE_PIPE_COMPLETE_OPERATION;
333 }
334
335 Pipe->InboundQuota = Request->InBufferSize;
336
337 Pipe->OutboundQuota = Request->OutBufferSize;
338
339 Pipe->TimeOut = Request->Timeout;
340
341 Status = STATUS_SUCCESS;
342 }
343 else
344 {
345 Status = STATUS_INVALID_PARAMETER;
346 }
347
348 DPRINT("Status (0x%X).\n", Status);
349
350 return Status;
351 }
352
353
354 /*
355 * FUNCTION: Peek at a pipe (get information about messages)
356 * ARGUMENTS:
357 * Irp = Pointer to I/O request packet
358 * IoStack = Pointer to current stack location of Irp
359 * RETURNS:
360 * Status of operation
361 */
362 static NTSTATUS
363 NpfsPeekPipe(PIRP Irp,
364 PIO_STACK_LOCATION IoStack)
365 {
366 ULONG OutputBufferLength;
367 PNPFS_PIPE Pipe;
368 PFILE_PIPE_PEEK_BUFFER Reply;
369 PNPFS_FCB Fcb;
370 NTSTATUS Status;
371
372 DPRINT("NpfsPeekPipe\n");
373
374 OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
375
376 /* Validate parameters */
377 if (OutputBufferLength < sizeof(FILE_PIPE_PEEK_BUFFER))
378 {
379 DPRINT("Buffer too small\n");
380 return STATUS_INVALID_PARAMETER;
381 }
382
383 Fcb = IoStack->FileObject->FsContext;
384 Reply = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer;
385 Pipe = Fcb->Pipe;
386
387 Status = STATUS_NOT_IMPLEMENTED;
388
389 return Status;
390 }
391
392
393
394 NTSTATUS STDCALL
395 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
396 PIRP Irp)
397 {
398 PIO_STACK_LOCATION IoStack;
399 PFILE_OBJECT FileObject;
400 NTSTATUS Status;
401 PNPFS_DEVICE_EXTENSION DeviceExt;
402 PNPFS_PIPE Pipe;
403 PNPFS_FCB Fcb;
404
405 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
406
407 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
408 IoStack = IoGetCurrentIrpStackLocation(Irp);
409 DPRINT("IoStack: %p\n", IoStack);
410 FileObject = IoStack->FileObject;
411 DPRINT("FileObject: %p\n", FileObject);
412 Fcb = FileObject->FsContext;
413 DPRINT("Fcb: %p\n", Fcb);
414 Pipe = Fcb->Pipe;
415 DPRINT("Pipe: %p\n", Pipe);
416 DPRINT("PipeName: %wZ\n", &Pipe->PipeName);
417
418 switch (IoStack->Parameters.FileSystemControl.FsControlCode)
419 {
420 case FSCTL_PIPE_ASSIGN_EVENT:
421 DPRINT("Assign event\n");
422 Status = STATUS_NOT_IMPLEMENTED;
423 break;
424
425 case FSCTL_PIPE_DISCONNECT:
426 DPRINT("Disconnecting pipe %wZ\n", &Pipe->PipeName);
427 Status = NpfsDisconnectPipe(Fcb);
428 break;
429
430 case FSCTL_PIPE_LISTEN:
431 DPRINT("Connecting pipe %wZ\n", &Pipe->PipeName);
432 Status = NpfsConnectPipe(Fcb);
433 break;
434
435 case FSCTL_PIPE_PEEK:
436 DPRINT("Peeking pipe %wZ\n", &Pipe->PipeName);
437 Status = NpfsPeekPipe(Irp, (PIO_STACK_LOCATION)IoStack);
438 break;
439
440 case FSCTL_PIPE_QUERY_EVENT:
441 DPRINT("Query event\n");
442 Status = STATUS_NOT_IMPLEMENTED;
443 break;
444
445 case FSCTL_PIPE_TRANSCEIVE:
446 DPRINT("Transceive\n");
447 Status = STATUS_NOT_IMPLEMENTED;
448 break;
449
450 case FSCTL_PIPE_WAIT:
451 DPRINT("Waiting for pipe %wZ\n", &Pipe->PipeName);
452 Status = NpfsWaitPipe(Irp, Fcb);
453 break;
454
455 case FSCTL_PIPE_IMPERSONATE:
456 DPRINT("Impersonate\n");
457 Status = STATUS_NOT_IMPLEMENTED;
458 break;
459
460 case FSCTL_PIPE_SET_CLIENT_PROCESS:
461 DPRINT("Set client process\n");
462 Status = STATUS_NOT_IMPLEMENTED;
463 break;
464
465 case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
466 DPRINT("Query client process\n");
467 Status = STATUS_NOT_IMPLEMENTED;
468 break;
469
470 case FSCTL_PIPE_GET_STATE:
471 DPRINT("Get state\n");
472 Status = NpfsGetState(Irp, (PIO_STACK_LOCATION)IoStack);
473 break;
474
475 case FSCTL_PIPE_SET_STATE:
476 DPRINT("Set state\n");
477 Status = NpfsSetState(Irp, (PIO_STACK_LOCATION)IoStack);
478 break;
479
480 case FSCTL_PIPE_INTERNAL_READ:
481 DPRINT("Internal read\n");
482 Status = STATUS_NOT_IMPLEMENTED;
483 break;
484
485 case FSCTL_PIPE_INTERNAL_WRITE:
486 DPRINT("Internal write\n");
487 Status = STATUS_NOT_IMPLEMENTED;
488 break;
489
490 case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
491 DPRINT("Internal transceive\n");
492 Status = STATUS_NOT_IMPLEMENTED;
493 break;
494
495 case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
496 DPRINT("Internal read overflow\n");
497 Status = STATUS_NOT_IMPLEMENTED;
498 break;
499
500 default:
501 DPRINT("IoControlCode: %x\n", IoStack->Parameters.FileSystemControl.FsControlCode)
502 Status = STATUS_UNSUCCESSFUL;
503 }
504
505 Irp->IoStatus.Status = Status;
506 Irp->IoStatus.Information = 0;
507
508 IoCompleteRequest(Irp, IO_NO_INCREMENT);
509
510 return(Status);
511 }
512
513
514 NTSTATUS STDCALL
515 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject,
516 PIRP Irp)
517 {
518 /* FIXME: Implement */
519
520 Irp->IoStatus.Status = STATUS_SUCCESS;
521 Irp->IoStatus.Information = 0;
522
523 IoCompleteRequest(Irp, IO_NO_INCREMENT);
524
525 return STATUS_SUCCESS;
526 }
527
528 /* EOF */