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