mirror of
https://github.com/reactos/reactos.git
synced 2024-07-10 14:45:06 +00:00
[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:
parent
2976384615
commit
b5edd2ce20
|
@ -5,6 +5,8 @@ list(APPEND SOURCE
|
|||
fileobsup.c
|
||||
main.c
|
||||
prefxsup.c
|
||||
read.c
|
||||
readsup.c
|
||||
secursup.c
|
||||
statesup.c
|
||||
strucsup.c
|
||||
|
@ -12,6 +14,7 @@ list(APPEND SOURCE
|
|||
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
189
reactos/drivers/filesystems/npfs_new/read.c
Normal file
189
reactos/drivers/filesystems/npfs_new/read.c
Normal 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;
|
||||
}
|
138
reactos/drivers/filesystems/npfs_new/readsup.c
Normal file
138
reactos/drivers/filesystems/npfs_new/readsup.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue