From 5f56974966c11444af267c6de44fd4d460a33148 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Tue, 20 Nov 2001 20:35:10 +0000 Subject: [PATCH] Implemented read/write. svn path=/trunk/; revision=2383 --- reactos/drivers/fs/np/create.c | 33 +++-- reactos/drivers/fs/np/finfo.c | 224 +++++++++++++++++------------- reactos/drivers/fs/np/fsctrl.c | 202 ++++++++++++++++----------- reactos/drivers/fs/np/npfs.c | 6 +- reactos/drivers/fs/np/npfs.h | 62 ++++----- reactos/drivers/fs/np/rw.c | 222 ++++++++++++++++++----------- reactos/include/napi/npipe.h | 8 ++ reactos/lib/kernel32/file/npipe.c | 207 +++++++++++++++++++++------ 8 files changed, 617 insertions(+), 347 deletions(-) diff --git a/reactos/drivers/fs/np/create.c b/reactos/drivers/fs/np/create.c index 5a819346b43..382fcf4fadc 100644 --- a/reactos/drivers/fs/np/create.c +++ b/reactos/drivers/fs/np/create.c @@ -1,4 +1,4 @@ -/* $Id: create.c,v 1.10 2001/10/21 18:58:31 chorns Exp $ +/* $Id: create.c,v 1.11 2001/11/20 20:34:29 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -53,6 +53,7 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject, Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); + DPRINT("No memory!\n"); return(STATUS_NO_MEMORY); } @@ -96,10 +97,18 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject, ClientFcb->OtherSide = NULL; ClientFcb->PipeState = FILE_PIPE_DISCONNECTED_STATE; + /* initialize data list */ + InitializeListHead(&ClientFcb->DataListHead); + KeInitializeSpinLock(&ClientFcb->DataListLock); + KeInitializeEvent(&ClientFcb->ConnectEvent, SynchronizationEvent, FALSE); + KeInitializeEvent(&ClientFcb->ReadEvent, + SynchronizationEvent, + FALSE); + KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql); InsertTailList(&Pipe->ClientFcbListHead, &ClientFcb->FcbListEntry); KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql); @@ -108,7 +117,8 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject, KeUnlockMutex(&DeviceExt->PipeListLock); - if (Disposition == FILE_OPEN) +#if 0 + if (Disposition == OPEN_EXISTING) { /* do not connect to listening servers */ FileObject->FsContext = ClientFcb; @@ -117,9 +127,11 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject, Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); + DPRINT("Success!\n"); return(STATUS_SUCCESS); } +#endif /* search for disconnected or listening server fcb */ current_entry = Pipe->ServerFcbListHead.Flink; @@ -167,6 +179,7 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject, Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); + DPRINT("Success!\n"); return(STATUS_SUCCESS); } @@ -238,11 +251,6 @@ 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; @@ -294,13 +302,20 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject, Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE; Fcb->ReadDataAvailable = 0; Fcb->WriteQuotaAvailable = 0; -// Fcb->InBuffer = NULL; -// Fcb->OutBuffer = NULL; + + /* initialize data list */ + InitializeListHead(&Fcb->DataListHead); + KeInitializeSpinLock(&Fcb->DataListLock); KeInitializeEvent(&Fcb->ConnectEvent, SynchronizationEvent, FALSE); + KeInitializeEvent(&Fcb->ReadEvent, + SynchronizationEvent, + FALSE); + + KeUnlockMutex(&DeviceExt->PipeListLock); FileObject->FsContext = Fcb; diff --git a/reactos/drivers/fs/np/finfo.c b/reactos/drivers/fs/np/finfo.c index e512c360bc7..549987e47de 100644 --- a/reactos/drivers/fs/np/finfo.c +++ b/reactos/drivers/fs/np/finfo.c @@ -1,4 +1,4 @@ -/* $Id: finfo.c,v 1.2 2001/07/29 16:40:20 ekohl Exp $ +/* $Id: finfo.c,v 1.3 2001/11/20 20:34:29 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -12,7 +12,7 @@ #include #include "npfs.h" -//#define NDEBUG +#define NDEBUG #include @@ -21,14 +21,37 @@ /* FUNCTIONS *****************************************************************/ static NTSTATUS -NpfsQueryLocalInformation(PDEVICE_OBJECT DeviceObject, - PNPFS_FCB Fcb, - PFILE_PIPE_LOCAL_INFORMATION Info, - PULONG BufferLength) +NpfsQueryPipeInformation(PDEVICE_OBJECT DeviceObject, + PNPFS_FCB Fcb, + PFILE_PIPE_INFORMATION Info, + PULONG BufferLength) { PNPFS_PIPE Pipe; - DPRINT("NpfsQueryLocalInformation()\n"); + DPRINT("NpfsQueryPipeInformation()\n"); + + Pipe = Fcb->Pipe; + + RtlZeroMemory(Info, + sizeof(FILE_PIPE_INFORMATION)); + +// Info->PipeMode = +// Info->CompletionMode = + + *BufferLength -= sizeof(FILE_PIPE_INFORMATION); + return(STATUS_SUCCESS); +} + + +static NTSTATUS +NpfsQueryLocalPipeInformation(PDEVICE_OBJECT DeviceObject, + PNPFS_FCB Fcb, + PFILE_PIPE_LOCAL_INFORMATION Info, + PULONG BufferLength) +{ + PNPFS_PIPE Pipe; + + DPRINT("NpfsQueryLocalPipeInformation()\n"); Pipe = Fcb->Pipe; @@ -64,63 +87,66 @@ NTSTATUS STDCALL NpfsQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp) { - PIO_STACK_LOCATION IoStack; - FILE_INFORMATION_CLASS FileInformationClass; - PFILE_OBJECT FileObject; - PNPFS_DEVICE_EXTENSION DeviceExtension; - PNPFS_FCB Fcb; - PNPFS_PIPE Pipe; - PVOID SystemBuffer; - ULONG BufferLength; - NTSTATUS Status; - - DPRINT("NpfsQueryInformation(DeviceObject %p Irp %p)\n", DeviceObject, Irp); - - IoStack = IoGetCurrentIrpStackLocation (Irp); - FileInformationClass = IoStack->Parameters.QueryFile.FileInformationClass; - DeviceExtension = DeviceObject->DeviceExtension; - FileObject = IoStack->FileObject; - Fcb = (PNPFS_FCB)FileObject->FsContext; - Pipe = Fcb->Pipe; - - SystemBuffer = Irp->AssociatedIrp.SystemBuffer; - BufferLength = IoStack->Parameters.QueryFile.Length; - - DPRINT("Pipe name: %wZ\n", &Pipe->PipeName); - DPRINT("FileInformationClass %d\n", FileInformationClass); - DPRINT("SystemBuffer %x\n", SystemBuffer); - DPRINT("BufferLength %lu\n", BufferLength); - - switch (FileInformationClass) - { - case FilePipeInformation: + PIO_STACK_LOCATION IoStack; + FILE_INFORMATION_CLASS FileInformationClass; + PFILE_OBJECT FileObject; + PNPFS_DEVICE_EXTENSION DeviceExtension; + PNPFS_FCB Fcb; + PNPFS_PIPE Pipe; + PVOID SystemBuffer; + ULONG BufferLength; + NTSTATUS Status; + + DPRINT("NpfsQueryInformation(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation (Irp); + FileInformationClass = IoStack->Parameters.QueryFile.FileInformationClass; + DeviceExtension = DeviceObject->DeviceExtension; + FileObject = IoStack->FileObject; + Fcb = (PNPFS_FCB)FileObject->FsContext; + Pipe = Fcb->Pipe; + + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + BufferLength = IoStack->Parameters.QueryFile.Length; + + DPRINT("Pipe name: %wZ\n", &Pipe->PipeName); + DPRINT("FileInformationClass %d\n", FileInformationClass); + DPRINT("SystemBuffer %p\n", SystemBuffer); + DPRINT("BufferLength %lu\n", BufferLength); + + switch (FileInformationClass) + { + case FilePipeInformation: + Status = NpfsQueryPipeInformation(DeviceObject, + Fcb, + SystemBuffer, + &BufferLength); + break; + + case FilePipeLocalInformation: + Status = NpfsQueryLocalPipeInformation(DeviceObject, + Fcb, + SystemBuffer, + &BufferLength); + break; + + case FilePipeRemoteInformation: Status = STATUS_NOT_IMPLEMENTED; break; - case FilePipeLocalInformation: - Status = NpfsQueryLocalInformation(DeviceObject, - Fcb, - SystemBuffer, - &BufferLength); - break; - - case FilePipeRemoteInformation: - Status = STATUS_NOT_IMPLEMENTED; - break; - - default: + default: Status = STATUS_NOT_SUPPORTED; - } - - Irp->IoStatus.Status = Status; - if (NT_SUCCESS(Status)) - Irp->IoStatus.Information = - IoStack->Parameters.QueryFile.Length - BufferLength; - else - Irp->IoStatus.Information = 0; - IoCompleteRequest (Irp, IO_NO_INCREMENT); - - return(Status); + } + + Irp->IoStatus.Status = Status; + if (NT_SUCCESS(Status)) + Irp->IoStatus.Information = + IoStack->Parameters.QueryFile.Length - BufferLength; + else + Irp->IoStatus.Information = 0; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return(Status); } @@ -128,52 +154,52 @@ NTSTATUS STDCALL NpfsSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp) { - PIO_STACK_LOCATION IoStack; - FILE_INFORMATION_CLASS FileInformationClass; - PFILE_OBJECT FileObject; - PNPFS_FCB Fcb; - PNPFS_PIPE Pipe; - PVOID SystemBuffer; - ULONG BufferLength; - NTSTATUS Status; - - DPRINT("NpfsSetInformation(DeviceObject %p Irp %p)\n", DeviceObject, Irp); - - IoStack = IoGetCurrentIrpStackLocation (Irp); - FileInformationClass = IoStack->Parameters.QueryFile.FileInformationClass; - FileObject = IoStack->FileObject; - Fcb = (PNPFS_FCB)FileObject->FsContext; - Pipe = Fcb->Pipe; - - SystemBuffer = Irp->AssociatedIrp.SystemBuffer; - BufferLength = IoStack->Parameters.QueryFile.Length; - - DPRINT("Pipe name: %wZ\n", &Pipe->PipeName); - DPRINT("FileInformationClass %d\n", FileInformationClass); - DPRINT("SystemBuffer %x\n", SystemBuffer); - DPRINT("BufferLength %lu\n", BufferLength); - - switch (FileInformationClass) - { - case FilePipeInformation: + PIO_STACK_LOCATION IoStack; + FILE_INFORMATION_CLASS FileInformationClass; + PFILE_OBJECT FileObject; + PNPFS_FCB Fcb; + PNPFS_PIPE Pipe; + PVOID SystemBuffer; + ULONG BufferLength; + NTSTATUS Status; + + DPRINT("NpfsSetInformation(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation (Irp); + FileInformationClass = IoStack->Parameters.QueryFile.FileInformationClass; + FileObject = IoStack->FileObject; + Fcb = (PNPFS_FCB)FileObject->FsContext; + Pipe = Fcb->Pipe; + + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + BufferLength = IoStack->Parameters.QueryFile.Length; + + DPRINT("Pipe name: %wZ\n", &Pipe->PipeName); + DPRINT("FileInformationClass %d\n", FileInformationClass); + DPRINT("SystemBuffer %p\n", SystemBuffer); + DPRINT("BufferLength %lu\n", BufferLength); + + switch (FileInformationClass) + { + case FilePipeInformation: Status = STATUS_NOT_IMPLEMENTED; break; - case FilePipeLocalInformation: + case FilePipeLocalInformation: Status = STATUS_NOT_IMPLEMENTED; break; - case FilePipeRemoteInformation: + case FilePipeRemoteInformation: Status = STATUS_NOT_IMPLEMENTED; break; - default: + default: Status = STATUS_NOT_SUPPORTED; - } - - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, - IO_NO_INCREMENT); - - return(Status); + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(Status); } /* EOF */ diff --git a/reactos/drivers/fs/np/fsctrl.c b/reactos/drivers/fs/np/fsctrl.c index 24d225da6d9..a4f60e40e8a 100644 --- a/reactos/drivers/fs/np/fsctrl.c +++ b/reactos/drivers/fs/np/fsctrl.c @@ -1,4 +1,4 @@ -/* $Id: fsctrl.c,v 1.7 2001/10/21 18:58:31 chorns Exp $ +/* $Id: fsctrl.c,v 1.8 2001/11/20 20:34:29 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -351,123 +351,163 @@ NpfsSetState( } +static NTSTATUS +NpfsPeekPipe(PIRP Irp, + PIO_STACK_LOCATION IoStack) +/* + * FUNCTION: Peek at a pipe (get information about messages) + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IoStack = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + ULONG OutputBufferLength; + PNPFS_PIPE Pipe; + PFILE_PIPE_PEEK_BUFFER Reply; + PNPFS_FCB Fcb; + NTSTATUS Status; + + DPRINT("NpfsPeekPipe\n"); + + OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + if (OutputBufferLength < sizeof(FILE_PIPE_PEEK_BUFFER)) + { + DPRINT("Buffer too small\n"); + return(STATUS_INVALID_PARAMETER); + } + + Fcb = IoStack->FileObject->FsContext; + Reply = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer; + Pipe = Fcb->Pipe; + + Status = STATUS_NOT_IMPLEMENTED; + + return(Status); +} + + + NTSTATUS STDCALL NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { - PIO_STACK_LOCATION IoStack; - PFILE_OBJECT FileObject; - NTSTATUS Status; - PNPFS_DEVICE_EXTENSION DeviceExt; - PNPFS_PIPE Pipe; - PNPFS_FCB Fcb; - - DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp); - - DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - IoStack = IoGetCurrentIrpStackLocation(Irp); - DPRINT("IoStack: %p\n", IoStack); - FileObject = IoStack->FileObject; - DPRINT("FileObject: %p\n", FileObject); - Fcb = FileObject->FsContext; - DPRINT("Fcb: %p\n", Fcb); - Pipe = Fcb->Pipe; - DPRINT("Pipe: %p\n", Pipe); - DPRINT("PipeName: %wZ\n", &Pipe->PipeName); - - switch (IoStack->Parameters.FileSystemControl.IoControlCode) - { + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + NTSTATUS Status; + PNPFS_DEVICE_EXTENSION DeviceExt; + PNPFS_PIPE Pipe; + PNPFS_FCB Fcb; + + DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + IoStack = IoGetCurrentIrpStackLocation(Irp); + DPRINT("IoStack: %p\n", IoStack); + FileObject = IoStack->FileObject; + DPRINT("FileObject: %p\n", FileObject); + Fcb = FileObject->FsContext; + DPRINT("Fcb: %p\n", Fcb); + Pipe = Fcb->Pipe; + DPRINT("Pipe: %p\n", Pipe); + DPRINT("PipeName: %wZ\n", &Pipe->PipeName); + + switch (IoStack->Parameters.FileSystemControl.IoControlCode) + { case FSCTL_PIPE_ASSIGN_EVENT: - DPRINT("Assign event\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; + 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; + DPRINT("Connecting pipe %wZ\n", &Pipe->PipeName); + Status = NpfsConnectPipe(Fcb); + break; case FSCTL_PIPE_PEEK: - DPRINT("Peek\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; + DPRINT("Peeking pipe %wZ\n", &Pipe->PipeName); + Status = NpfsPeekPipe(Irp, IoStack); + break; case FSCTL_PIPE_QUERY_EVENT: - DPRINT("Query event\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; + DPRINT("Query event\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; case FSCTL_PIPE_TRANSCEIVE: - DPRINT("Transceive\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; + 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; + DPRINT("Impersonate\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; case FSCTL_PIPE_SET_CLIENT_PROCESS: - DPRINT("Set client process\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; + 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; + DPRINT("Query client process\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; case FSCTL_PIPE_GET_STATE: - DPRINT("Get state\n"); - Status = NpfsGetState(Irp, IoStack); - break; + DPRINT("Get state\n"); + Status = NpfsGetState(Irp, IoStack); + break; case FSCTL_PIPE_SET_STATE: - DPRINT("Set state\n"); - Status = NpfsSetState(Irp, IoStack); - break; + DPRINT("Set state\n"); + Status = NpfsSetState(Irp, IoStack); + break; case FSCTL_PIPE_INTERNAL_READ: - DPRINT("Internal read\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; + DPRINT("Internal read\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; case FSCTL_PIPE_INTERNAL_WRITE: - DPRINT("Internal write\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; + DPRINT("Internal write\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; case FSCTL_PIPE_INTERNAL_TRANSCEIVE: - DPRINT("Internal transceive\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; + 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; + DPRINT("Internal read overflow\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; default: - DPRINT("IoControlCode: %x\n", IoStack->Parameters.FileSystemControl.IoControlCode) - Status = STATUS_UNSUCCESSFUL; - } - - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return(Status); + DPRINT("IoControlCode: %x\n", IoStack->Parameters.FileSystemControl.IoControlCode) + Status = STATUS_UNSUCCESSFUL; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); } /* EOF */ diff --git a/reactos/drivers/fs/np/npfs.c b/reactos/drivers/fs/np/npfs.c index ef487dd7b03..f47244453a4 100644 --- a/reactos/drivers/fs/np/npfs.c +++ b/reactos/drivers/fs/np/npfs.c @@ -1,4 +1,4 @@ -/* $Id: npfs.c,v 1.2 2001/10/21 18:58:31 chorns Exp $ +/* $Id: npfs.c,v 1.3 2001/11/20 20:34:29 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -30,7 +30,6 @@ DriverEntry(PDRIVER_OBJECT DriverObject, DbgPrint("Named Pipe FSD 0.0.2\n"); - DeviceObject->Flags = 0; DriverObject->MajorFunction[IRP_MJ_CREATE] = NpfsCreate; DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = NpfsCreateNamedPipe; @@ -70,6 +69,9 @@ DriverEntry(PDRIVER_OBJECT DriverObject, return(Status); } + /* initialize the device object */ + DeviceObject->Flags = DO_DIRECT_IO; + /* initialize the device extension */ DeviceExtension = DeviceObject->DeviceExtension; InitializeListHead(&DeviceExtension->PipeListHead); diff --git a/reactos/drivers/fs/np/npfs.h b/reactos/drivers/fs/np/npfs.h index 12380a3f04f..b8f2697e08a 100644 --- a/reactos/drivers/fs/np/npfs.h +++ b/reactos/drivers/fs/np/npfs.h @@ -4,8 +4,8 @@ typedef struct { - LIST_ENTRY PipeListHead; - KMUTEX PipeListLock; + LIST_ENTRY PipeListHead; + KMUTEX PipeListLock; } NPFS_DEVICE_EXTENSION, *PNPFS_DEVICE_EXTENSION; typedef struct @@ -18,40 +18,38 @@ typedef struct typedef struct { - UNICODE_STRING PipeName; - LIST_ENTRY PipeListEntry; - 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; - ULONG CurrentInstances; - ULONG InboundQuota; - ULONG OutboundQuota; - LARGE_INTEGER TimeOut; + UNICODE_STRING PipeName; + LIST_ENTRY PipeListEntry; + KSPIN_LOCK FcbListLock; + LIST_ENTRY ServerFcbListHead; + LIST_ENTRY ClientFcbListHead; + ULONG ReferenceCount; + ULONG PipeType; + ULONG PipeReadMode; + ULONG PipeWriteMode; + ULONG PipeBlockMode; + ULONG PipeConfiguration; + ULONG MaximumInstances; + ULONG CurrentInstances; + ULONG InboundQuota; + ULONG OutboundQuota; + LARGE_INTEGER TimeOut; } NPFS_PIPE, *PNPFS_PIPE; typedef struct _NPFS_FCB { - LIST_ENTRY FcbListEntry; - struct _NPFS_FCB* OtherSide; - PNPFS_PIPE Pipe; - KEVENT ConnectEvent; - ULONG PipeEnd; - ULONG PipeState; - ULONG ReadDataAvailable; - ULONG WriteQuotaAvailable; + LIST_ENTRY FcbListEntry; + struct _NPFS_FCB* OtherSide; + PNPFS_PIPE Pipe; + KEVENT ConnectEvent; + KEVENT ReadEvent; + ULONG PipeEnd; + ULONG PipeState; + ULONG ReadDataAvailable; + ULONG WriteQuotaAvailable; + + LIST_ENTRY DataListHead; /* Data queue */ + KSPIN_LOCK DataListLock; /* Data queue lock */ } NPFS_FCB, *PNPFS_FCB; diff --git a/reactos/drivers/fs/np/rw.c b/reactos/drivers/fs/np/rw.c index 21882b34c7e..00e2c7b81d9 100644 --- a/reactos/drivers/fs/np/rw.c +++ b/reactos/drivers/fs/np/rw.c @@ -1,4 +1,4 @@ -/* $Id: rw.c,v 1.4 2001/10/21 18:58:32 chorns Exp $ +/* $Id: rw.c,v 1.5 2001/11/20 20:34:29 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -18,30 +18,29 @@ /* FUNCTIONS *****************************************************************/ -static inline VOID NpfsFreePipeData( - PNPFS_PIPE_DATA PipeData) +static inline VOID +NpfsFreePipeData(PNPFS_PIPE_DATA PipeData) { if (PipeData->Data) - { - ExFreePool(PipeData->Data); - } + { + ExFreePool(PipeData->Data); + } ExFreeToNPagedLookasideList(&NpfsPipeDataLookasideList, PipeData); } static inline PNPFS_PIPE_DATA -NpfsAllocatePipeData( - PVOID Data, - ULONG Size) +NpfsAllocatePipeData(PVOID Data, + ULONG Size) { PNPFS_PIPE_DATA PipeData; PipeData = ExAllocateFromNPagedLookasideList(&NpfsPipeDataLookasideList); if (!PipeData) - { - return NULL; - } + { + return NULL; + } PipeData->Data = Data; PipeData->Size = Size; @@ -90,93 +89,134 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp) PNPFS_PIPE_DATA Current; ULONG Information; PNPFS_FCB Fcb; + PNPFS_FCB ReadFcb; PNPFS_PIPE Pipe; - ULONG Length; - PVOID Buffer; + ULONG Length; + PVOID Buffer; ULONG CopyLength; + BOOLEAN DataListEmpty; 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; + ReadFcb = Fcb->OtherSide; + + if (ReadFcb == NULL) + { + DPRINT("Pipe is NOT connected!\n"); + Status = STATUS_UNSUCCESSFUL; + Length = 0; + goto done; + } + + if (Irp->MdlAddress == NULL) + { + DPRINT("Irp->MdlAddress == NULL\n"); + Status = STATUS_UNSUCCESSFUL; + Length = 0; + goto done; + } + Status = STATUS_SUCCESS; Length = IoStack->Parameters.Read.Length; - DPRINT("Irp->MdlAddress %p\n", Irp->MdlAddress); - Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); - KeAcquireSpinLock(&Pipe->ServerDataListLock, &OldIrql); + DPRINT("Length %d Buffer %x\n",Length,Buffer); + + KeAcquireSpinLock(&ReadFcb->DataListLock, &OldIrql); + DataListEmpty = IsListEmpty(&ReadFcb->DataListHead); + KeReleaseSpinLock(&ReadFcb->DataListLock, OldIrql); + + /* FIXME: check if in blocking mode */ + if (DataListEmpty == TRUE) + { + /* Wait for ReadEvent to become signaled */ + DPRINT("Waiting for readable data\n"); + Status = KeWaitForSingleObject(&Fcb->ReadEvent, + UserRequest, + KernelMode, + FALSE, + NULL); + DPRINT("Finished waiting! Status: %x\n", Status); + } + + KeAcquireSpinLock(&ReadFcb->DataListLock, &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(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; - } - - if ((CurrentEntry != &Pipe->ServerDataListHead) && (Current->Offset != Current->Size)) { - DPRINT("Putting pipe data at %p back in queue\n", Current); + DPRINT("Byte stream mode\n"); - /* The caller's buffer could not contain the complete message, - so put it back on the queue */ - InsertHeadList(&Pipe->ServerDataListHead, &Current->ListEntry); + /* Byte stream mode */ + Information = 0; + CurrentEntry = ReadFcb->DataListHead.Flink; + while ((Length > 0) && (CurrentEntry = RemoveHeadList(&ReadFcb->DataListHead))) + { + 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; + } + + if ((CurrentEntry != &ReadFcb->DataListHead) && (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(&ReadFcb->DataListHead, &Current->ListEntry); + } } - } else - { - DPRINT("Message mode\n"); + { + DPRINT("Message mode\n"); - /* Message mode */ - CurrentEntry = Pipe->ServerDataListHead.Flink; - if (CurrentEntry = RemoveHeadList(&Pipe->ServerDataListHead)) - { - Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry); + /* Message mode */ + CurrentEntry = ReadFcb->DataListHead.Flink; + if (CurrentEntry = RemoveHeadList(&ReadFcb->DataListHead)) + { + Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry); - DPRINT("Took pipe data at %p off the queue\n", Current); + 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; + /* 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; + Current->Offset += CopyLength; - CurrentEntry = CurrentEntry->Flink; + CurrentEntry = CurrentEntry->Flink; + } } - } - KeReleaseSpinLock(&Pipe->ServerDataListLock, OldIrql); + KeReleaseSpinLock(&ReadFcb->DataListLock, OldIrql); + /* reset ReaderEvent */ + KeResetEvent(&Fcb->ReadEvent); + +done: Irp->IoStatus.Status = Status; Irp->IoStatus.Information = Information; - + IoCompleteRequest(Irp, IO_NO_INCREMENT); - + return(Status); } @@ -207,26 +247,46 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject, Pipe = Fcb->Pipe; Length = IoStack->Parameters.Write.Length; - Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress); Offset = IoStack->Parameters.Write.ByteOffset.u.LowPart; + if (Irp->MdlAddress == NULL) + { + DbgPrint ("Irp->MdlAddress == NULL\n"); + Status = STATUS_UNSUCCESSFUL; + Length = 0; + goto done; + } + + if (Fcb->OtherSide == NULL) + { + DPRINT("Pipe is NOT connected!\n"); + Status = STATUS_UNSUCCESSFUL; + Length = 0; + goto done; + } + + Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress); + DPRINT("Length %d Buffer %x Offset %x\n",Length,Buffer,Offset); + PipeData = NpfsInitializePipeData(Buffer, Length); if (PipeData) - { - DPRINT("Attaching pipe data at %p (%d bytes)\n", PipeData, Length); + { + DPRINT("Attaching pipe data at %p (%d bytes)\n", PipeData, Length); - KeAcquireSpinLock(&Pipe->ServerDataListLock, &OldIrql); + KeAcquireSpinLock(&Fcb->DataListLock, &OldIrql); + InsertTailList(&Fcb->DataListHead, &PipeData->ListEntry); + KeReleaseSpinLock(&Fcb->DataListLock, OldIrql); - InsertTailList(&Pipe->ServerDataListHead, &PipeData->ListEntry); - - KeReleaseSpinLock(&Pipe->ServerDataListLock, OldIrql); - } + /* signal the readers ReadEvent */ + KeSetEvent(&Fcb->OtherSide->ConnectEvent, IO_NO_INCREMENT, FALSE); + } else - { - Length = 0; - Status = STATUS_INSUFFICIENT_RESOURCES; - } + { + Length = 0; + Status = STATUS_INSUFFICIENT_RESOURCES; + } +done: Irp->IoStatus.Status = Status; Irp->IoStatus.Information = Length; diff --git a/reactos/include/napi/npipe.h b/reactos/include/napi/npipe.h index 76101019be4..b89972fd887 100644 --- a/reactos/include/napi/npipe.h +++ b/reactos/include/napi/npipe.h @@ -159,6 +159,14 @@ typedef struct _NPFS_GET_STATE LARGE_INTEGER Timeout; } NPFS_GET_STATE, *PNPFS_GET_STATE; +typedef struct _FILE_PIPE_PEEK_BUFFER +{ + ULONG NamedPipeState; + ULONG ReadDataAvailable; + ULONG NumberOfMessages; + ULONG MessageLength; + CHAR Data[1]; +} FILE_PIPE_PEEK_BUFFER, *PFILE_PIPE_PEEK_BUFFER; #define FILE_PIPE_BYTE_STREAM_TYPE 0x00000000 #define FILE_PIPE_MESSAGE_TYPE 0x00000001 diff --git a/reactos/lib/kernel32/file/npipe.c b/reactos/lib/kernel32/file/npipe.c index 24249e526bc..eb2503b88f7 100644 --- a/reactos/lib/kernel32/file/npipe.c +++ b/reactos/lib/kernel32/file/npipe.c @@ -1,4 +1,4 @@ -/* $Id: npipe.c,v 1.8 2001/10/21 19:06:42 chorns Exp $ +/* $Id: npipe.c,v 1.9 2001/11/20 20:35:10 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -441,7 +441,7 @@ SetNamedPipeHandleState(HANDLE hNamedPipe, } -WINBOOL STDCALL +BOOL STDCALL CallNamedPipeA(LPCSTR lpNamedPipeName, LPVOID lpInBuffer, DWORD nInBufferSize, @@ -450,12 +450,27 @@ CallNamedPipeA(LPCSTR lpNamedPipeName, LPDWORD lpBytesRead, DWORD nTimeOut) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + UNICODE_STRING PipeName; + BOOL Result; + + RtlCreateUnicodeStringFromAsciiz(&PipeName, + (LPSTR)lpNamedPipeName); + + Result = CallNamedPipeW(PipeName.Buffer, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize, + lpBytesRead, + nTimeOut); + + RtlFreeUnicodeString(&PipeName); + + return(Result); } -WINBOOL STDCALL +BOOL STDCALL CallNamedPipeW(LPCWSTR lpNamedPipeName, LPVOID lpInBuffer, DWORD nInBufferSize, @@ -464,45 +479,45 @@ CallNamedPipeW(LPCWSTR lpNamedPipeName, LPDWORD lpBytesRead, DWORD nTimeOut) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; } -WINBOOL STDCALL +BOOL STDCALL DisconnectNamedPipe(HANDLE hNamedPipe) { - IO_STATUS_BLOCK Iosb; - NTSTATUS Status; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; - Status = NtFsControlFile(hNamedPipe, - NULL, - NULL, - NULL, - &Iosb, - FSCTL_PIPE_DISCONNECT, - NULL, - 0, - NULL, - 0); - if (Status == STATUS_PENDING) - { - Status = NtWaitForSingleObject(hNamedPipe, - FALSE, - NULL); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return(FALSE); - } - } + Status = NtFsControlFile(hNamedPipe, + NULL, + NULL, + NULL, + &Iosb, + FSCTL_PIPE_DISCONNECT, + NULL, + 0, + NULL, + 0); + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(hNamedPipe, + FALSE, + NULL); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + } - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return(FALSE); - } - return(TRUE); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + return(TRUE); } @@ -515,8 +530,46 @@ GetNamedPipeHandleStateW(HANDLE hNamedPipe, LPWSTR lpUserName, DWORD nMaxUserNameSize) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + FILE_PIPE_LOCAL_INFORMATION LocalInfo; + FILE_PIPE_INFORMATION PipeInfo; + IO_STATUS_BLOCK StatusBlock; + NTSTATUS Status; + + if (lpState != NULL) + { + Status = NtQueryInformationFile(hNamedPipe, + &StatusBlock, + &PipeInfo, + sizeof(FILE_PIPE_INFORMATION), + FilePipeInformation); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + *lpState = 0; /* FIXME */ + } + + if (lpCurInstances != NULL) + { + Status = NtQueryInformationFile(hNamedPipe, + &StatusBlock, + &LocalInfo, + sizeof(FILE_PIPE_LOCAL_INFORMATION), + FilePipeLocalInformation); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + *lpCurInstances = min(LocalInfo.CurrentInstances, 255); + } + + + /* FIXME: retrieve remaining information */ + + + return(TRUE); } @@ -580,7 +633,7 @@ GetNamedPipeInfo(HANDLE hNamedPipe, } -WINBOOL STDCALL +BOOL STDCALL PeekNamedPipe(HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize, @@ -588,12 +641,80 @@ PeekNamedPipe(HANDLE hNamedPipe, LPDWORD lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + PFILE_PIPE_PEEK_BUFFER Buffer; + IO_STATUS_BLOCK Iosb; + ULONG BufferSize; + NTSTATUS Status; + + BufferSize = nBufferSize + sizeof(FILE_PIPE_PEEK_BUFFER); + Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + BufferSize); + + Status = NtFsControlFile(hNamedPipe, + NULL, + NULL, + NULL, + &Iosb, + FSCTL_PIPE_PEEK, + NULL, + 0, + Buffer, + BufferSize); + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(hNamedPipe, + FALSE, + NULL); + if (NT_SUCCESS(Status)) + Status = Iosb.Status; + } + + if (Status == STATUS_BUFFER_OVERFLOW) + { + Status = STATUS_SUCCESS; + } + + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Buffer); + SetLastErrorByStatus(Status); + return(FALSE); + } + + if (lpTotalBytesAvail != NULL) + { + *lpTotalBytesAvail = Buffer->ReadDataAvailable; + } + + if (lpBytesRead != NULL) + { + *lpBytesRead = Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER); + } + + if (lpBytesLeftThisMessage != NULL) + { + *lpBytesLeftThisMessage = Buffer->MessageLength - + (Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER)); + } + + if (lpBuffer != NULL) + { + memcpy(lpBuffer, Buffer->Data, + min(nBufferSize, Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER))); + } + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Buffer); + + return(TRUE); } -WINBOOL STDCALL +BOOL STDCALL TransactNamedPipe(HANDLE hNamedPipe, LPVOID lpInBuffer, DWORD nInBufferSize,