24d225da6d9297440303bdd63f8175d4f8cad2de
[reactos.git] / reactos / drivers / fs / np / fsctrl.c
1 /* $Id: fsctrl.c,v 1.7 2001/10/21 18:58:31 chorns 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 PNPFS_FCB ServerFcb;
120
121 DPRINT("NpfsDisconnectPipe()\n");
122
123 if (Fcb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
124 return(STATUS_SUCCESS);
125
126 if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
127 {
128 Fcb->PipeState = FILE_PIPE_DISCONNECTED_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
144 /* FIXME: remove data queue(s) */
145
146 DPRINT("Pipe disconnected\n");
147 return(STATUS_SUCCESS);
148 }
149
150 return(STATUS_UNSUCCESSFUL);
151 }
152
153
154 static NTSTATUS
155 NpfsWaitPipe(PIRP Irp,
156 PNPFS_FCB Fcb)
157 {
158 PNPFS_PIPE Pipe;
159 PLIST_ENTRY current_entry;
160 PNPFS_FCB ServerFcb;
161 PNPFS_WAIT_PIPE WaitPipe;
162 NTSTATUS Status;
163
164 DPRINT("NpfsWaitPipe\n");
165
166 WaitPipe = (PNPFS_WAIT_PIPE)Irp->AssociatedIrp.SystemBuffer;
167 Pipe = Fcb->Pipe;
168
169 /* search for listening server */
170 current_entry = Pipe->ServerFcbListHead.Flink;
171 while (current_entry != &Pipe->ServerFcbListHead)
172 {
173 ServerFcb = CONTAINING_RECORD(current_entry,
174 NPFS_FCB,
175 FcbListEntry);
176
177 if (ServerFcb->PipeState == FILE_PIPE_LISTENING_STATE)
178 break;
179
180 current_entry = current_entry->Flink;
181 }
182
183 if (current_entry != &Pipe->ServerFcbListHead)
184 {
185 /* found a listening server fcb */
186 DPRINT("Listening server fcb found -- connecting\n");
187
188 Status = STATUS_SUCCESS;
189 }
190 else
191 {
192 /* no listening server fcb found -- wait for one */
193 Fcb->PipeState = FILE_PIPE_LISTENING_STATE;
194
195 Status = KeWaitForSingleObject(&Fcb->ConnectEvent,
196 UserRequest,
197 KernelMode,
198 FALSE,
199 &WaitPipe->Timeout);
200 }
201
202 return(Status);
203 }
204
205
206 static NTSTATUS
207 NpfsGetState(
208 PIRP Irp,
209 PIO_STACK_LOCATION IrpSp)
210 /*
211 * FUNCTION: Return current state of a pipe
212 * ARGUMENTS:
213 * Irp = Pointer to I/O request packet
214 * IrpSp = Pointer to current stack location of Irp
215 * RETURNS:
216 * Status of operation
217 */
218 {
219 ULONG OutputBufferLength;
220 PNPFS_GET_STATE Reply;
221 NTSTATUS Status;
222 PNPFS_PIPE Pipe;
223 PNPFS_FCB Fcb;
224
225 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
226
227 /* Validate parameters */
228 if (OutputBufferLength >= sizeof(NPFS_GET_STATE))
229 {
230 Fcb = IrpSp->FileObject->FsContext;
231 Reply = (PNPFS_GET_STATE)Irp->AssociatedIrp.SystemBuffer;
232 Pipe = Fcb->Pipe;
233
234 if (Pipe->PipeWriteMode == FILE_PIPE_MESSAGE_MODE)
235 {
236 Reply->WriteModeMessage = TRUE;
237 }
238 else
239 {
240 Reply->WriteModeMessage = FALSE;
241 }
242
243 if (Pipe->PipeReadMode == FILE_PIPE_MESSAGE_MODE)
244 {
245 Reply->ReadModeMessage = TRUE;
246 }
247 else
248 {
249 Reply->ReadModeMessage = FALSE;
250 }
251
252 if (Pipe->PipeBlockMode == FILE_PIPE_QUEUE_OPERATION)
253 {
254 Reply->NonBlocking = TRUE;
255 }
256 else
257 {
258 Reply->NonBlocking = FALSE;
259 }
260
261 Reply->InBufferSize = Pipe->InboundQuota;
262
263 Reply->OutBufferSize = Pipe->OutboundQuota;
264
265 Reply->Timeout = Pipe->TimeOut;
266
267 Status = STATUS_SUCCESS;
268 }
269 else
270 {
271 Status = STATUS_INVALID_PARAMETER;
272 }
273
274 DPRINT("Status (0x%X).\n", Status);
275
276 return Status;
277 }
278
279
280 static NTSTATUS
281 NpfsSetState(
282 PIRP Irp,
283 PIO_STACK_LOCATION IrpSp)
284 /*
285 * FUNCTION: Set state of a pipe
286 * ARGUMENTS:
287 * Irp = Pointer to I/O request packet
288 * IrpSp = Pointer to current stack location of Irp
289 * RETURNS:
290 * Status of operation
291 */
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 NTSTATUS STDCALL
355 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
356 PIRP Irp)
357 {
358 PIO_STACK_LOCATION IoStack;
359 PFILE_OBJECT FileObject;
360 NTSTATUS Status;
361 PNPFS_DEVICE_EXTENSION DeviceExt;
362 PNPFS_PIPE Pipe;
363 PNPFS_FCB Fcb;
364
365 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
366
367 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
368 IoStack = IoGetCurrentIrpStackLocation(Irp);
369 DPRINT("IoStack: %p\n", IoStack);
370 FileObject = IoStack->FileObject;
371 DPRINT("FileObject: %p\n", FileObject);
372 Fcb = FileObject->FsContext;
373 DPRINT("Fcb: %p\n", Fcb);
374 Pipe = Fcb->Pipe;
375 DPRINT("Pipe: %p\n", Pipe);
376 DPRINT("PipeName: %wZ\n", &Pipe->PipeName);
377
378 switch (IoStack->Parameters.FileSystemControl.IoControlCode)
379 {
380 case FSCTL_PIPE_ASSIGN_EVENT:
381 DPRINT("Assign event\n");
382 Status = STATUS_NOT_IMPLEMENTED;
383 break;
384
385 case FSCTL_PIPE_DISCONNECT:
386 DPRINT("Disconnecting pipe %wZ\n", &Pipe->PipeName);
387 Status = NpfsDisconnectPipe(Fcb);
388 break;
389
390 case FSCTL_PIPE_LISTEN:
391 DPRINT("Connecting pipe %wZ\n", &Pipe->PipeName);
392 Status = NpfsConnectPipe(Fcb);
393 break;
394
395 case FSCTL_PIPE_PEEK:
396 DPRINT("Peek\n");
397 Status = STATUS_NOT_IMPLEMENTED;
398 break;
399
400 case FSCTL_PIPE_QUERY_EVENT:
401 DPRINT("Query event\n");
402 Status = STATUS_NOT_IMPLEMENTED;
403 break;
404
405 case FSCTL_PIPE_TRANSCEIVE:
406 DPRINT("Transceive\n");
407 Status = STATUS_NOT_IMPLEMENTED;
408 break;
409
410 case FSCTL_PIPE_WAIT:
411 DPRINT("Waiting for pipe %wZ\n", &Pipe->PipeName);
412 Status = NpfsWaitPipe(Irp, Fcb);
413 break;
414
415 case FSCTL_PIPE_IMPERSONATE:
416 DPRINT("Impersonate\n");
417 Status = STATUS_NOT_IMPLEMENTED;
418 break;
419
420 case FSCTL_PIPE_SET_CLIENT_PROCESS:
421 DPRINT("Set client process\n");
422 Status = STATUS_NOT_IMPLEMENTED;
423 break;
424
425 case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
426 DPRINT("Query client process\n");
427 Status = STATUS_NOT_IMPLEMENTED;
428 break;
429
430 case FSCTL_PIPE_GET_STATE:
431 DPRINT("Get state\n");
432 Status = NpfsGetState(Irp, IoStack);
433 break;
434
435 case FSCTL_PIPE_SET_STATE:
436 DPRINT("Set state\n");
437 Status = NpfsSetState(Irp, IoStack);
438 break;
439
440 case FSCTL_PIPE_INTERNAL_READ:
441 DPRINT("Internal read\n");
442 Status = STATUS_NOT_IMPLEMENTED;
443 break;
444
445 case FSCTL_PIPE_INTERNAL_WRITE:
446 DPRINT("Internal write\n");
447 Status = STATUS_NOT_IMPLEMENTED;
448 break;
449
450 case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
451 DPRINT("Internal transceive\n");
452 Status = STATUS_NOT_IMPLEMENTED;
453 break;
454
455 case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
456 DPRINT("Internal read overflow\n");
457 Status = STATUS_NOT_IMPLEMENTED;
458 break;
459
460 default:
461 DPRINT("IoControlCode: %x\n", IoStack->Parameters.FileSystemControl.IoControlCode)
462 Status = STATUS_UNSUCCESSFUL;
463 }
464
465 Irp->IoStatus.Status = Status;
466 Irp->IoStatus.Information = 0;
467
468 IoCompleteRequest(Irp, IO_NO_INCREMENT);
469
470 return(Status);
471 }
472
473 /* EOF */