Author: fireball Date: Fri May 4 14:15:00 2007 New Revision: 26631
URL: http://svn.reactos.org/svn/reactos?rev=26631&view=rev Log: - Prepare a playground for a new NPFS driver implementation.
Added: trunk/reactos/drivers/filesystems/npfs_new/ (with props) trunk/reactos/drivers/filesystems/npfs_new/create.c (with props) trunk/reactos/drivers/filesystems/npfs_new/finfo.c (with props) trunk/reactos/drivers/filesystems/npfs_new/fsctrl.c (with props) trunk/reactos/drivers/filesystems/npfs_new/npfs.c (with props) trunk/reactos/drivers/filesystems/npfs_new/npfs.h (with props) trunk/reactos/drivers/filesystems/npfs_new/npfs.rbuild (with props) trunk/reactos/drivers/filesystems/npfs_new/npfs.rc trunk/reactos/drivers/filesystems/npfs_new/rw.c (with props) trunk/reactos/drivers/filesystems/npfs_new/volume.c (with props)
Propchange: trunk/reactos/drivers/filesystems/npfs_new/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Fri May 4 14:15:00 2007 @@ -1,0 +1,13 @@ +base.tmp +junk.tmp +temp.exp +npfs.coff +*.d +*.o +*.a +*.sym +*.sys +*.map +GNUmakefile +*.vcproj +*.user
Added: trunk/reactos/drivers/filesystems/npfs_new/create.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/npfs_ne... ============================================================================== --- trunk/reactos/drivers/filesystems/npfs_new/create.c (added) +++ trunk/reactos/drivers/filesystems/npfs_new/create.c Fri May 4 14:15:00 2007 @@ -1,0 +1,18 @@ +/* + * PROJECT: ReactOS Drivers + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/filesystems/npfs/create.c + * PURPOSE: Named pipe filesystem + * PROGRAMMERS: + */ + +/* INCLUDES ******************************************************************/ + +#include "npfs.h" + +//#define NDEBUG +#include <debug.h> + +/* FUNCTIONS *****************************************************************/ + +/* EOF */
Propchange: trunk/reactos/drivers/filesystems/npfs_new/create.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/drivers/filesystems/npfs_new/finfo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/npfs_ne... ============================================================================== --- trunk/reactos/drivers/filesystems/npfs_new/finfo.c (added) +++ trunk/reactos/drivers/filesystems/npfs_new/finfo.c Fri May 4 14:15:00 2007 @@ -1,0 +1,18 @@ +/* + * PROJECT: ReactOS Drivers + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/filesystems/npfs/finfo.c + * PURPOSE: Named pipe filesystem + * PROGRAMMERS: + */ + +/* INCLUDES ******************************************************************/ + +#include "npfs.h" + +//#define NDEBUG +#include <debug.h> + +/* FUNCTIONS *****************************************************************/ + +/* EOF */
Propchange: trunk/reactos/drivers/filesystems/npfs_new/finfo.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/drivers/filesystems/npfs_new/fsctrl.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/npfs_ne... ============================================================================== --- trunk/reactos/drivers/filesystems/npfs_new/fsctrl.c (added) +++ trunk/reactos/drivers/filesystems/npfs_new/fsctrl.c Fri May 4 14:15:00 2007 @@ -1,0 +1,19 @@ +/* + * PROJECT: ReactOS Drivers + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/filesystems/npfs/fsctrl.c + * PURPOSE: Named pipe filesystem + * PROGRAMMERS: + */ + +/* INCLUDES ******************************************************************/ + +#include "npfs.h" + +//#define NDEBUG +#include <debug.h> + +/* FUNCTIONS *****************************************************************/ + + +/* EOF */
Propchange: trunk/reactos/drivers/filesystems/npfs_new/fsctrl.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/drivers/filesystems/npfs_new/npfs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/npfs_ne... ============================================================================== --- trunk/reactos/drivers/filesystems/npfs_new/npfs.c (added) +++ trunk/reactos/drivers/filesystems/npfs_new/npfs.c Fri May 4 14:15:00 2007 @@ -1,0 +1,89 @@ +/* + * PROJECT: ReactOS Drivers + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/filesystems/npfs/npfs.c + * PURPOSE: Named pipe filesystem + * PROGRAMMERS: + */ + +/* INCLUDES ******************************************************************/ + +#include "npfs.h" + +//#define NDEBUG +#include <debug.h> + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +{ + PNPFS_DEVICE_EXTENSION DeviceExtension; + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceName; + NTSTATUS Status; + + DPRINT("Named Pipe FSD 0.0.2\n"); + + ASSERT (sizeof(NPFS_CONTEXT) <= FIELD_OFFSET(IRP, Tail.Overlay.DriverContext)); + ASSERT (sizeof(NPFS_WAITER_ENTRY) <= FIELD_OFFSET(IRP, Tail.Overlay.DriverContext)); + + DriverObject->MajorFunction[IRP_MJ_CREATE] = NpfsCreate; + DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = + NpfsCreateNamedPipe; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = NpfsClose; + DriverObject->MajorFunction[IRP_MJ_READ] = NpfsRead; + DriverObject->MajorFunction[IRP_MJ_WRITE] = NpfsWrite; + DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = + NpfsQueryInformation; + DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = + NpfsSetInformation; + DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = + NpfsQueryVolumeInformation; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = NpfsCleanup; + DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = NpfsFlushBuffers; + // DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = + // NpfsDirectoryControl; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = + NpfsFileSystemControl; + // DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = + // NpfsQuerySecurity; + // DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = + // NpfsSetSecurity; + + DriverObject->DriverUnload = NULL; + + RtlInitUnicodeString(&DeviceName, L"\Device\NamedPipe"); + Status = IoCreateDevice(DriverObject, + sizeof(NPFS_DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_NAMED_PIPE, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to create named pipe device! (Status %x)\n", Status); + return Status; + } + + /* initialize the device object */ + DeviceObject->Flags = DO_DIRECT_IO; + + /* initialize the device extension */ + DeviceExtension = DeviceObject->DeviceExtension; + InitializeListHead(&DeviceExtension->PipeListHead); + InitializeListHead(&DeviceExtension->ThreadListHead); + KeInitializeMutex(&DeviceExtension->PipeListLock, 0); + DeviceExtension->EmptyWaiterCount = 0; + + /* set the size quotas */ + DeviceExtension->MinQuota = PAGE_SIZE; + DeviceExtension->DefaultQuota = 8 * PAGE_SIZE; + DeviceExtension->MaxQuota = 64 * PAGE_SIZE; + + return STATUS_SUCCESS; +} + +/* EOF */
Propchange: trunk/reactos/drivers/filesystems/npfs_new/npfs.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/drivers/filesystems/npfs_new/npfs.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/npfs_ne... ============================================================================== --- trunk/reactos/drivers/filesystems/npfs_new/npfs.h (added) +++ trunk/reactos/drivers/filesystems/npfs_new/npfs.h Fri May 4 14:15:00 2007 @@ -1,0 +1,122 @@ +#ifndef __DRIVERS_FS_NP_NPFS_H +#define __DRIVERS_FS_NP_NPFS_H + +#include <ntifs.h> +#include <ndk/iotypes.h> + +typedef struct _NPFS_DEVICE_EXTENSION +{ + LIST_ENTRY PipeListHead; + LIST_ENTRY ThreadListHead; + KMUTEX PipeListLock; + ULONG EmptyWaiterCount; + ULONG MinQuota; + ULONG DefaultQuota; + ULONG MaxQuota; +} NPFS_DEVICE_EXTENSION, *PNPFS_DEVICE_EXTENSION; + +typedef struct _NPFS_FCB +{ + FSRTL_COMMON_FCB_HEADER RFCB; + UNICODE_STRING PipeName; + LIST_ENTRY PipeListEntry; + KMUTEX CcbListLock; + LIST_ENTRY ServerCcbListHead; + LIST_ENTRY ClientCcbListHead; + LIST_ENTRY WaiterListHead; + LIST_ENTRY EmptyBufferListHead; + ULONG PipeType; + ULONG ReadMode; + ULONG WriteMode; + ULONG CompletionMode; + ULONG PipeConfiguration; + ULONG MaximumInstances; + ULONG CurrentInstances; + ULONG InboundQuota; + ULONG OutboundQuota; + LARGE_INTEGER TimeOut; +} NPFS_FCB, *PNPFS_FCB; + +typedef struct _NPFS_CCB +{ + LIST_ENTRY CcbListEntry; + struct _NPFS_CCB* OtherSide; + struct ETHREAD *Thread; + PNPFS_FCB Fcb; + KEVENT ConnectEvent; + KEVENT ReadEvent; + KEVENT WriteEvent; + ULONG PipeEnd; + ULONG PipeState; + ULONG ReadDataAvailable; + ULONG WriteQuotaAvailable; + + LIST_ENTRY ReadRequestListHead; + + PVOID Data; + PVOID ReadPtr; + PVOID WritePtr; + ULONG MaxDataLength; + + FAST_MUTEX DataListLock; /* Data queue lock */ +} NPFS_CCB, *PNPFS_CCB; + +typedef struct _NPFS_CONTEXT +{ + LIST_ENTRY ListEntry; + PKEVENT WaitEvent; +} NPFS_CONTEXT, *PNPFS_CONTEXT; + +typedef struct _NPFS_THREAD_CONTEXT +{ + ULONG Count; + KEVENT Event; + PNPFS_DEVICE_EXTENSION DeviceExt; + LIST_ENTRY ListEntry; + PVOID WaitObjectArray[MAXIMUM_WAIT_OBJECTS]; + KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS]; + PIRP WaitIrpArray[MAXIMUM_WAIT_OBJECTS]; +} NPFS_THREAD_CONTEXT, *PNPFS_THREAD_CONTEXT; + +typedef struct _NPFS_WAITER_ENTRY +{ + LIST_ENTRY Entry; + PNPFS_CCB Ccb; +} NPFS_WAITER_ENTRY, *PNPFS_WAITER_ENTRY; + + +extern NPAGED_LOOKASIDE_LIST NpfsPipeDataLookasideList; + + +#define KeLockMutex(x) KeWaitForSingleObject(x, \ + UserRequest, \ + KernelMode, \ + FALSE, \ + NULL); + +#define KeUnlockMutex(x) KeReleaseMutex(x, FALSE); + +#define PAGE_ROUND_UP(x) ( (((ULONG_PTR)x)%PAGE_SIZE) ? ((((ULONG_PTR)x)&(~(PAGE_SIZE-1)))+PAGE_SIZE) : ((ULONG_PTR)x) ) + +NTSTATUS STDCALL NpfsCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL NpfsCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL NpfsClose(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +NTSTATUS STDCALL NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL NpfsWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +NTSTATUS STDCALL NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +NTSTATUS STDCALL NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +NTSTATUS STDCALL NpfsQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL NpfsSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +NTSTATUS STDCALL NpfsQueryVolumeInformation (PDEVICE_OBJECT DeviceObject, PIRP Irp); + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath); + +#endif /* __DRIVERS_FS_NP_NPFS_H */
Propchange: trunk/reactos/drivers/filesystems/npfs_new/npfs.h ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/drivers/filesystems/npfs_new/npfs.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/npfs_ne... ============================================================================== --- trunk/reactos/drivers/filesystems/npfs_new/npfs.rbuild (added) +++ trunk/reactos/drivers/filesystems/npfs_new/npfs.rbuild Fri May 4 14:15:00 2007 @@ -1,0 +1,15 @@ +<module name="npfs" type="kernelmodedriver" installbase="system32/drivers" installname="npfs.sys"> + <include base="npfs">.</include> + <define name="__USE_W32API" /> + <define name="__NO_CTYPE_INLINES" /> + <library>ntoskrnl</library> + <library>hal</library> + <file>create.c</file> + <file>finfo.c</file> + <file>fsctrl.c</file> + <file>npfs.c</file> + <file>rw.c</file> + <file>volume.c</file> + <file>npfs.rc</file> + <pch>npfs.h</pch> +</module>
Propchange: trunk/reactos/drivers/filesystems/npfs_new/npfs.rbuild ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/drivers/filesystems/npfs_new/npfs.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/npfs_ne... ============================================================================== --- trunk/reactos/drivers/filesystems/npfs_new/npfs.rc (added) +++ trunk/reactos/drivers/filesystems/npfs_new/npfs.rc Fri May 4 14:15:00 2007 @@ -1,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "Named Pipe IFS Driver\0" +#define REACTOS_STR_INTERNAL_NAME "npfs\0" +#define REACTOS_STR_ORIGINAL_FILENAME "npfs.sys\0" +#include <reactos/version.rc>
Added: trunk/reactos/drivers/filesystems/npfs_new/rw.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/npfs_ne... ============================================================================== --- trunk/reactos/drivers/filesystems/npfs_new/rw.c (added) +++ trunk/reactos/drivers/filesystems/npfs_new/rw.c Fri May 4 14:15:00 2007 @@ -1,0 +1,779 @@ +/* + * PROJECT: ReactOS Drivers + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/filesystems/npfs/rw.c + * PURPOSE: Named pipe filesystem + * PROGRAMMERS: + */ + +/* INCLUDES ******************************************************************/ + +#include "npfs.h" + +//#define NDEBUG +#include <debug.h> + +/* FUNCTIONS *****************************************************************/ + +#ifndef NDEBUG +VOID HexDump(PUCHAR Buffer, ULONG Length) +{ + CHAR Line[65]; + UCHAR ch; + const char Hex[] = "0123456789ABCDEF"; + int i, j; + + DbgPrint("---------------\n"); + + for (i = 0; i < Length; i+= 16) + { + memset(Line, ' ', 64); + Line[64] = 0; + + for (j = 0; j < 16 && j + i < Length; j++) + { + ch = Buffer[i + j]; + Line[3*j + 0] = Hex[ch >> 4]; + Line[3*j + 1] = Hex[ch & 0x0f]; + Line[48 + j] = isprint(ch) ? ch : '.'; + } + DbgPrint("%s\n", Line); + } + DbgPrint("---------------\n"); +} +#endif + +static VOID STDCALL +NpfsReadWriteCancelRoutine(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PNPFS_CONTEXT Context; + PNPFS_DEVICE_EXTENSION DeviceExt; + PIO_STACK_LOCATION IoStack; + PNPFS_CCB Ccb; + BOOLEAN Complete = FALSE; + + DPRINT("NpfsReadWriteCancelRoutine(DeviceObject %x, Irp %x)\n", DeviceObject, Irp); + + IoReleaseCancelSpinLock(Irp->CancelIrql); + + Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext; + DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + IoStack = IoGetCurrentIrpStackLocation(Irp); + Ccb = IoStack->FileObject->FsContext2; + + KeLockMutex(&DeviceExt->PipeListLock); + ExAcquireFastMutex(&Ccb->DataListLock); + switch(IoStack->MajorFunction) + { + case IRP_MJ_READ: + if (Ccb->ReadRequestListHead.Flink != &Context->ListEntry) + { + /* we are not the first in the list, remove an complete us */ + RemoveEntryList(&Context->ListEntry); + Complete = TRUE; + } + else + { + KeSetEvent(&Ccb->ReadEvent, IO_NO_INCREMENT, FALSE); + } + break; + default: + KEBUGCHECK(0); + } + ExReleaseFastMutex(&Ccb->DataListLock); + KeUnlockMutex(&DeviceExt->PipeListLock); + if (Complete) + { + Irp->IoStatus.Status = STATUS_CANCELLED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } +} + +static VOID STDCALL +NpfsWaiterThread(PVOID InitContext) +{ + PNPFS_THREAD_CONTEXT ThreadContext = (PNPFS_THREAD_CONTEXT) InitContext; + ULONG CurrentCount; + ULONG Count = 0; + PIRP Irp = NULL; + PIRP NextIrp; + NTSTATUS Status; + BOOLEAN Terminate = FALSE; + BOOLEAN Cancel = FALSE; + PIO_STACK_LOCATION IoStack = NULL; + PNPFS_CONTEXT Context; + PNPFS_CONTEXT NextContext; + PNPFS_CCB Ccb; + + KeLockMutex(&ThreadContext->DeviceExt->PipeListLock); + + while (1) + { + CurrentCount = ThreadContext->Count; + KeUnlockMutex(&ThreadContext->DeviceExt->PipeListLock); + if (Irp) + { + if (Cancel) + { + Irp->IoStatus.Status = STATUS_CANCELLED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + else + { + switch (IoStack->MajorFunction) + { + case IRP_MJ_READ: + NpfsRead(IoStack->DeviceObject, Irp); + break; + default: + KEBUGCHECK(0); + } + } + } + if (Terminate) + { + break; + } + Status = KeWaitForMultipleObjects(CurrentCount, + ThreadContext->WaitObjectArray, + WaitAny, + Executive, + KernelMode, + FALSE, + NULL, + ThreadContext->WaitBlockArray); + if (!NT_SUCCESS(Status)) + { + KEBUGCHECK(0); + } + KeLockMutex(&ThreadContext->DeviceExt->PipeListLock); + Count = Status - STATUS_SUCCESS; + ASSERT (Count < CurrentCount); + if (Count > 0) + { + Irp = ThreadContext->WaitIrpArray[Count]; + ThreadContext->Count--; + ThreadContext->DeviceExt->EmptyWaiterCount++; + ThreadContext->WaitObjectArray[Count] = ThreadContext->WaitObjectArray[ThreadContext->Count]; + ThreadContext->WaitIrpArray[Count] = ThreadContext->WaitIrpArray[ThreadContext->Count]; + + Cancel = (NULL == IoSetCancelRoutine(Irp, NULL)); + Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext; + IoStack = IoGetCurrentIrpStackLocation(Irp); + + if (Cancel) + { + Ccb = IoStack->FileObject->FsContext2; + ExAcquireFastMutex(&Ccb->DataListLock); + RemoveEntryList(&Context->ListEntry); + switch (IoStack->MajorFunction) + { + case IRP_MJ_READ: + if (!IsListEmpty(&Ccb->ReadRequestListHead)) + { + /* put the next request on the wait list */ + NextContext = CONTAINING_RECORD(Ccb->ReadRequestListHead.Flink, NPFS_CONTEXT, ListEntry); + ThreadContext->WaitObjectArray[ThreadContext->Count] = NextContext->WaitEvent; + NextIrp = CONTAINING_RECORD(NextContext, IRP, Tail.Overlay.DriverContext); + ThreadContext->WaitIrpArray[ThreadContext->Count] = NextIrp; + ThreadContext->Count++; + ThreadContext->DeviceExt->EmptyWaiterCount--; + } + break; + default: + KEBUGCHECK(0); + } + ExReleaseFastMutex(&Ccb->DataListLock); + } + } + else + { + /* someone has add a new wait request */ + Irp = NULL; + } + if (ThreadContext->Count == 1 && ThreadContext->DeviceExt->EmptyWaiterCount >= MAXIMUM_WAIT_OBJECTS) + { + /* it exist an other thread with empty wait slots, we can remove our thread from the list */ + RemoveEntryList(&ThreadContext->ListEntry); + ThreadContext->DeviceExt->EmptyWaiterCount -= MAXIMUM_WAIT_OBJECTS - 1; + Terminate = TRUE; + } + } + ExFreePool(ThreadContext); +} + +static NTSTATUS +NpfsAddWaitingReadWriteRequest(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PLIST_ENTRY ListEntry; + PNPFS_THREAD_CONTEXT ThreadContext = NULL; + NTSTATUS Status; + HANDLE hThread; + KIRQL oldIrql; + + PNPFS_CONTEXT Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext; + PNPFS_DEVICE_EXTENSION DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + DPRINT("NpfsAddWaitingReadWriteRequest(DeviceObject %p, Irp %p)\n", DeviceObject, Irp); + + KeLockMutex(&DeviceExt->PipeListLock); + + ListEntry = DeviceExt->ThreadListHead.Flink; + while (ListEntry != &DeviceExt->ThreadListHead) + { + ThreadContext = CONTAINING_RECORD(ListEntry, NPFS_THREAD_CONTEXT, ListEntry); + if (ThreadContext->Count < MAXIMUM_WAIT_OBJECTS) + { + break; + } + ListEntry = ListEntry->Flink; + } + if (ListEntry == &DeviceExt->ThreadListHead) + { + ThreadContext = ExAllocatePool(NonPagedPool, sizeof(NPFS_THREAD_CONTEXT)); + if (ThreadContext == NULL) + { + KeUnlockMutex(&DeviceExt->PipeListLock); + return STATUS_NO_MEMORY; + } + ThreadContext->DeviceExt = DeviceExt; + KeInitializeEvent(&ThreadContext->Event, SynchronizationEvent, FALSE); + ThreadContext->Count = 1; + ThreadContext->WaitObjectArray[0] = &ThreadContext->Event; + + + DPRINT("Creating a new system thread for waiting read/write requests\n"); + + Status = PsCreateSystemThread(&hThread, + THREAD_ALL_ACCESS, + NULL, + NULL, + NULL, + NpfsWaiterThread, + (PVOID)ThreadContext); + if (!NT_SUCCESS(Status)) + { + ExFreePool(ThreadContext); + KeUnlockMutex(&DeviceExt->PipeListLock); + return Status; + } + InsertHeadList(&DeviceExt->ThreadListHead, &ThreadContext->ListEntry); + DeviceExt->EmptyWaiterCount += MAXIMUM_WAIT_OBJECTS - 1; + } + IoMarkIrpPending(Irp); + + IoAcquireCancelSpinLock(&oldIrql); + if (Irp->Cancel) + { + IoReleaseCancelSpinLock(oldIrql); + Status = STATUS_CANCELLED; + } + else + { + (void)IoSetCancelRoutine(Irp, NpfsReadWriteCancelRoutine); + IoReleaseCancelSpinLock(oldIrql); + ThreadContext->WaitObjectArray[ThreadContext->Count] = Context->WaitEvent; + ThreadContext->WaitIrpArray[ThreadContext->Count] = Irp; + ThreadContext->Count++; + DeviceExt->EmptyWaiterCount--; + KeSetEvent(&ThreadContext->Event, IO_NO_INCREMENT, FALSE); + Status = STATUS_SUCCESS; + } + KeUnlockMutex(&DeviceExt->PipeListLock); + return Status; +} + +NTSTATUS STDCALL +NpfsRead(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PFILE_OBJECT FileObject; + NTSTATUS Status; + NTSTATUS OriginalStatus = STATUS_SUCCESS; + PNPFS_CCB Ccb; + PNPFS_CONTEXT Context; + KEVENT Event; + ULONG Length; + ULONG Information = 0; + ULONG CopyLength; + ULONG TempLength; + BOOLEAN IsOriginalRequest = TRUE; + PVOID Buffer; + + DPRINT("NpfsRead(DeviceObject %p, Irp %p)\n", DeviceObject, Irp); + + if (Irp->MdlAddress == NULL) + { + DPRINT("Irp->MdlAddress == NULL\n"); + Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + goto done; + } + + FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject; + Ccb = FileObject->FsContext2; + Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext; + + if (Ccb->OtherSide == NULL) + { + DPRINT("Pipe is NOT connected!\n"); + if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE) + Status = STATUS_PIPE_LISTENING; + else if (Ccb->PipeState == FILE_PIPE_DISCONNECTED_STATE) + Status = STATUS_PIPE_DISCONNECTED; + else + Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + goto done; + } + + if (Ccb->Data == NULL) + { + DPRINT1("Pipe is NOT readable!\n"); + Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + goto done; + } + + ExAcquireFastMutex(&Ccb->DataListLock); + + if (IoIsOperationSynchronous(Irp)) + { + InsertTailList(&Ccb->ReadRequestListHead, &Context->ListEntry); + if (Ccb->ReadRequestListHead.Flink != &Context->ListEntry) + { + KeInitializeEvent(&Event, SynchronizationEvent, FALSE); + Context->WaitEvent = &Event; + ExReleaseFastMutex(&Ccb->DataListLock); + Status = KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + if (!NT_SUCCESS(Status)) + { + KEBUGCHECK(0); + } + ExAcquireFastMutex(&Ccb->DataListLock); + } + Irp->IoStatus.Information = 0; + } + else + { + KIRQL oldIrql; + if (IsListEmpty(&Ccb->ReadRequestListHead) || + Ccb->ReadRequestListHead.Flink != &Context->ListEntry) + { + /* this is a new request */ + Irp->IoStatus.Information = 0; + Context->WaitEvent = &Ccb->ReadEvent; + InsertTailList(&Ccb->ReadRequestListHead, &Context->ListEntry); + if (Ccb->ReadRequestListHead.Flink != &Context->ListEntry) + { + /* there was already a request on the list */ + IoAcquireCancelSpinLock(&oldIrql); + if (Irp->Cancel) + { + IoReleaseCancelSpinLock(oldIrql); + RemoveEntryList(&Context->ListEntry); + ExReleaseFastMutex(&Ccb->DataListLock); + Status = STATUS_CANCELLED; + goto done; + } + (void)IoSetCancelRoutine(Irp, NpfsReadWriteCancelRoutine); + IoReleaseCancelSpinLock(oldIrql); + ExReleaseFastMutex(&Ccb->DataListLock); + IoMarkIrpPending(Irp); + Status = STATUS_PENDING; + goto done; + } + } + } + + while (1) + { + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + Information = Irp->IoStatus.Information; + Length = IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length; + ASSERT (Information <= Length); + Buffer = (PVOID)((ULONG_PTR)Buffer + Information); + Length -= Information; + Status = STATUS_SUCCESS; + + while (1) + { + if (Ccb->ReadDataAvailable == 0) + { + if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE) + { + ASSERT(Ccb->OtherSide != NULL); + KeSetEvent(&Ccb->OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE); + } + if (Information > 0 && + (Ccb->Fcb->ReadMode != FILE_PIPE_BYTE_STREAM_MODE || + Ccb->PipeState != FILE_PIPE_CONNECTED_STATE)) + { + break; + } + if (Ccb->PipeState != FILE_PIPE_CONNECTED_STATE) + { + DPRINT("PipeState: %x\n", Ccb->PipeState); + Status = STATUS_PIPE_BROKEN; + break; + } + ExReleaseFastMutex(&Ccb->DataListLock); + if (IoIsOperationSynchronous(Irp)) + { + /* Wait for ReadEvent to become signaled */ + + DPRINT("Waiting for readable data (%wZ)\n", &Ccb->Fcb->PipeName); + Status = KeWaitForSingleObject(&Ccb->ReadEvent, + UserRequest, + KernelMode, + FALSE, + NULL); + DPRINT("Finished waiting (%wZ)! Status: %x\n", &Ccb->Fcb->PipeName, Status); + ExAcquireFastMutex(&Ccb->DataListLock); + } + else + { + Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext; + + Context->WaitEvent = &Ccb->ReadEvent; + Status = NpfsAddWaitingReadWriteRequest(DeviceObject, Irp); + + if (NT_SUCCESS(Status)) + { + Status = STATUS_PENDING; + } + ExAcquireFastMutex(&Ccb->DataListLock); + break; + } + } + ASSERT(IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL); + if (Ccb->Fcb->ReadMode == FILE_PIPE_BYTE_STREAM_MODE) + { + DPRINT("Byte stream mode\n"); + /* Byte stream mode */ + while (Length > 0 && Ccb->ReadDataAvailable > 0) + { + CopyLength = min(Ccb->ReadDataAvailable, Length); + if ((ULONG_PTR)Ccb->ReadPtr + CopyLength <= (ULONG_PTR)Ccb->Data + Ccb->MaxDataLength) + { + memcpy(Buffer, Ccb->ReadPtr, CopyLength); + Ccb->ReadPtr = (PVOID)((ULONG_PTR)Ccb->ReadPtr + CopyLength); + if (Ccb->ReadPtr == (PVOID)((ULONG_PTR)Ccb->Data + Ccb->MaxDataLength)) + { + Ccb->ReadPtr = Ccb->Data; + } + } + else + { + TempLength = (ULONG)((ULONG_PTR)Ccb->Data + Ccb->MaxDataLength - (ULONG_PTR)Ccb->ReadPtr); + memcpy(Buffer, Ccb->ReadPtr, TempLength); + memcpy((PVOID)((ULONG_PTR)Buffer + TempLength), Ccb->Data, CopyLength - TempLength); + Ccb->ReadPtr = (PVOID)((ULONG_PTR)Ccb->Data + CopyLength - TempLength); + } + + Buffer = (PVOID)((ULONG_PTR)Buffer + CopyLength); + Length -= CopyLength; + Information += CopyLength; + + Ccb->ReadDataAvailable -= CopyLength; + Ccb->WriteQuotaAvailable += CopyLength; + } + + if (Length == 0) + { + if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE) + { + KeSetEvent(&Ccb->OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE); + } + KeResetEvent(&Ccb->ReadEvent); + break; + } + } + else + { + DPRINT("Message mode\n"); + + /* Message mode */ + if (Ccb->ReadDataAvailable) + { + /* Truncate the message if the receive buffer is too small */ + CopyLength = min(Ccb->ReadDataAvailable, Length); + memcpy(Buffer, Ccb->Data, CopyLength); + +#ifndef NDEBUG + DPRINT("Length %d Buffer %x\n",CopyLength,Buffer); + HexDump((PUCHAR)Buffer, CopyLength); +#endif + + Information = CopyLength; + + if (Ccb->ReadDataAvailable > Length) + { + memmove(Ccb->Data, (PVOID)((ULONG_PTR)Ccb->Data + Length), + Ccb->ReadDataAvailable - Length); + Ccb->ReadDataAvailable -= Length; + Status = STATUS_MORE_ENTRIES; + } + else + { + KeResetEvent(&Ccb->ReadEvent); + if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE) + { + KeSetEvent(&Ccb->OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE); + } + Ccb->ReadDataAvailable = 0; + Ccb->WriteQuotaAvailable = Ccb->MaxDataLength; + } + } + + if (Information > 0) + { + break; + } + } + } + Irp->IoStatus.Information = Information; + Irp->IoStatus.Status = Status; + + ASSERT(IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL); + + if (IoIsOperationSynchronous(Irp)) + { + RemoveEntryList(&Context->ListEntry); + if (!IsListEmpty(&Ccb->ReadRequestListHead)) + { + Context = CONTAINING_RECORD(Ccb->ReadRequestListHead.Flink, NPFS_CONTEXT, ListEntry); + KeSetEvent(Context->WaitEvent, IO_NO_INCREMENT, FALSE); + } + ExReleaseFastMutex(&Ccb->DataListLock); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + DPRINT("NpfsRead done (Status %lx)\n", Status); + return Status; + } + else + { + if (IsOriginalRequest) + { + IsOriginalRequest = FALSE; + OriginalStatus = Status; + } + if (Status == STATUS_PENDING) + { + ExReleaseFastMutex(&Ccb->DataListLock); + DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus); + return OriginalStatus; + } + RemoveEntryList(&Context->ListEntry); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + if (IsListEmpty(&Ccb->ReadRequestListHead)) + { + ExReleaseFastMutex(&Ccb->DataListLock); + DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus); + return OriginalStatus; + } + Context = CONTAINING_RECORD(Ccb->ReadRequestListHead.Flink, NPFS_CONTEXT, ListEntry); + Irp = CONTAINING_RECORD(Context, IRP, Tail.Overlay.DriverContext); + } + } + +done: + Irp->IoStatus.Status = Status; + + if (Status != STATUS_PENDING) + { + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + DPRINT("NpfsRead done (Status %lx)\n", Status); + + return Status; +} + +NTSTATUS STDCALL +NpfsWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + PNPFS_FCB Fcb = NULL; + PNPFS_CCB Ccb = NULL; + PNPFS_CCB ReaderCcb; + PUCHAR Buffer; + NTSTATUS Status = STATUS_SUCCESS; + ULONG Length; + ULONG Offset; + ULONG Information; + ULONG CopyLength; + ULONG TempLength; + + DPRINT("NpfsWrite()\n"); + + IoStack = IoGetCurrentIrpStackLocation(Irp); + FileObject = IoStack->FileObject; + DPRINT("FileObject %p\n", FileObject); + DPRINT("Pipe name %wZ\n", &FileObject->FileName); + + Ccb = FileObject->FsContext2; + ReaderCcb = Ccb->OtherSide; + Fcb = Ccb->Fcb; + + Length = IoStack->Parameters.Write.Length; + Offset = IoStack->Parameters.Write.ByteOffset.u.LowPart; + Information = 0; + + if (Irp->MdlAddress == NULL) + { + DPRINT("Irp->MdlAddress == NULL\n"); + Status = STATUS_UNSUCCESSFUL; + Length = 0; + goto done; + } + + if (ReaderCcb == NULL) + { + DPRINT("Pipe is NOT connected!\n"); + if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE) + Status = STATUS_PIPE_LISTENING; + else if (Ccb->PipeState == FILE_PIPE_DISCONNECTED_STATE) + Status = STATUS_PIPE_DISCONNECTED; + else + Status = STATUS_UNSUCCESSFUL; + Length = 0; + goto done; + } + + if (ReaderCcb->Data == NULL) + { + DPRINT("Pipe is NOT writable!\n"); + Status = STATUS_UNSUCCESSFUL; + Length = 0; + goto done; + } + + Status = STATUS_SUCCESS; + Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress); + + ExAcquireFastMutex(&ReaderCcb->DataListLock); +#ifndef NDEBUG + DPRINT("Length %d Buffer %x Offset %x\n",Length,Buffer,Offset); + HexDump(Buffer, Length); +#endif + + while(1) + { + if (ReaderCcb->WriteQuotaAvailable == 0) + { + KeSetEvent(&ReaderCcb->ReadEvent, IO_NO_INCREMENT, FALSE); + if (Ccb->PipeState != FILE_PIPE_CONNECTED_STATE) + { + Status = STATUS_PIPE_BROKEN; + ExReleaseFastMutex(&ReaderCcb->DataListLock); + goto done; + } + ExReleaseFastMutex(&ReaderCcb->DataListLock); + + DPRINT("Waiting for buffer space (%S)\n", Fcb->PipeName.Buffer); + Status = KeWaitForSingleObject(&Ccb->WriteEvent, + UserRequest, + KernelMode, + FALSE, + NULL); + DPRINT("Finished waiting (%S)! Status: %x\n", Fcb->PipeName.Buffer, Status); + + /* + * It's possible that the event was signaled because the + * other side of pipe was closed. + */ + if (Ccb->PipeState != FILE_PIPE_CONNECTED_STATE) + { + DPRINT("PipeState: %x\n", Ccb->PipeState); + Status = STATUS_PIPE_BROKEN; + // ExReleaseFastMutex(&ReaderCcb->DataListLock); + goto done; + } + + ExAcquireFastMutex(&ReaderCcb->DataListLock); + } + + if (Fcb->WriteMode == FILE_PIPE_BYTE_STREAM_MODE) + { + DPRINT("Byte stream mode\n"); + while (Length > 0 && ReaderCcb->WriteQuotaAvailable > 0) + { + CopyLength = min(Length, ReaderCcb->WriteQuotaAvailable); + if ((ULONG_PTR)ReaderCcb->WritePtr + CopyLength <= (ULONG_PTR)ReaderCcb->Data + ReaderCcb->MaxDataLength) + { + memcpy(ReaderCcb->WritePtr, Buffer, CopyLength); + ReaderCcb->WritePtr = (PVOID)((ULONG_PTR)ReaderCcb->WritePtr + CopyLength); + if ((ULONG_PTR)ReaderCcb->WritePtr == (ULONG_PTR)ReaderCcb->Data + ReaderCcb->MaxDataLength) + { + ReaderCcb->WritePtr = ReaderCcb->Data; + } + } + else + { + TempLength = (ULONG)((ULONG_PTR)ReaderCcb->Data + ReaderCcb->MaxDataLength - (ULONG_PTR)ReaderCcb->WritePtr); + memcpy(ReaderCcb->WritePtr, Buffer, TempLength); + memcpy(ReaderCcb->Data, Buffer + TempLength, CopyLength - TempLength); + ReaderCcb->WritePtr = (PVOID)((ULONG_PTR)ReaderCcb->Data + CopyLength - TempLength); + } + + Buffer += CopyLength; + Length -= CopyLength; + Information += CopyLength; + + ReaderCcb->ReadDataAvailable += CopyLength; + ReaderCcb->WriteQuotaAvailable -= CopyLength; + } + + if (Length == 0) + { + KeSetEvent(&ReaderCcb->ReadEvent, IO_NO_INCREMENT, FALSE); + KeResetEvent(&Ccb->WriteEvent); + break; + } + } + else + { + DPRINT("Message mode\n"); + if (Length > 0) + { + CopyLength = min(Length, ReaderCcb->WriteQuotaAvailable); + memcpy(ReaderCcb->Data, Buffer, CopyLength); + + Information = CopyLength; + ReaderCcb->ReadDataAvailable = CopyLength; + ReaderCcb->WriteQuotaAvailable = 0; + } + + if (Information > 0) + { + KeSetEvent(&ReaderCcb->ReadEvent, IO_NO_INCREMENT, FALSE); + KeResetEvent(&Ccb->WriteEvent); + break; + } + } + } + + ExReleaseFastMutex(&ReaderCcb->DataListLock); + +done: + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Information; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + DPRINT("NpfsWrite done (Status %lx)\n", Status); + + return Status; +} + +/* EOF */
Propchange: trunk/reactos/drivers/filesystems/npfs_new/rw.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/drivers/filesystems/npfs_new/volume.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/npfs_ne... ============================================================================== --- trunk/reactos/drivers/filesystems/npfs_new/volume.c (added) +++ trunk/reactos/drivers/filesystems/npfs_new/volume.c Fri May 4 14:15:00 2007 @@ -1,0 +1,19 @@ +/* + * PROJECT: ReactOS Drivers + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/filesystems/npfs/volume.c + * PURPOSE: Named pipe filesystem + * PROGRAMMERS: + */ + +/* INCLUDES *****************************************************************/ + +#include "npfs.h" + +//#define NDEBUG +#include <debug.h> + +/* FUNCTIONS ****************************************************************/ + + +/* EOF */
Propchange: trunk/reactos/drivers/filesystems/npfs_new/volume.c ------------------------------------------------------------------------------ svn:eol-style = native