[NPFS-NEW]: Add data queue management routines, and add read support. Implement NpFsdRead & NpfsCommonRead (Peek is inherently implemented too, just didn't write the FSCTL handlers yet). Next up will be Write/Peek/Close/Cleanup. Code is WIP.

svn path=/trunk/; revision=59998
This commit is contained in:
Alex Ionescu 2013-09-09 01:16:06 +00:00
parent 2976384615
commit b5edd2ce20
7 changed files with 934 additions and 42 deletions

View file

@ -1,17 +1,20 @@
list(APPEND SOURCE
create.c
datasup.c
fileobsup.c
main.c
prefxsup.c
secursup.c
statesup.c
strucsup.c
waitsup.c)
create.c
datasup.c
fileobsup.c
main.c
prefxsup.c
read.c
readsup.c
secursup.c
statesup.c
strucsup.c
waitsup.c)
add_library(npfs_new SHARED ${SOURCE})
set_module_type(npfs_new kernelmodedriver)
target_link_libraries(npfs_new ${PSEH_LIB})
add_importlibs(npfs_new ntoskrnl hal)
add_pch(npfs_new npfs.h)
add_cd_file(TARGET npfs_new DESTINATION reactos/system32/drivers FOR all)

View file

@ -25,6 +25,435 @@ NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue,
DataQueue->ByteOffset = 0;
DataQueue->QueueState = Empty;
DataQueue->Quota = Quota;
InitializeListHead(&DataQueue->List);
InitializeListHead(&DataQueue->Queue);
return STATUS_SUCCESS;
}
VOID
NTAPI
NpCompleteStalledWrites(IN PNP_DATA_QUEUE DataQueue,
IN PLIST_ENTRY List)
{
ULONG QuotaLeft, ByteOffset, DataLeft, NewQuotaLeft;
PNP_DATA_QUEUE_ENTRY DataQueueEntry;
PIRP Irp;
PLIST_ENTRY NextEntry;
QuotaLeft = DataQueue->Quota - DataQueue->QuotaUsed;
ByteOffset = DataQueue->ByteOffset;
NextEntry = DataQueue->Queue.Flink;
while (NextEntry != &DataQueue->Queue)
{
if ( !QuotaLeft ) break;
DataQueueEntry = CONTAINING_RECORD(NextEntry, NP_DATA_QUEUE_ENTRY, Irp);
Irp = DataQueueEntry->Irp;
if ((DataQueueEntry->DataEntryType == 0) && (Irp))
{
DataLeft = DataQueueEntry->DataSize - ByteOffset;
if ( DataQueueEntry->QuotaInEntry < DataLeft )
{
NewQuotaLeft = DataLeft - DataQueueEntry->QuotaInEntry;
if ( NewQuotaLeft > QuotaLeft ) NewQuotaLeft = QuotaLeft;
QuotaLeft -= NewQuotaLeft;
DataQueueEntry->QuotaInEntry += NewQuotaLeft;
if (DataQueueEntry->QuotaInEntry == DataLeft &&
IoSetCancelRoutine(Irp, NULL))
{
DataQueueEntry->Irp = NULL;
Irp->IoStatus.Status = 0;
Irp->IoStatus.Information = DataQueueEntry->DataSize;
InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
}
}
}
NextEntry = NextEntry->Flink;
ByteOffset = 0;
}
DataQueue->QuotaUsed = DataQueue->Quota - QuotaLeft;
}
PIRP
NTAPI
NpRemoveDataQueueEntry(IN PNP_DATA_QUEUE DataQueue,
IN BOOLEAN Flag,
IN PLIST_ENTRY List)
{
PIRP Irp;
PNP_DATA_QUEUE_ENTRY QueueEntry;
BOOLEAN HasWrites;
if ( DataQueue->QueueState == Empty)
{
Irp = NULL;
ASSERT(IsListEmpty(&DataQueue->Queue));
ASSERT(DataQueue->EntriesInQueue == 0);
ASSERT(DataQueue->BytesInQueue == 0);
ASSERT(DataQueue->QuotaUsed == 0);
}
else
{
QueueEntry = CONTAINING_RECORD(RemoveHeadList(&DataQueue->Queue),
NP_DATA_QUEUE_ENTRY,
QueueEntry);
DataQueue->BytesInQueue -= QueueEntry->DataSize;
--DataQueue->EntriesInQueue;
HasWrites = 1;
if ( !DataQueue->QueueState != WriteEntries || DataQueue->QuotaUsed < DataQueue->Quota || !QueueEntry->QuotaInEntry )
{
HasWrites = 0;
}
DataQueue->QuotaUsed -= QueueEntry->QuotaInEntry;
if (DataQueue->Queue.Flink == &DataQueue->Queue)
{
DataQueue->QueueState = Empty;
HasWrites = 0;
}
Irp = QueueEntry->Irp;
NpFreeClientSecurityContext(QueueEntry->ClientSecurityContext);
if (Irp && IoSetCancelRoutine(Irp, NULL))
{
Irp->Tail.Overlay.DriverContext[3] = 0;
}
ExFreePool(QueueEntry);
if ( Flag )
{
NpGetNextRealDataQueueEntry(DataQueue, List);
}
if ( HasWrites )
{
NpCompleteStalledWrites(DataQueue, List);
}
}
DataQueue->ByteOffset = 0;
return Irp;
}
PNP_DATA_QUEUE_ENTRY
NTAPI
NpGetNextRealDataQueueEntry(IN PNP_DATA_QUEUE DataQueue,
IN PLIST_ENTRY List)
{
PNP_DATA_QUEUE_ENTRY DataEntry;
ULONG Type;
PIRP Irp;
PLIST_ENTRY NextEntry;
PAGED_CODE();
DataEntry = NULL;
NextEntry = DataQueue->Queue.Flink;
while (NextEntry != &DataQueue->Queue)
{
DataEntry = CONTAINING_RECORD(NextEntry, NP_DATA_QUEUE_ENTRY, QueueEntry);
Type = DataEntry->DataEntryType;
if ( Type == Buffered || Type == Unbuffered ) break;
Irp = NpRemoveDataQueueEntry(DataQueue, 0, List);
if ( Irp )
{
Irp->IoStatus.Status = STATUS_SUCCESS;
InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
}
}
return DataEntry;
}
VOID
NTAPI
NpCancelDataQueueIrp(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PNP_DATA_QUEUE DataQueue;
PNP_DATA_QUEUE_ENTRY DataEntry;
LIST_ENTRY List;
PSECURITY_CLIENT_CONTEXT ClientSecurityContext;
BOOLEAN CompleteWrites, FirstEntry;
PLIST_ENTRY NextEntry, ThisEntry;
if ( DeviceObject ) IoReleaseCancelSpinLock(Irp->CancelIrql);
InitializeListHead(&List);
DataQueue = (PNP_DATA_QUEUE)Irp->Tail.Overlay.DriverContext[2];
ClientSecurityContext = NULL;
if ( DeviceObject )
{
FsRtlEnterFileSystem();
ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
}
DataEntry = (PNP_DATA_QUEUE_ENTRY)Irp->Tail.Overlay.DriverContext[3];
if ( DataEntry )
{
if (DataEntry->QueueEntry.Blink == &DataQueue->Queue )
{
DataQueue->ByteOffset = 0;
FirstEntry = 1;
}
else
{
FirstEntry = 0;
}
RemoveEntryList(&DataEntry->QueueEntry);
ClientSecurityContext = DataEntry->ClientSecurityContext;
CompleteWrites = 1;
if ( !DataQueue->QueueState != WriteEntries || DataQueue->QuotaUsed < DataQueue->Quota || !DataEntry->QuotaInEntry )
{
CompleteWrites = 0;
}
DataQueue->BytesInQueue -= DataEntry->DataSize;
DataQueue->QuotaUsed -= DataEntry->QuotaInEntry;
--DataQueue->EntriesInQueue;
if (DataQueue->Queue.Flink == &DataQueue->Queue )
{
DataQueue->QueueState = Empty;
ASSERT(DataQueue->BytesInQueue == 0);
ASSERT(DataQueue->EntriesInQueue == 0);
ASSERT(DataQueue->QuotaUsed == 0);
}
else
{
if ( FirstEntry )
{
NpGetNextRealDataQueueEntry(DataQueue, &List);
}
if ( CompleteWrites )
{
NpCompleteStalledWrites(DataQueue, &List);
}
}
}
if ( DeviceObject )
{
ExReleaseResourceLite(&NpVcb->Lock);
FsRtlExitFileSystem();
}
if ( DataEntry ) ExFreePool(DataEntry);
NpFreeClientSecurityContext(ClientSecurityContext);
Irp->IoStatus.Status = STATUS_CANCELLED;
IofCompleteRequest(Irp, IO_DISK_INCREMENT);
NextEntry = List.Flink;
while (NextEntry != &List)
{
ThisEntry = NextEntry;
NextEntry = NextEntry->Flink;
Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
}
}
NTSTATUS
NTAPI
NpAddDataQueueEntry(IN BOOLEAN ServerSide,
IN PNP_CCB Ccb,
IN PNP_DATA_QUEUE DataQueue,
IN ULONG Who,
IN ULONG Type,
IN ULONG DataSize,
IN PIRP Irp,
IN PVOID Buffer,
IN ULONG ByteOffset)
{
NTSTATUS Status;
PNP_DATA_QUEUE_ENTRY DataEntry;
SIZE_T EntrySize;
ULONG QuotaInEntry;
PSECURITY_CLIENT_CONTEXT ClientContext;
BOOLEAN HasSpace;
ClientContext = NULL;
ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who));
Status = STATUS_SUCCESS;
if ((Type != 2) && (Who == WriteEntries))
{
Status = NpGetClientSecurityContext(ServerSide,
Ccb,
Irp ? Irp->Tail.Overlay.Thread :
PsGetCurrentThread(),
&ClientContext);
if (!NT_SUCCESS(Status)) return Status;
}
switch (Type)
{
case Unbuffered:
case 2:
case 3:
ASSERT(Irp != NULL);
DataEntry = ExAllocatePoolWithQuotaTag(NonPagedPool, sizeof(*DataEntry), 'rFpN');
if ( DataEntry )
{
DataEntry->DataEntryType = Type;
DataEntry->QuotaInEntry = 0;
DataEntry->Irp = Irp;
DataEntry->DataSize = DataSize;
DataEntry->ClientSecurityContext = ClientContext;
ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who));
Status = STATUS_PENDING;
break;
}
NpFreeClientSecurityContext(ClientContext);
return STATUS_INSUFFICIENT_RESOURCES;
case Buffered:
EntrySize = sizeof(*DataEntry);
if ( Who != Empty)
{
EntrySize = DataSize + sizeof(*DataEntry);
if ((DataSize + sizeof(*DataEntry)) < DataSize )
{
NpFreeClientSecurityContext(ClientContext);
return STATUS_INVALID_PARAMETER;
}
}
QuotaInEntry = DataSize - ByteOffset;
if ( DataQueue->Quota - DataQueue->QuotaUsed < QuotaInEntry )
{
QuotaInEntry = DataQueue->Quota - DataQueue->QuotaUsed;
HasSpace = 1;
}
else
{
HasSpace = 0;
}
DataEntry = ExAllocatePoolWithQuotaTag(NonPagedPool, EntrySize, 'rFpN');
if ( !DataEntry )
{
NpFreeClientSecurityContext(ClientContext);
return STATUS_INSUFFICIENT_RESOURCES;
}
DataEntry->QuotaInEntry = QuotaInEntry;
DataEntry->Irp = Irp;
DataEntry->DataEntryType = Buffered;
DataEntry->ClientSecurityContext = ClientContext;
DataEntry->DataSize = DataSize;
if ( Who == ReadEntries)
{
ASSERT(Irp);
Status = STATUS_PENDING;
ASSERT((DataQueue->QueueState == Empty) ||
(DataQueue->QueueState == Who));
}
else
{
_SEH2_TRY
{
RtlCopyMemory(DataEntry + 1,
Irp ? Irp->UserBuffer: Buffer,
DataSize);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
NpFreeClientSecurityContext(ClientContext);
return _SEH2_GetExceptionCode();
}
_SEH2_END;
if ( HasSpace && Irp )
{
Status = STATUS_PENDING;
}
else
{
DataEntry->Irp = 0;
Status = STATUS_SUCCESS;
}
ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who));
}
default:
ASSERT(FALSE);
NpFreeClientSecurityContext(ClientContext);
return STATUS_INVALID_PARAMETER;
}
ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who));
if ( DataQueue->QueueState == Empty )
{
ASSERT(DataQueue->BytesInQueue == 0);
ASSERT(DataQueue->EntriesInQueue == 0);
ASSERT(IsListEmpty (&DataQueue->Queue));
}
else
{
ASSERT(DataQueue->QueueState == Who);
ASSERT(DataQueue->QueueState != Empty);
ASSERT(DataQueue->EntriesInQueue != 0);
}
DataQueue->QuotaUsed += DataEntry->QuotaInEntry;
DataQueue->QueueState = Who;
DataQueue->BytesInQueue += DataEntry->DataSize;
++DataQueue->EntriesInQueue;
if ( ByteOffset )
{
DataQueue->ByteOffset = ByteOffset;
ASSERT(Who == WriteEntries);
ASSERT(ByteOffset < DataEntry->DataSize);
ASSERT(DataQueue->EntriesInQueue == 1);
}
InsertTailList(&DataQueue->Queue, &DataEntry->QueueEntry);
if ( Status == STATUS_PENDING )
{
IoMarkIrpPending(Irp);
Irp->Tail.Overlay.DriverContext[2] = DataQueue;
Irp->Tail.Overlay.DriverContext[3] = DataEntry;
IoSetCancelRoutine(Irp, NpCancelDataQueueIrp);
if ( Irp->Cancel )
{
IoSetCancelRoutine(Irp, NULL);
NpCancelDataQueueIrp(0, Irp);
}
}
return Status;
}

