Various fixes to DPRINT parameter list.
[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: drivers/fs/np/fsctrl.c
6 * PURPOSE: Named pipe filesystem
7 * PROGRAMMER: David Welch <welch@cwcom.net>
8 * Eric Kohl
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ntifs.h>
14 #include "npfs.h"
15
16 #define NDEBUG
17 #include <debug.h>
18
19 /* FUNCTIONS *****************************************************************/
20
21 static VOID STDCALL
22 NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
23 IN PIRP Irp)
24 {
25 PNPFS_WAITER_ENTRY Waiter;
26
27 DPRINT1("NpfsListeningCancelRoutine() called\n");
28
29 Waiter = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext;
30
31 IoReleaseCancelSpinLock(Irp->CancelIrql);
32
33
34 KeLockMutex(&Waiter->Fcb->Pipe->FcbListLock);
35 RemoveEntryList(&Waiter->Entry);
36 KeUnlockMutex(&Waiter->Fcb->Pipe->FcbListLock);
37
38 Irp->IoStatus.Status = STATUS_CANCELLED;
39 Irp->IoStatus.Information = 0;
40 IoCompleteRequest(Irp, IO_NO_INCREMENT);
41 }
42
43
44 static NTSTATUS
45 NpfsAddListeningServerInstance(PIRP Irp,
46 PNPFS_FCB Fcb)
47 {
48 PNPFS_WAITER_ENTRY Entry;
49 KIRQL oldIrql;
50
51 Entry = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext;
52
53 Entry->Fcb = Fcb;
54
55 KeLockMutex(&Fcb->Pipe->FcbListLock);
56
57 IoMarkIrpPending(Irp);
58 InsertTailList(&Fcb->Pipe->WaiterListHead, &Entry->Entry);
59
60 IoAcquireCancelSpinLock(&oldIrql);
61 if (!Irp->Cancel)
62 {
63 IoSetCancelRoutine(Irp, NpfsListeningCancelRoutine);
64 IoReleaseCancelSpinLock(oldIrql);
65 KeUnlockMutex(&Fcb->Pipe->FcbListLock);
66 return STATUS_PENDING;
67 }
68 IoReleaseCancelSpinLock(oldIrql);
69
70 RemoveEntryList(&Entry->Entry);
71
72 Irp->IoStatus.Status = STATUS_CANCELLED;
73 Irp->IoStatus.Information = 0;
74 IoCompleteRequest(Irp, IO_NO_INCREMENT);
75 KeUnlockMutex(&Fcb->Pipe->FcbListLock);
76
77 return STATUS_CANCELLED;
78 }
79
80
81 static NTSTATUS
82 NpfsConnectPipe(PIRP Irp,
83 PNPFS_FCB Fcb)
84 {
85 PNPFS_PIPE Pipe;
86 PLIST_ENTRY current_entry;
87 PNPFS_FCB ClientFcb;
88 NTSTATUS Status;
89
90 DPRINT("NpfsConnectPipe()\n");
91
92 if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
93 {
94 KeResetEvent(&Fcb->ConnectEvent);
95 return STATUS_PIPE_CONNECTED;
96 }
97
98 if (Fcb->PipeState == FILE_PIPE_CLOSING_STATE)
99 return STATUS_PIPE_CLOSING;
100
101 DPRINT("Waiting for connection...\n");
102
103 Pipe = Fcb->Pipe;
104
105 /* search for a listening client fcb */
106 KeLockMutex(&Pipe->FcbListLock);
107
108 current_entry = Pipe->ClientFcbListHead.Flink;
109 while (current_entry != &Pipe->ClientFcbListHead)
110 {
111 ClientFcb = CONTAINING_RECORD(current_entry,
112 NPFS_FCB,
113 FcbListEntry);
114
115 if (ClientFcb->PipeState == 0)
116 {
117 /* found a passive (waiting) client fcb */
118 DPRINT("Passive (waiting) client fcb found -- wake the client\n");
119 KeSetEvent(&ClientFcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
120 break;
121 }
122
123 #if 0
124 if (ClientFcb->PipeState == FILE_PIPE_LISTENING_STATE)
125 {
126 /* found a listening client fcb */
127 DPRINT("Listening client fcb found -- connecting\n");
128
129 /* connect client and server fcb's */
130 Fcb->OtherSide = ClientFcb;
131 ClientFcb->OtherSide = Fcb;
132
133 /* set connected state */
134 Fcb->PipeState = FILE_PIPE_CONNECTED_STATE;
135 ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
136
137 KeUnlockMutex(&Pipe->FcbListLock);
138
139 /* FIXME: create and initialize data queues */
140
141 /* signal client's connect event */
142 DPRINT("Setting the ConnectEvent for %x\n", ClientFcb);
143 KeSetEvent(&ClientFcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
144
145 return STATUS_PIPE_CONNECTED;
146 }
147 #endif
148
149 current_entry = current_entry->Flink;
150 }
151
152 /* no listening client fcb found */
153 DPRINT("No listening client fcb found -- waiting for client\n");
154
155 Fcb->PipeState = FILE_PIPE_LISTENING_STATE;
156
157 Status = NpfsAddListeningServerInstance(Irp, Fcb);
158
159 KeUnlockMutex(&Pipe->FcbListLock);
160
161 DPRINT("NpfsConnectPipe() done (Status %lx)\n", Status);
162
163 return Status;
164 }
165
166
167 static NTSTATUS
168 NpfsDisconnectPipe(PNPFS_FCB Fcb)
169 {
170 NTSTATUS Status;
171 PNPFS_FCB OtherSide;
172 PNPFS_PIPE Pipe;
173 BOOL Server;
174
175 DPRINT("NpfsDisconnectPipe()\n");
176
177 Pipe = Fcb->Pipe;
178 KeLockMutex(&Pipe->FcbListLock);
179
180 if (Fcb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
181 {
182 DPRINT("Pipe is already disconnected\n");
183 Status = STATUS_SUCCESS;
184 }
185 else if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
186 {
187 Server = (Fcb->PipeEnd == FILE_PIPE_SERVER_END);
188 OtherSide = Fcb->OtherSide;
189 Fcb->OtherSide = NULL;
190 /* Lock the server first */
191 if (Server)
192 {
193 ExAcquireFastMutex(&Fcb->DataListLock);
194 ExAcquireFastMutex(&OtherSide->DataListLock);
195 }
196 else
197 {
198 ExAcquireFastMutex(&OtherSide->DataListLock);
199 ExAcquireFastMutex(&Fcb->DataListLock);
200 }
201 OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
202 OtherSide->OtherSide = NULL;
203 /*
204 * Signaling the write event. If is possible that an other
205 * thread waits for an empty buffer.
206 */
207 KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
208 KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
209 if (Server)
210 {
211 ExReleaseFastMutex(&Fcb->DataListLock);
212 ExReleaseFastMutex(&OtherSide->DataListLock);
213 }
214 else
215 {
216 ExReleaseFastMutex(&OtherSide->DataListLock);
217 ExReleaseFastMutex(&OtherSide->DataListLock);
218 }
219 Status = STATUS_SUCCESS;
220 }
221 else if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
222 {
223 PLIST_ENTRY Entry;
224 PNPFS_WAITER_ENTRY WaitEntry = NULL;
225 BOOLEAN Complete = FALSE;
226 PIRP Irp = NULL;
227
228 Entry = Fcb->Pipe->WaiterListHead.Flink;
229 while (Entry != &Fcb->Pipe->WaiterListHead)
230 {
231 WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry);
232 if (WaitEntry->Fcb == Fcb)
233 {
234 RemoveEntryList(Entry);
235 Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DriverContext);
236 Complete = (NULL == IoSetCancelRoutine(Irp, NULL));
237 break;
238 }
239 Entry = Entry->Flink;
240 }
241
242 if (Irp)
243 {
244 if (Complete)
245 {
246 Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
247 Irp->IoStatus.Information = 0;
248 IoCompleteRequest(Irp, IO_NO_INCREMENT);
249 }
250 }
251 Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
252 Status = STATUS_SUCCESS;
253 }
254 else if (Fcb->PipeState == FILE_PIPE_CLOSING_STATE)
255 {
256 Status = STATUS_PIPE_CLOSING;
257 }
258 else
259 {
260 Status = STATUS_UNSUCCESSFUL;
261 }
262 KeUnlockMutex(&Pipe->FcbListLock);
263 return Status;
264 }
265
266
267 static NTSTATUS
268 NpfsWaitPipe(PIRP Irp,
269 PNPFS_FCB Fcb)
270 {
271 PNPFS_PIPE Pipe;
272 PLIST_ENTRY current_entry;
273 PNPFS_FCB ServerFcb;
274 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe;
275 NTSTATUS Status;
276
277 DPRINT("NpfsWaitPipe\n");
278
279 WaitPipe = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
280 Pipe = Fcb->Pipe;
281
282 if (Fcb->PipeState != 0)
283 {
284 DPRINT("Pipe is not in passive (waiting) state!\n");
285 return STATUS_UNSUCCESSFUL;
286 }
287
288 /* search for listening server */
289 current_entry = Pipe->ServerFcbListHead.Flink;
290 while (current_entry != &Pipe->ServerFcbListHead)
291 {
292 ServerFcb = CONTAINING_RECORD(current_entry,
293 NPFS_FCB,
294 FcbListEntry);
295
296 if (ServerFcb->PipeState == FILE_PIPE_LISTENING_STATE)
297 {
298 /* found a listening server fcb */
299 DPRINT("Listening server fcb found -- connecting\n");
300
301 return STATUS_SUCCESS;
302 }
303
304 current_entry = current_entry->Flink;
305 }
306
307 /* no listening server fcb found -- wait for one */
308 Status = KeWaitForSingleObject(&Fcb->ConnectEvent,
309 UserRequest,
310 KernelMode,
311 FALSE,
312 &WaitPipe->Timeout);
313
314 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status);
315
316 return Status;
317 }
318
319
320 /*
321 * FUNCTION: Return current state of a pipe
322 * ARGUMENTS:
323 * Irp = Pointer to I/O request packet
324 * IrpSp = Pointer to current stack location of Irp
325 * RETURNS:
326 * Status of operation
327 */
328
329 /*
330 * FUNCTION: Peek at a pipe (get information about messages)
331 * ARGUMENTS:
332 * Irp = Pointer to I/O request packet
333 * IoStack = Pointer to current stack location of Irp
334 * RETURNS:
335 * Status of operation
336 */
337 static NTSTATUS
338 NpfsPeekPipe(PIRP Irp,
339 PIO_STACK_LOCATION IoStack)
340 {
341 ULONG OutputBufferLength;
342 PNPFS_PIPE Pipe;
343 PFILE_PIPE_PEEK_BUFFER Reply;
344 PNPFS_FCB Fcb;
345 NTSTATUS Status;
346
347 DPRINT("NpfsPeekPipe\n");
348
349 OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
350
351 /* Validate parameters */
352 if (OutputBufferLength < sizeof(FILE_PIPE_PEEK_BUFFER))
353 {
354 DPRINT("Buffer too small\n");
355 return STATUS_INVALID_PARAMETER;
356 }
357
358 Fcb = IoStack->FileObject->FsContext;
359 Reply = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer;
360 Pipe = Fcb->Pipe;
361
362 Status = STATUS_NOT_IMPLEMENTED;
363
364 return Status;
365 }
366
367
368 NTSTATUS STDCALL
369 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
370 PIRP Irp)
371 {
372 PIO_STACK_LOCATION IoStack;
373 PFILE_OBJECT FileObject;
374 NTSTATUS Status;
375 PNPFS_DEVICE_EXTENSION DeviceExt;
376 PNPFS_PIPE Pipe;
377 PNPFS_FCB Fcb;
378
379 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
380
381 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
382 IoStack = IoGetCurrentIrpStackLocation(Irp);
383 DPRINT("IoStack: %p\n", IoStack);
384 FileObject = IoStack->FileObject;
385 DPRINT("FileObject: %p\n", FileObject);
386 Fcb = FileObject->FsContext;
387 DPRINT("Fcb: %p\n", Fcb);
388 Pipe = Fcb->Pipe;
389 DPRINT("Pipe: %p\n", Pipe);
390 DPRINT("PipeName: %wZ\n", &Pipe->PipeName);
391
392 Irp->IoStatus.Information = 0;
393
394 switch (IoStack->Parameters.FileSystemControl.FsControlCode)
395 {
396 case FSCTL_PIPE_ASSIGN_EVENT:
397 DPRINT("Assign event\n");
398 Status = STATUS_NOT_IMPLEMENTED;
399 break;
400
401 case FSCTL_PIPE_DISCONNECT:
402 DPRINT("Disconnecting pipe %wZ\n", &Pipe->PipeName);
403 Status = NpfsDisconnectPipe(Fcb);
404 break;
405
406 case FSCTL_PIPE_LISTEN:
407 DPRINT("Connecting pipe %wZ\n", &Pipe->PipeName);
408 Status = NpfsConnectPipe(Irp, Fcb);
409 break;
410
411 case FSCTL_PIPE_PEEK:
412 DPRINT("Peeking pipe %wZ\n", &Pipe->PipeName);
413 Status = NpfsPeekPipe(Irp, (PIO_STACK_LOCATION)IoStack);
414 break;
415
416 case FSCTL_PIPE_QUERY_EVENT:
417 DPRINT("Query event\n");
418 Status = STATUS_NOT_IMPLEMENTED;
419 break;
420
421 case FSCTL_PIPE_TRANSCEIVE:
422 DPRINT("Transceive\n");
423 Status = STATUS_NOT_IMPLEMENTED;
424 break;
425
426 case FSCTL_PIPE_WAIT:
427 DPRINT("Waiting for pipe %wZ\n", &Pipe->PipeName);
428 Status = NpfsWaitPipe(Irp, Fcb);
429 break;
430
431 case FSCTL_PIPE_IMPERSONATE:
432 DPRINT("Impersonate\n");
433 Status = STATUS_NOT_IMPLEMENTED;
434 break;
435
436 case FSCTL_PIPE_SET_CLIENT_PROCESS:
437 DPRINT("Set client process\n");
438 Status = STATUS_NOT_IMPLEMENTED;
439 break;
440
441 case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
442 DPRINT("Query client process\n");
443 Status = STATUS_NOT_IMPLEMENTED;
444 break;
445
446 case FSCTL_PIPE_INTERNAL_READ:
447 DPRINT("Internal read\n");
448 Status = STATUS_NOT_IMPLEMENTED;
449 break;
450
451 case FSCTL_PIPE_INTERNAL_WRITE:
452 DPRINT("Internal write\n");
453 Status = STATUS_NOT_IMPLEMENTED;
454 break;
455
456 case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
457 DPRINT("Internal transceive\n");
458 Status = STATUS_NOT_IMPLEMENTED;
459 break;
460
461 case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
462 DPRINT("Internal read overflow\n");
463 Status = STATUS_NOT_IMPLEMENTED;
464 break;
465
466 default:
467 DPRINT("IoControlCode: %x\n", IoStack->Parameters.FileSystemControl.FsControlCode);
468 Status = STATUS_UNSUCCESSFUL;
469 }
470
471 if (Status != STATUS_PENDING)
472 {
473 Irp->IoStatus.Status = Status;
474
475 IoCompleteRequest(Irp, IO_NO_INCREMENT);
476 }
477
478 return Status;
479 }
480
481
482 NTSTATUS STDCALL
483 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject,
484 PIRP Irp)
485 {
486 /* FIXME: Implement */
487
488 Irp->IoStatus.Status = STATUS_SUCCESS;
489 Irp->IoStatus.Information = 0;
490
491 IoCompleteRequest(Irp, IO_NO_INCREMENT);
492
493 return STATUS_SUCCESS;
494 }
495
496 /* EOF */