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