[NPFS]
[reactos.git] / reactos / drivers / filesystems / npfs / fsctrl.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/fs/np/fsctrl.c
5 * PURPOSE: Named pipe filesystem
6 * PROGRAMMER: David Welch <welch@cwcom.net>
7 * Eric Kohl
8 * Michael Martin
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include "npfs.h"
14
15 #define NDEBUG
16 #include <debug.h>
17
18 //#define USING_PROPER_NPFS_WAIT_SEMANTICS
19
20 /* FUNCTIONS *****************************************************************/
21
22 static DRIVER_CANCEL NpfsListeningCancelRoutine;
23 static VOID NTAPI
24 NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
25 IN PIRP Irp)
26 {
27 PNPFS_WAITER_ENTRY Waiter;
28
29 Waiter = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext;
30
31 DPRINT("NpfsListeningCancelRoutine() called for <%wZ>\n",
32 &Waiter->Ccb->Fcb->PipeName);
33
34 IoReleaseCancelSpinLock(Irp->CancelIrql);
35
36
37 KeLockMutex(&Waiter->Ccb->Fcb->CcbListLock);
38 RemoveEntryList(&Waiter->Entry);
39 KeUnlockMutex(&Waiter->Ccb->Fcb->CcbListLock);
40
41 Irp->IoStatus.Status = STATUS_CANCELLED;
42 Irp->IoStatus.Information = 0;
43 IoCompleteRequest(Irp, IO_NO_INCREMENT);
44 }
45
46
47 static NTSTATUS
48 NpfsAddListeningServerInstance(PIRP Irp,
49 PNPFS_CCB Ccb)
50 {
51 PNPFS_WAITER_ENTRY Entry;
52 KIRQL oldIrql;
53
54 Entry = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext;
55
56 Entry->Ccb = Ccb;
57
58 KeLockMutex(&Ccb->Fcb->CcbListLock);
59
60 IoAcquireCancelSpinLock(&oldIrql);
61 if (!Irp->Cancel)
62 {
63 Ccb->PipeState = FILE_PIPE_LISTENING_STATE;
64 IoMarkIrpPending(Irp);
65 InsertTailList(&Ccb->Fcb->WaiterListHead, &Entry->Entry);
66 (void)IoSetCancelRoutine(Irp, NpfsListeningCancelRoutine);
67 IoReleaseCancelSpinLock(oldIrql);
68 KeUnlockMutex(&Ccb->Fcb->CcbListLock);
69 return STATUS_PENDING;
70 }
71 IoReleaseCancelSpinLock(oldIrql);
72
73 RemoveEntryList(&Entry->Entry);
74
75 Irp->IoStatus.Status = STATUS_CANCELLED;
76 Irp->IoStatus.Information = 0;
77 IoCompleteRequest(Irp, IO_NO_INCREMENT);
78 KeUnlockMutex(&Ccb->Fcb->CcbListLock);
79
80 return STATUS_CANCELLED;
81 }
82
83
84 static NTSTATUS
85 NpfsConnectPipe(PIRP Irp,
86 PNPFS_CCB Ccb)
87 {
88 PIO_STACK_LOCATION IoStack;
89 PFILE_OBJECT FileObject;
90 ULONG Flags;
91 PLIST_ENTRY current_entry;
92 PNPFS_FCB Fcb;
93 PNPFS_CCB ClientCcb;
94 NTSTATUS Status;
95 KPROCESSOR_MODE WaitMode;
96
97 DPRINT("NpfsConnectPipe()\n");
98
99 /* Fail, if the CCB is not a pipe CCB */
100 if (Ccb->Type != CCB_PIPE)
101 {
102 DPRINT("Not a pipe\n");
103 return STATUS_ILLEGAL_FUNCTION;
104 }
105
106 /* Fail, if the CCB is not a server end CCB */
107 if (Ccb->PipeEnd != FILE_PIPE_SERVER_END)
108 {
109 DPRINT("Not the server end\n");
110 return STATUS_ILLEGAL_FUNCTION;
111 }
112
113 if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE)
114 {
115 KeResetEvent(&Ccb->ConnectEvent);
116 return STATUS_PIPE_CONNECTED;
117 }
118
119 if (Ccb->PipeState == FILE_PIPE_CLOSING_STATE)
120 return STATUS_PIPE_CLOSING;
121
122 DPRINT("Waiting for connection...\n");
123
124 Fcb = Ccb->Fcb;
125 IoStack = IoGetCurrentIrpStackLocation(Irp);
126 FileObject = IoStack->FileObject;
127 Flags = FileObject->Flags;
128 WaitMode = Irp->RequestorMode;
129
130 /* search for a listening client fcb */
131 KeLockMutex(&Fcb->CcbListLock);
132
133 current_entry = Fcb->ClientCcbListHead.Flink;
134 while (current_entry != &Fcb->ClientCcbListHead)
135 {
136 ClientCcb = CONTAINING_RECORD(current_entry,
137 NPFS_CCB,
138 CcbListEntry);
139
140 if (ClientCcb->PipeState == 0)
141 {
142 /* found a passive (waiting) client CCB */
143 DPRINT("Passive (waiting) client CCB found -- wake the client\n");
144 KeSetEvent(&ClientCcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
145 break;
146 }
147
148 #if 0
149 if (ClientCcb->PipeState == FILE_PIPE_LISTENING_STATE)
150 {
151 /* found a listening client CCB */
152 DPRINT("Listening client CCB found -- connecting\n");
153
154 /* connect client and server CCBs */
155 Ccb->OtherSide = ClientCcb;
156 ClientCcb->OtherSide = Ccb;
157
158 /* set connected state */
159 Ccb->PipeState = FILE_PIPE_CONNECTED_STATE;
160 ClientCcb->PipeState = FILE_PIPE_CONNECTED_STATE;
161
162 KeUnlockMutex(&Fcb->CcbListLock);
163
164 /* FIXME: create and initialize data queues */
165
166 /* signal client's connect event */
167 DPRINT("Setting the ConnectEvent for %x\n", ClientCcb);
168 KeSetEvent(&ClientCcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
169
170 return STATUS_PIPE_CONNECTED;
171 }
172 #endif
173
174 current_entry = current_entry->Flink;
175 }
176
177 /* no listening client fcb found */
178 DPRINT("No listening client fcb found -- waiting for client\n");
179
180 Status = NpfsAddListeningServerInstance(Irp, Ccb);
181
182 KeUnlockMutex(&Fcb->CcbListLock);
183
184 if ((Status == STATUS_PENDING) && (Flags & FO_SYNCHRONOUS_IO))
185 {
186 KeWaitForSingleObject(&Ccb->ConnectEvent,
187 UserRequest,
188 WaitMode,
189 (Flags & FO_ALERTABLE_IO) != 0,
190 NULL);
191 }
192
193 DPRINT("NpfsConnectPipe() done (Status %lx)\n", Status);
194
195 return Status;
196 }
197
198
199 static NTSTATUS
200 NpfsDisconnectPipe(PNPFS_CCB Ccb)
201 {
202 NTSTATUS Status;
203 PNPFS_FCB Fcb;
204 PNPFS_CCB OtherSide;
205 BOOLEAN Server;
206
207 DPRINT("NpfsDisconnectPipe()\n");
208
209 /* Fail, if the CCB is not a pipe CCB */
210 if (Ccb->Type != CCB_PIPE)
211 {
212 DPRINT("Not a pipe\n");
213 return STATUS_ILLEGAL_FUNCTION;
214 }
215
216 /* Fail, if the CCB is not a server end CCB */
217 if (Ccb->PipeEnd != FILE_PIPE_SERVER_END)
218 {
219 DPRINT("Not the server end\n");
220 return STATUS_ILLEGAL_FUNCTION;
221 }
222
223 Fcb = Ccb->Fcb;
224 KeLockMutex(&Fcb->CcbListLock);
225
226 if (Ccb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
227 {
228 DPRINT("Pipe is already disconnected\n");
229 Status = STATUS_PIPE_DISCONNECTED;
230 }
231 else if ((!Ccb->OtherSide) && (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE))
232 {
233 ExAcquireFastMutex(&Ccb->DataListLock);
234 Ccb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
235 ExReleaseFastMutex(&Ccb->DataListLock);
236 Status = STATUS_SUCCESS;
237 }
238 else if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE)
239 {
240 Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END);
241 OtherSide = Ccb->OtherSide;
242 //Ccb->OtherSide = NULL;
243 Ccb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
244 /* Lock the server first */
245 if (Server)
246 {
247 ExAcquireFastMutex(&Ccb->DataListLock);
248 ExAcquireFastMutex(&OtherSide->DataListLock);
249 }
250 else
251 {
252 ExAcquireFastMutex(&OtherSide->DataListLock);
253 ExAcquireFastMutex(&Ccb->DataListLock);
254 }
255 OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
256 //OtherSide->OtherSide = NULL;
257 /*
258 * Signaling the write event. If is possible that an other
259 * thread waits for an empty buffer.
260 */
261 KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
262 KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
263 if (Server)
264 {
265 ExReleaseFastMutex(&OtherSide->DataListLock);
266 ExReleaseFastMutex(&Ccb->DataListLock);
267 }
268 else
269 {
270 ExReleaseFastMutex(&Ccb->DataListLock);
271 ExReleaseFastMutex(&OtherSide->DataListLock);
272 }
273 Status = STATUS_SUCCESS;
274 }
275 else if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
276 {
277 PLIST_ENTRY Entry;
278 PNPFS_WAITER_ENTRY WaitEntry = NULL;
279 BOOLEAN Complete = FALSE;
280 PIRP Irp = NULL;
281
282 Entry = Ccb->Fcb->WaiterListHead.Flink;
283 while (Entry != &Ccb->Fcb->WaiterListHead)
284 {
285 WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry);
286 if (WaitEntry->Ccb == Ccb)
287 {
288 RemoveEntryList(Entry);
289 Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DriverContext);
290 Complete = (NULL != IoSetCancelRoutine(Irp, NULL));
291 break;
292 }
293 Entry = Entry->Flink;
294 }
295
296 if (Irp)
297 {
298 if (Complete)
299 {
300 Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
301 Irp->IoStatus.Information = 0;
302 IoCompleteRequest(Irp, IO_NO_INCREMENT);
303 }
304 }
305 Ccb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
306 Status = STATUS_SUCCESS;
307 }
308 else if (Ccb->PipeState == FILE_PIPE_CLOSING_STATE)
309 {
310 Status = STATUS_PIPE_CLOSING;
311 }
312 else
313 {
314 Status = STATUS_UNSUCCESSFUL;
315 }
316 KeUnlockMutex(&Fcb->CcbListLock);
317 return Status;
318 }
319
320 static NTSTATUS
321 NpfsWaitPipe(PIRP Irp,
322 PNPFS_CCB Ccb)
323 {
324 PLIST_ENTRY current_entry;
325 PNPFS_FCB Fcb;
326 PNPFS_CCB ServerCcb;
327 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe;
328 PLARGE_INTEGER TimeOut;
329 NTSTATUS Status;
330 PEXTENDED_IO_STACK_LOCATION IoStack;
331 PFILE_OBJECT FileObject;
332 PNPFS_VCB Vcb;
333
334 IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
335 ASSERT(IoStack);
336 FileObject = IoStack->FileObject;
337 ASSERT(FileObject);
338
339 DPRINT("Waiting on Pipe %wZ\n", &FileObject->FileName);
340
341 WaitPipe = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
342
343 ASSERT(Ccb->Fcb);
344 ASSERT(Ccb->Fcb->Vcb);
345
346 /* Get the VCB */
347 Vcb = Ccb->Fcb->Vcb;
348
349 /* Lock the pipe list */
350 KeLockMutex(&Vcb->PipeListLock);
351
352 /* File a pipe with the given name */
353 Fcb = NpfsFindPipe(Vcb,
354 &FileObject->FileName);
355
356 /* Unlock the pipe list */
357 KeUnlockMutex(&Vcb->PipeListLock);
358
359 /* Fail if not pipe was found */
360 if (Fcb == NULL)
361 {
362 DPRINT("No pipe found!\n", Fcb);
363 return STATUS_OBJECT_NAME_NOT_FOUND;
364 }
365
366 /* search for listening server */
367 current_entry = Fcb->ServerCcbListHead.Flink;
368 while (current_entry != &Fcb->ServerCcbListHead)
369 {
370 ServerCcb = CONTAINING_RECORD(current_entry,
371 NPFS_CCB,
372 CcbListEntry);
373
374 if (ServerCcb->PipeState == FILE_PIPE_LISTENING_STATE)
375 {
376 /* found a listening server CCB */
377 DPRINT("Listening server CCB found -- connecting\n");
378 NpfsDereferenceFcb(Fcb);
379 return STATUS_SUCCESS;
380 }
381
382 current_entry = current_entry->Flink;
383 }
384
385 /* No listening server fcb found, so wait for one */
386
387 /* If a timeout specified */
388 if (WaitPipe->TimeoutSpecified)
389 {
390 /* NMPWAIT_USE_DEFAULT_WAIT = 0 */
391 if (WaitPipe->Timeout.QuadPart == 0)
392 {
393 TimeOut = &Fcb->TimeOut;
394 }
395 else
396 {
397 TimeOut = &WaitPipe->Timeout;
398 }
399 }
400 else
401 {
402 /* Wait forever */
403 TimeOut = NULL;
404 }
405 NpfsDereferenceFcb(Fcb);
406
407 Status = KeWaitForSingleObject(&Ccb->ConnectEvent,
408 UserRequest,
409 Irp->RequestorMode,
410 (Ccb->FileObject->Flags & FO_ALERTABLE_IO) != 0,
411 TimeOut);
412 if ((Status == STATUS_USER_APC) || (Status == STATUS_KERNEL_APC) || (Status == STATUS_ALERTED))
413 Status = STATUS_CANCELLED;
414
415 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status);
416
417 return Status;
418 }
419
420 NTSTATUS
421 NpfsWaitPipe2(PIRP Irp,
422 PNPFS_CCB Ccb)
423 {
424 PLIST_ENTRY current_entry;
425 PNPFS_FCB Fcb;
426 PNPFS_CCB ServerCcb;
427 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe;
428 LARGE_INTEGER TimeOut;
429 NTSTATUS Status;
430 #ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
431 PNPFS_VCB Vcb;
432 UNICODE_STRING PipeName;
433 #endif
434
435 DPRINT("NpfsWaitPipe\n");
436
437 WaitPipe = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
438
439 #ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
440 /* Fail, if the CCB does not represent the root directory */
441 if (Ccb->Type != CCB_DIRECTORY)
442 return STATUS_ILLEGAL_FUNCTION;
443
444 /* Calculate the pipe name length and allocate the buffer */
445 PipeName.Length = WaitPipe->NameLength + sizeof(WCHAR);
446 PipeName.MaximumLength = PipeName.Length + sizeof(WCHAR);
447 PipeName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
448 PipeName.MaximumLength,
449 TAG_NPFS_NAMEBLOCK);
450 if (PipeName.Buffer == NULL)
451 {
452 DPRINT1("Could not allocate memory for the pipe name!\n");
453 return STATUS_NO_MEMORY;
454 }
455
456 /* Copy the pipe name into the buffer, prepend a backslash and append a 0 character */
457 PipeName.Buffer[0] = L'\\';
458 RtlCopyMemory(&PipeName.Buffer[1],
459 &WaitPipe->Name[0],
460 WaitPipe->NameLength);
461 PipeName.Buffer[PipeName.Length / sizeof(WCHAR)] = 0;
462
463 DPRINT("Waiting for Pipe %wZ\n", &PipeName);
464
465 /* Get the VCB */
466 Vcb = Ccb->Fcb->Vcb;
467
468 /* Lock the pipe list */
469 KeLockMutex(&Vcb->PipeListLock);
470
471 /* File a pipe with the given name */
472 Fcb = NpfsFindPipe(Vcb,
473 &PipeName);
474
475 /* Unlock the pipe list */
476 KeUnlockMutex(&Vcb->PipeListLock);
477
478 /* Release the pipe name buffer */
479 ExFreePoolWithTag(PipeName.Buffer, TAG_NPFS_NAMEBLOCK);
480
481 /* Fail if not pipe was found */
482 if (Fcb == NULL)
483 {
484 DPRINT("No pipe found!\n", Fcb);
485 return STATUS_OBJECT_NAME_NOT_FOUND;
486 }
487
488 DPRINT("Fcb %p\n", Fcb);
489 #else
490 Fcb = Ccb->Fcb;
491
492 if (Ccb->PipeState != 0)
493 {
494 DPRINT("Pipe is not in passive (waiting) state!\n");
495 return STATUS_UNSUCCESSFUL;
496 }
497 #endif
498
499 /* search for listening server */
500 current_entry = Fcb->ServerCcbListHead.Flink;
501 while (current_entry != &Fcb->ServerCcbListHead)
502 {
503 ServerCcb = CONTAINING_RECORD(current_entry,
504 NPFS_CCB,
505 CcbListEntry);
506
507 if (ServerCcb->PipeState == FILE_PIPE_LISTENING_STATE)
508 {
509 /* found a listening server CCB */
510 DPRINT("Listening server CCB found -- connecting\n");
511 #ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
512 NpfsDereferenceFcb(Fcb);
513 #endif
514 return STATUS_SUCCESS;
515 }
516
517 current_entry = current_entry->Flink;
518 }
519
520 /* No listening server fcb found */
521
522 /* If no timeout specified, use the default one */
523 if (WaitPipe->TimeoutSpecified)
524 TimeOut = WaitPipe->Timeout;
525 else
526 TimeOut = Fcb->TimeOut;
527 #ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
528 NpfsDereferenceFcb(Fcb);
529 #endif
530
531 /* Wait for one */
532 Status = KeWaitForSingleObject(&Ccb->ConnectEvent,
533 UserRequest,
534 Irp->RequestorMode,
535 (Ccb->FileObject->Flags & FO_ALERTABLE_IO) != 0,
536 &TimeOut);
537 if ((Status == STATUS_USER_APC) || (Status == STATUS_KERNEL_APC) || (Status == STATUS_ALERTED))
538 Status = STATUS_CANCELLED;
539
540 DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status);
541
542 return Status;
543 }
544
545
546 /*
547 * FUNCTION: Return current state of a pipe
548 * ARGUMENTS:
549 * Irp = Pointer to I/O request packet
550 * IrpSp = Pointer to current stack location of Irp
551 * RETURNS:
552 * Status of operation
553 */
554
555 /*
556 * FUNCTION: Peek at a pipe (get information about messages)
557 * ARGUMENTS:
558 * Irp = Pointer to I/O request packet
559 * IoStack = Pointer to current stack location of Irp
560 * RETURNS:
561 * Status of operation
562 */
563 static NTSTATUS
564 NpfsPeekPipe(PIRP Irp,
565 PIO_STACK_LOCATION IoStack)
566 {
567 ULONG OutputBufferLength;
568 ULONG ReturnLength = 0;
569 PFILE_PIPE_PEEK_BUFFER Reply;
570 //PNPFS_FCB Fcb;
571 PNPFS_CCB Ccb;
572 NTSTATUS Status;
573 ULONG MessageCount = 0;
574 ULONG MessageLength;
575 ULONG ReadDataAvailable;
576 PVOID BufferPtr;
577
578 DPRINT("NpfsPeekPipe\n");
579
580 OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
581 DPRINT("OutputBufferLength: %lu\n", OutputBufferLength);
582
583 /* Validate parameters */
584 if (OutputBufferLength < FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]))
585 {
586 DPRINT1("Buffer too small\n");
587 return STATUS_INVALID_PARAMETER;
588 }
589
590 Ccb = IoStack->FileObject->FsContext2;
591 Reply = Irp->AssociatedIrp.SystemBuffer;
592 //Fcb = Ccb->Fcb;
593
594
595 Reply->NamedPipeState = Ccb->PipeState;
596
597 Reply->ReadDataAvailable = Ccb->ReadDataAvailable;
598 DPRINT("ReadDataAvailable: %lu\n", Ccb->ReadDataAvailable);
599
600 ExAcquireFastMutex(&Ccb->DataListLock);
601 BufferPtr = Ccb->ReadPtr;
602 DPRINT("BufferPtr = %x\n", BufferPtr);
603 if (Ccb->Fcb->PipeType == FILE_PIPE_BYTE_STREAM_TYPE)
604 {
605 DPRINT("Byte Stream Mode\n");
606 Reply->MessageLength = Ccb->ReadDataAvailable;
607 DPRINT("Reply->MessageLength %lu\n", Reply->MessageLength);
608 MessageCount = 1;
609
610 if (OutputBufferLength >= FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[Ccb->ReadDataAvailable]))
611 {
612 RtlCopyMemory(Reply->Data, BufferPtr, Ccb->ReadDataAvailable);
613 ReturnLength = Ccb->ReadDataAvailable;
614 }
615 }
616 else
617 {
618 DPRINT("Message Mode\n");
619 ReadDataAvailable = Ccb->ReadDataAvailable;
620
621 if (ReadDataAvailable > 0)
622 {
623 RtlCopyMemory(&Reply->MessageLength,
624 BufferPtr,
625 sizeof(Reply->MessageLength));
626
627 while ((ReadDataAvailable > 0) && (BufferPtr < Ccb->WritePtr))
628 {
629 RtlCopyMemory(&MessageLength, BufferPtr, sizeof(MessageLength));
630
631 ASSERT(MessageLength > 0);
632
633 DPRINT("MessageLength = %lu\n", MessageLength);
634 ReadDataAvailable -= MessageLength;
635 MessageCount++;
636
637 /* If its the first message, copy the Message if the size of buffer is large enough */
638 if (MessageCount == 1)
639 {
640 if (OutputBufferLength >= FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[MessageLength]))
641 {
642 RtlCopyMemory(Reply->Data,
643 (PVOID)((ULONG_PTR)BufferPtr + sizeof(MessageLength)),
644 MessageLength);
645 ReturnLength = MessageLength;
646 }
647 }
648
649 BufferPtr = (PVOID)((ULONG_PTR)BufferPtr + sizeof(MessageLength) + MessageLength);
650 DPRINT("BufferPtr = %x\n", BufferPtr);
651 DPRINT("ReadDataAvailable: %lu\n", ReadDataAvailable);
652 }
653
654 if (ReadDataAvailable != 0)
655 {
656 DPRINT1("Possible memory corruption.\n");
657 ASSERT(FALSE);
658 }
659 }
660 }
661 ExReleaseFastMutex(&Ccb->DataListLock);
662
663 Reply->NumberOfMessages = MessageCount;
664
665 Irp->IoStatus.Information = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[ReturnLength]);
666 Irp->IoStatus.Status = STATUS_SUCCESS;
667
668 Status = STATUS_SUCCESS;
669
670 DPRINT("NpfsPeekPipe done\n");
671
672 return Status;
673 }
674
675
676 NTSTATUS NTAPI
677 NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
678 PIRP Irp)
679 {
680 PIO_STACK_LOCATION IoStack;
681 PFILE_OBJECT FileObject;
682 NTSTATUS Status;
683 //PNPFS_VCB Vcb;
684 PNPFS_FCB Fcb;
685 PNPFS_CCB Ccb;
686
687 DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
688
689 //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
690 IoStack = IoGetCurrentIrpStackLocation(Irp);
691 DPRINT("IoStack: %p\n", IoStack);
692 FileObject = IoStack->FileObject;
693 DPRINT("FileObject: %p\n", FileObject);
694 Ccb = FileObject->FsContext2;
695 DPRINT("CCB: %p\n", Ccb);
696 Fcb = Ccb->Fcb;
697 DPRINT("Pipe: %p\n", Fcb);
698 DPRINT("PipeName: %wZ\n", &Fcb->PipeName);
699
700 Irp->IoStatus.Information = 0;
701
702 switch (IoStack->Parameters.FileSystemControl.FsControlCode)
703 {
704 case FSCTL_PIPE_ASSIGN_EVENT:
705 DPRINT1("Assign event not implemented\n");
706 Status = STATUS_NOT_IMPLEMENTED;
707 break;
708
709 case FSCTL_PIPE_DISCONNECT:
710 DPRINT("Disconnecting pipe %wZ\n", &Fcb->PipeName);
711 Status = NpfsDisconnectPipe(Ccb);
712 break;
713
714 case FSCTL_PIPE_LISTEN:
715 DPRINT("Connecting pipe %wZ\n", &Fcb->PipeName);
716 Status = NpfsConnectPipe(Irp, Ccb);
717 break;
718
719 case FSCTL_PIPE_PEEK:
720 DPRINT("Peeking pipe %wZ\n", &Fcb->PipeName);
721 Status = NpfsPeekPipe(Irp, (PIO_STACK_LOCATION)IoStack);
722 break;
723
724 case FSCTL_PIPE_QUERY_EVENT:
725 DPRINT1("Query event not implemented\n");
726 Status = STATUS_NOT_IMPLEMENTED;
727 break;
728
729 case FSCTL_PIPE_TRANSCEIVE:
730 /* If you implement this, please remove the workaround in
731 lib/kernel32/file/npipe.c function TransactNamedPipe() */
732 DPRINT1("Transceive not implemented\n");
733 Status = STATUS_NOT_IMPLEMENTED;
734 break;
735
736 case FSCTL_PIPE_WAIT:
737 DPRINT("Waiting for pipe %wZ\n", &Fcb->PipeName);
738 Status = NpfsWaitPipe(Irp, Ccb);
739 break;
740
741 case FSCTL_PIPE_IMPERSONATE:
742 DPRINT1("Impersonate not implemented\n");
743 Status = STATUS_NOT_IMPLEMENTED;
744 break;
745
746 case FSCTL_PIPE_SET_CLIENT_PROCESS:
747 DPRINT1("Set client process not implemented\n");
748 Status = STATUS_NOT_IMPLEMENTED;
749 break;
750
751 case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
752 DPRINT1("Query client process not implemented\n");
753 Status = STATUS_NOT_IMPLEMENTED;
754 break;
755
756 case FSCTL_PIPE_INTERNAL_READ:
757 DPRINT1("Internal read not implemented\n");
758 Status = STATUS_NOT_IMPLEMENTED;
759 break;
760
761 case FSCTL_PIPE_INTERNAL_WRITE:
762 DPRINT1("Internal write not implemented\n");
763 Status = STATUS_NOT_IMPLEMENTED;
764 break;
765
766 case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
767 DPRINT1("Internal transceive not implemented\n");
768 Status = STATUS_NOT_IMPLEMENTED;
769 break;
770
771 case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
772 DPRINT1("Internal read overflow not implemented\n");
773 Status = STATUS_NOT_IMPLEMENTED;
774 break;
775
776 default:
777 DPRINT1("Unrecognized IoControlCode: %x\n",
778 IoStack->Parameters.FileSystemControl.FsControlCode);
779 Status = STATUS_UNSUCCESSFUL;
780 }
781
782 if (Status != STATUS_PENDING)
783 {
784 Irp->IoStatus.Status = Status;
785
786 IoCompleteRequest(Irp, IO_NO_INCREMENT);
787 }
788
789 return Status;
790 }
791
792
793 NTSTATUS NTAPI
794 NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject,
795 PIRP Irp)
796 {
797 /* FIXME: Implement */
798
799 Irp->IoStatus.Status = STATUS_SUCCESS;
800 Irp->IoStatus.Information = 0;
801
802 IoCompleteRequest(Irp, IO_NO_INCREMENT);
803
804 return STATUS_SUCCESS;
805 }
806
807 /* EOF */