sys: fsctl

This commit is contained in:
Bill Zissimopoulos 2015-11-24 20:10:29 -08:00
parent e60e63ada0
commit cac74f3b63
7 changed files with 58 additions and 122 deletions

View File

@ -149,7 +149,6 @@
<ClCompile Include="..\..\src\sys\resource.c" /> <ClCompile Include="..\..\src\sys\resource.c" />
<ClCompile Include="..\..\src\sys\security.c" /> <ClCompile Include="..\..\src\sys\security.c" />
<ClCompile Include="..\..\src\sys\shutdown.c" /> <ClCompile Include="..\..\src\sys\shutdown.c" />
<ClCompile Include="..\..\src\sys\transact.c" />
<ClCompile Include="..\..\src\sys\volinfo.c" /> <ClCompile Include="..\..\src\sys\volinfo.c" />
<ClCompile Include="..\..\src\sys\write.c" /> <ClCompile Include="..\..\src\sys\write.c" />
</ItemGroup> </ItemGroup>

View File

@ -77,9 +77,6 @@
<ClCompile Include="..\..\src\sys\ioq.c"> <ClCompile Include="..\..\src\sys\ioq.c">
<Filter>Source</Filter> <Filter>Source</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\sys\transact.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\src\sys\driver.h"> <ClInclude Include="..\..\src\sys\driver.h">

View File

@ -31,6 +31,7 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
#define FSP_FSCTL_CREATE_BUFFER_SIZE 64 #define FSP_FSCTL_CREATE_BUFFER_SIZE 64
#define FSP_FSCTL_TRANSACT_BUFFER_SIZE 4096 #define FSP_FSCTL_TRANSACT_BUFFER_SIZE 4096
#define FSP_FSCTL_TRANSACT_REQ_SIZEMAX 1536
/* marshalling */ /* marshalling */
#pragma warning(push) #pragma warning(push)

View File

