- Implement NpQueryClientProcess and NpSetClientProcess
- Add a fast I/O dispatch table and implement NpFastRead and NpFastWrite
The NPFS driver is now good enough to boot Windows 2003 to desktop!

svn path=/trunk/; revision=61906
This commit is contained in:
Timo Kreuzer 2014-02-01 20:41:16 +00:00
parent e61f3d956b
commit 005703c2dc
5 changed files with 295 additions and 15 deletions

View file

@ -53,10 +53,86 @@ NpInternalWrite(IN PDEVICE_OBJECT DeviceObject,
NTSTATUS NTSTATUS
NTAPI NTAPI
NpQueryClientProcess(IN PDEVICE_OBJECT DeviceObject, NpQueryClientProcess(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) IN PIRP Irp)
{ {
UNIMPLEMENTED; PIO_STACK_LOCATION IoStackLocation;
return STATUS_NOT_IMPLEMENTED; 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 NTSTATUS
@ -64,8 +140,72 @@ NTAPI
NpSetClientProcess(IN PDEVICE_OBJECT DeviceObject, NpSetClientProcess(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) IN PIRP Irp)
{ {
UNIMPLEMENTED; PIO_STACK_LOCATION IoStackLocation;
return STATUS_NOT_IMPLEMENTED; 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 NTSTATUS
@ -201,7 +341,7 @@ NpListen(IN PDEVICE_OBJECT DeviceObject,
NTSTATUS NTSTATUS
NTAPI NTAPI
NpPeek(IN PDEVICE_OBJECT DeviceObject, NpPeek(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp, IN PIRP Irp,
IN PLIST_ENTRY List) IN PLIST_ENTRY List)
{ {
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IoStack;
@ -490,7 +630,7 @@ NpTransceive(IN PDEVICE_OBJECT DeviceObject,
} }
if (!NT_SUCCESS(Status)) goto Quickie; if (!NT_SUCCESS(Status)) goto Quickie;
if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
ASSERT(ReadQueue->QueueState == Empty); ASSERT(ReadQueue->QueueState == Empty);
Status = NpAddDataQueueEntry(NamedPipeEnd, Status = NpAddDataQueueEntry(NamedPipeEnd,
@ -648,7 +788,7 @@ NpCommonFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
NpAcquireSharedVcb(); NpAcquireSharedVcb();
Status = NpInternalTransceive(DeviceObject, Irp, &DeferredList); Status = NpInternalTransceive(DeviceObject, Irp, &DeferredList);
break; break;
case FSCTL_PIPE_INTERNAL_READ_OVFLOW: case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
Overflow = TRUE; Overflow = TRUE;
// on purpose // on purpose

View file

@ -20,6 +20,14 @@ PVOID NpAliases;
PNPFS_ALIAS NpAliasList; PNPFS_ALIAS NpAliasList;
PNPFS_ALIAS NpAliasListByLength[MAX_INDEXED_LENGTH + 1 - MIN_INDEXED_LENGTH]; PNPFS_ALIAS NpAliasListByLength[MAX_INDEXED_LENGTH + 1 - MIN_INDEXED_LENGTH];
FAST_IO_DISPATCH NpFastIoDispatch =
{
sizeof(FAST_IO_DISPATCH),
NULL,
NpFastRead,
NpFastWrite,
};
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
NTSTATUS NTSTATUS
@ -311,6 +319,7 @@ NpFsdDirectoryControl(IN PDEVICE_OBJECT DeviceObject,
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
NTSTATUS NTSTATUS
NTAPI NTAPI
DriverEntry(IN PDRIVER_OBJECT DriverObject, DriverEntry(IN PDRIVER_OBJECT DriverObject,
@ -321,7 +330,7 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
NTSTATUS Status; NTSTATUS Status;
UNREFERENCED_PARAMETER(RegistryPath); UNREFERENCED_PARAMETER(RegistryPath);
DPRINT1("Next-Generation NPFS-Lite\n"); DPRINT1("Next-Generation NPFS-Advanced\n");
Status = NpInitializeAliases(); Status = NpInitializeAliases();
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -347,6 +356,8 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
DriverObject->DriverUnload = NULL; DriverObject->DriverUnload = NULL;
DriverObject->FastIoDispatch = &NpFastIoDispatch;
RtlInitUnicodeString(&DeviceName, L"\\Device\\NamedPipe"); RtlInitUnicodeString(&DeviceName, L"\\Device\\NamedPipe");
Status = IoCreateDevice(DriverObject, Status = IoCreateDevice(DriverObject,
sizeof(NP_VCB), sizeof(NP_VCB),

View file

@ -360,6 +360,18 @@ typedef struct _NPFS_QUERY_VALUE_CONTEXT
extern PNPFS_ALIAS NpAliasList; extern PNPFS_ALIAS NpAliasList;
extern PNPFS_ALIAS NpAliasListByLength[MAX_INDEXED_LENGTH + 1 - MIN_INDEXED_LENGTH]; 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 ******************************************************************/ /* FUNCTIONS ******************************************************************/
// //
@ -674,6 +686,34 @@ NTAPI
NpFsdRead(IN PDEVICE_OBJECT DeviceObject, NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp); 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 NTSTATUS
NTAPI NTAPI

View file

@ -16,6 +16,8 @@
/* GLOBALS ********************************************************************/ /* GLOBALS ********************************************************************/
LONG NpSlowReadCalls; LONG NpSlowReadCalls;
ULONG NpFastReadTrue;
ULONG NpFastReadFalse;
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
@ -23,8 +25,8 @@ BOOLEAN
NTAPI NTAPI
NpCommonRead(IN PFILE_OBJECT FileObject, NpCommonRead(IN PFILE_OBJECT FileObject,
IN PVOID Buffer, IN PVOID Buffer,
IN ULONG BufferSize, IN ULONG BufferSize,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PIRP Irp, IN PIRP Irp,
IN PLIST_ENTRY List) IN PLIST_ENTRY List)
{ {
@ -190,4 +192,46 @@ NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
return IoStatus.Status; 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 */ /* EOF */

View file

@ -16,6 +16,8 @@
/* GLOBALS ********************************************************************/ /* GLOBALS ********************************************************************/
LONG NpSlowWriteCalls; LONG NpSlowWriteCalls;
ULONG NpFastWriteTrue;
ULONG NpFastWriteFalse;
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
@ -23,10 +25,10 @@ BOOLEAN
NTAPI NTAPI
NpCommonWrite(IN PFILE_OBJECT FileObject, NpCommonWrite(IN PFILE_OBJECT FileObject,
IN PVOID Buffer, IN PVOID Buffer,
IN ULONG DataSize, IN ULONG DataSize,
IN PETHREAD Thread, IN PETHREAD Thread,
IN PIO_STATUS_BLOCK IoStatus, IN PIO_STATUS_BLOCK IoStatus,
IN PIRP Irp, IN PIRP Irp,
IN PLIST_ENTRY List) IN PLIST_ENTRY List)
{ {
NODE_TYPE_CODE NodeType; NODE_TYPE_CODE NodeType;
@ -207,4 +209,47 @@ NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
return IoStatus.Status; 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 */ /* EOF */