diff --git a/reactos/drivers/filesystems/npfs/fsctrl.c b/reactos/drivers/filesystems/npfs/fsctrl.c index 10288a7d0d5..dc3526d35ea 100644 --- a/reactos/drivers/filesystems/npfs/fsctrl.c +++ b/reactos/drivers/filesystems/npfs/fsctrl.c @@ -53,10 +53,86 @@ NpInternalWrite(IN PDEVICE_OBJECT DeviceObject, NTSTATUS NTAPI NpQueryClientProcess(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) + IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PIO_STACK_LOCATION IoStackLocation; + NODE_TYPE_CODE NodeTypeCode; + PNP_CCB Ccb; + PNP_CLIENT_PROCESS ClientSession, QueryBuffer; + ULONG Length; + PAGED_CODE(); + + /* Get the current stack location */ + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + /* Decode the file object and check the node type */ + NodeTypeCode = NpDecodeFileObject(IoStackLocation->FileObject, 0, &Ccb, 0); + if (NodeTypeCode != NPFS_NTC_CCB) + { + return STATUS_PIPE_DISCONNECTED; + } + + /* Get the length of the query buffer */ + Length = IoStackLocation->Parameters.QueryFile.Length; + if (Length < 8) + { + return STATUS_INVALID_PARAMETER; + } + + QueryBuffer = Irp->AssociatedIrp.SystemBuffer; + + /* Lock the Ccb */ + ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE); + + /* Get the CCBs client session and check if it's set */ + ClientSession = Ccb->ClientSession; + if (ClientSession != NULL) + { + /* Copy first 2 fields */ + QueryBuffer->Unknown = ClientSession->Unknown; + QueryBuffer->Process = ClientSession->Process; + } + else + { + /* Copy the process from the CCB */ + QueryBuffer->Unknown = NULL; + QueryBuffer->Process = Ccb->Process; + } + + /* Does the caller provide a large enough buffer for the full data? */ + if (Length >= sizeof(NP_CLIENT_PROCESS)) + { + Irp->IoStatus.Information = sizeof(NP_CLIENT_PROCESS); + + /* Do we have a ClientSession structure? */ + if (ClientSession != NULL) + { + /* Copy length and the data */ + QueryBuffer->DataLength = ClientSession->DataLength; + RtlCopyMemory(QueryBuffer->Buffer, + ClientSession->Buffer, + ClientSession->DataLength); + + /* NULL terminate the buffer */ + NT_ASSERT(QueryBuffer->DataLength <= 30); + QueryBuffer->Buffer[QueryBuffer->DataLength / sizeof(WCHAR)] = 0; + } + else + { + /* No data */ + QueryBuffer->DataLength = 0; + QueryBuffer->Buffer[0] = 0; + } + } + else + { + Irp->IoStatus.Information = FIELD_OFFSET(NP_CLIENT_PROCESS, DataLength); + } + + /* Unlock the Ccb */ + ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); + + return STATUS_SUCCESS; } NTSTATUS @@ -64,8 +140,72 @@ NTAPI NpSetClientProcess(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PIO_STACK_LOCATION IoStackLocation; + NODE_TYPE_CODE NodeTypeCode; + PNP_CCB Ccb; + ULONG Length; + PNP_CLIENT_PROCESS InputBuffer, ClientSession, OldClientSession; + PAGED_CODE(); + + /* Get the current stack location */ + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + /* Only kernel calls are allowed! */ + if (IoStackLocation->MinorFunction != IRP_MN_KERNEL_CALL) + { + return STATUS_ACCESS_DENIED; + } + + /* Decode the file object and check the node type */ + NodeTypeCode = NpDecodeFileObject(IoStackLocation->FileObject, 0, &Ccb, 0); + if (NodeTypeCode != NPFS_NTC_CCB) + { + return STATUS_PIPE_DISCONNECTED; + } + + /* Get the length of the query buffer and check if it's valid */ + Length = IoStackLocation->Parameters.QueryFile.Length; + if (Length != sizeof(NP_CLIENT_PROCESS)) + { + return STATUS_INVALID_PARAMETER; + } + + /* Get the buffer and check if the data Length is valid */ + InputBuffer = Irp->AssociatedIrp.SystemBuffer; + if (InputBuffer->DataLength > 30) + { + return STATUS_INVALID_PARAMETER; + } + + /* Allocate a new structure */ + ClientSession = ExAllocatePoolWithQuotaTag(PagedPool, + sizeof(NP_CLIENT_PROCESS), + 'iFpN'); + + /* Copy the full input buffer */ + RtlCopyMemory(ClientSession, InputBuffer, sizeof(NP_CLIENT_PROCESS)); + + /* Lock the Ccb */ + ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE); + + /* Get the old ClientSession and set the new */ + OldClientSession = Ccb->ClientSession; + Ccb->ClientSession = ClientSession; + + /* Copy the process to the CCB */ + Ccb->Process = ClientSession->Process; + + /* Unlock the Ccb */ + ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); + + /* Check if there was already a ClientSession */ + if (OldClientSession != NULL) + { + /* Free it */ + ExFreePoolWithTag(OldClientSession, 'iFpN'); + } + + return STATUS_SUCCESS; } NTSTATUS @@ -201,7 +341,7 @@ NpListen(IN PDEVICE_OBJECT DeviceObject, NTSTATUS NTAPI NpPeek(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, + IN PIRP Irp, IN PLIST_ENTRY List) { PIO_STACK_LOCATION IoStack; @@ -490,7 +630,7 @@ NpTransceive(IN PDEVICE_OBJECT DeviceObject, } if (!NT_SUCCESS(Status)) goto Quickie; - + if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); ASSERT(ReadQueue->QueueState == Empty); Status = NpAddDataQueueEntry(NamedPipeEnd, @@ -648,7 +788,7 @@ NpCommonFileSystemControl(IN PDEVICE_OBJECT DeviceObject, NpAcquireSharedVcb(); Status = NpInternalTransceive(DeviceObject, Irp, &DeferredList); break; - + case FSCTL_PIPE_INTERNAL_READ_OVFLOW: Overflow = TRUE; // on purpose diff --git a/reactos/drivers/filesystems/npfs/main.c b/reactos/drivers/filesystems/npfs/main.c index c30d64e2a17..d45e00deb72 100644 --- a/reactos/drivers/filesystems/npfs/main.c +++ b/reactos/drivers/filesystems/npfs/main.c @@ -20,6 +20,14 @@ PVOID NpAliases; PNPFS_ALIAS NpAliasList; PNPFS_ALIAS NpAliasListByLength[MAX_INDEXED_LENGTH + 1 - MIN_INDEXED_LENGTH]; +FAST_IO_DISPATCH NpFastIoDispatch = +{ + sizeof(FAST_IO_DISPATCH), + NULL, + NpFastRead, + NpFastWrite, +}; + /* FUNCTIONS ******************************************************************/ NTSTATUS @@ -311,6 +319,7 @@ NpFsdDirectoryControl(IN PDEVICE_OBJECT DeviceObject, return STATUS_NOT_IMPLEMENTED; } + NTSTATUS NTAPI DriverEntry(IN PDRIVER_OBJECT DriverObject, @@ -321,7 +330,7 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, NTSTATUS Status; UNREFERENCED_PARAMETER(RegistryPath); - DPRINT1("Next-Generation NPFS-Lite\n"); + DPRINT1("Next-Generation NPFS-Advanced\n"); Status = NpInitializeAliases(); if (!NT_SUCCESS(Status)) @@ -347,6 +356,8 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, DriverObject->DriverUnload = NULL; + DriverObject->FastIoDispatch = &NpFastIoDispatch; + RtlInitUnicodeString(&DeviceName, L"\\Device\\NamedPipe"); Status = IoCreateDevice(DriverObject, sizeof(NP_VCB), diff --git a/reactos/drivers/filesystems/npfs/npfs.h b/reactos/drivers/filesystems/npfs/npfs.h index c33ce43fe3e..7bc2fbf080a 100644 --- a/reactos/drivers/filesystems/npfs/npfs.h +++ b/reactos/drivers/filesystems/npfs/npfs.h @@ -360,6 +360,18 @@ typedef struct _NPFS_QUERY_VALUE_CONTEXT extern PNPFS_ALIAS NpAliasList; extern PNPFS_ALIAS NpAliasListByLength[MAX_INDEXED_LENGTH + 1 - MIN_INDEXED_LENGTH]; +// +// This structure is actually a user-mode structure and should go into a share header +// +typedef struct _NP_CLIENT_PROCESS +{ + PVOID Unknown; + PVOID Process; + USHORT DataLength; + WCHAR Buffer[17]; +} NP_CLIENT_PROCESS, *PNP_CLIENT_PROCESS; + + /* FUNCTIONS ******************************************************************/ // @@ -674,6 +686,34 @@ NTAPI NpFsdRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); +_Function_class_(FAST_IO_READ) +_IRQL_requires_same_ +BOOLEAN +NTAPI +NpFastRead( + _In_ PFILE_OBJECT FileObject, + _In_ PLARGE_INTEGER FileOffset, + _In_ ULONG Length, + _In_ BOOLEAN Wait, + _In_ ULONG LockKey, + _Out_ PVOID Buffer, + _Out_ PIO_STATUS_BLOCK IoStatus, + _In_ PDEVICE_OBJECT DeviceObject); + +_Function_class_(FAST_IO_WRITE) +_IRQL_requires_same_ +BOOLEAN +NTAPI +NpFastWrite( + _In_ PFILE_OBJECT FileObject, + _In_ PLARGE_INTEGER FileOffset, + _In_ ULONG Length, + _In_ BOOLEAN Wait, + _In_ ULONG LockKey, + _In_ PVOID Buffer, + _Out_ PIO_STATUS_BLOCK IoStatus, + _In_ PDEVICE_OBJECT DeviceObject); + NTSTATUS NTAPI diff --git a/reactos/drivers/filesystems/npfs/read.c b/reactos/drivers/filesystems/npfs/read.c index 4189868e518..60e48d3af65 100644 --- a/reactos/drivers/filesystems/npfs/read.c +++ b/reactos/drivers/filesystems/npfs/read.c @@ -16,6 +16,8 @@ /* GLOBALS ********************************************************************/ LONG NpSlowReadCalls; +ULONG NpFastReadTrue; +ULONG NpFastReadFalse; /* FUNCTIONS ******************************************************************/ @@ -23,8 +25,8 @@ BOOLEAN NTAPI NpCommonRead(IN PFILE_OBJECT FileObject, IN PVOID Buffer, - IN ULONG BufferSize, - OUT PIO_STATUS_BLOCK IoStatus, + IN ULONG BufferSize, + OUT PIO_STATUS_BLOCK IoStatus, IN PIRP Irp, IN PLIST_ENTRY List) { @@ -190,4 +192,46 @@ NpFsdRead(IN PDEVICE_OBJECT DeviceObject, return IoStatus.Status; } + +_Function_class_(FAST_IO_READ) +_IRQL_requires_same_ +BOOLEAN +NTAPI +NpFastRead( + _In_ PFILE_OBJECT FileObject, + _In_ PLARGE_INTEGER FileOffset, + _In_ ULONG Length, + _In_ BOOLEAN Wait, + _In_ ULONG LockKey, + _Out_ PVOID Buffer, + _Out_ PIO_STATUS_BLOCK IoStatus, + _In_ PDEVICE_OBJECT DeviceObject) +{ + LIST_ENTRY DeferredList; + BOOLEAN Result; + PAGED_CODE(); + + InitializeListHead(&DeferredList); + + FsRtlEnterFileSystem(); + NpAcquireSharedVcb(); + + Result = NpCommonRead(FileObject, + Buffer, + Length, + IoStatus, + NULL, + &DeferredList); + if (Result) + ++NpFastReadTrue; + else + ++NpFastReadFalse; + + NpReleaseVcb(); + NpCompleteDeferredIrps(&DeferredList); + FsRtlExitFileSystem(); + + return Result; +} + /* EOF */ diff --git a/reactos/drivers/filesystems/npfs/write.c b/reactos/drivers/filesystems/npfs/write.c index f8aa1500f39..7297a5bf7a2 100644 --- a/reactos/drivers/filesystems/npfs/write.c +++ b/reactos/drivers/filesystems/npfs/write.c @@ -16,6 +16,8 @@ /* GLOBALS ********************************************************************/ LONG NpSlowWriteCalls; +ULONG NpFastWriteTrue; +ULONG NpFastWriteFalse; /* FUNCTIONS ******************************************************************/ @@ -23,10 +25,10 @@ BOOLEAN NTAPI NpCommonWrite(IN PFILE_OBJECT FileObject, IN PVOID Buffer, - IN ULONG DataSize, - IN PETHREAD Thread, - IN PIO_STATUS_BLOCK IoStatus, - IN PIRP Irp, + IN ULONG DataSize, + IN PETHREAD Thread, + IN PIO_STATUS_BLOCK IoStatus, + IN PIRP Irp, IN PLIST_ENTRY List) { NODE_TYPE_CODE NodeType; @@ -207,4 +209,47 @@ NpFsdWrite(IN PDEVICE_OBJECT DeviceObject, return IoStatus.Status; } + +_Function_class_(FAST_IO_WRITE) +_IRQL_requires_same_ +BOOLEAN +NTAPI +NpFastWrite( + _In_ PFILE_OBJECT FileObject, + _In_ PLARGE_INTEGER FileOffset, + _In_ ULONG Length, + _In_ BOOLEAN Wait, + _In_ ULONG LockKey, + _In_ PVOID Buffer, + _Out_ PIO_STATUS_BLOCK IoStatus, + _In_ PDEVICE_OBJECT DeviceObject) +{ + LIST_ENTRY DeferredList; + BOOLEAN Result; + PAGED_CODE(); + + InitializeListHead(&DeferredList); + + FsRtlEnterFileSystem(); + NpAcquireSharedVcb(); + + Result = NpCommonWrite(FileObject, + Buffer, + Length, + PsGetCurrentThread(), + IoStatus, + NULL, + &DeferredList); + if (Result) + ++NpFastWriteTrue; + else + ++NpFastWriteFalse; + + NpReleaseVcb(); + NpCompleteDeferredIrps(&DeferredList); + FsRtlExitFileSystem(); + + return Result; +} + /* EOF */