@ -162,25 +162,14 @@ typedef struct
IO_CSQ PendingIoCsq, ProcessIoCsq; IO_CSQ PendingIoCsq, ProcessIoCsq;
} FSP_IOQ; } FSP_IOQ;
VOID FspIoqInitialize(FSP_IOQ *Ioq); VOID FspIoqInitialize(FSP_IOQ *Ioq);
VOID FspIoqEnable(FSP_IOQ *Ioq, int Delta); BOOLEAN FspIoqEnabled(FSP_IOQ *Ioq);
PKEVENT FspIoqPendingIrpEvent(FSP_IOQ *Ioq); VOID FspIoqDisable(FSP_IOQ *Ioq);
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp); BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp);
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, ULONG millis); PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, ULONG millis);
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp); BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp);
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint); PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint);
VOID FspIoqCancelAll(FSP_IOQ *Ioq); VOID FspIoqCancelAll(FSP_IOQ *Ioq);
/* transact thread */
typedef struct
{
PKTHREAD Thread;
KEVENT Event;
FSP_IOQ *TransactIoq, *Ioq;
} FSP_TRANSACT_THREAD;
NTSTATUS FspTransactThreadStart(FSP_TRANSACT_THREAD *TransactThread,
FSP_IOQ *TransactIoq, FSP_IOQ *Ioq);
VOID FspTransactThreadStop(FSP_TRANSACT_THREAD *TransactThread);
/* device extensions */ /* device extensions */
enum enum
{ {
@ -199,8 +188,7 @@ typedef struct
typedef struct typedef struct
{ {
FSP_DEVICE_EXTENSION Base; FSP_DEVICE_EXTENSION Base;
FSP_IOQ TransactIoq, Ioq; FSP_IOQ Ioq;
FSP_TRANSACT_THREAD TransactThread;
UINT8 SecurityDescriptorBuf[]; UINT8 SecurityDescriptorBuf[];
} FSP_FSVRT_DEVICE_EXTENSION; } FSP_FSVRT_DEVICE_EXTENSION;
typedef struct typedef struct

View File

@ -79,15 +79,10 @@ static NTSTATUS FspFsctlCreateVolume(
{ {
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject); FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
FsvrtDeviceExtension->Base.Kind = FspFsvrtDeviceExtensionKind; FsvrtDeviceExtension->Base.Kind = FspFsvrtDeviceExtensionKind;
FspIoqInitialize(&FsvrtDeviceExtension->TransactIoq);
FspIoqInitialize(&FsvrtDeviceExtension->Ioq); FspIoqInitialize(&FsvrtDeviceExtension->Ioq);
RtlCopyMemory(FspFsvrtDeviceExtension(FsvrtDeviceObject)->SecurityDescriptorBuf, RtlCopyMemory(FspFsvrtDeviceExtension(FsvrtDeviceObject)->SecurityDescriptorBuf,
SecurityDescriptor, InputBufferLength); SecurityDescriptor, InputBufferLength);
Irp->IoStatus.Information = DeviceName.Length + 1; Irp->IoStatus.Information = DeviceName.Length + 1;
Result = FspTransactThreadStart(&FsvrtDeviceExtension->TransactThread,
&FsvrtDeviceExtension->TransactIoq, &FsvrtDeviceExtension->Ioq);
if (!NT_SUCCESS(Result))
IoDeleteDevice(FsvrtDeviceObject);
} }
/* free the temporary security descriptor */ /* free the temporary security descriptor */
@ -125,9 +120,10 @@ static NTSTATUS FspFsvrtTransact(
NTSTATUS Result; NTSTATUS Result;
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject); FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
PUINT8 SystemBufferEnd; PUINT8 SystemBufferPtr, SystemBufferEnd;
FSP_TRANSACT_RSP *Response; FSP_TRANSACT_RSP *Response;
PIRP ProcessIrp; FSP_TRANSACT_REQ *Request;
PIRP ProcessIrp, PendingIrp;
/* access check */ /* access check */
Result = FspSecuritySubjectContextAccessCheck( Result = FspSecuritySubjectContextAccessCheck(
@ -155,12 +151,43 @@ static NTSTATUS FspFsvrtTransact(
Response = (PVOID)((PUINT8)Response + Response->Size); Response = (PVOID)((PUINT8)Response + Response->Size);
} }
if (FspIoqPostIrp(&FsvrtDeviceExtension->TransactIoq, Irp)) /* wait for a pending IRP */
Result = STATUS_PENDING; while (0 == (PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, 300)))
else {
Result = STATUS_ACCESS_DENIED; if (!FspIoqEnabled(&FsvrtDeviceExtension->Ioq))
return STATUS_CANCELLED;
}
return Result; /* send any pending IRP's to the user-mode file system */
SystemBufferPtr = SystemBuffer;
SystemBufferEnd = (PUINT8)SystemBuffer + OutputBufferLength;
ASSERT(SystemBufferPtr + FSP_FSCTL_TRANSACT_REQ_SIZEMAX + sizeof(Request->Size) <= SystemBufferEnd);
for (BOOLEAN LoopedOnce = FALSE;; LoopedOnce = TRUE)
{
if (SystemBufferPtr + FSP_FSCTL_TRANSACT_REQ_SIZEMAX + sizeof(Request->Size) > SystemBufferEnd)
break;
if (!FspIoqStartProcessingIrp(&FsvrtDeviceExtension->Ioq, PendingIrp))
{
FspCompleteRequest(PendingIrp, STATUS_CANCELLED);
if (!LoopedOnce)
return STATUS_CANCELLED;
break;
}
Request = PendingIrp->Tail.Overlay.DriverContext[0];
RtlCopyMemory(SystemBufferPtr, Request, Request->Size);
SystemBufferPtr += Request->Size;
PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, 0);
if (0 == PendingIrp)
break;
}
ASSERT(SystemBufferPtr + sizeof(Request->Size) <= SystemBufferEnd);
RtlZeroMemory(SystemBufferPtr, SystemBufferEnd - SystemBufferPtr);
Irp->IoStatus.Information = SystemBufferPtr - (PUINT8)SystemBuffer;
return STATUS_SUCCESS;
} }
static NTSTATUS FspFsctlFileSystemControl( static NTSTATUS FspFsctlFileSystemControl(

View File

@ -57,7 +57,7 @@
static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext) static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext)
{ {
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq); FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq);
if (0 > Ioq->Enabled) if (0 >= Ioq->Enabled)
return STATUS_ACCESS_DENIED; return STATUS_ACCESS_DENIED;
InsertTailList(&Ioq->PendingIrpList, &Irp->Tail.Overlay.ListEntry); InsertTailList(&Ioq->PendingIrpList, &Irp->Tail.Overlay.ListEntry);
/* list is not empty; wake up any waiters */ /* list is not empty; wake up any waiters */
@ -101,7 +101,7 @@ static VOID FspIoqPendingCompleteCanceledIrp(PIO_CSQ IoCsq, PIRP Irp)
static NTSTATUS FspIoqProcessInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext) static NTSTATUS FspIoqProcessInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext)
{ {
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq); FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
if (0 > Ioq->Enabled) if (0 >= Ioq->Enabled)
return STATUS_ACCESS_DENIED; return STATUS_ACCESS_DENIED;
InsertTailList(&Ioq->ProcessIrpList, &Irp->Tail.Overlay.ListEntry); InsertTailList(&Ioq->ProcessIrpList, &Irp->Tail.Overlay.ListEntry);
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -164,21 +164,27 @@ VOID FspIoqInitialize(FSP_IOQ *Ioq)
FspIoqProcessAcquireLock, FspIoqProcessAcquireLock,
FspIoqProcessReleaseLock, FspIoqProcessReleaseLock,
FspIoqProcessCompleteCanceledIrp); FspIoqProcessCompleteCanceledIrp);
Ioq->Enabled = 1;
} }
VOID FspIoqEnable(FSP_IOQ *Ioq, int Delta) BOOLEAN FspIoqEnabled(FSP_IOQ *Ioq)
{
BOOLEAN Result;
KIRQL Irql;
KeAcquireSpinLock(&Ioq->SpinLock, &Irql);
Result = 0 < Ioq->Enabled;
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
return Result;
}
VOID FspIoqDisable(FSP_IOQ *Ioq)
{ {
KIRQL Irql; KIRQL Irql;
KeAcquireSpinLock(&Ioq->SpinLock, &Irql); KeAcquireSpinLock(&Ioq->SpinLock, &Irql);
Ioq->Enabled += Delta; Ioq->Enabled = 0;
KeReleaseSpinLock(&Ioq->SpinLock, Irql); KeReleaseSpinLock(&Ioq->SpinLock, Irql);
} }
PKEVENT FspIoqPendingIrpEvent(FSP_IOQ *Ioq)
{
return &Ioq->PendingIrpEvent;
}
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp) BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp)
{ {
NTSTATUS Result; NTSTATUS Result;

View File

@ -1,82 +0,0 @@
/**
* @file sys/transact.c
*
* @copyright 2015 Bill Zissimopoulos
*/
#include <sys/driver.h>
static KSTART_ROUTINE FspTransactThread;
NTSTATUS FspTransactThreadStart(FSP_TRANSACT_THREAD *TransactThread,
FSP_IOQ *TransactIoq, FSP_IOQ *Ioq);
VOID FspTransactThreadStop(FSP_TRANSACT_THREAD *TransactThread);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspTransactThread)
#pragma alloc_text(PAGE, FspTransactThreadStart)
#pragma alloc_text(PAGE, FspTransactThreadStop)
#endif
static VOID FspTransactThread(PVOID StartContext)
{
PAGED_CODE();
FSP_TRANSACT_THREAD *TransactThread = StartContext;
PVOID WaitObjects[2];
WaitObjects[0] = &TransactThread->Event;
WaitObjects[1] = FspIoqPendingIrpEvent(TransactThread->TransactIoq);
for (;;)
{
NTSTATUS Result;
PIRP Irp;
Result = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, Executive, KernelMode, FALSE, 0, 0);
if (STATUS_WAIT_0 == Result)
break; /* stop thread */
else if (STATUS_WAIT_1 != Result)
continue; /* retry */
Irp = FspIoqNextPendingIrp(TransactThread->TransactIoq, 0);
if (0 == Irp)
continue; /* retry */
}
PsTerminateSystemThread(STATUS_SUCCESS);
}
NTSTATUS FspTransactThreadStart(FSP_TRANSACT_THREAD *TransactThread,
FSP_IOQ *TransactIoq, FSP_IOQ *Ioq)
{
PAGED_CODE();
NTSTATUS Result;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE ThreadHandle;
RtlZeroMemory(TransactThread, sizeof *TransactThread);
KeInitializeEvent(&TransactThread->Event, NotificationEvent, FALSE);
TransactThread->TransactIoq = TransactIoq;
TransactThread->Ioq = Ioq;
InitializeObjectAttributes(&ObjectAttributes, 0, OBJ_KERNEL_HANDLE, 0, 0);
Result = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, &ObjectAttributes, 0, 0,
FspTransactThread, TransactThread);
if (!NT_SUCCESS(Result))
return Result;
Result = ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS, *PsThreadType, KernelMode,
&TransactThread->Thread, 0);
ASSERT(NT_SUCCESS(Result));
ZwClose(ThreadHandle);
return STATUS_SUCCESS;
}
VOID FspTransactThreadStop(FSP_TRANSACT_THREAD *TransactThread)
{
PAGED_CODE();
KeSetEvent(&TransactThread->Event, 1, TRUE);
KeWaitForSingleObject(&TransactThread->Thread, Executive, KernelMode, FALSE, 0);
}