diff --git a/build/VStudio/testing/winfsp-tests.vcxproj b/build/VStudio/testing/winfsp-tests.vcxproj
index 9bbe80cb..5ddf40fd 100644
--- a/build/VStudio/testing/winfsp-tests.vcxproj
+++ b/build/VStudio/testing/winfsp-tests.vcxproj
@@ -202,6 +202,7 @@
+
diff --git a/build/VStudio/testing/winfsp-tests.vcxproj.filters b/build/VStudio/testing/winfsp-tests.vcxproj.filters
index 9295b644..9afe1684 100644
--- a/build/VStudio/testing/winfsp-tests.vcxproj.filters
+++ b/build/VStudio/testing/winfsp-tests.vcxproj.filters
@@ -82,6 +82,9 @@
Source
+
+ Source
+
diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h
index 324c3e1d..25dee19d 100644
--- a/inc/winfsp/winfsp.h
+++ b/inc/winfsp/winfsp.h
@@ -1627,6 +1627,7 @@ FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
PULONG PBytesTransferred, ULONG Timeout,
PSID Sid);
+FSP_API NTSTATUS FspVersion(PUINT32 PVersion);
/*
* Delay load
diff --git a/src/dll/util.c b/src/dll/util.c
index ec6bc4d2..0f2f8a8d 100644
--- a/src/dll/util.c
+++ b/src/dll/util.c
@@ -163,3 +163,47 @@ exit:
return Result;
}
+
+FSP_API NTSTATUS FspVersion(PUINT32 PVersion)
+{
+ static UINT32 Version;
+
+ if (0 == Version)
+ {
+ /*
+ * This check is not thread-safe, but that should be ok.
+ * Two threads competing to read the version will read
+ * the same value from the Version resource.
+ */
+ extern HINSTANCE DllInstance;
+ WCHAR ModuleFileName[MAX_PATH];
+ PVOID VersionInfo;
+ DWORD Size;
+ VS_FIXEDFILEINFO *FixedFileInfo = 0;
+
+ if (0 != GetModuleFileNameW(DllInstance, ModuleFileName, MAX_PATH))
+ {
+ Size = GetFileVersionInfoSizeW(ModuleFileName, &Size/*dummy*/);
+ if (0 < Size)
+ {
+ VersionInfo = MemAlloc(Size);
+ if (0 != VersionInfo &&
+ GetFileVersionInfoW(ModuleFileName, 0, Size, VersionInfo) &&
+ VerQueryValueW(VersionInfo, L"\\", &FixedFileInfo, &Size))
+ {
+ /* 32-bit store should be atomic! */
+ Version = FixedFileInfo->dwFileVersionMS;
+ }
+
+ MemFree(VersionInfo);
+ }
+ }
+
+ if (0 == FixedFileInfo)
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *PVersion = Version;
+
+ return STATUS_SUCCESS;
+}
diff --git a/tst/winfsp-tests/version-test.c b/tst/winfsp-tests/version-test.c
new file mode 100644
index 00000000..8d1a030a
--- /dev/null
+++ b/tst/winfsp-tests/version-test.c
@@ -0,0 +1,44 @@
+/**
+ * @file version-test.c
+ *
+ * @copyright 2015-2017 Bill Zissimopoulos
+ */
+/*
+ * This file is part of WinFsp.
+ *
+ * You can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 3 as published by the Free Software
+ * Foundation.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * software.
+ */
+
+#include
+#include
+
+#include "winfsp-tests.h"
+
+static void version_test(void)
+{
+ /* this is not a real test! */
+
+ UINT32 Version1, Version2;
+ NTSTATUS Result;
+
+ Result = FspVersion(&Version1);
+ ASSERT(NT_SUCCESS(Result));
+
+ Result = FspVersion(&Version2);
+ ASSERT(NT_SUCCESS(Result));
+
+ ASSERT(Version1 == Version2);
+
+ FspDebugLog(__FUNCTION__ ": FspVersion=%d.%d\n", HIWORD(Version1), LOWORD(Version1));
+}
+
+void version_tests(void)
+{
+ TEST(version_test);
+}
diff --git a/tst/winfsp-tests/winfsp-tests.c b/tst/winfsp-tests/winfsp-tests.c
index b5053caa..e82999a0 100644
--- a/tst/winfsp-tests/winfsp-tests.c
+++ b/tst/winfsp-tests/winfsp-tests.c
@@ -184,6 +184,7 @@ int main(int argc, char *argv[])
TESTSUITE(eventlog_tests);
TESTSUITE(path_tests);
TESTSUITE(dirbuf_tests);
+ TESTSUITE(version_tests);
TESTSUITE(mount_tests);
TESTSUITE(timeout_tests);
TESTSUITE(memfs_tests);