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