mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
sys: initial ProcessBuffer implementation
This commit is contained in:
parent
441c45c77f
commit
4b43cc590f
@ -174,6 +174,7 @@
|
||||
<ClCompile Include="..\..\src\sys\lockctl.c" />
|
||||
<ClCompile Include="..\..\src\sys\meta.c" />
|
||||
<ClCompile Include="..\..\src\sys\name.c" />
|
||||
<ClCompile Include="..\..\src\sys\psbuffer.c" />
|
||||
<ClCompile Include="..\..\src\sys\read.c" />
|
||||
<ClCompile Include="..\..\src\sys\security.c" />
|
||||
<ClCompile Include="..\..\src\sys\shutdown.c" />
|
||||
|
@ -98,6 +98,9 @@
|
||||
<ClCompile Include="..\..\src\sys\statistics.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sys\psbuffer.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\sys\driver.h">
|
||||
|
@ -148,7 +148,8 @@ typedef struct
|
||||
/* kernel-mode flags */
|
||||
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */
|
||||
UINT32 PassQueryDirectoryPattern:1; /* pass Pattern during QueryDirectory operations */
|
||||
UINT32 KmReservedFlags:4;
|
||||
UINT32 AlwaysUseDoubleBuffering:1;
|
||||
UINT32 KmReservedFlags:3;
|
||||
/* user-mode flags */
|
||||
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */
|
||||
UINT32 UmFileContextIsFullContext:1; /* user mode: FileContext parameter is FullContext */
|
||||
|
162
src/sys/dirctl.c
162
src/sys/dirctl.c
@ -78,6 +78,7 @@ enum
|
||||
{
|
||||
/* QueryDirectory */
|
||||
RequestIrp = 0,
|
||||
RequestCookie = 1,
|
||||
RequestMdl = 1,
|
||||
RequestAddress = 2,
|
||||
RequestProcess = 3,
|
||||
@ -833,41 +834,68 @@ NTSTATUS FspFsvolDirectoryControlPrepare(
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result;
|
||||
PMDL Mdl = 0;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
|
||||
Mdl = IoAllocateMdl(
|
||||
Irp->AssociatedIrp.SystemBuffer,
|
||||
Request->Req.QueryDirectory.Length,
|
||||
FALSE, FALSE, 0);
|
||||
if (0 == Mdl)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
MmBuildMdlForNonPagedPool(Mdl);
|
||||
|
||||
/* map the MDL into user-mode */
|
||||
Result = FspMapLockedPagesInUserMode(Mdl, &Address, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
if (FspFsvolDeviceQueryDirectoryShouldUseProcessBuffer(
|
||||
IoGetCurrentIrpStackLocation(Irp)->DeviceObject, Request->Req.QueryDirectory.Length))
|
||||
{
|
||||
if (0 != Mdl)
|
||||
IoFreeMdl(Mdl);
|
||||
NTSTATUS Result;
|
||||
PVOID Cookie;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
|
||||
return Result;
|
||||
Result = FspProcessBufferAcquire(Request->Req.QueryDirectory.Length, &Cookie, &Address);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
/* get a pointer to the current process so that we can release the buffer later */
|
||||
Process = PsGetCurrentProcess();
|
||||
ObReferenceObject(Process);
|
||||
|
||||
Request->Req.QueryDirectory.Address = (UINT64)(UINT_PTR)Address;
|
||||
|
||||
FspIopRequestContext(Request, RequestCookie) = Cookie;
|
||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
NTSTATUS Result;
|
||||
PMDL Mdl = 0;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
|
||||
/* get a pointer to the current process so that we can unmap the address later */
|
||||
Process = PsGetCurrentProcess();
|
||||
ObReferenceObject(Process);
|
||||
Mdl = IoAllocateMdl(
|
||||
Irp->AssociatedIrp.SystemBuffer,
|
||||
Request->Req.QueryDirectory.Length,
|
||||
FALSE, FALSE, 0);
|
||||
if (0 == Mdl)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
Request->Req.QueryDirectory.Address = (UINT64)(UINT_PTR)Address;
|
||||
MmBuildMdlForNonPagedPool(Mdl);
|
||||
|
||||
FspIopRequestContext(Request, RequestMdl) = Mdl;
|
||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||
/* map the MDL into user-mode */
|
||||
Result = FspMapLockedPagesInUserMode(Mdl, &Address, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (0 != Mdl)
|
||||
IoFreeMdl(Mdl);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* get a pointer to the current process so that we can unmap the address later */
|
||||
Process = PsGetCurrentProcess();
|
||||
ObReferenceObject(Process);
|
||||
|
||||
Request->Req.QueryDirectory.Address = (UINT64)(UINT_PTR)Address;
|
||||
|
||||
FspIopRequestContext(Request, RequestMdl) = Mdl;
|
||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS FspFsvolDirectoryControlComplete(
|
||||
@ -910,6 +938,24 @@ NTSTATUS FspFsvolDirectoryControlComplete(
|
||||
|
||||
if (FspFsctlTransactQueryDirectoryKind == Request->Kind)
|
||||
{
|
||||
if (FspFsvolDeviceQueryDirectoryShouldUseProcessBuffer(
|
||||
IrpSp->DeviceObject, Request->Req.QueryDirectory.Length))
|
||||
{
|
||||
PVOID Address = FspIopRequestContext(Request, RequestAddress);
|
||||
|
||||
ASSERT(0 != Address);
|
||||
try
|
||||
{
|
||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Address, Response->IoStatus.Information);
|
||||
}
|
||||
except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Result = GetExceptionCode();
|
||||
Result = FsRtlIsNtstatusExpected(Result) ? STATUS_INVALID_USER_BUFFER : Result;
|
||||
FSP_RETURN();
|
||||
}
|
||||
}
|
||||
|
||||
DirInfoChangeNumber = FspFileNodeDirInfoChangeNumber(FileNode);
|
||||
Request->Kind = FspFsctlTransactReservedKind;
|
||||
FspIopResetRequest(Request, 0);
|
||||
@ -1010,29 +1056,57 @@ static VOID FspFsvolQueryDirectoryRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, P
|
||||
PAGED_CODE();
|
||||
|
||||
PIRP Irp = Context[RequestIrp];
|
||||
PMDL Mdl = Context[RequestMdl];
|
||||
PVOID Address = Context[RequestAddress];
|
||||
PEPROCESS Process = Context[RequestProcess];
|
||||
|
||||
if (0 != Address)
|
||||
if (0 != Irp && FspFsvolDeviceQueryDirectoryShouldUseProcessBuffer(
|
||||
IoGetCurrentIrpStackLocation(Irp)->DeviceObject, Request->Req.QueryDirectory.Length))
|
||||
{
|
||||
KAPC_STATE ApcState;
|
||||
BOOLEAN Attach;
|
||||
PVOID Cookie = Context[RequestCookie];
|
||||
PVOID Address = Context[RequestAddress];
|
||||
PEPROCESS Process = Context[RequestProcess];
|
||||
|
||||
ASSERT(0 != Process);
|
||||
Attach = Process != PsGetCurrentProcess();
|
||||
if (0 != Address)
|
||||
{
|
||||
KAPC_STATE ApcState;
|
||||
BOOLEAN Attach;
|
||||
|
||||
if (Attach)
|
||||
KeStackAttachProcess(Process, &ApcState);
|
||||
MmUnmapLockedPages(Address, Mdl);
|
||||
if (Attach)
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
ASSERT(0 != Process);
|
||||
Attach = Process != PsGetCurrentProcess();
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
if (Attach)
|
||||
KeStackAttachProcess(Process, &ApcState);
|
||||
FspProcessBufferRelease(Cookie, Address);
|
||||
if (Attach)
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PMDL Mdl = Context[RequestMdl];
|
||||
PVOID Address = Context[RequestAddress];
|
||||
PEPROCESS Process = Context[RequestProcess];
|
||||
|
||||
if (0 != Mdl)
|
||||
IoFreeMdl(Mdl);
|
||||
if (0 != Address)
|
||||
{
|
||||
KAPC_STATE ApcState;
|
||||
BOOLEAN Attach;
|
||||
|
||||
ASSERT(0 != Process);
|
||||
Attach = Process != PsGetCurrentProcess();
|
||||
|
||||
if (Attach)
|
||||
KeStackAttachProcess(Process, &ApcState);
|
||||
MmUnmapLockedPages(Address, Mdl);
|
||||
if (Attach)
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
|
||||
if (0 != Mdl)
|
||||
IoFreeMdl(Mdl);
|
||||
}
|
||||
|
||||
if (0 != Irp)
|
||||
{
|
||||
|
@ -46,6 +46,10 @@ NTSTATUS DriverEntry(
|
||||
|
||||
FspDriverMultiVersionInitialize();
|
||||
|
||||
Result = FspProcessBufferInitialize();
|
||||
if (!NT_SUCCESS(Result))
|
||||
FSP_RETURN();
|
||||
|
||||
FspDriverObject = DriverObject;
|
||||
ExInitializeResourceLite(&FspDeviceGlobalResource);
|
||||
|
||||
@ -59,14 +63,21 @@ NTSTATUS DriverEntry(
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlDiskDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspProcessBufferFinalize();
|
||||
FSP_RETURN();
|
||||
}
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlNetDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
FSP_RETURN(FspDeviceDelete(FspFsctlDiskDeviceObject));
|
||||
{
|
||||
FspDeviceDelete(FspFsctlDiskDeviceObject);
|
||||
FspProcessBufferFinalize();
|
||||
FSP_RETURN();
|
||||
}
|
||||
Result = FspDeviceInitialize(FspFsctlDiskDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
Result = FspDeviceInitialize(FspFsctlNetDeviceObject);
|
||||
@ -207,6 +218,8 @@ VOID FspUnload(
|
||||
ExDeleteResourceLite(&FspDeviceGlobalResource);
|
||||
FspDriverObject = 0;
|
||||
|
||||
FspProcessBufferFinalize();
|
||||
|
||||
#pragma prefast(suppress:28175, "We are in DriverUnload: ok to access DriverName")
|
||||
FSP_LEAVE_VOID("DriverName=\"%wZ\"",
|
||||
&DriverObject->DriverName);
|
||||
|
@ -601,6 +601,14 @@ VOID FspIrpHookReset(PIRP Irp);
|
||||
PVOID FspIrpHookContext(PVOID Context);
|
||||
NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
||||
|
||||
/* process buffers */
|
||||
#define FspProcessBufferSizeMax (64 * 1024)
|
||||
NTSTATUS FspProcessBufferInitialize(VOID);
|
||||
VOID FspProcessBufferFinalize(VOID);
|
||||
VOID FspProcessBufferCollect(HANDLE ProcessId);
|
||||
NTSTATUS FspProcessBufferAcquire(SIZE_T BufferSize, PVOID *PBufferCookie, PVOID *PBuffer);
|
||||
VOID FspProcessBufferRelease(PVOID BufferCookie, PVOID Buffer);
|
||||
|
||||
/* IRP context */
|
||||
#define FspIrpTimestampInfinity ((ULONG)-1L)
|
||||
#define FspIrpTimestamp(Irp) \
|
||||
@ -1048,6 +1056,23 @@ FSP_FSVOL_DEVICE_EXTENSION *FspFsvolDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||
ASSERT(FspFsvolDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
|
||||
return DeviceObject->DeviceExtension;
|
||||
}
|
||||
static inline
|
||||
BOOLEAN FspFsvolDeviceReadShouldUseProcessBuffer(PDEVICE_OBJECT FsvolDeviceObject, SIZE_T BufferSize)
|
||||
{
|
||||
return FspProcessBufferSizeMax >= BufferSize ||
|
||||
FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.AlwaysUseDoubleBuffering;
|
||||
}
|
||||
static inline
|
||||
BOOLEAN FspFsvolDeviceWriteShouldUseProcessBuffer(PDEVICE_OBJECT FsvolDeviceObject, SIZE_T BufferSize)
|
||||
{
|
||||
return FspProcessBufferSizeMax >= BufferSize ||
|
||||
FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.AlwaysUseDoubleBuffering;
|
||||
}
|
||||
static inline
|
||||
BOOLEAN FspFsvolDeviceQueryDirectoryShouldUseProcessBuffer(PDEVICE_OBJECT FsvolDeviceObject, SIZE_T BufferSize)
|
||||
{
|
||||
return FspFsvolDeviceReadShouldUseProcessBuffer(FsvolDeviceObject, BufferSize);
|
||||
}
|
||||
NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
|
||||
PUNICODE_STRING DeviceName, DEVICE_TYPE DeviceType, ULONG DeviceCharacteristics,
|
||||
PUNICODE_STRING DeviceSddl, LPCGUID DeviceClassGuid,
|
||||
|
280
src/sys/psbuffer.c
Normal file
280
src/sys/psbuffer.c
Normal file
@ -0,0 +1,280 @@
|
||||
/**
|
||||
* @file sys/psbuffer.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <sys/driver.h>
|
||||
|
||||
#define SafeGetCurrentProcessId() (PsGetProcessId(PsGetCurrentProcess()))
|
||||
|
||||
#define FspProcessBufferCountMax (2 >= FspProcessorCount ? 2 : (8 <= FspProcessorCount ? 8 : FspProcessorCount))
|
||||
#define ProcessBufferBucketCount 61 /* are you going to have that many file systems? */
|
||||
|
||||
typedef struct _FSP_PROCESS_BUFFER_ITEM
|
||||
{
|
||||
struct _FSP_PROCESS_BUFFER_ITEM *DictNext;
|
||||
struct _FSP_PROCESS_BUFFER_LIST_ENTRY *BufferList;
|
||||
ULONG BufferCount;
|
||||
HANDLE ProcessId;
|
||||
} FSP_PROCESS_BUFFER_ITEM;
|
||||
|
||||
typedef struct _FSP_PROCESS_BUFFER_LIST_ENTRY
|
||||
{
|
||||
struct _FSP_PROCESS_BUFFER_LIST_ENTRY *Next;
|
||||
PVOID Buffer;
|
||||
} FSP_PROCESS_BUFFER_LIST_ENTRY;
|
||||
|
||||
static KSPIN_LOCK ProcessBufferLock;
|
||||
static FSP_PROCESS_BUFFER_ITEM *ProcessBufferBuckets[ProcessBufferBucketCount];
|
||||
|
||||
static VOID FspProcessBufferNotifyRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create);
|
||||
|
||||
static inline FSP_PROCESS_BUFFER_ITEM *FspProcessBufferLookupItemAtDpcLevel(HANDLE ProcessId)
|
||||
{
|
||||
FSP_PROCESS_BUFFER_ITEM *Item = 0;
|
||||
ULONG HashIndex = FspHashMixPointer(ProcessId) % ProcessBufferBucketCount;
|
||||
for (FSP_PROCESS_BUFFER_ITEM *ItemX = ProcessBufferBuckets[HashIndex]; ItemX; ItemX = ItemX->DictNext)
|
||||
if (ItemX->ProcessId == ProcessId)
|
||||
{
|
||||
Item = ItemX;
|
||||
break;
|
||||
}
|
||||
return Item;
|
||||
}
|
||||
|
||||
static inline VOID FspProcessBufferAddItemAtDpcLevel(FSP_PROCESS_BUFFER_ITEM *Item)
|
||||
{
|
||||
ULONG HashIndex = FspHashMixPointer(Item->ProcessId) % ProcessBufferBucketCount;
|
||||
#if DBG
|
||||
for (FSP_PROCESS_BUFFER_ITEM *ItemX = ProcessBufferBuckets[HashIndex]; ItemX; ItemX = ItemX->DictNext)
|
||||
ASSERT(ItemX->ProcessId != Item->ProcessId);
|
||||
#endif
|
||||
Item->DictNext = ProcessBufferBuckets[HashIndex];
|
||||
ProcessBufferBuckets[HashIndex] = Item;
|
||||
}
|
||||
|
||||
static inline FSP_PROCESS_BUFFER_ITEM *FspProcessBufferRemoveItemAtDpcLevel(HANDLE ProcessId)
|
||||
{
|
||||
FSP_PROCESS_BUFFER_ITEM *Item = 0;
|
||||
ULONG HashIndex = FspHashMixPointer(ProcessId) % ProcessBufferBucketCount;
|
||||
for (FSP_PROCESS_BUFFER_ITEM **P = &ProcessBufferBuckets[HashIndex]; *P; P = &(*P)->DictNext)
|
||||
if ((*P)->ProcessId == ProcessId)
|
||||
{
|
||||
Item = *P;
|
||||
*P = (*P)->DictNext;
|
||||
break;
|
||||
}
|
||||
return Item;
|
||||
}
|
||||
|
||||
static inline VOID FspProcessBufferReuseEntry(HANDLE ProcessId,
|
||||
FSP_PROCESS_BUFFER_LIST_ENTRY *BufferEntry)
|
||||
{
|
||||
KIRQL Irql;
|
||||
FSP_PROCESS_BUFFER_ITEM *Item;
|
||||
|
||||
KeAcquireSpinLock(&ProcessBufferLock, &Irql);
|
||||
|
||||
Item = FspProcessBufferLookupItemAtDpcLevel(ProcessId);
|
||||
|
||||
if (0 != Item)
|
||||
{
|
||||
BufferEntry->Next = Item->BufferList;
|
||||
Item->BufferList = BufferEntry;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&ProcessBufferLock, Irql);
|
||||
|
||||
if (0 == Item)
|
||||
{
|
||||
if (0 != BufferEntry->Buffer)
|
||||
{
|
||||
SIZE_T BufferSize = 0;
|
||||
ZwFreeVirtualMemory(ZwCurrentProcess(), BufferEntry->Buffer, &BufferSize, MEM_RELEASE);
|
||||
}
|
||||
|
||||
FspFree(BufferEntry);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS FspProcessBufferInitialize(VOID)
|
||||
{
|
||||
KeInitializeSpinLock(&ProcessBufferLock);
|
||||
|
||||
return PsSetCreateProcessNotifyRoutine(FspProcessBufferNotifyRoutine, FALSE);
|
||||
}
|
||||
|
||||
VOID FspProcessBufferFinalize(VOID)
|
||||
{
|
||||
PsSetCreateProcessNotifyRoutine(FspProcessBufferNotifyRoutine, TRUE);
|
||||
}
|
||||
|
||||
static VOID FspProcessBufferNotifyRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)
|
||||
{
|
||||
if (!Create)
|
||||
FspProcessBufferCollect(ProcessId);
|
||||
}
|
||||
|
||||
VOID FspProcessBufferCollect(HANDLE ProcessId)
|
||||
{
|
||||
KIRQL Irql;
|
||||
FSP_PROCESS_BUFFER_ITEM *Item = 0;
|
||||
|
||||
KeAcquireSpinLock(&ProcessBufferLock, &Irql);
|
||||
|
||||
Item = FspProcessBufferRemoveItemAtDpcLevel(ProcessId);
|
||||
|
||||
KeReleaseSpinLock(&ProcessBufferLock, Irql);
|
||||
|
||||
if (0 != Item)
|
||||
{
|
||||
DEBUGLOG("pid=%ld", (ULONG)(UINT_PTR)ProcessId);
|
||||
|
||||
for (FSP_PROCESS_BUFFER_LIST_ENTRY *P = Item->BufferList, *Next; P; P = Next)
|
||||
{
|
||||
Next = P->Next;
|
||||
FspFree(P);
|
||||
}
|
||||
|
||||
FspFree(Item);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS FspProcessBufferAcquire(SIZE_T BufferSize, PVOID *PBufferCookie, PVOID *PBuffer)
|
||||
{
|
||||
if (FspProcessBufferSizeMax >= BufferSize)
|
||||
{
|
||||
HANDLE ProcessId = SafeGetCurrentProcessId();
|
||||
KIRQL Irql;
|
||||
FSP_PROCESS_BUFFER_ITEM *Item, *NewItem;
|
||||
FSP_PROCESS_BUFFER_LIST_ENTRY *BufferEntry = 0;
|
||||
BOOLEAN AllocNoReuse;
|
||||
NTSTATUS Result;
|
||||
|
||||
KeAcquireSpinLock(&ProcessBufferLock, &Irql);
|
||||
|
||||
Item = FspProcessBufferLookupItemAtDpcLevel(ProcessId);
|
||||
|
||||
if (0 != Item)
|
||||
{
|
||||
BufferEntry = Item->BufferList;
|
||||
if (0 != BufferEntry)
|
||||
Item->BufferList = BufferEntry->Next;
|
||||
}
|
||||
|
||||
AllocNoReuse = 0 == BufferEntry &&
|
||||
(0 != Item && FspProcessBufferCountMax <= Item->BufferCount);
|
||||
|
||||
KeReleaseSpinLock(&ProcessBufferLock, Irql);
|
||||
|
||||
if (AllocNoReuse)
|
||||
goto alloc_no_reuse;
|
||||
|
||||
if (0 == BufferEntry)
|
||||
{
|
||||
*PBufferCookie = 0;
|
||||
*PBuffer = 0;
|
||||
|
||||
BufferEntry = FspAllocNonPaged(sizeof *BufferEntry);
|
||||
if (0 == BufferEntry)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
RtlZeroMemory(BufferEntry, sizeof *BufferEntry);
|
||||
|
||||
NewItem = FspAllocNonPaged(sizeof *NewItem);
|
||||
if (0 == NewItem)
|
||||
{
|
||||
FspFree(BufferEntry);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
RtlZeroMemory(NewItem, sizeof *NewItem);
|
||||
|
||||
KeAcquireSpinLock(&ProcessBufferLock, &Irql);
|
||||
|
||||
Item = FspProcessBufferLookupItemAtDpcLevel(ProcessId);
|
||||
|
||||
if (0 == Item)
|
||||
{
|
||||
Item = NewItem;
|
||||
NewItem = 0;
|
||||
Item->BufferCount = 1;
|
||||
Item->ProcessId = ProcessId;
|
||||
FspProcessBufferAddItemAtDpcLevel(Item);
|
||||
}
|
||||
else if (FspProcessBufferCountMax > Item->BufferCount)
|
||||
Item->BufferCount++;
|
||||
else
|
||||
AllocNoReuse = TRUE;
|
||||
|
||||
KeReleaseSpinLock(&ProcessBufferLock, Irql);
|
||||
|
||||
if (0 != NewItem)
|
||||
FspFree(NewItem);
|
||||
|
||||
if (AllocNoReuse)
|
||||
{
|
||||
FspFree(BufferEntry);
|
||||
goto alloc_no_reuse;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == BufferEntry->Buffer)
|
||||
{
|
||||
BufferSize = FspProcessBufferSizeMax;
|
||||
Result = ZwAllocateVirtualMemory(ZwCurrentProcess(),
|
||||
&BufferEntry->Buffer, 0, &BufferSize, MEM_COMMIT, PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
/* failed to allocate actual buffer; reuse BufferEntry */
|
||||
FspProcessBufferReuseEntry(ProcessId, BufferEntry);
|
||||
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
*PBufferCookie = BufferEntry;
|
||||
*PBuffer = BufferEntry->Buffer;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
alloc_no_reuse:
|
||||
NTSTATUS Result;
|
||||
|
||||
*PBufferCookie = 0;
|
||||
Result = ZwAllocateVirtualMemory(ZwCurrentProcess(),
|
||||
PBuffer, 0, &BufferSize, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
VOID FspProcessBufferRelease(PVOID BufferCookie, PVOID Buffer)
|
||||
{
|
||||
if (0 != BufferCookie)
|
||||
{
|
||||
HANDLE ProcessId = SafeGetCurrentProcessId();
|
||||
FSP_PROCESS_BUFFER_LIST_ENTRY *BufferEntry = BufferCookie;
|
||||
|
||||
ASSERT(Buffer == BufferEntry->Buffer);
|
||||
|
||||
FspProcessBufferReuseEntry(ProcessId, BufferEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
SIZE_T BufferSize = 0;
|
||||
ZwFreeVirtualMemory(ZwCurrentProcess(), Buffer, &BufferSize, MEM_RELEASE);
|
||||
}
|
||||
}
|
177
src/sys/read.c
177
src/sys/read.c
@ -44,6 +44,7 @@ enum
|
||||
{
|
||||
/* ReadNonCached */
|
||||
RequestIrp = 0,
|
||||
RequestCookie = 1,
|
||||
RequestSafeMdl = 1,
|
||||
RequestAddress = 2,
|
||||
RequestProcess = 3,
|
||||
@ -346,41 +347,71 @@ NTSTATUS FspFsvolReadPrepare(
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result;
|
||||
FSP_SAFE_MDL *SafeMdl = 0;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
|
||||
/* create a "safe" MDL if necessary */
|
||||
if (!FspSafeMdlCheck(Irp->MdlAddress))
|
||||
if (FspFsvolDeviceReadShouldUseProcessBuffer(
|
||||
IoGetCurrentIrpStackLocation(Irp)->DeviceObject, Request->Req.Read.Length))
|
||||
{
|
||||
Result = FspSafeMdlCreate(Irp->MdlAddress, IoWriteAccess, &SafeMdl);
|
||||
NTSTATUS Result;
|
||||
PVOID Cookie;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
|
||||
if (0 == MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority))
|
||||
return STATUS_INSUFFICIENT_RESOURCES; /* something is seriously screwy! */
|
||||
|
||||
Result = FspProcessBufferAcquire(Request->Req.Read.Length, &Cookie, &Address);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* map the MDL into user-mode */
|
||||
Result = FspMapLockedPagesInUserMode(
|
||||
0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress, &Address, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
/* get a pointer to the current process so that we can release the buffer later */
|
||||
Process = PsGetCurrentProcess();
|
||||
ObReferenceObject(Process);
|
||||
|
||||
Request->Req.Read.Address = (UINT64)(UINT_PTR)Address;
|
||||
|
||||
FspIopRequestContext(Request, RequestCookie) = Cookie;
|
||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 != SafeMdl)
|
||||
FspSafeMdlDelete(SafeMdl);
|
||||
NTSTATUS Result;
|
||||
FSP_SAFE_MDL *SafeMdl = 0;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
|
||||
return Result;
|
||||
/* create a "safe" MDL if necessary */
|
||||
if (!FspSafeMdlCheck(Irp->MdlAddress))
|
||||
{
|
||||
Result = FspSafeMdlCreate(Irp->MdlAddress, IoWriteAccess, &SafeMdl);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* map the MDL into user-mode */
|
||||
Result = FspMapLockedPagesInUserMode(
|
||||
0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress, &Address, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (0 != SafeMdl)
|
||||
FspSafeMdlDelete(SafeMdl);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* get a pointer to the current process so that we can unmap the address later */
|
||||
Process = PsGetCurrentProcess();
|
||||
ObReferenceObject(Process);
|
||||
|
||||
Request->Req.Read.Address = (UINT64)(UINT_PTR)Address;
|
||||
|
||||
FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl;
|
||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* get a pointer to the current process so that we can unmap the address later */
|
||||
Process = PsGetCurrentProcess();
|
||||
ObReferenceObject(Process);
|
||||
|
||||
Request->Req.Read.Address = (UINT64)(UINT_PTR)Address;
|
||||
|
||||
FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl;
|
||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS FspFsvolReadComplete(
|
||||
@ -400,15 +431,37 @@ NTSTATUS FspFsvolReadComplete(
|
||||
if (Response->IoStatus.Information > Request->Req.Read.Length)
|
||||
FSP_RETURN(Result = STATUS_INTERNAL_ERROR);
|
||||
|
||||
FSP_SAFE_MDL *SafeMdl = FspIopRequestContext(Request, RequestSafeMdl);
|
||||
if (FspFsvolDeviceReadShouldUseProcessBuffer(
|
||||
IrpSp->DeviceObject, Request->Req.Read.Length))
|
||||
{
|
||||
PVOID Address = FspIopRequestContext(Request, RequestAddress);
|
||||
PVOID SystemAddress = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
|
||||
|
||||
ASSERT(0 != Address);
|
||||
try
|
||||
{
|
||||
RtlCopyMemory(SystemAddress, Address, Response->IoStatus.Information);
|
||||
}
|
||||
except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Result = GetExceptionCode();
|
||||
Result = FsRtlIsNtstatusExpected(Result) ? STATUS_INVALID_USER_BUFFER : Result;
|
||||
FSP_RETURN();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FSP_SAFE_MDL *SafeMdl = FspIopRequestContext(Request, RequestSafeMdl);
|
||||
|
||||
if (0 != SafeMdl)
|
||||
FspSafeMdlCopyBack(SafeMdl);
|
||||
}
|
||||
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
LARGE_INTEGER ReadOffset = IrpSp->Parameters.Read.ByteOffset;
|
||||
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
|
||||
BOOLEAN SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
|
||||
|
||||
if (0 != SafeMdl)
|
||||
FspSafeMdlCopyBack(SafeMdl);
|
||||
|
||||
/* if we are top-level */
|
||||
if (0 == FspIrpTopFlags(Irp))
|
||||
{
|
||||
@ -442,29 +495,57 @@ static VOID FspFsvolReadNonCachedRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PV
|
||||
PAGED_CODE();
|
||||
|
||||
PIRP Irp = Context[RequestIrp];
|
||||
FSP_SAFE_MDL *SafeMdl = Context[RequestSafeMdl];
|
||||
PVOID Address = Context[RequestAddress];
|
||||
PEPROCESS Process = Context[RequestProcess];
|
||||
|
||||
if (0 != Address)
|
||||
if (0 != Irp && FspFsvolDeviceReadShouldUseProcessBuffer(
|
||||
IoGetCurrentIrpStackLocation(Irp)->DeviceObject, Request->Req.Read.Length))
|
||||
{
|
||||
KAPC_STATE ApcState;
|
||||
BOOLEAN Attach;
|
||||
PVOID Cookie = Context[RequestCookie];
|
||||
PVOID Address = Context[RequestAddress];
|
||||
PEPROCESS Process = Context[RequestProcess];
|
||||
|
||||
ASSERT(0 != Process);
|
||||
Attach = Process != PsGetCurrentProcess();
|
||||
if (0 != Address)
|
||||
{
|
||||
KAPC_STATE ApcState;
|
||||
BOOLEAN Attach;
|
||||
|
||||
if (Attach)
|
||||
KeStackAttachProcess(Process, &ApcState);
|
||||
MmUnmapLockedPages(Address, 0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress);
|
||||
if (Attach)
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
ASSERT(0 != Process);
|
||||
Attach = Process != PsGetCurrentProcess();
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
if (Attach)
|
||||
KeStackAttachProcess(Process, &ApcState);
|
||||
FspProcessBufferRelease(Cookie, Address);
|
||||
if (Attach)
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FSP_SAFE_MDL *SafeMdl = Context[RequestSafeMdl];
|
||||
PVOID Address = Context[RequestAddress];
|
||||
PEPROCESS Process = Context[RequestProcess];
|
||||
|
||||
if (0 != SafeMdl)
|
||||
FspSafeMdlDelete(SafeMdl);
|
||||
if (0 != Address)
|
||||
{
|
||||
KAPC_STATE ApcState;
|
||||
BOOLEAN Attach;
|
||||
|
||||
ASSERT(0 != Process);
|
||||
Attach = Process != PsGetCurrentProcess();
|
||||
|
||||
if (Attach)
|
||||
KeStackAttachProcess(Process, &ApcState);
|
||||
MmUnmapLockedPages(Address, 0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress);
|
||||
if (Attach)
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
|
||||
if (0 != SafeMdl)
|
||||
FspSafeMdlDelete(SafeMdl);
|
||||
}
|
||||
|
||||
if (0 != Irp)
|
||||
{
|
||||
|
163
src/sys/write.c
163
src/sys/write.c
@ -45,6 +45,7 @@ enum
|
||||
{
|
||||
/* WriteNonCached */
|
||||
RequestIrp = 0,
|
||||
RequestCookie = 1,
|
||||
RequestSafeMdl = 1,
|
||||
RequestAddress = 2,
|
||||
RequestProcess = 3,
|
||||
@ -416,41 +417,87 @@ NTSTATUS FspFsvolWritePrepare(
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result;
|
||||
FSP_SAFE_MDL *SafeMdl = 0;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
|
||||
/* create a "safe" MDL if necessary */
|
||||
if (!FspSafeMdlCheck(Irp->MdlAddress))
|
||||
if (FspFsvolDeviceWriteShouldUseProcessBuffer(
|
||||
IoGetCurrentIrpStackLocation(Irp)->DeviceObject, Request->Req.Write.Length))
|
||||
{
|
||||
Result = FspSafeMdlCreate(Irp->MdlAddress, IoReadAccess, &SafeMdl);
|
||||
NTSTATUS Result;
|
||||
PVOID Cookie;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
PVOID SystemAddress = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
|
||||
|
||||
if (0 == SystemAddress)
|
||||
return STATUS_INSUFFICIENT_RESOURCES; /* something is seriously screwy! */
|
||||
|
||||
Result = FspProcessBufferAcquire(Request->Req.Write.Length, &Cookie, &Address);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* map the MDL into user-mode */
|
||||
Result = FspMapLockedPagesInUserMode(
|
||||
0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress, &Address, FspMvMdlMappingNoWrite);
|
||||
if (!NT_SUCCESS(Result))
|
||||
ASSERT(0 != Address);
|
||||
try
|
||||
{
|
||||
RtlCopyMemory(Address, SystemAddress, Request->Req.Write.Length);
|
||||
}
|
||||
except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Result = GetExceptionCode();
|
||||
Result = FsRtlIsNtstatusExpected(Result) ? STATUS_INVALID_USER_BUFFER : Result;
|
||||
|
||||
FspProcessBufferRelease(Cookie, Address);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* get a pointer to the current process so that we can release the buffer later */
|
||||
Process = PsGetCurrentProcess();
|
||||
ObReferenceObject(Process);
|
||||
|
||||
Request->Req.Write.Address = (UINT64)(UINT_PTR)Address;
|
||||
|
||||
FspIopRequestContext(Request, RequestCookie) = Cookie;
|
||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 != SafeMdl)
|
||||
FspSafeMdlDelete(SafeMdl);
|
||||
NTSTATUS Result;
|
||||
FSP_SAFE_MDL *SafeMdl = 0;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
|
||||
return Result;
|
||||
/* create a "safe" MDL if necessary */
|
||||
if (!FspSafeMdlCheck(Irp->MdlAddress))
|
||||
{
|
||||
Result = FspSafeMdlCreate(Irp->MdlAddress, IoReadAccess, &SafeMdl);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* map the MDL into user-mode */
|
||||
Result = FspMapLockedPagesInUserMode(
|
||||
0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress, &Address, FspMvMdlMappingNoWrite);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (0 != SafeMdl)
|
||||
FspSafeMdlDelete(SafeMdl);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* get a pointer to the current process so that we can unmap the address later */
|
||||
Process = PsGetCurrentProcess();
|
||||
ObReferenceObject(Process);
|
||||
|
||||
Request->Req.Write.Address = (UINT64)(UINT_PTR)Address;
|
||||
|
||||
FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl;
|
||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* get a pointer to the current process so that we can unmap the address later */
|
||||
Process = PsGetCurrentProcess();
|
||||
ObReferenceObject(Process);
|
||||
|
||||
Request->Req.Write.Address = (UINT64)(UINT_PTR)Address;
|
||||
|
||||
FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl;
|
||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS FspFsvolWriteComplete(
|
||||
@ -524,29 +571,57 @@ static VOID FspFsvolWriteNonCachedRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, P
|
||||
PAGED_CODE();
|
||||
|
||||
PIRP Irp = Context[RequestIrp];
|
||||
FSP_SAFE_MDL *SafeMdl = Context[RequestSafeMdl];
|
||||
PVOID Address = Context[RequestAddress];
|
||||
PEPROCESS Process = Context[RequestProcess];
|
||||
|
||||
if (0 != Address)
|
||||
if (0 != Irp && FspFsvolDeviceWriteShouldUseProcessBuffer(
|
||||
IoGetCurrentIrpStackLocation(Irp)->DeviceObject, Request->Req.Write.Length))
|
||||
{
|
||||
KAPC_STATE ApcState;
|
||||
BOOLEAN Attach;
|
||||
PVOID Cookie = Context[RequestCookie];
|
||||
PVOID Address = Context[RequestAddress];
|
||||
PEPROCESS Process = Context[RequestProcess];
|
||||
|
||||
ASSERT(0 != Process);
|
||||
Attach = Process != PsGetCurrentProcess();
|
||||
if (0 != Address)
|
||||
{
|
||||
KAPC_STATE ApcState;
|
||||
BOOLEAN Attach;
|
||||
|
||||
if (Attach)
|
||||
KeStackAttachProcess(Process, &ApcState);
|
||||
MmUnmapLockedPages(Address, 0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress);
|
||||
if (Attach)
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
ASSERT(0 != Process);
|
||||
Attach = Process != PsGetCurrentProcess();
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
if (Attach)
|
||||
KeStackAttachProcess(Process, &ApcState);
|
||||
FspProcessBufferRelease(Cookie, Address);
|
||||
if (Attach)
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FSP_SAFE_MDL *SafeMdl = Context[RequestSafeMdl];
|
||||
PVOID Address = Context[RequestAddress];
|
||||
PEPROCESS Process = Context[RequestProcess];
|
||||
|
||||
if (0 != SafeMdl)
|
||||
FspSafeMdlDelete(SafeMdl);
|
||||
if (0 != Address)
|
||||
{
|
||||
KAPC_STATE ApcState;
|
||||
BOOLEAN Attach;
|
||||
|
||||
ASSERT(0 != Process);
|
||||
Attach = Process != PsGetCurrentProcess();
|
||||
|
||||
if (Attach)
|
||||
KeStackAttachProcess(Process, &ApcState);
|
||||
MmUnmapLockedPages(Address, 0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress);
|
||||
if (Attach)
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
|
||||
if (0 != SafeMdl)
|
||||
FspSafeMdlDelete(SafeMdl);
|
||||
}
|
||||
|
||||
if (0 != Irp)
|
||||
{
|
||||
|
@ -45,9 +45,11 @@ FSP_FSCTL_STATIC_ASSERT(MEMFS_MAX_PATH > MAX_PATH,
|
||||
/*
|
||||
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes
|
||||
* a check for the Write buffer to ensure that it is read-only.
|
||||
*
|
||||
* Since ProcessBuffer support in the FSD, this is no longer a guarantee.
|
||||
*/
|
||||
#if !defined(NDEBUG)
|
||||
#define DEBUG_BUFFER_CHECK
|
||||
//#define DEBUG_BUFFER_CHECK
|
||||
#endif
|
||||
|
||||
#define MEMFS_SECTOR_SIZE 512
|
||||
|
Loading…
x
Reference in New Issue
Block a user