diff --git a/build/VStudio/winfsp_sys.vcxproj b/build/VStudio/winfsp_sys.vcxproj
index 2177afe5..4d50bb29 100644
--- a/build/VStudio/winfsp_sys.vcxproj
+++ b/build/VStudio/winfsp_sys.vcxproj
@@ -156,6 +156,7 @@
+
diff --git a/build/VStudio/winfsp_sys.vcxproj.filters b/build/VStudio/winfsp_sys.vcxproj.filters
index fea8d778..29d159a0 100644
--- a/build/VStudio/winfsp_sys.vcxproj.filters
+++ b/build/VStudio/winfsp_sys.vcxproj.filters
@@ -83,6 +83,9 @@
Source
+
+ Source
+
diff --git a/src/sys/driver.h b/src/sys/driver.h
index 94353413..bb7b15d7 100644
--- a/src/sys/driver.h
+++ b/src/sys/driver.h
@@ -476,10 +476,10 @@ typedef struct
BOOLEAN DeletePending; /* FileDispositionInformation */
BOOLEAN DeleteOnClose; /* FILE_DELETE_ON_CLOSE */
FSP_DEVICE_GENERIC_TABLE_ELEMENT ElementStorage;
- PDEVICE_OBJECT FsvolDeviceObject;
UINT64 UserContext;
#endif
/* read-only after creation */
+ PDEVICE_OBJECT FsvolDeviceObject;
UNICODE_STRING FileName;
WCHAR FileNameBuf[];
} FSP_FILE_CONTEXT;
diff --git a/src/sys/filectx.c b/src/sys/filectx.c
new file mode 100644
index 00000000..7444c0f4
--- /dev/null
+++ b/src/sys/filectx.c
@@ -0,0 +1,72 @@
+/**
+ * @file sys/filectx.c
+ *
+ * @copyright 2015 Bill Zissimopoulos
+ */
+
+#include
+
+NTSTATUS FspFileContextCreate(PDEVICE_OBJECT DeviceObject,
+ ULONG ExtraSize, FSP_FILE_CONTEXT **PFsContext);
+VOID FspFileContextDelete(FSP_FILE_CONTEXT *Context);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FspFileContextCreate)
+#pragma alloc_text(PAGE, FspFileContextDelete)
+#endif
+
+NTSTATUS FspFileContextCreate(PDEVICE_OBJECT DeviceObject,
+ ULONG ExtraSize, FSP_FILE_CONTEXT **PFsContext)
+{
+ PAGED_CODE();
+
+ *PFsContext = 0;
+
+ FSP_FILE_CONTEXT_NONPAGED *NonPaged = FspAllocNonPaged(sizeof *NonPaged);
+ if (0 == NonPaged)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ FSP_FILE_CONTEXT *FsContext = FspAlloc(sizeof *FsContext + ExtraSize);
+ if (0 == FsContext)
+ {
+ FspFree(NonPaged);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(NonPaged, sizeof *NonPaged);
+ ExInitializeResourceLite(&NonPaged->Resource);
+ ExInitializeResourceLite(&NonPaged->PagingIoResource);
+ ExInitializeFastMutex(&NonPaged->HeaderFastMutex);
+
+ RtlZeroMemory(FsContext, sizeof *FsContext + ExtraSize);
+ FsContext->Header.NodeTypeCode = FspFileContextFileKind;
+ FsContext->Header.NodeByteSize = sizeof *FsContext;
+ FsContext->Header.IsFastIoPossible = FastIoIsQuestionable;
+ FsContext->Header.Resource = &NonPaged->Resource;
+ FsContext->Header.PagingIoResource = &NonPaged->PagingIoResource;
+ FsRtlSetupAdvancedHeader(&FsContext->Header, &NonPaged->HeaderFastMutex);
+ FsContext->NonPaged = NonPaged;
+ FsContext->RefCount = 1;
+ FsContext->FsvolDeviceObject = DeviceObject;
+ FspDeviceRetain(FsContext->FsvolDeviceObject);
+ RtlInitEmptyUnicodeString(&FsContext->FileName, FsContext->FileNameBuf, (USHORT)ExtraSize);
+
+ *PFsContext = FsContext;
+
+ return STATUS_SUCCESS;
+}
+
+VOID FspFileContextDelete(FSP_FILE_CONTEXT *FsContext)
+{
+ PAGED_CODE();
+
+ FsRtlTeardownPerStreamContexts(&FsContext->Header);
+
+ FspDeviceRelease(FsContext->FsvolDeviceObject);
+
+ ExDeleteResourceLite(&FsContext->NonPaged->PagingIoResource);
+ ExDeleteResourceLite(&FsContext->NonPaged->Resource);
+ FspFree(FsContext->NonPaged);
+
+ FspFree(FsContext);
+}