diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj
index e4ee655d..f020d1aa 100644
--- a/build/VStudio/winfsp_dll.vcxproj
+++ b/build/VStudio/winfsp_dll.vcxproj
@@ -25,6 +25,7 @@
+
diff --git a/build/VStudio/winfsp_dll.vcxproj.filters b/build/VStudio/winfsp_dll.vcxproj.filters
index 77379d2c..9b711ee0 100644
--- a/build/VStudio/winfsp_dll.vcxproj.filters
+++ b/build/VStudio/winfsp_dll.vcxproj.filters
@@ -34,6 +34,9 @@
Source
+
+ Source
+
diff --git a/src/dll/fsctl.c b/src/dll/fsctl.c
new file mode 100644
index 00000000..89f66c95
--- /dev/null
+++ b/src/dll/fsctl.c
@@ -0,0 +1,110 @@
+/**
+ * @file dll/fsctl.c
+ *
+ * @copyright 2015 Bill Zissimopoulos
+ */
+
+#include
+
+#define GLOBALROOT L"\\\\?\\GLOBALROOT"
+#define PREFIXW L"" FSP_FSCTL_VOLUME_PARAMS_PREFIX
+#define PREFIXW_SIZE (sizeof PREFIXW - sizeof(WCHAR))
+
+FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
+ const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
+ PWCHAR VolumePathBuf, SIZE_T VolumePathSize,
+ PHANDLE PVolumeHandle)
+{
+ NTSTATUS Result;
+ PWSTR DeviceRoot;
+ SIZE_T DeviceRootSize, DevicePathSize;
+ WCHAR DevicePathBuf[MAX_PATH], *DevicePathPtr, *DevicePathEnd;
+ HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
+ DWORD Bytes;
+
+ if (sizeof(WCHAR) <= VolumePathSize)
+ VolumePathBuf[0] = L'\0';
+ *PVolumeHandle = INVALID_HANDLE_VALUE;
+
+ /* check lengths; everything (including encoded volume params) must fit within MAX_PATH */
+ DeviceRoot = L'\\' == DevicePath[0] ? GLOBALROOT : GLOBALROOT "\\Device\\";
+ DeviceRootSize = lstrlenW(DeviceRoot) * sizeof(WCHAR);
+ DevicePathSize = lstrlenW(DevicePath) * sizeof(WCHAR);
+ if (DeviceRootSize + DevicePathSize + PREFIXW_SIZE +
+ sizeof *VolumeParams * sizeof(WCHAR) + sizeof(WCHAR) > sizeof DevicePathBuf)
+ return STATUS_INVALID_PARAMETER;
+
+ /* prepare the device path to be opened; encode the volume params in the Unicode private area */
+ DevicePathPtr = DevicePathBuf;
+ memcpy(DevicePathPtr, DeviceRoot, DeviceRootSize);
+ DevicePathPtr = (PVOID)((PUINT8)DevicePathPtr + DeviceRootSize);
+ memcpy(DevicePathPtr, DevicePath, DevicePathSize);
+ DevicePathPtr = (PVOID)((PUINT8)DevicePathPtr + DevicePathSize);
+ memcpy(DevicePathPtr, PREFIXW, PREFIXW_SIZE);
+ DevicePathPtr = (PVOID)((PUINT8)DevicePathPtr + PREFIXW_SIZE);
+ DevicePathEnd = (PVOID)((PUINT8)DevicePathPtr + sizeof *VolumeParams * sizeof(WCHAR));
+ for (PUINT8 VolumeParamsPtr = (PVOID)VolumeParams;
+ DevicePathEnd > DevicePathPtr; DevicePathPtr++, VolumeParamsPtr++)
+ {
+ WCHAR Value = 0xF000 | *VolumeParamsPtr;
+ *DevicePathPtr = Value;
+ }
+ *DevicePathPtr = L'\0';
+
+ VolumeHandle = CreateFileW(DevicePathBuf,
+ 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
+ if (INVALID_HANDLE_VALUE == VolumeHandle)
+ {
+ Result = FspNtStatusFromWin32(GetLastError());
+ if (STATUS_OBJECT_NAME_NOT_FOUND == Result)
+ Result = STATUS_NO_SUCH_DEVICE;
+ goto exit;
+ }
+
+ if (!DeviceIoControl(VolumeHandle, FSP_FSCTL_VOLUME_NAME,
+ 0, 0,
+ VolumePathBuf, (DWORD)VolumePathSize,
+ &Bytes, 0))
+ {
+ Result = FspNtStatusFromWin32(GetLastError());
+ goto exit;
+ }
+
+ Result = STATUS_SUCCESS;
+
+exit:
+ if (NT_SUCCESS(Result))
+ *PVolumeHandle = VolumeHandle;
+ else
+ CloseHandle(VolumeHandle);
+
+ return Result;
+}
+
+FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
+ PVOID ResponseBuf, SIZE_T ResponseBufSize,
+ PVOID RequestBuf, SIZE_T *PRequestBufSize)
+{
+ NTSTATUS Result = STATUS_SUCCESS;
+ DWORD Bytes = 0;
+
+ if (0 != PRequestBufSize)
+ {
+ Bytes = (DWORD)*PRequestBufSize;
+ *PRequestBufSize = 0;
+ }
+
+ if (!DeviceIoControl(VolumeHandle, FSP_FSCTL_TRANSACT,
+ ResponseBuf, (DWORD)ResponseBufSize, RequestBuf, Bytes,
+ &Bytes, 0))
+ {
+ Result = FspNtStatusFromWin32(GetLastError());
+ goto exit;
+ }
+
+ if (0 != PRequestBufSize)
+ *PRequestBufSize = Bytes;
+
+exit:
+ return Result;
+}
diff --git a/src/dll/library.h b/src/dll/library.h
index 786de058..bb084683 100644
--- a/src/dll/library.h
+++ b/src/dll/library.h
@@ -26,14 +26,6 @@ static inline PVOID MemAlloc(SIZE_T Size)
extern HANDLE ProcessHeap;
return HeapAlloc(ProcessHeap, 0, Size);
}
-static inline PVOID MemAllocSLE(SIZE_T Size)
-{
- extern HANDLE ProcessHeap;
- PVOID Pointer = HeapAlloc(ProcessHeap, 0, Size);
- if (0 == Pointer)
- SetLastError(ERROR_NO_SYSTEM_RESOURCES);
- return Pointer;
-}
static inline VOID MemFree(PVOID Pointer)
{
extern HANDLE ProcessHeap;
diff --git a/src/sys/volume.c b/src/sys/volume.c
index 8b37d312..2a95609c 100644
--- a/src/sys/volume.c
+++ b/src/sys/volume.c
@@ -67,7 +67,8 @@ NTSTATUS FspVolumeCreate(
return STATUS_INVALID_PARAMETER;
/* copy the VolumeParams */
- for (USHORT Index = 0, Length = FileObject->FileName.Length / 2; Length > Index; Index++)
+ for (USHORT Index = PREFIXW_SIZE / sizeof(WCHAR), Length = FileObject->FileName.Length / 2;
+ Length > Index; Index++)
{
WCHAR Value = FileObject->FileName.Buffer[Index];
if (0xF000 != (Value & 0xFF00))