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