NPFS read/write functionality.

svn path=/trunk/; revision=2309
This commit is contained in:
Casper Hornstrup 2001-10-21 18:58:32 +00:00
parent 26090a1b08
commit f611cbbe42
5 changed files with 441 additions and 80 deletions

View file

@ -1,4 +1,4 @@
/* $Id: create.c,v 1.9 2001/10/20 15:30:07 ekohl Exp $
/* $Id: create.c,v 1.10 2001/10/21 18:58:31 chorns Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -13,7 +13,7 @@
#include "npfs.h"
//#define NDEBUG
#define NDEBUG
#include <debug.h>
@ -178,7 +178,6 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
{
PIO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject;
NTSTATUS Status = STATUS_SUCCESS;
PNPFS_DEVICE_EXTENSION DeviceExt;
PNPFS_PIPE Pipe;
PNPFS_FCB Fcb;
@ -239,7 +238,13 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
InitializeListHead(&Pipe->ClientFcbListHead);
KeInitializeSpinLock(&Pipe->FcbListLock);
InitializeListHead(&Pipe->ServerDataListHead);
KeInitializeSpinLock(&Pipe->ServerDataListLock);
InitializeListHead(&Pipe->ClientDataListHead);
KeInitializeSpinLock(&Pipe->ClientDataListLock);
Pipe->PipeType = Buffer->WriteModeMessage;
Pipe->PipeWriteMode = Buffer->WriteModeMessage;
Pipe->PipeReadMode = Buffer->ReadModeMessage;
Pipe->PipeBlockMode = Buffer->NonBlocking;
Pipe->PipeConfiguration = IoStack->Parameters.Create.Options & 0x3;
@ -300,12 +305,12 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
FileObject->FsContext = Fcb;
Irp->IoStatus.Status = Status;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(Status);
return(STATUS_SUCCESS);
}

View file

@ -1,4 +1,4 @@
/* $Id: fsctrl.c,v 1.6 2001/10/20 15:30:07 ekohl Exp $
/* $Id: fsctrl.c,v 1.7 2001/10/21 18:58:31 chorns Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -13,7 +13,7 @@
#include <ddk/ntddk.h>
#include "npfs.h"
//#define NDEBUG
#define NDEBUG
#include <debug.h>
@ -203,6 +203,154 @@ NpfsWaitPipe(PIRP Irp,
}
static NTSTATUS
NpfsGetState(
PIRP Irp,
PIO_STACK_LOCATION IrpSp)
/*
* FUNCTION: Return current state of a pipe
* ARGUMENTS:
* Irp = Pointer to I/O request packet
* IrpSp = Pointer to current stack location of Irp
* RETURNS:
* Status of operation
*/
{
ULONG OutputBufferLength;
PNPFS_GET_STATE Reply;
NTSTATUS Status;
PNPFS_PIPE Pipe;
PNPFS_FCB Fcb;
OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
/* Validate parameters */
if (OutputBufferLength >= sizeof(NPFS_GET_STATE))
{
Fcb = IrpSp->FileObject->FsContext;
Reply = (PNPFS_GET_STATE)Irp->AssociatedIrp.SystemBuffer;
Pipe = Fcb->Pipe;
if (Pipe->PipeWriteMode == FILE_PIPE_MESSAGE_MODE)
{
Reply->WriteModeMessage = TRUE;
}
else
{
Reply->WriteModeMessage = FALSE;
}
if (Pipe->PipeReadMode == FILE_PIPE_MESSAGE_MODE)
{
Reply->ReadModeMessage = TRUE;
}
else
{
Reply->ReadModeMessage = FALSE;
}
if (Pipe->PipeBlockMode == FILE_PIPE_QUEUE_OPERATION)
{
Reply->NonBlocking = TRUE;
}
else
{
Reply->NonBlocking = FALSE;
}
Reply->InBufferSize = Pipe->InboundQuota;
Reply->OutBufferSize = Pipe->OutboundQuota;
Reply->Timeout = Pipe->TimeOut;
Status = STATUS_SUCCESS;
}
else
{
Status = STATUS_INVALID_PARAMETER;
}
DPRINT("Status (0x%X).\n", Status);
return Status;
}
static NTSTATUS
NpfsSetState(
PIRP Irp,
PIO_STACK_LOCATION IrpSp)
/*
* FUNCTION: Set state of a pipe
* ARGUMENTS:
* Irp = Pointer to I/O request packet
* IrpSp = Pointer to current stack location of Irp
* RETURNS:
* Status of operation
*/
{
ULONG InputBufferLength;
PNPFS_SET_STATE Request;
PNPFS_PIPE Pipe;
NTSTATUS Status;
PNPFS_FCB Fcb;
InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
/* Validate parameters */
if (InputBufferLength >= sizeof(NPFS_SET_STATE))
{
Fcb = IrpSp->FileObject->FsContext;
Request = (PNPFS_SET_STATE)Irp->AssociatedIrp.SystemBuffer;
Pipe = Fcb->Pipe;
if (Request->WriteModeMessage)
{
Pipe->PipeWriteMode = FILE_PIPE_MESSAGE_MODE;
}
else
{
Pipe->PipeWriteMode = FILE_PIPE_BYTE_STREAM_MODE;
}
if (Request->ReadModeMessage)
{
Pipe->PipeReadMode = FILE_PIPE_MESSAGE_MODE;
}
else
{
Pipe->PipeReadMode = FILE_PIPE_BYTE_STREAM_MODE;
}
if (Request->NonBlocking)
{
Pipe->PipeBlockMode = FILE_PIPE_QUEUE_OPERATION;
}
else
{
Pipe->PipeBlockMode = FILE_PIPE_COMPLETE_OPERATION;
}
Pipe->InboundQuota = Request->InBufferSize;
Pipe->OutboundQuota = Request->OutBufferSize;
Pipe->TimeOut = Request->Timeout;
Status = STATUS_SUCCESS;
}
else
{
Status = STATUS_INVALID_PARAMETER;
}
DPRINT("Status (0x%X).\n", Status);
return Status;
}
NTSTATUS STDCALL
NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
@ -229,9 +377,9 @@ NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
switch (IoStack->Parameters.FileSystemControl.IoControlCode)
{
case FSCTL_PIPE_LISTEN:
DPRINT("Connecting pipe %wZ\n", &Pipe->PipeName);
Status = NpfsConnectPipe(Fcb);
case FSCTL_PIPE_ASSIGN_EVENT:
DPRINT("Assign event\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case FSCTL_PIPE_DISCONNECT:
@ -239,11 +387,76 @@ NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
Status = NpfsDisconnectPipe(Fcb);
break;
case FSCTL_PIPE_LISTEN:
DPRINT("Connecting pipe %wZ\n", &Pipe->PipeName);
Status = NpfsConnectPipe(Fcb);
break;
case FSCTL_PIPE_PEEK:
DPRINT("Peek\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case FSCTL_PIPE_QUERY_EVENT:
DPRINT("Query event\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case FSCTL_PIPE_TRANSCEIVE:
DPRINT("Transceive\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case FSCTL_PIPE_WAIT:
DPRINT("Waiting for pipe %wZ\n", &Pipe->PipeName);
Status = NpfsWaitPipe(Irp, Fcb);
break;
case FSCTL_PIPE_IMPERSONATE:
DPRINT("Impersonate\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case FSCTL_PIPE_SET_CLIENT_PROCESS:
DPRINT("Set client process\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
DPRINT("Query client process\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case FSCTL_PIPE_GET_STATE:
DPRINT("Get state\n");
Status = NpfsGetState(Irp, IoStack);
break;
case FSCTL_PIPE_SET_STATE:
DPRINT("Set state\n");
Status = NpfsSetState(Irp, IoStack);
break;
case FSCTL_PIPE_INTERNAL_READ:
DPRINT("Internal read\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case FSCTL_PIPE_INTERNAL_WRITE:
DPRINT("Internal write\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
DPRINT("Internal transceive\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
DPRINT("Internal read overflow\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
default:
DPRINT("IoControlCode: %x\n", IoStack->Parameters.FileSystemControl.IoControlCode)
Status = STATUS_UNSUCCESSFUL;

View file

@ -1,4 +1,4 @@
/* $Id: npfs.c,v 1.1 2001/07/29 16:40:20 ekohl Exp $
/* $Id: npfs.c,v 1.2 2001/10/21 18:58:31 chorns Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -12,9 +12,10 @@
#include <ddk/ntddk.h>
#include "npfs.h"
//#define NDEBUG
#define NDEBUG
#include <debug.h>
NPAGED_LOOKASIDE_LIST NpfsPipeDataLookasideList;
/* FUNCTIONS *****************************************************************/
@ -75,6 +76,15 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
KeInitializeMutex(&DeviceExtension->PipeListLock,
0);
ExInitializeNPagedLookasideList(
&NpfsPipeDataLookasideList,
NULL,
NULL,
0,
sizeof(NPFS_PIPE_DATA),
TAG('N', 'P', 'D', 'A'),
0);
return(STATUS_SUCCESS);
}

View file

@ -8,6 +8,14 @@ typedef struct
KMUTEX PipeListLock;
} NPFS_DEVICE_EXTENSION, *PNPFS_DEVICE_EXTENSION;
typedef struct
{
LIST_ENTRY ListEntry;
ULONG Size;
PVOID Data;
ULONG Offset;
} NPFS_PIPE_DATA, *PNPFS_PIPE_DATA;
typedef struct
{
UNICODE_STRING PipeName;
@ -15,9 +23,16 @@ typedef struct
KSPIN_LOCK FcbListLock;
LIST_ENTRY ServerFcbListHead;
LIST_ENTRY ClientFcbListHead;
/* Server posted data */
LIST_ENTRY ServerDataListHead;
KSPIN_LOCK ServerDataListLock;
/* Client posted data */
LIST_ENTRY ClientDataListHead;
KSPIN_LOCK ClientDataListLock;
ULONG ReferenceCount;
ULONG PipeType;
ULONG PipeReadMode;
ULONG PipeWriteMode;
ULONG PipeBlockMode;
ULONG PipeConfiguration;
ULONG MaximumInstances;
@ -40,6 +55,9 @@ typedef struct _NPFS_FCB
} NPFS_FCB, *PNPFS_FCB;
extern NPAGED_LOOKASIDE_LIST NpfsPipeDataLookasideList;
#define KeLockMutex(x) KeWaitForSingleObject(x, \
UserRequest, \
KernelMode, \
@ -48,6 +66,8 @@ typedef struct _NPFS_FCB
#define KeUnlockMutex(x) KeReleaseMutex(x, FALSE);
#define CP DPRINT("\n");
NTSTATUS STDCALL NpfsCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL NpfsClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);

View file

@ -1,4 +1,4 @@
/* $Id: rw.c,v 1.3 2001/07/29 16:40:20 ekohl Exp $
/* $Id: rw.c,v 1.4 2001/10/21 18:58:32 chorns Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -12,12 +12,71 @@
#include <ddk/ntddk.h>
#include "npfs.h"
//#define NDEBUG
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
static inline VOID NpfsFreePipeData(
PNPFS_PIPE_DATA PipeData)
{
if (PipeData->Data)
{
ExFreePool(PipeData->Data);
}
ExFreeToNPagedLookasideList(&NpfsPipeDataLookasideList, PipeData);
}
static inline PNPFS_PIPE_DATA
NpfsAllocatePipeData(
PVOID Data,
ULONG Size)
{
PNPFS_PIPE_DATA PipeData;
PipeData = ExAllocateFromNPagedLookasideList(&NpfsPipeDataLookasideList);
if (!PipeData)
{
return NULL;
}
PipeData->Data = Data;
PipeData->Size = Size;
PipeData->Offset = 0;
return PipeData;
}
static inline PNPFS_PIPE_DATA
NpfsInitializePipeData(
PVOID Data,
ULONG Size)
{
PNPFS_PIPE_DATA PipeData;
PVOID Buffer;
Buffer = ExAllocatePool(NonPagedPool, Size);
if (!Buffer)
{
return NULL;
}
RtlMoveMemory(Buffer, Data, Size);
PipeData = NpfsAllocatePipeData(Buffer, Size);
if (!PipeData)
{
ExFreePool(Buffer);
}
return PipeData;
}
NTSTATUS STDCALL
NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
@ -26,56 +85,92 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
NTSTATUS Status;
PNPFS_DEVICE_EXTENSION DeviceExt;
PWSTR PipeName;
// PNPFS_FSCONTEXT PipeDescr;
KIRQL oldIrql;
PLIST_ENTRY current_entry;
// PNPFS_CONTEXT current;
KIRQL OldIrql;
PLIST_ENTRY CurrentEntry;
PNPFS_PIPE_DATA Current;
ULONG Information;
PNPFS_FCB Fcb;
PNPFS_PIPE Pipe;
ULONG Length;
PVOID Buffer;
ULONG CopyLength;
DPRINT1("NpfsRead()\n");
DPRINT("NpfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
IoStack = IoGetCurrentIrpStackLocation(Irp);
FileObject = IoStack->FileObject;
Fcb = FileObject->FsContext;
Pipe = Fcb->Pipe;
Status = STATUS_SUCCESS;
Information = 0;
#if 0
PipeDescr = FileObject->FsContext;
if (PipeType & NPFS_READMODE_BYTE)
{
PLIST_ENTRY current_entry;
PNPFS_MSG current;
KIRQL oldIrql;
ULONG Length;
PVOID Buffer;
KeAcquireSpinLock(&PipeDescr->MsgListLock, &oldIrql);
current_entry = PipeDescr->MsgListHead.Flink;
Information = 0;
Length = IoStack->Parameters.Read.Length;
DPRINT("Irp->MdlAddress %p\n", Irp->MdlAddress);
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
while (Length > 0 &&
current_entry != &PipeDescr->MsgListHead)
KeAcquireSpinLock(&Pipe->ServerDataListLock, &OldIrql);
if (Pipe->PipeReadMode & FILE_PIPE_BYTE_STREAM_MODE)
{
current = CONTAINING_RECORD(current_entry,
NPFS_MSG,
ListEntry);
DPRINT("Byte stream mode\n");
memcpy(Buffer, current->Buffer, current->Length);
Buffer = Buffer + current->Length;
Length = Length - current->Length;
Information = Information + current->Length;
/* Byte stream mode */
Information = 0;
CurrentEntry = Pipe->ServerDataListHead.Flink;
while ((Length > 0) && (CurrentEntry = RemoveHeadList(&Pipe->ServerDataListHead)))
{
Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry);
current_entry = current_entry->Flink;
DPRINT("Took pipe data at %p off the queue\n", Current);
CopyLength = RtlMin(Current->Size, Length);
RtlCopyMemory(Buffer,
((PVOID)((ULONG_PTR)Current->Data + Current->Offset)),
CopyLength);
Buffer += CopyLength;
Length -= CopyLength;
Information += CopyLength;
/* Update the data buffer */
Current->Offset += CopyLength;
Current->Size -= CopyLength;
CurrentEntry = CurrentEntry->Flink;
}
if ((CurrentEntry != &Pipe->ServerDataListHead) && (Current->Offset != Current->Size))
{
DPRINT("Putting pipe data at %p back in queue\n", Current);
/* The caller's buffer could not contain the complete message,
so put it back on the queue */
InsertHeadList(&Pipe->ServerDataListHead, &Current->ListEntry);
}
}
else
{
DPRINT("Message mode\n");
/* Message mode */
CurrentEntry = Pipe->ServerDataListHead.Flink;
if (CurrentEntry = RemoveHeadList(&Pipe->ServerDataListHead))
{
Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry);
DPRINT("Took pipe data at %p off the queue\n", Current);
/* Truncate the message if the receive buffer is too small */
CopyLength = RtlMin(Current->Size, Length);
RtlCopyMemory(Buffer, Current->Data, CopyLength);
Information = CopyLength;
Current->Offset += CopyLength;
CurrentEntry = CurrentEntry->Flink;
}
#endif
}
KeReleaseSpinLock(&Pipe->ServerDataListLock, OldIrql);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Information;
@ -98,6 +193,8 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
NTSTATUS Status = STATUS_SUCCESS;
ULONG Length;
ULONG Offset;
KIRQL OldIrql;
PNPFS_PIPE_DATA PipeData;
DPRINT("NpfsWrite()\n");
@ -113,6 +210,22 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress);
Offset = IoStack->Parameters.Write.ByteOffset.u.LowPart;
PipeData = NpfsInitializePipeData(Buffer, Length);
if (PipeData)
{
DPRINT("Attaching pipe data at %p (%d bytes)\n", PipeData, Length);
KeAcquireSpinLock(&Pipe->ServerDataListLock, &OldIrql);
InsertTailList(&Pipe->ServerDataListHead, &PipeData->ListEntry);
KeReleaseSpinLock(&Pipe->ServerDataListLock, OldIrql);
}
else
{
Length = 0;
Status = STATUS_INSUFFICIENT_RESOURCES;
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Length;