View file

@ -16,20 +16,6 @@ NpFsdClose(IN PDEVICE_OBJECT DeviceObject,
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,

View file

@ -3,6 +3,7 @@
//
#include <ntifs.h>
#include <ntndk.h>
#include <pseh/pseh2.h>
#define UNIMPLEMENTED
#define DPRINT1 DbgPrint
@ -31,15 +32,26 @@ typedef USHORT NODE_TYPE_CODE, *PNODE_TYPE_CODE;
//
typedef enum _NP_DATA_QUEUE_STATE
{
ReadEntries = 0,
WriteEntries = 1,
Empty = 2
} NP_DATA_QUEUE_STATE;
//
// Data Queue Entry Types
//
typedef enum _NP_DATA_QUEUE_ENTRY_TYPE
{
Buffered = 0,
Unbuffered
} NP_DATA_QUEUE_ENTRY_TYPE;
//
// An Input or Output Data Queue. Each CCB has two of these.
//
typedef struct _NP_DATA_QUEUE
{
LIST_ENTRY List;
LIST_ENTRY Queue;
ULONG QueueState;
ULONG BytesInQueue;
ULONG EntriesInQueue;
@ -48,6 +60,19 @@ typedef struct _NP_DATA_QUEUE
ULONG Quota;
} NP_DATA_QUEUE, *PNP_DATA_QUEUE;
//
// The Entries that go into the Queue
//
typedef struct _NP_DATA_QUEUE_ENTRY
{
LIST_ENTRY QueueEntry;
ULONG DataEntryType;
PIRP Irp;
ULONG QuotaInEntry;
PSECURITY_CLIENT_CONTEXT ClientSecurityContext;
ULONG DataSize;
} NP_DATA_QUEUE_ENTRY, *PNP_DATA_QUEUE_ENTRY;
//
// A Wait Queue. Only the VCB has one of these.
//
@ -57,6 +82,14 @@ typedef struct _NP_WAIT_QUEUE
KSPIN_LOCK WaitLock;
} NP_WAIT_QUEUE, *PNP_WAIT_QUEUE;
//
// The event buffer in the NonPaged CCB
//
typedef struct _NP_EVENT_BUFFER
{
PKEVENT Event;
} NP_EVENT_BUFFER, *PNP_EVENT_BUFFER;
//
// The CCB for the Root DCB
//
@ -76,7 +109,7 @@ typedef struct _NP_CB_HEADER
LIST_ENTRY DcbEntry;
PVOID ParentDcb;
ULONG CurrentInstances;
ULONG OtherCount;
ULONG ServerOpenCount;
PSECURITY_DESCRIPTOR SecurityDescriptor;
} NP_CB_HEADER, *PNP_CB_HEADER;
@ -144,8 +177,8 @@ typedef struct _NP_FCB
typedef struct _NP_NONPAGED_CCB
{
NODE_TYPE_CODE NodeType;
PVOID EventBufferClient;
PVOID EventBufferServer;
PNP_EVENT_BUFFER EventBufferClient;
PNP_EVENT_BUFFER EventBufferServer;
ERESOURCE Lock;
} NP_NONPAGED_CCB, *PNP_NONPAGED_CCB;
@ -201,6 +234,34 @@ NTSTATUS
NTAPI
NpUninitializeDataQueue(IN PNP_DATA_QUEUE DataQueue);
PNP_DATA_QUEUE_ENTRY
NTAPI
NpGetNextRealDataQueueEntry(IN PNP_DATA_QUEUE DataQueue,
IN PLIST_ENTRY List);
PIRP
NTAPI
NpRemoveDataQueueEntry(IN PNP_DATA_QUEUE DataQueue,
IN BOOLEAN Flag,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpAddDataQueueEntry(IN BOOLEAN ServerSide,
IN PNP_CCB Ccb,
IN PNP_DATA_QUEUE DataQueue,
IN ULONG Who,
IN ULONG Type,
IN ULONG DataSize,
IN PIRP Irp,
IN PVOID Buffer,
IN ULONG ByteOffset);
VOID
NTAPI
NpCompleteStalledWrites(IN PNP_DATA_QUEUE DataQueue,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue,
@ -265,6 +326,15 @@ NpSetConnectedPipeState(IN PNP_CCB Ccb,
IN PFILE_OBJECT FileObject,
IN PLIST_ENTRY List);
VOID
NTAPI
NpFreeClientSecurityContext(IN PSECURITY_CLIENT_CONTEXT ClientContext);
VOID
NTAPI
NpCopyClientContext(IN PNP_CCB Ccb,
IN PNP_DATA_QUEUE_ENTRY DataQueueEntry);
VOID
NTAPI
NpUninitializeSecurity(IN PNP_CCB Ccb);
@ -275,6 +345,13 @@ NpInitializeSecurity(IN PNP_CCB Ccb,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
IN PETHREAD Thread);
NTSTATUS
NTAPI
NpGetClientSecurityContext(IN BOOLEAN ServerSide,
IN PNP_CCB Ccb,
IN PETHREAD Thread,
IN PSECURITY_CLIENT_CONTEXT *Context);
VOID
NTAPI
NpSetFileObject(IN PFILE_OBJECT FileObject,
@ -316,3 +393,20 @@ NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
IN NTSTATUS Status,
IN PLIST_ENTRY ListEntry);
IO_STATUS_BLOCK
NTAPI
NpReadDataQueue(IN PNP_DATA_QUEUE DataQueue,
IN BOOLEAN Peek,
IN BOOLEAN ReadOverflowOperation,
IN PVOID Buffer,
IN ULONG BufferSize,
IN ULONG Mode,
IN PNP_CCB Ccb,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);

View file

@ -0,0 +1,189 @@
#include "npfs.h"
LONG NpSlowReadCalls;
BOOLEAN
NTAPI
NpCommonRead(IN PFILE_OBJECT FileObject,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT PIO_STATUS_BLOCK IoStatus,
IN PIRP Irp,
IN PLIST_ENTRY List)
{
NODE_TYPE_CODE NodeType;
ULONG NamedPipeConfiguation;
PNP_DATA_QUEUE Queue;
PNP_EVENT_BUFFER EventBuffer;
NTSTATUS Status;
BOOLEAN ServerSide;
PNP_CCB Ccb;
PNP_NONPAGED_CCB NonPagedCcb;
BOOLEAN ReadOk;
PAGED_CODE();
IoStatus->Information = 0;
NodeType = NpDecodeFileObject(FileObject, NULL, &Ccb, &ServerSide);
if (!NodeType)
{
IoStatus->Status = STATUS_PIPE_DISCONNECTED;
return TRUE;
}
if ( NodeType != NPFS_NTC_CCB )
{
IoStatus->Status = STATUS_INVALID_PARAMETER;
return TRUE;
}
NonPagedCcb = Ccb->NonPagedCcb;
ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE);
//ms_exc.registration.TryLevel = 0;
if ( Ccb->NamedPipeState == FILE_PIPE_DISCONNECTED_STATE || Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE )
{
IoStatus->Status = Ccb->NamedPipeState != FILE_PIPE_DISCONNECTED_STATE ? STATUS_PIPE_LISTENING : STATUS_PIPE_DISCONNECTED;
ReadOk = TRUE;
goto Quickie;
}
ASSERT((Ccb->NamedPipeState == FILE_PIPE_CONNECTED_STATE) || (Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE));
NamedPipeConfiguation = Ccb->Fcb->NamedPipeConfiguration;
if ((ServerSide == 1 && NamedPipeConfiguation == FILE_PIPE_OUTBOUND) ||
(ServerSide == 0 && NamedPipeConfiguation == FILE_PIPE_INBOUND) )
{
IoStatus->Status = STATUS_INVALID_PARAMETER;
ReadOk = TRUE;
goto Quickie;
}
if ( ServerSide == 1 )
{
Queue = &Ccb->InQueue;
EventBuffer = NonPagedCcb->EventBufferClient;
}
else
{
Queue = &Ccb->OutQueue;
EventBuffer = NonPagedCcb->EventBufferServer;
}
if ( Queue->QueueState == WriteEntries )
{
*IoStatus = NpReadDataQueue(Queue,
FALSE,
FALSE,
Buffer,
BufferSize,
ServerSide ? Ccb->ServerReadMode : Ccb->ClientReadMode,
Ccb,
List);
if (!NT_SUCCESS(IoStatus->Status))
{
ReadOk = TRUE;
goto Quickie;
}
ReadOk = TRUE;
if ( EventBuffer ) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
goto Quickie;
}
if ( Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE )
{
IoStatus->Status = STATUS_PIPE_BROKEN;
ReadOk = TRUE;
if ( EventBuffer ) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
goto Quickie;
}
if ((ServerSide ? Ccb->ServerCompletionMode : Ccb->ServerCompletionMode) == FILE_PIPE_COMPLETE_OPERATION)
{
IoStatus->Status = STATUS_PIPE_EMPTY;
ReadOk = TRUE;
if ( EventBuffer ) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
goto Quickie;
}
if ( Irp )
{
Status = NpAddDataQueueEntry(ServerSide,
Ccb,
Queue,
0,
0,
BufferSize,
Irp,
0,
0);
IoStatus->Status = Status;
if (!NT_SUCCESS(Status))
{
ReadOk = FALSE;
goto Quickie;
}
ReadOk = TRUE;
if ( EventBuffer ) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
goto Quickie;
}
ReadOk = FALSE;
Quickie:
//ms_exc.registration.TryLevel = -1;
ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
return ReadOk;
}
NTSTATUS
NTAPI
NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
IO_STATUS_BLOCK IoStatus;
LIST_ENTRY List;
PLIST_ENTRY NextEntry, ThisEntry;
PAGED_CODE();
NpSlowReadCalls++;
InitializeListHead(&List);
IoStack = IoGetCurrentIrpStackLocation(Irp);
FsRtlEnterFileSystem();
ExAcquireResourceSharedLite(&NpVcb->Lock, TRUE);
NpCommonRead(IoStack->FileObject,
Irp->UserBuffer,
IoStack->Parameters.Read.Length,
&IoStatus,
Irp,
&List);
ExReleaseResourceLite(&NpVcb->Lock);
NextEntry = List.Flink;
while (NextEntry != &List)
{
ThisEntry = NextEntry;
NextEntry = NextEntry->Flink;
Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
}
FsRtlExitFileSystem();
if ( IoStatus.Status != STATUS_PENDING )
{
Irp->IoStatus.Information = IoStatus.Information;
Irp->IoStatus.Status = IoStatus.Status;
IofCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
}
return IoStatus.Status;
}

