From 44a17d0b4ddf7a1a2d1a4a7d602053ef7bf2c3ac Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Tue, 15 Dec 2015 13:15:44 -0800 Subject: [PATCH] dll: FspFileSystemLoop --- build/VStudio/winfsp_dll.vcxproj | 1 + build/VStudio/winfsp_dll.vcxproj.filters | 3 + inc/winfsp/winfsp.h | 28 +++++ src/dll/fsctl.c | 13 +- src/dll/library.h | 1 - src/dll/loop.c | 144 +++++++++++++++++++++++ tst/winfsp-tests/mount-test.c | 1 - 7 files changed, 186 insertions(+), 5 deletions(-) create mode 100644 src/dll/loop.c diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj index 57701b93..68b428f0 100644 --- a/build/VStudio/winfsp_dll.vcxproj +++ b/build/VStudio/winfsp_dll.vcxproj @@ -173,6 +173,7 @@ + diff --git a/build/VStudio/winfsp_dll.vcxproj.filters b/build/VStudio/winfsp_dll.vcxproj.filters index 07ee53e1..8c278830 100644 --- a/build/VStudio/winfsp_dll.vcxproj.filters +++ b/build/VStudio/winfsp_dll.vcxproj.filters @@ -23,6 +23,9 @@ Source + + Source + diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index c38274d0..b4ced623 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -19,6 +19,34 @@ #define FSP_API __declspec(dllimport) #endif +#include + +typedef struct _FSP_FILE_SYSTEM FSP_FILE_SYSTEM; +typedef NTSTATUS FSP_FILE_SYSTEM_PR(FSP_FILE_SYSTEM *, FSP_FSCTL_TRANSACT_REQ *); +typedef VOID FSP_FILE_SYSTEM_OP(FSP_FILE_SYSTEM *, FSP_FSCTL_TRANSACT_REQ *); +typedef struct _FSP_FILE_SYSTEM +{ + UINT16 Version; + PVOID UserContext; + HANDLE VolumeHandle; + FSP_FILE_SYSTEM_PR *ProcessRequest; + FSP_FILE_SYSTEM_OP *Operations[FspFsctlTransactKindCount]; +} FSP_FILE_SYSTEM; + +FSP_API NTSTATUS FspFileSystemCreate(FSP_FILE_SYSTEM_PR *ProcessRequest, + FSP_FILE_SYSTEM **PFileSystem); +FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem); +FSP_API NTSTATUS FspFileSystemLoop(FSP_FILE_SYSTEM *FileSystem); + +FSP_API NTSTATUS FspProcessRequestDirect(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request); +FSP_API NTSTATUS FspProcessRequestInPool(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request); +FSP_API NTSTATUS FspProduceResponse(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_RSP *Response); +FSP_API NTSTATUS FspProduceResponseWithStatus(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, NTSTATUS Result); + FSP_API NTSTATUS FspNtStatusFromWin32(DWORD Error); FSP_API VOID FspDebugLog(const char *format, ...); diff --git a/src/dll/fsctl.c b/src/dll/fsctl.c index 140d4586..3cf50f1a 100644 --- a/src/dll/fsctl.c +++ b/src/dll/fsctl.c @@ -241,17 +241,24 @@ FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle, PVOID RequestBuf, SIZE_T *PRequestBufSize) { NTSTATUS Result = STATUS_SUCCESS; - DWORD Bytes; + DWORD Bytes = 0; + + if (0 != *PRequestBufSize) + { + Bytes = (DWORD)*PRequestBufSize; + *PRequestBufSize = 0; + } if (!DeviceIoControl(VolumeHandle, FSP_FSCTL_TRANSACT, - ResponseBuf, (DWORD)ResponseBufSize, RequestBuf, (DWORD)*PRequestBufSize, + ResponseBuf, (DWORD)ResponseBufSize, RequestBuf, Bytes, &Bytes, 0)) { Result = FspNtStatusFromWin32(GetLastError()); goto exit; } - *PRequestBufSize = Bytes; + if (0 != *PRequestBufSize) + *PRequestBufSize = Bytes; exit: return Result; diff --git a/src/dll/library.h b/src/dll/library.h index 6e1dc747..ef8b2bb9 100644 --- a/src/dll/library.h +++ b/src/dll/library.h @@ -9,7 +9,6 @@ #define WINFSP_DLL_INTERNAL #include -#include #include #define LIBRARY_NAME "WinFsp" diff --git a/src/dll/loop.c b/src/dll/loop.c new file mode 100644 index 00000000..d61b1ed0 --- /dev/null +++ b/src/dll/loop.c @@ -0,0 +1,144 @@ +/** + * @file dll/loop.c + * + * @copyright 2015 Bill Zissimopoulos + */ + +#include + +typedef struct _FSP_WORK_ITEM +{ + FSP_FILE_SYSTEM *FileSystem; + __declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 RequestBuf[]; +} FSP_WORK_ITEM; + +FSP_API NTSTATUS FspFileSystemCreate(FSP_FILE_SYSTEM_PR *ProcessRequest, + FSP_FILE_SYSTEM **PFileSystem) +{ + FSP_FILE_SYSTEM *FileSystem; + + *PFileSystem = 0; + + if (0 == ProcessRequest) + return STATUS_INVALID_PARAMETER; + + FileSystem = malloc(sizeof *FileSystem); + if (0 == FileSystem) + return STATUS_INSUFFICIENT_RESOURCES; + + memset(FileSystem, 0, sizeof *FileSystem); + FileSystem->ProcessRequest = ProcessRequest; + + *PFileSystem = FileSystem; + + return STATUS_SUCCESS; +} + +FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem) +{ + free(FileSystem); +} + +FSP_API NTSTATUS FspFileSystemLoop(FSP_FILE_SYSTEM *FileSystem) +{ + NTSTATUS Result; + PUINT8 RequestBuf, RequestBufEnd; + SIZE_T RequestBufSize; + FSP_FSCTL_TRANSACT_REQ *Request, *NextRequest; + + RequestBuf = malloc(FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMIN); + if (0 == RequestBuf) + return STATUS_INSUFFICIENT_RESOURCES; + + for (;;) + { + RequestBufSize = FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMIN; + Result = FspFsctlTransact(FileSystem->VolumeHandle, 0, 0, RequestBuf, &RequestBufSize); + if (!NT_SUCCESS(Result)) + goto exit; + RequestBufEnd = RequestBuf + RequestBufSize; + + Request = (PVOID)RequestBuf; + for (;;) + { + NextRequest = FspFsctlTransactConsumeRequest(Request, RequestBufEnd); + if (0 == NextRequest) + break; + + Result = FileSystem->ProcessRequest(FileSystem, Request); + if (!NT_SUCCESS(Result)) + goto exit; + + Request = NextRequest; + } + } + +exit: + free(RequestBuf); + + return Result; +} + +FSP_API NTSTATUS FspProcessRequestDirect(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request) +{ + if (FspFsctlTransactKindCount <= Request->Kind || 0 == FileSystem->Operations[Request->Kind]) + return FspProduceResponseWithStatus(FileSystem, Request, STATUS_INVALID_DEVICE_REQUEST); + + FileSystem->Operations[Request->Kind](FileSystem, Request); + return STATUS_SUCCESS; +} + +static DWORD WINAPI FspProcessRequestInPoolWorker(PVOID Param) +{ + FSP_WORK_ITEM *WorkItem = Param; + FSP_FSCTL_TRANSACT_REQ *Request = (PVOID)WorkItem->RequestBuf; + + WorkItem->FileSystem->Operations[Request->Kind](WorkItem->FileSystem, Request); + free(WorkItem); + + return 0; +} + +FSP_API NTSTATUS FspProcessRequestInPool(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request) +{ + if (FspFsctlTransactKindCount <= Request->Kind || 0 == FileSystem->Operations[Request->Kind]) + return FspProduceResponseWithStatus(FileSystem, Request, STATUS_INVALID_DEVICE_REQUEST); + + FSP_WORK_ITEM *WorkItem; + BOOLEAN Success; + + WorkItem = malloc(sizeof *WorkItem + Request->Size); + if (0 == WorkItem) + return STATUS_INSUFFICIENT_RESOURCES; + + WorkItem->FileSystem = FileSystem; + memcpy(WorkItem->RequestBuf, Request, Request->Size); + + Success = QueueUserWorkItem(FspProcessRequestInPoolWorker, WorkItem, WT_EXECUTEDEFAULT); + if (!Success) + { + free(WorkItem); + return FspNtStatusFromWin32(GetLastError()); + } + + return STATUS_SUCCESS; +} + +FSP_API NTSTATUS FspProduceResponse(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_RSP *Response) +{ + return FspFsctlTransact(FileSystem->VolumeHandle, Response, Response->Size, 0, 0); +} + +FSP_API NTSTATUS FspProduceResponseWithStatus(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, NTSTATUS Result) +{ + FSP_FSCTL_TRANSACT_RSP Response = { 0 }; + Response.Size = sizeof Response; + Response.Kind = Request->Kind; + Response.Hint = Request->Hint; + Response.IoStatus.Status = Result; + return FspProduceResponse(FileSystem, &Response); +} diff --git a/tst/winfsp-tests/mount-test.c b/tst/winfsp-tests/mount-test.c index 079bff58..e372f5b2 100644 --- a/tst/winfsp-tests/mount-test.c +++ b/tst/winfsp-tests/mount-test.c @@ -1,5 +1,4 @@ #include -#include #include #include #include