mirror of
https://github.com/reactos/reactos.git
synced 2024-10-07 18:04:41 +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
|
fileobsup.c
|
||||||
main.c
|
main.c
|
||||||
prefxsup.c
|
prefxsup.c
|
||||||
|
read.c
|
||||||
|
readsup.c
|
||||||
secursup.c
|
secursup.c
|
||||||
statesup.c
|
statesup.c
|
||||||
strucsup.c
|
strucsup.c
|
||||||
|
@ -12,6 +14,7 @@ list(APPEND SOURCE
|
||||||
|
|
||||||
add_library(npfs_new SHARED ${SOURCE})
|
add_library(npfs_new SHARED ${SOURCE})
|
||||||
set_module_type(npfs_new kernelmodedriver)
|
set_module_type(npfs_new kernelmodedriver)
|
||||||
|
target_link_libraries(npfs_new ${PSEH_LIB})
|
||||||
add_importlibs(npfs_new ntoskrnl hal)
|
add_importlibs(npfs_new ntoskrnl hal)
|
||||||
add_pch(npfs_new npfs.h)
|
add_pch(npfs_new npfs.h)
|
||||||
add_cd_file(TARGET npfs_new DESTINATION reactos/system32/drivers FOR all)
|
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->ByteOffset = 0;
|
||||||
DataQueue->QueueState = Empty;
|
DataQueue->QueueState = Empty;
|
||||||
DataQueue->Quota = Quota;
|
DataQueue->Quota = Quota;
|
||||||
InitializeListHead(&DataQueue->List);
|
InitializeListHead(&DataQueue->Queue);
|
||||||
return STATUS_SUCCESS;
|
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;
|
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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
|
NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
//
|
//
|
||||||
#include <ntifs.h>
|
#include <ntifs.h>
|
||||||
#include <ntndk.h>
|
#include <ntndk.h>
|
||||||
|
#include <pseh/pseh2.h>
|
||||||
#define UNIMPLEMENTED
|
#define UNIMPLEMENTED
|
||||||
#define DPRINT1 DbgPrint
|
#define DPRINT1 DbgPrint
|
||||||
|
|
||||||
|
@ -31,15 +32,26 @@ typedef USHORT NODE_TYPE_CODE, *PNODE_TYPE_CODE;
|
||||||
//
|
//
|
||||||
typedef enum _NP_DATA_QUEUE_STATE
|
typedef enum _NP_DATA_QUEUE_STATE
|
||||||
{
|
{
|
||||||
|
ReadEntries = 0,
|
||||||
|
WriteEntries = 1,
|
||||||
Empty = 2
|
Empty = 2
|
||||||
} NP_DATA_QUEUE_STATE;
|
} 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.
|
// An Input or Output Data Queue. Each CCB has two of these.
|
||||||
//
|
//
|
||||||
typedef struct _NP_DATA_QUEUE
|
typedef struct _NP_DATA_QUEUE
|
||||||
{
|
{
|
||||||
LIST_ENTRY List;
|
LIST_ENTRY Queue;
|
||||||
ULONG QueueState;
|
ULONG QueueState;
|
||||||
ULONG BytesInQueue;
|
ULONG BytesInQueue;
|
||||||
ULONG EntriesInQueue;
|
ULONG EntriesInQueue;
|
||||||
|
@ -48,6 +60,19 @@ typedef struct _NP_DATA_QUEUE
|
||||||
ULONG Quota;
|
ULONG Quota;
|
||||||
} NP_DATA_QUEUE, *PNP_DATA_QUEUE;
|
} 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.
|
// A Wait Queue. Only the VCB has one of these.
|
||||||
//
|
//
|
||||||
|
@ -57,6 +82,14 @@ typedef struct _NP_WAIT_QUEUE
|
||||||
KSPIN_LOCK WaitLock;
|
KSPIN_LOCK WaitLock;
|
||||||
} NP_WAIT_QUEUE, *PNP_WAIT_QUEUE;
|
} 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
|
// The CCB for the Root DCB
|
||||||
//
|
//
|
||||||
|
@ -76,7 +109,7 @@ typedef struct _NP_CB_HEADER
|
||||||
LIST_ENTRY DcbEntry;
|
LIST_ENTRY DcbEntry;
|
||||||
PVOID ParentDcb;
|
PVOID ParentDcb;
|
||||||
ULONG CurrentInstances;
|
ULONG CurrentInstances;
|
||||||
ULONG OtherCount;
|
ULONG ServerOpenCount;
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
||||||
} NP_CB_HEADER, *PNP_CB_HEADER;
|
} NP_CB_HEADER, *PNP_CB_HEADER;
|
||||||
|
|
||||||
|
@ -144,8 +177,8 @@ typedef struct _NP_FCB
|
||||||
typedef struct _NP_NONPAGED_CCB
|
typedef struct _NP_NONPAGED_CCB
|
||||||
{
|
{
|
||||||
NODE_TYPE_CODE NodeType;
|
NODE_TYPE_CODE NodeType;
|
||||||
PVOID EventBufferClient;
|
PNP_EVENT_BUFFER EventBufferClient;
|
||||||
PVOID EventBufferServer;
|
PNP_EVENT_BUFFER EventBufferServer;
|
||||||
ERESOURCE Lock;
|
ERESOURCE Lock;
|
||||||
} NP_NONPAGED_CCB, *PNP_NONPAGED_CCB;
|
} NP_NONPAGED_CCB, *PNP_NONPAGED_CCB;
|
||||||
|
|
||||||
|
@ -201,6 +234,34 @@ NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NpUninitializeDataQueue(IN PNP_DATA_QUEUE DataQueue);
|
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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue,
|
NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue,
|
||||||
|
@ -265,6 +326,15 @@ NpSetConnectedPipeState(IN PNP_CCB Ccb,
|
||||||
IN PFILE_OBJECT FileObject,
|
IN PFILE_OBJECT FileObject,
|
||||||
IN PLIST_ENTRY List);
|
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
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
NpUninitializeSecurity(IN PNP_CCB Ccb);
|
NpUninitializeSecurity(IN PNP_CCB Ccb);
|
||||||
|
@ -275,6 +345,13 @@ NpInitializeSecurity(IN PNP_CCB Ccb,
|
||||||
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
|
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
|
||||||
IN PETHREAD Thread);
|
IN PETHREAD Thread);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NpGetClientSecurityContext(IN BOOLEAN ServerSide,
|
||||||
|
IN PNP_CCB Ccb,
|
||||||
|
IN PETHREAD Thread,
|
||||||
|
IN PSECURITY_CLIENT_CONTEXT *Context);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
NpSetFileObject(IN PFILE_OBJECT FileObject,
|
NpSetFileObject(IN PFILE_OBJECT FileObject,
|
||||||
|
@ -316,3 +393,20 @@ NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
|
||||||
IN NTSTATUS Status,
|
IN NTSTATUS Status,
|
||||||
IN PLIST_ENTRY ListEntry);
|
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"
|
#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
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
NpUninitializeSecurity(IN PNP_CCB Ccb)
|
NpUninitializeSecurity(IN PNP_CCB Ccb)
|
||||||
{
|
{
|
||||||
PACCESS_TOKEN ClientToken;
|
|
||||||
PSECURITY_CLIENT_CONTEXT ClientContext;
|
|
||||||
TOKEN_TYPE TokenType;
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
ClientContext = Ccb->ClientContext;
|
NpFreeClientSecurityContext(Ccb->ClientContext);
|
||||||
if (!ClientContext) return;
|
Ccb->ClientContext = NULL;
|
||||||
|
|
||||||
TokenType = SeTokenType(ClientContext->ClientToken);
|
|
||||||
ClientToken = Ccb->ClientContext->ClientToken;
|
|
||||||
if ((TokenType == TokenPrimary) || (ClientToken))
|
|
||||||
{
|
|
||||||
ObfDereferenceObject(ClientToken);
|
|
||||||
}
|
|
||||||
ExFreePool(Ccb->ClientContext);
|
|
||||||
Ccb->ClientContext = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -63,3 +83,36 @@ NpInitializeSecurity(IN PNP_CCB Ccb,
|
||||||
Ccb->ClientContext = 0;
|
Ccb->ClientContext = 0;
|
||||||
return Status;
|
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