View file

@ -0,0 +1,138 @@
#include "npfs.h"
IO_STATUS_BLOCK
NTAPI
NpReadDataQueue(IN PNP_DATA_QUEUE DataQueue,
IN BOOLEAN Peek,
IN BOOLEAN ReadOverflowOperation,
IN PVOID Buffer,
IN ULONG BufferSize,
IN ULONG Mode,
IN PNP_CCB Ccb,
IN PLIST_ENTRY List)
{
PNP_DATA_QUEUE_ENTRY DataEntry, TempDataEntry;
PVOID DataBuffer;
ULONG DataSize, DataLength, TotalBytesCopied, RemainingSize, Offset;
PIRP Irp;
IO_STATUS_BLOCK Status;
BOOLEAN CompleteWrites = FALSE;
PAGED_CODE();
if ( ReadOverflowOperation ) Peek = TRUE;
RemainingSize = BufferSize;
Status.Status = 0;
TotalBytesCopied = 0;
if ( Peek )
{
DataEntry = CONTAINING_RECORD(DataQueue->Queue.Flink,
NP_DATA_QUEUE_ENTRY,
QueueEntry);
}
else
{
DataEntry = NpGetNextRealDataQueueEntry(DataQueue, List);
}
while (&DataEntry->QueueEntry != &DataQueue->Queue && RemainingSize )
{
if ( !Peek || (DataEntry->DataEntryType == Buffered || DataEntry->DataEntryType == Unbuffered ))
{
if ( DataEntry->DataEntryType == Unbuffered )
{
DataBuffer = DataEntry->Irp->AssociatedIrp.SystemBuffer;
}
else
{
DataBuffer = &DataEntry[1];
}
DataSize = DataEntry->DataSize;
Offset = DataSize;
if (&DataEntry->QueueEntry == DataQueue->Queue.Flink)
{
Offset = DataSize - DataQueue->ByteOffset;
}
DataLength = Offset;
if ( Offset >= RemainingSize ) DataLength = RemainingSize;
_SEH2_TRY
{
RtlCopyMemory((PVOID)((ULONG_PTR)Buffer + BufferSize - RemainingSize),
(PVOID)((ULONG_PTR)DataBuffer + DataSize - Offset),
DataLength);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ASSERT(FALSE);
}
_SEH2_END;
RemainingSize -= DataLength;
Offset -= DataLength;
TotalBytesCopied += DataLength;
if ( !Peek )
{
DataEntry->QuotaInEntry -= DataLength;
DataQueue->QuotaUsed -= DataLength;
DataQueue->ByteOffset += DataLength;
CompleteWrites = TRUE;;
}
NpCopyClientContext(Ccb, DataEntry);
if ( Offset || (ReadOverflowOperation && !TotalBytesCopied ))
{
if ( Mode == FILE_PIPE_MESSAGE_MODE )
{
Status.Status = STATUS_BUFFER_OVERFLOW;
break;
}
}
else
{
if ( !Peek || ReadOverflowOperation )
{
if ( ReadOverflowOperation)
{
TempDataEntry = NpGetNextRealDataQueueEntry(DataQueue, List);
ASSERT(TempDataEntry == DataEntry);
}
Irp = NpRemoveDataQueueEntry(DataQueue, TRUE, List);
if ( Irp )
{
Irp->IoStatus.Information = DataSize;
Irp->IoStatus.Status = STATUS_SUCCESS;
InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
}
}
if ( Mode == FILE_PIPE_MESSAGE_MODE )
{
Status.Status = STATUS_SUCCESS;
break;
}
ASSERT(!ReadOverflowOperation);
}
}
if ( Peek )
{
DataEntry = CONTAINING_RECORD(DataEntry->QueueEntry.Flink,
NP_DATA_QUEUE_ENTRY,
QueueEntry);
}
else
{
DataEntry = NpGetNextRealDataQueueEntry(DataQueue, List);
}
}
Status.Information = TotalBytesCopied;
if ( CompleteWrites ) NpCompleteStalledWrites(DataQueue, List);
return Status;
}

View file

@ -1,25 +1,45 @@
#include "npfs.h"
VOID
NTAPI
NpFreeClientSecurityContext(IN PSECURITY_CLIENT_CONTEXT ClientContext)
{
TOKEN_TYPE TokenType;
PVOID ClientToken;
if (!ClientContext) return;
TokenType = SeTokenType(ClientContext->ClientToken);
ClientToken = ClientContext->ClientToken;
if ((TokenType == TokenPrimary) || (ClientToken))
{
ObfDereferenceObject(ClientToken);
}
ExFreePool(ClientContext);
}
VOID
NTAPI
NpCopyClientContext(IN PNP_CCB Ccb,
IN PNP_DATA_QUEUE_ENTRY DataQueueEntry)
{
PAGED_CODE();
if (!DataQueueEntry->ClientSecurityContext) return;
NpFreeClientSecurityContext(Ccb->ClientContext);
Ccb->ClientContext = DataQueueEntry->ClientSecurityContext;
DataQueueEntry->ClientSecurityContext = NULL;
}
VOID
NTAPI
NpUninitializeSecurity(IN PNP_CCB Ccb)
{
PACCESS_TOKEN ClientToken;
PSECURITY_CLIENT_CONTEXT ClientContext;
TOKEN_TYPE TokenType;
PAGED_CODE();
ClientContext = Ccb->ClientContext;
if (!ClientContext) return;
TokenType = SeTokenType(ClientContext->ClientToken);
ClientToken = Ccb->ClientContext->ClientToken;
if ((TokenType == TokenPrimary) || (ClientToken))
{
ObfDereferenceObject(ClientToken);
}
ExFreePool(Ccb->ClientContext);
Ccb->ClientContext = 0;
NpFreeClientSecurityContext(Ccb->ClientContext);
Ccb->ClientContext = NULL;
}
NTSTATUS
@ -63,3 +83,36 @@ NpInitializeSecurity(IN PNP_CCB Ccb,
Ccb->ClientContext = 0;
return Status;
}
NTSTATUS
NTAPI
NpGetClientSecurityContext(IN BOOLEAN ServerSide,
IN PNP_CCB Ccb,
IN PETHREAD Thread,
IN PSECURITY_CLIENT_CONTEXT *Context)
{
PSECURITY_CLIENT_CONTEXT NewContext;
NTSTATUS Status;
PAGED_CODE();
if ( ServerSide || Ccb->ClientQos.ContextTrackingMode != 1 )
{
NewContext = NULL;
Status = STATUS_SUCCESS;
}
else
{
NewContext = ExAllocatePoolWithQuotaTag(PagedPool, sizeof(*NewContext), 'sFpN');
if ( !NewContext ) return STATUS_INSUFFICIENT_RESOURCES;
Status = SeCreateClientSecurity(Thread, &Ccb->ClientQos, 0, NewContext);
if (!NT_SUCCESS(Status))
{
ExFreePool(NewContext);
NewContext = NULL;
}
}
*Context = NewContext;
return Status;
}