2004-05-07 12:13:13 +00:00
|
|
|
/* $Id: rw.c,v 1.14 2004/05/07 12:13:13 navaraf Exp $
|
2000-03-26 22:00:10 +00:00
|
|
|
*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* FILE: services/fs/np/rw.c
|
|
|
|
* PURPOSE: Named pipe filesystem
|
|
|
|
* PROGRAMMER: David Welch <welch@cwcom.net>
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
|
2002-09-08 10:23:54 +00:00
|
|
|
#include <ddk/ntddk.h>
|
2003-11-17 02:12:52 +00:00
|
|
|
#include <rosrtl/minmax.h>
|
2001-05-01 11:09:01 +00:00
|
|
|
#include "npfs.h"
|
2000-03-26 22:00:10 +00:00
|
|
|
|
2004-05-07 12:13:13 +00:00
|
|
|
//#define NDEBUG
|
2001-05-01 11:09:01 +00:00
|
|
|
#include <debug.h>
|
2000-03-26 22:00:10 +00:00
|
|
|
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
2001-05-01 11:09:01 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
2000-03-26 22:00:10 +00:00
|
|
|
{
|
2001-10-21 18:58:32 +00:00
|
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
PFILE_OBJECT FileObject;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PNPFS_DEVICE_EXTENSION DeviceExt;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
ULONG Information;
|
|
|
|
PNPFS_FCB Fcb;
|
2001-11-20 20:35:10 +00:00
|
|
|
PNPFS_FCB ReadFcb;
|
2001-10-21 18:58:32 +00:00
|
|
|
PNPFS_PIPE Pipe;
|
2001-11-20 20:35:10 +00:00
|
|
|
ULONG Length;
|
|
|
|
PVOID Buffer;
|
2001-10-21 18:58:32 +00:00
|
|
|
ULONG CopyLength;
|
2003-06-21 19:55:55 +00:00
|
|
|
ULONG TempLength;
|
2001-10-21 18:58:32 +00:00
|
|
|
|
|
|
|
DPRINT("NpfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
|
2001-11-20 20:35:10 +00:00
|
|
|
|
2001-10-21 18:58:32 +00:00
|
|
|
DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
FileObject = IoStack->FileObject;
|
|
|
|
Fcb = FileObject->FsContext;
|
|
|
|
Pipe = Fcb->Pipe;
|
2001-11-20 20:35:10 +00:00
|
|
|
ReadFcb = Fcb->OtherSide;
|
2001-10-21 18:58:32 +00:00
|
|
|
|
2001-11-20 20:35:10 +00:00
|
|
|
if (ReadFcb == NULL)
|
|
|
|
{
|
|
|
|
DPRINT("Pipe is NOT connected!\n");
|
2004-04-12 13:03:29 +00:00
|
|
|
if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
|
|
|
|
Status = STATUS_PIPE_LISTENING;
|
|
|
|
else if (Fcb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
|
|
|
|
Status = STATUS_PIPE_DISCONNECTED;
|
|
|
|
else
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
2002-05-07 22:41:22 +00:00
|
|
|
Information = 0;
|
2001-11-20 20:35:10 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2001-10-21 18:58:32 +00:00
|
|
|
|
2001-11-20 20:35:10 +00:00
|
|
|
if (Irp->MdlAddress == NULL)
|
|
|
|
{
|
|
|
|
DPRINT("Irp->MdlAddress == NULL\n");
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
2002-05-07 22:41:22 +00:00
|
|
|
Information = 0;
|
2001-11-20 20:35:10 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2003-06-21 19:55:55 +00:00
|
|
|
|
|
|
|
if (ReadFcb->Data == NULL)
|
|
|
|
{
|
|
|
|
DPRINT("Pipe is NOT readable!\n");
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
Information = 0;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2001-10-21 18:58:32 +00:00
|
|
|
|
2001-11-20 20:35:10 +00:00
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
Length = IoStack->Parameters.Read.Length;
|
2002-05-07 22:41:22 +00:00
|
|
|
Information = 0;
|
2001-10-21 18:58:32 +00:00
|
|
|
|
2001-11-20 20:35:10 +00:00
|
|
|
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
|
|
|
|
KeAcquireSpinLock(&ReadFcb->DataListLock, &OldIrql);
|
2002-05-07 22:41:22 +00:00
|
|
|
while (1)
|
2003-06-21 19:55:55 +00:00
|
|
|
{
|
|
|
|
/* FIXME: check if in blocking mode */
|
|
|
|
if (ReadFcb->ReadDataAvailable == 0)
|
|
|
|
{
|
|
|
|
KeResetEvent(&Fcb->Event);
|
|
|
|
KeSetEvent(&ReadFcb->Event, IO_NO_INCREMENT, FALSE);
|
|
|
|
KeReleaseSpinLock(&ReadFcb->DataListLock, OldIrql);
|
|
|
|
if (Information > 0)
|
|
|
|
{
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
|
|
|
|
{
|
2004-04-12 13:03:29 +00:00
|
|
|
DPRINT("PipeState: %x\n", Fcb->PipeState);
|
2003-06-21 19:55:55 +00:00
|
|
|
Status = STATUS_PIPE_BROKEN;
|
|
|
|
goto done;
|
|
|
|
}
|
2004-05-07 12:13:13 +00:00
|
|
|
/* Wait for ReadEvent to become signaled */
|
|
|
|
DPRINT("Waiting for readable data (%S)\n", Pipe->PipeName.Buffer);
|
|
|
|
Status = KeWaitForSingleObject(&Fcb->Event,
|
|
|
|
UserRequest,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
|
|
|
DPRINT("Finished waiting (%S)! Status: %x\n", Pipe->PipeName.Buffer, Status);
|
|
|
|
/*
|
|
|
|
* It's possible that the event was signaled because the
|
|
|
|
* other side of pipe was closed.
|
|
|
|
*/
|
|
|
|
if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
|
|
|
|
{
|
|
|
|
DPRINT("PipeState: %x\n", Fcb->PipeState);
|
|
|
|
Status = STATUS_PIPE_BROKEN;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
KeAcquireSpinLock(&ReadFcb->DataListLock, &OldIrql);
|
2002-05-07 22:41:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Pipe->PipeReadMode == FILE_PIPE_BYTE_STREAM_MODE)
|
2003-06-21 19:55:55 +00:00
|
|
|
{
|
|
|
|
DPRINT("Byte stream mode\n");
|
|
|
|
/* Byte stream mode */
|
|
|
|
while (Length > 0 && ReadFcb->ReadDataAvailable > 0)
|
2002-05-07 22:41:22 +00:00
|
|
|
{
|
2003-11-17 02:12:52 +00:00
|
|
|
CopyLength = RtlRosMin(ReadFcb->ReadDataAvailable, Length);
|
2003-06-21 19:55:55 +00:00
|
|
|
if (ReadFcb->ReadPtr + CopyLength <= ReadFcb->Data + ReadFcb->MaxDataLength)
|
|
|
|
{
|
|
|
|
memcpy(Buffer, ReadFcb->ReadPtr, CopyLength);
|
|
|
|
ReadFcb->ReadPtr += CopyLength;
|
|
|
|
if (ReadFcb->ReadPtr == ReadFcb->Data + ReadFcb->MaxDataLength)
|
|
|
|
{
|
|
|
|
ReadFcb->ReadPtr = ReadFcb->Data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TempLength = ReadFcb->Data + ReadFcb->MaxDataLength - ReadFcb->ReadPtr;
|
|
|
|
memcpy(Buffer, ReadFcb->ReadPtr, TempLength);
|
|
|
|
memcpy(Buffer + TempLength, ReadFcb->Data, CopyLength - TempLength);
|
|
|
|
ReadFcb->ReadPtr = ReadFcb->Data + CopyLength - TempLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
Buffer += CopyLength;
|
|
|
|
Length -= CopyLength;
|
|
|
|
Information += CopyLength;
|
|
|
|
|
|
|
|
ReadFcb->ReadDataAvailable -= CopyLength;
|
|
|
|
ReadFcb->WriteQuotaAvailable += CopyLength;
|
2002-05-07 22:41:22 +00:00
|
|
|
}
|
2001-10-21 18:58:32 +00:00
|
|
|
|
2002-05-07 22:41:22 +00:00
|
|
|
if (Length == 0)
|
2003-06-21 19:55:55 +00:00
|
|
|
{
|
|
|
|
KeSetEvent(&ReadFcb->Event, IO_NO_INCREMENT, FALSE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-05-07 22:41:22 +00:00
|
|
|
else
|
2003-06-21 19:55:55 +00:00
|
|
|
{
|
|
|
|
DPRINT("Message mode\n");
|
2001-10-21 18:58:32 +00:00
|
|
|
|
2003-06-21 19:55:55 +00:00
|
|
|
/* Message mode */
|
|
|
|
if (ReadFcb->ReadDataAvailable)
|
|
|
|
{
|
|
|
|
/* Truncate the message if the receive buffer is too small */
|
2003-11-17 02:12:52 +00:00
|
|
|
CopyLength = RtlRosMin(ReadFcb->ReadDataAvailable, Length);
|
2003-06-21 19:55:55 +00:00
|
|
|
memcpy(Buffer, ReadFcb->Data, CopyLength);
|
2001-10-21 18:58:32 +00:00
|
|
|
|
2004-04-10 16:20:59 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
DPRINT("Length %d Buffer %x\n",CopyLength,Buffer);
|
|
|
|
{
|
|
|
|
DbgPrint("------\n");
|
|
|
|
ULONG X;
|
|
|
|
for (X = 0; X < CopyLength; X++)
|
|
|
|
DbgPrint("%02x ", ((PUCHAR)Buffer)[X]);
|
|
|
|
DbgPrint("\n");
|
|
|
|
DbgPrint("------\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-06-21 19:55:55 +00:00
|
|
|
Information = CopyLength;
|
|
|
|
ReadFcb->ReadDataAvailable = 0;
|
|
|
|
ReadFcb->WriteQuotaAvailable = ReadFcb->MaxDataLength;
|
|
|
|
}
|
|
|
|
if (Information > 0)
|
|
|
|
{
|
|
|
|
KeSetEvent(&ReadFcb->Event, IO_NO_INCREMENT, FALSE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-11-20 20:35:10 +00:00
|
|
|
KeReleaseSpinLock(&ReadFcb->DataListLock, OldIrql);
|
2001-10-21 18:58:32 +00:00
|
|
|
|
2001-11-20 20:35:10 +00:00
|
|
|
done:
|
2001-10-21 18:58:32 +00:00
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
Irp->IoStatus.Information = Information;
|
2001-11-20 20:35:10 +00:00
|
|
|
|
2001-10-21 18:58:32 +00:00
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
2001-11-20 20:35:10 +00:00
|
|
|
|
2001-10-21 18:58:32 +00:00
|
|
|
return(Status);
|
2000-03-26 22:00:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-05-01 11:09:01 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
NpfsWrite(PDEVICE_OBJECT DeviceObject,
|
|
|
|
PIRP Irp)
|
|
|
|
{
|
2001-07-29 16:41:25 +00:00
|
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
PFILE_OBJECT FileObject;
|
|
|
|
PNPFS_FCB Fcb = NULL;
|
|
|
|
PNPFS_PIPE Pipe = NULL;
|
|
|
|
PUCHAR Buffer;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
ULONG Length;
|
|
|
|
ULONG Offset;
|
2001-10-21 18:58:32 +00:00
|
|
|
KIRQL OldIrql;
|
2003-06-21 19:55:55 +00:00
|
|
|
ULONG Information;
|
|
|
|
ULONG CopyLength;
|
|
|
|
ULONG TempLength;
|
2001-05-01 11:09:01 +00:00
|
|
|
|
2001-07-29 16:41:25 +00:00
|
|
|
DPRINT("NpfsWrite()\n");
|
2001-05-01 11:09:01 +00:00
|
|
|
|
2001-07-29 16:41:25 +00:00
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
FileObject = IoStack->FileObject;
|
|
|
|
DPRINT("FileObject %p\n", FileObject);
|
|
|
|
DPRINT("Pipe name %wZ\n", &FileObject->FileName);
|
2001-05-01 11:09:01 +00:00
|
|
|
|
2001-07-29 16:41:25 +00:00
|
|
|
Fcb = FileObject->FsContext;
|
|
|
|
Pipe = Fcb->Pipe;
|
|
|
|
|
|
|
|
Length = IoStack->Parameters.Write.Length;
|
|
|
|
Offset = IoStack->Parameters.Write.ByteOffset.u.LowPart;
|
2003-06-21 19:55:55 +00:00
|
|
|
Information = 0;
|
2001-07-29 16:41:25 +00:00
|
|
|
|
2001-11-20 20:35:10 +00:00
|
|
|
if (Irp->MdlAddress == NULL)
|
|
|
|
{
|
2004-04-12 13:03:29 +00:00
|
|
|
DPRINT("Irp->MdlAddress == NULL\n");
|
2001-11-20 20:35:10 +00:00
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
Length = 0;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Fcb->OtherSide == NULL)
|
|
|
|
{
|
|
|
|
DPRINT("Pipe is NOT connected!\n");
|
2004-04-12 13:03:29 +00:00
|
|
|
if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
|
|
|
|
Status = STATUS_PIPE_LISTENING;
|
|
|
|
else if (Fcb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
|
|
|
|
Status = STATUS_PIPE_DISCONNECTED;
|
|
|
|
else
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
2001-11-20 20:35:10 +00:00
|
|
|
Length = 0;
|
|
|
|
goto done;
|
|
|
|
}
|
2003-06-21 19:55:55 +00:00
|
|
|
|
|
|
|
if (Fcb->Data == NULL)
|
|
|
|
{
|
|
|
|
DPRINT("Pipe is NOT writable!\n");
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
Length = 0;
|
|
|
|
goto done;
|
|
|
|
}
|
2001-11-20 20:35:10 +00:00
|
|
|
|
2003-06-21 19:55:55 +00:00
|
|
|
Status = STATUS_SUCCESS;
|
2001-11-20 20:35:10 +00:00
|
|
|
Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress);
|
2004-04-10 16:20:59 +00:00
|
|
|
#ifndef NDEBUG
|
2001-11-20 20:35:10 +00:00
|
|
|
DPRINT("Length %d Buffer %x Offset %x\n",Length,Buffer,Offset);
|
2004-04-10 16:20:59 +00:00
|
|
|
{
|
|
|
|
DbgPrint("------\n");
|
|
|
|
ULONG X;
|
|
|
|
for (X = 0; X < Length; X++)
|
|
|
|
DbgPrint("%02x ", Buffer[X]);
|
|
|
|
DbgPrint("\n");
|
|
|
|
DbgPrint("------\n");
|
|
|
|
}
|
|
|
|
#endif
|
2001-11-20 20:35:10 +00:00
|
|
|
|
2003-06-21 19:55:55 +00:00
|
|
|
KeAcquireSpinLock(&Fcb->DataListLock, &OldIrql);
|
|
|
|
while(1)
|
2001-11-20 20:35:10 +00:00
|
|
|
{
|
2003-06-21 19:55:55 +00:00
|
|
|
if (Fcb->WriteQuotaAvailable == 0)
|
|
|
|
{
|
|
|
|
KeResetEvent(&Fcb->Event);
|
|
|
|
KeSetEvent(&Fcb->OtherSide->Event, IO_NO_INCREMENT, FALSE);
|
|
|
|
KeReleaseSpinLock(&Fcb->DataListLock, OldIrql);
|
|
|
|
if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
|
|
|
|
{
|
|
|
|
Status = STATUS_PIPE_BROKEN;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
DPRINT("Waiting for buffer space (%S)\n", Pipe->PipeName.Buffer);
|
|
|
|
Status = KeWaitForSingleObject(&Fcb->Event,
|
|
|
|
UserRequest,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
|
|
|
DPRINT("Finished waiting (%S)! Status: %x\n", Pipe->PipeName.Buffer, Status);
|
2004-05-07 12:13:13 +00:00
|
|
|
/*
|
|
|
|
* It's possible that the event was signaled because the
|
|
|
|
* other side of pipe was closed.
|
|
|
|
*/
|
|
|
|
if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
|
|
|
|
{
|
|
|
|
DPRINT("PipeState: %x\n", Fcb->PipeState);
|
|
|
|
Status = STATUS_PIPE_BROKEN;
|
|
|
|
goto done;
|
|
|
|
}
|
2003-06-21 19:55:55 +00:00
|
|
|
KeAcquireSpinLock(&Fcb->DataListLock, &OldIrql);
|
|
|
|
}
|
2004-05-05 18:30:16 +00:00
|
|
|
if (Pipe->PipeWriteMode == FILE_PIPE_BYTE_STREAM_MODE)
|
2003-06-21 19:55:55 +00:00
|
|
|
{
|
|
|
|
DPRINT("Byte stream mode\n");
|
|
|
|
while (Length > 0 && Fcb->WriteQuotaAvailable > 0)
|
|
|
|
{
|
2003-11-17 02:12:52 +00:00
|
|
|
CopyLength = RtlRosMin(Length, Fcb->WriteQuotaAvailable);
|
2003-06-21 19:55:55 +00:00
|
|
|
if (Fcb->WritePtr + CopyLength <= Fcb->Data + Fcb->MaxDataLength)
|
|
|
|
{
|
|
|
|
memcpy(Fcb->WritePtr, Buffer, CopyLength);
|
|
|
|
Fcb->WritePtr += CopyLength;
|
|
|
|
if (Fcb->WritePtr == Fcb->Data + Fcb->MaxDataLength)
|
|
|
|
{
|
|
|
|
Fcb->WritePtr = Fcb->Data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TempLength = Fcb->Data + Fcb->MaxDataLength - Fcb->WritePtr;
|
|
|
|
memcpy(Fcb->WritePtr, Buffer, TempLength);
|
|
|
|
memcpy(Fcb->Data, Buffer + TempLength, CopyLength - TempLength);
|
|
|
|
Fcb->WritePtr = Fcb->Data + CopyLength - TempLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
Buffer += CopyLength;
|
|
|
|
Length -= CopyLength;
|
|
|
|
Information += CopyLength;
|
|
|
|
|
|
|
|
Fcb->ReadDataAvailable += CopyLength;
|
|
|
|
Fcb->WriteQuotaAvailable -= CopyLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Length == 0)
|
|
|
|
{
|
|
|
|
KeSetEvent(&Fcb->OtherSide->Event, IO_NO_INCREMENT, FALSE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Length > 0)
|
|
|
|
{
|
2003-11-17 02:12:52 +00:00
|
|
|
CopyLength = RtlRosMin(Length, Fcb->WriteQuotaAvailable);
|
2004-04-10 16:20:59 +00:00
|
|
|
memcpy(Fcb->Data, Buffer, CopyLength);
|
2003-06-21 19:55:55 +00:00
|
|
|
|
|
|
|
Information = CopyLength;
|
|
|
|
Fcb->ReadDataAvailable = CopyLength;
|
|
|
|
Fcb->WriteQuotaAvailable = 0;
|
|
|
|
}
|
|
|
|
if (Information > 0)
|
|
|
|
{
|
|
|
|
KeSetEvent(&Fcb->OtherSide->Event, IO_NO_INCREMENT, FALSE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2001-11-20 20:35:10 +00:00
|
|
|
}
|
2003-06-21 19:55:55 +00:00
|
|
|
KeReleaseSpinLock(&Fcb->DataListLock, OldIrql);
|
2001-07-29 16:41:25 +00:00
|
|
|
|
2001-11-20 20:35:10 +00:00
|
|
|
done:
|
2001-07-29 16:41:25 +00:00
|
|
|
Irp->IoStatus.Status = Status;
|
2003-06-21 19:55:55 +00:00
|
|
|
Irp->IoStatus.Information = Information;
|
2001-07-29 16:41:25 +00:00
|
|
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
2003-06-21 19:55:55 +00:00
|
|
|
|
2001-07-29 16:41:25 +00:00
|
|
|
return(Status);
|
2001-05-01 11:09:01 +00:00
|
|
|
}
|
|
|
|
|
2000-03-26 22:00:10 +00:00
|
|
|
/* EOF */
|