diff --git a/reactos/drivers/fs/np/create.c b/reactos/drivers/fs/np/create.c index d3379a04a99..5a819346b43 100644 --- a/reactos/drivers/fs/np/create.c +++ b/reactos/drivers/fs/np/create.c @@ -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 @@ -45,7 +45,7 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject, Disposition = ((IoStack->Parameters.Create.Options >> 24) & 0xff); DPRINT("FileObject %p\n", FileObject); DPRINT("FileName %wZ\n", &FileObject->FileName); - + ClientFcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB)); if (ClientFcb == NULL) { @@ -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; @@ -238,8 +237,14 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject, InitializeListHead(&Pipe->ServerFcbListHead); 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); } diff --git a/reactos/drivers/fs/np/fsctrl.c b/reactos/drivers/fs/np/fsctrl.c index 915737b0f88..24d225da6d9 100644 --- a/reactos/drivers/fs/np/fsctrl.c +++ b/reactos/drivers/fs/np/fsctrl.c @@ -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 #include "npfs.h" -//#define NDEBUG +#define NDEBUG #include @@ -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,20 +377,85 @@ NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject, switch (IoStack->Parameters.FileSystemControl.IoControlCode) { - case FSCTL_PIPE_LISTEN: - DPRINT("Connecting pipe %wZ\n", &Pipe->PipeName); - Status = NpfsConnectPipe(Fcb); - break; + case FSCTL_PIPE_ASSIGN_EVENT: + DPRINT("Assign event\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; case FSCTL_PIPE_DISCONNECT: - DPRINT("Disconnecting pipe %wZ\n", &Pipe->PipeName); - Status = NpfsDisconnectPipe(Fcb); - break; + DPRINT("Disconnecting pipe %wZ\n", &Pipe->PipeName); + 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; + 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) diff --git a/reactos/drivers/fs/np/npfs.c b/reactos/drivers/fs/np/npfs.c index cb884cf8ffd..ef487dd7b03 100644 --- a/reactos/drivers/fs/np/npfs.c +++ b/reactos/drivers/fs/np/npfs.c @@ -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 #include "npfs.h" -//#define NDEBUG +#define NDEBUG #include +NPAGED_LOOKASIDE_LIST NpfsPipeDataLookasideList; /* FUNCTIONS *****************************************************************/ @@ -74,7 +75,16 @@ DriverEntry(PDRIVER_OBJECT DriverObject, InitializeListHead(&DeviceExtension->PipeListHead); KeInitializeMutex(&DeviceExtension->PipeListLock, 0); - + + ExInitializeNPagedLookasideList( + &NpfsPipeDataLookasideList, + NULL, + NULL, + 0, + sizeof(NPFS_PIPE_DATA), + TAG('N', 'P', 'D', 'A'), + 0); + return(STATUS_SUCCESS); } diff --git a/reactos/drivers/fs/np/npfs.h b/reactos/drivers/fs/np/npfs.h index 67a5208f19d..12380a3f04f 100644 --- a/reactos/drivers/fs/np/npfs.h +++ b/reactos/drivers/fs/np/npfs.h @@ -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); diff --git a/reactos/drivers/fs/np/rw.c b/reactos/drivers/fs/np/rw.c index a166f653e09..21882b34c7e 100644 --- a/reactos/drivers/fs/np/rw.c +++ b/reactos/drivers/fs/np/rw.c @@ -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,77 +12,172 @@ #include #include "npfs.h" -//#define NDEBUG +#define NDEBUG #include /* 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) { - PIO_STACK_LOCATION IoStack; - PFILE_OBJECT FileObject; - NTSTATUS Status; - PNPFS_DEVICE_EXTENSION DeviceExt; - PWSTR PipeName; -// PNPFS_FSCONTEXT PipeDescr; - KIRQL oldIrql; - PLIST_ENTRY current_entry; -// PNPFS_CONTEXT current; - ULONG Information; - - DPRINT1("NpfsRead()\n"); - - DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - IoStack = IoGetCurrentIrpStackLocation(Irp); - FileObject = IoStack->FileObject; - - Status = STATUS_SUCCESS; - Information = 0; - -#if 0 - PipeDescr = FileObject->FsContext; - - if (PipeType & NPFS_READMODE_BYTE) - { - PLIST_ENTRY current_entry; - PNPFS_MSG current; - KIRQL oldIrql; + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + NTSTATUS Status; + PNPFS_DEVICE_EXTENSION DeviceExt; + PWSTR PipeName; + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PNPFS_PIPE_DATA Current; + ULONG Information; + PNPFS_FCB Fcb; + PNPFS_PIPE Pipe; ULONG Length; PVOID Buffer; - - KeAcquireSpinLock(&PipeDescr->MsgListLock, &oldIrql); - current_entry = PipeDescr->MsgListHead.Flink; - Information = 0; - Length = IoStack->Parameters.Read.Length; - Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); - while (Length > 0 && - current_entry != &PipeDescr->MsgListHead) + ULONG CopyLength; + + 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; + Length = IoStack->Parameters.Read.Length; + + DPRINT("Irp->MdlAddress %p\n", Irp->MdlAddress); + + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + KeAcquireSpinLock(&Pipe->ServerDataListLock, &OldIrql); + + if (Pipe->PipeReadMode & FILE_PIPE_BYTE_STREAM_MODE) + { + DPRINT("Byte stream mode\n"); + + /* Byte stream mode */ + Information = 0; + CurrentEntry = Pipe->ServerDataListHead.Flink; + while ((Length > 0) && (CurrentEntry = RemoveHeadList(&Pipe->ServerDataListHead))) { - current = CONTAINING_RECORD(current_entry, - NPFS_MSG, - ListEntry); - - memcpy(Buffer, current->Buffer, current->Length); - Buffer = Buffer + current->Length; - Length = Length - current->Length; - Information = Information + current->Length; - - current_entry = current_entry->Flink; + Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry); + + 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; } - } - else - { - } -#endif + + 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; + } + } + + KeReleaseSpinLock(&Pipe->ServerDataListLock, OldIrql); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = Information; + IoCompleteRequest(Irp, IO_NO_INCREMENT); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return(Status); + return(Status); } @@ -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;