- Fixed various problems (hangs/crashes) with connecting, disconnecting and closing...
[reactos.git] / reactos / drivers / fs / np / fsctrl.c
1 /* $Id: fsctrl.c,v 1.15 2004/05/05 18:30:16 navaraf Exp $
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
46 KeLockMutex(&Pipe->FcbListLock);
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 == FILE_PIPE_LISTENING_STATE)
55 {
56 break;
57 }
58
59 current_entry = current_entry->Flink;
60 }
61
62 if (current_entry != &Pipe->ClientFcbListHead)
63 {
64 /* found a listening client fcb */
65 DPRINT("Listening client fcb found -- connecting\n");
66
67 /* connect client and server fcb's */
68 Fcb->OtherSide = ClientFcb;
69 ClientFcb->OtherSide = Fcb;
70
71 /* set connected state */
72 Fcb->PipeState = FILE_PIPE_CONNECTED_STATE;
73 ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
74
75 KeUnlockMutex(&Pipe->FcbListLock);
76
77 /* FIXME: create and initialize data queues */
78
79 /* signal client's connect event */
80 DPRINT("Setting the ConnectEvent for %x\n", ClientFcb);
81 KeSetEvent(&ClientFcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
82
83 Status = STATUS_PIPE_CONNECTED;
84 }
85 else
86 {
87 /* no listening client fcb found */
88 DPRINT("No listening client fcb found -- waiting for client\n");
89
90 KeUnlockMutex(&Pipe->FcbListLock);
91
92 Fcb->PipeState = FILE_PIPE_LISTENING_STATE;
93
94 Status = KeWaitForSingleObject(&Fcb->ConnectEvent,
95 UserRequest,
96 KernelMode,
97 FALSE,
98 NULL);
99
100 if (NT_SUCCESS(Status))
101 {
102 Status = STATUS_PIPE_CONNECTED;
103 Fcb->PipeState = FILE_PIPE_CONNECTED_STATE;
104 }
105
106 DPRINT("Finished waiting! Status: %x\n", Status);
107 }
108
109 DPRINT("Client Fcb: %p\n", Fcb->OtherSide);
110
111 return Status;
112 }
113
114
115 static NTSTATUS
116 NpfsDisconnectPipe(PNPFS_FCB Fcb)
117 {
118 DPRINT("NpfsDisconnectPipe()\n");
119
120 if (Fcb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
121 return(STATUS_SUCCESS);
122
123 if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
124 {
125 Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
126 /* FIXME: Shouldn't this be FILE_PIPE_CLOSING_STATE? */
127 Fcb->OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
128
129 /* FIXME: remove data queue(s) */
130
131 Fcb->OtherSide->OtherSide = NULL;
132 Fcb->OtherSide = NULL;
133
134 DPRINT("Pipe disconnected\n");
135 return(STATUS_SUCCESS);
136 }
137
138 if (Fcb->PipeState == FILE_PIPE_CLOSING_STATE)
139 {
140 Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
141 Fcb->OtherSide = NULL;
142
143 /* FIXME: remove data queue(s) */
144
145 DPRINT("Pipe disconnected\n");
146 return(STATUS_SUCCESS);
147 }
148
149 return(STATUS_UNSUCCESSFUL);
150 }
151
152
153 static NTSTATUS
154 NpfsWaitPipe(PIRP Irp,
155 PNPFS_FCB Fcb)
156 {
157 PNPFS_PIPE Pipe;
158 PLIST_ENTRY current_entry;
159 PNPFS_FCB ServerFcb;
160 PNPFS_WAIT_PIPE WaitPipe;
161 NTSTATUS Status;
162
163 DPRINT("NpfsWaitPipe\n");
164
165 WaitPipe = (PNPFS_WAIT_PIPE)Irp->AssociatedIrp.SystemBuffer;
166 Pipe = Fcb->Pipe;
167
168 /* search for listening server */
169 current_entry = Pipe->ServerFcbListHead.Flink;
170 while (current_entry != &Pipe->ServerFcbListHead)
171 {
172 ServerFcb = CONTAINING_RECORD(current_entry,
173 NPFS_FCB,
174 FcbListEntry);
175
176 if (ServerFcb->PipeState == FILE_PIPE_LISTENING_STATE)
177 break;
178
179 current_entry = current_entry->Flink;
180 }
181
182 if (current_entry != &Pipe->ServerFcbListHead)
183 {
184 /* found a listening server fcb */
185 DPRINT("Listening server fcb found -- connecting\n");
186
187 Status = STATUS_SUCCESS;
188 }
189 else
190 {
191 /* no listening server fcb found -- wait for one */
192 Fcb->PipeState = FILE_PIPE_LISTENING_STATE;
193
194 Status = KeWaitForSingleObject(&Fcb->ConnectEvent,
195 UserRequest,
196 KernelMode,
197 FALSE,
198 &WaitPipe->Timeout);
199 }
200
201 return(Status);
202 }
203
204
205 static NTSTATUS
206 NpfsGetState(
207 PIRP Irp,
208 PIO_STACK_LOCATION IrpSp)
209 /*
210 * FUNCTION: Return current state of a pipe
211 * ARGUMENTS:
212 * Irp = Pointer to I/O request packet
213 * IrpSp = Pointer to current stack location of Irp
214 * RETURNS:
215 * Status of operation
216 */
217 {
218 ULONG OutputBufferLength;
219 PNPFS_GET_STATE Reply;
220 NTSTATUS Status;
221 PNPFS_PIPE Pipe;
222 PNPFS_FCB Fcb;
223
224 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
225
226 /* Validate parameters */
227 if (OutputBufferLength >= sizeof(NPFS_GET_STATE))
228 {
229 Fcb = IrpSp->FileObject->FsContext;
230 Reply = (PNPFS_GET_STATE)Irp->AssociatedIrp.SystemBuffer;
231 Pipe = Fcb->Pipe;
232
233 if (Pipe->PipeWriteMode == FILE_PIPE_MESSAGE_MODE)
234 {
235 Reply->WriteModeMessage = TRUE;
236 }
237 else
238 {
239 Reply->WriteModeMessage = FALSE;
240 }
241
242 if (Pipe->PipeReadMode == FILE_PIPE_MESSAGE_MODE)
243 {
244 Reply->ReadModeMessage = TRUE;
245 }
246 else
247 {
248 Reply->ReadModeMessage = FALSE;
249 }
250
251 if (Pipe->PipeBlockMode == FILE_PIPE_QUEUE_OPERATION)
252 {
253 Reply->NonBlocking = TRUE;
254 }
255 else
256 {
257 Reply->NonBlocking = FALSE;
258 }
259
260 Reply->InBufferSize = Pipe->InboundQuota;
261
262 Reply->OutBufferSize = Pipe->OutboundQuota;
263
264 Reply->Timeout = Pipe->TimeOut;
265
266 Status = STATUS_SUCCESS;
267 }
268 else
269 {
270 Status = STATUS_INVALID_PARAMETER;
271 }
272
273 DPRINT("Status (0x%X).\n", Status);
274
275 return Status;
276 }
277
278
279 static NTSTATUS
280 NpfsSetState(
281 PIRP Irp,
282 PIO_STACK_LOCATION IrpSp)
283 /*
284 * FUNCTION: Set state of a pipe
285 * ARGUMENTS:
286 * Irp = Pointer to I/O request packet
287 * IrpSp = Pointer to current stack location of Irp
288 * RETURNS:
289 * Status of operation
290 */
291 {
292 ULONG InputBufferLength;
293 PNPFS_SET_STATE Request;
294 PNPFS_PIPE Pipe;
295 NTSTATUS Status;
296 PNPFS_FCB Fcb;
297
298 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
299
300 /* Validate parameters */
301 if (InputBufferLength >= sizeof(NPFS_SET_STATE))
302 {
303 Fcb = IrpSp->FileObject->FsContext;
304 Request = (PNPFS_SET_STATE)Irp->AssociatedIrp.SystemBuffer;
305 Pipe = Fcb->Pipe;
306
307 if (Request->WriteModeMessage)
308 {
309 Pipe->PipeWriteMode = FILE_PIPE_MESSAGE_MODE;
310 }
311 else
312 {
313 Pipe->PipeWriteMode = FILE_PIPE_BYTE_STREAM_MODE;
314 }
315
316 if (Request->ReadModeMessage)
317 {
318 Pipe->PipeReadMode = FILE_PIPE_MESSAGE_MODE;
319 }
320 else
321 {
322 Pipe->PipeReadMode = FILE_PIPE_BYTE_STREAM_MODE;
323 }
324
325 if (Request->NonBlocking)
326 {
327 Pipe->PipeBlockMode = FILE_PIPE_QUEUE_OPERATION;
328 }
329 else
330 {
331 Pipe->PipeBlockMode = FILE_PIPE_COMPLETE_OPERATION;
332 }
333
334 Pipe->InboundQuota = Request->InBufferSize;
335
336 Pipe->OutboundQuota = Request->OutBufferSize;
337
338 Pipe->TimeOut = Request->Timeout;
339
340 Status = STATUS_SUCCESS;
341 }
342 else
343 {
344 Status = STATUS_INVALID_PARAMETER;
345 }
346
347 DPRINT("Status (0x%X).\n", Status);
348
349 return Status;
350 }
351
352
353 static NTSTATUS
354 NpfsPeekPipe(PIRP Irp,
355 PIO_STACK_LOCATION IoStack)
356 /*
357 * FUNCTION: Peek at a pipe (get information about messages)
358 * ARGUMENTS:
359 * Irp = Pointer to I/O request packet
360 * IoStack = Pointer to current stack location of Irp
361 * RETURNS:
362 * Status of operation
363 */
364 {
365 ULONG OutputBufferLength;
366 PNPFS_PIPE Pipe;
367 PFILE_PIPE_PEEK_BUFFER Reply;
368 PNPFS_FCB Fcb;
369 NTSTATUS Status;
370
371 DPRINT("NpfsPeekPipe\n");
372
373 OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
374
375 /* Validate parameters */
376 if (OutputBufferLength < sizeof(FILE_PIPE_PEEK_BUFFER))
377 {
378 DPRINT("Buffer too small\n");
379 return(STATUS_INVALID_PARAMETER);
380 }
381
382 Fcb = IoStack->FileObject->FsContext;
383 Reply = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer;
384 Pipe = Fcb->Pipe;
385
386 Status = STATUS_NOT_IMPLEMENTED;
387
388 return(Status);
389 }
390
391
392
393 NTSTATUS STDCALL
394 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
395 PIRP Irp)
396 {
397 PEXTENDED_IO_STACK_LOCATION IoStack;
398 PFILE_OBJECT FileObject;
399 NTSTATUS Status;
400 PNPFS_DEVICE_EXTENSION DeviceExt;
401 PNPFS_PIPE Pipe;
402 PNPFS_FCB Fcb;
403
404 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
405
406 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
407 IoStack = (PEXTENDED_IO_STACK_LOCATION) IoGetCurrentIrpStackLocation(Irp);
408 DPRINT("IoStack: %p\n", IoStack);
409 FileObject = IoStack->FileObject;
410 DPRINT("FileObject: %p\n", FileObject);
411 Fcb = FileObject->FsContext;
412 DPRINT("Fcb: %p\n", Fcb);
413 Pipe = Fcb->Pipe;
414 DPRINT("Pipe: %p\n", Pipe);
415 DPRINT("PipeName: %wZ\n", &Pipe->PipeName);
416
417 switch (IoStack->Parameters.FileSystemControl.FsControlCode)
418 {
419 case FSCTL_PIPE_ASSIGN_EVENT:
420 DPRINT("Assign event\n");
421 Status = STATUS_NOT_IMPLEMENTED;
422 break;
423
424 case FSCTL_PIPE_DISCONNECT:
425 DPRINT("Disconnecting pipe %wZ\n", &Pipe->PipeName);
426 Status = NpfsDisconnectPipe(Fcb);
427 break;
428
429 case FSCTL_PIPE_LISTEN:
430 DPRINT("Connecting pipe %wZ\n", &Pipe->PipeName);
431 Status = NpfsConnectPipe(Fcb);
432 break;
433
434 case FSCTL_PIPE_PEEK:
435 DPRINT("Peeking pipe %wZ\n", &Pipe->PipeName);
436 Status = NpfsPeekPipe(Irp, (PIO_STACK_LOCATION)IoStack);
437 break;
438
439 case FSCTL_PIPE_QUERY_EVENT:
440 DPRINT("Query event\n");
441 Status = STATUS_NOT_IMPLEMENTED;
442 break;
443
444 case FSCTL_PIPE_TRANSCEIVE:
445 DPRINT("Transceive\n");
446 Status = STATUS_NOT_IMPLEMENTED;
447 break;
448
449 case FSCTL_PIPE_WAIT:
450 DPRINT("Waiting for pipe %wZ\n", &Pipe->PipeName);
451 Status = NpfsWaitPipe(Irp, Fcb);
452 break;
453
454 case FSCTL_PIPE_IMPERSONATE:
455 DPRINT("Impersonate\n");
456 Status = STATUS_NOT_IMPLEMENTED;
457 break;
458
459 case FSCTL_PIPE_SET_CLIENT_PROCESS:
460 DPRINT("Set client process\n");
461 Status = STATUS_NOT_IMPLEMENTED;
462 break;
463
464 case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
465 DPRINT("Query client process\n");
466 Status = STATUS_NOT_IMPLEMENTED;
467 break;
468
469 case FSCTL_PIPE_GET_STATE:
470 DPRINT("Get state\n");
471 Status = NpfsGetState(Irp, (PIO_STACK_LOCATION)IoStack);
472 break;
473
474 case FSCTL_PIPE_SET_STATE:
475 DPRINT("Set state\n");
476 Status = NpfsSetState(Irp, (PIO_STACK_LOCATION)IoStack);
477 break;
478
479 case FSCTL_PIPE_INTERNAL_READ:
480 DPRINT("Internal read\n");
481 Status = STATUS_NOT_IMPLEMENTED;
482 break;
483
484 case FSCTL_PIPE_INTERNAL_WRITE:
485 DPRINT("Internal write\n");
486 Status = STATUS_NOT_IMPLEMENTED;
487 break;
488
489 case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
490 DPRINT("Internal transceive\n");
491 Status = STATUS_NOT_IMPLEMENTED;
492 break;
493
494 case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
495 DPRINT("Internal read overflow\n");
496 Status = STATUS_NOT_IMPLEMENTED;
497 break;
498
499 default:
500 DPRINT("IoControlCode: %x\n", IoStack->Parameters.FileSystemControl.FsControlCode)
501 Status = STATUS_UNSUCCESSFUL;
502 }
503
504 Irp->IoStatus.Status = Status;
505 Irp->IoStatus.Information = 0;
506
507 IoCompleteRequest(Irp, IO_NO_INCREMENT);
508
509 return(Status);
510 }
511
512
513 NTSTATUS STDCALL
514 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject,
515 PIRP Irp)
516 {
517 /* FIXME: Implement */
518
519 Irp->IoStatus.Status = STATUS_SUCCESS;
520 Irp->IoStatus.Information = 0;
521
522 IoCompleteRequest(Irp, IO_NO_INCREMENT);
523
524 return STATUS_SUCCESS;
525 }
526
527 /* EOF */