diff --git a/build/VStudio/launcher/launchctl.vcxproj b/build/VStudio/launcher/launchctl.vcxproj
index f8912642..cb72c6e0 100644
--- a/build/VStudio/launcher/launchctl.vcxproj
+++ b/build/VStudio/launcher/launchctl.vcxproj
@@ -105,6 +105,7 @@
false
Default
MultiThreaded
+ /Gs16384 %(AdditionalOptions)
Console
@@ -123,6 +124,7 @@
false
Default
MultiThreaded
+ /Gs16384 %(AdditionalOptions)
Console
@@ -142,6 +144,7 @@
..\..\..\src;..\..\..\inc
false
MultiThreaded
+ /Gs16384 %(AdditionalOptions)
Console
@@ -163,6 +166,7 @@
..\..\..\src;..\..\..\inc
false
MultiThreaded
+ /Gs16384 %(AdditionalOptions)
Console
diff --git a/build/VStudio/launcher/launcher.vcxproj b/build/VStudio/launcher/launcher.vcxproj
index e687d74a..af1c1e54 100644
--- a/build/VStudio/launcher/launcher.vcxproj
+++ b/build/VStudio/launcher/launcher.vcxproj
@@ -105,6 +105,7 @@
Default
false
MultiThreaded
+ /Gs16384 %(AdditionalOptions)
Console
@@ -124,6 +125,7 @@
Default
false
MultiThreaded
+ /Gs16384 %(AdditionalOptions)
Console
@@ -144,6 +146,7 @@
..\..\..\src;..\..\..\inc
false
MultiThreaded
+ /Gs16384 %(AdditionalOptions)
Console
@@ -166,6 +169,7 @@
..\..\..\src;..\..\..\inc
false
MultiThreaded
+ /Gs16384 %(AdditionalOptions)
Console
diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj
index d7e697da..8b8dc2ac 100644
--- a/build/VStudio/winfsp_dll.vcxproj
+++ b/build/VStudio/winfsp_dll.vcxproj
@@ -173,6 +173,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
MultiThreaded
Default
false
+ /Gs16384 %(AdditionalOptions)
Windows
@@ -198,6 +199,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
MultiThreaded
Default
false
+ /Gs16384 %(AdditionalOptions)
Windows
@@ -224,6 +226,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
..\..\src;..\..\inc
MultiThreaded
false
+ /Gs16384 %(AdditionalOptions)
Windows
@@ -252,6 +255,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
..\..\src;..\..\inc
MultiThreaded
false
+ /Gs16384 %(AdditionalOptions)
Windows
diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h
index 7dfbc13c..d54c7fcc 100644
--- a/inc/winfsp/fsctl.h
+++ b/inc/winfsp/fsctl.h
@@ -63,6 +63,7 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
#define FSP_FSCTL_TRANSACT_REQ_SIZEMAX (4096 - 64) /* 64: size for internal request header */
#define FSP_FSCTL_TRANSACT_RSP_SIZEMAX (4096 - 64) /* symmetry! */
+#define FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMAX (FSP_FSCTL_TRANSACT_REQ_SIZEMAX - sizeof(FSP_FSCTL_TRANSACT_REQ))
#define FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX (FSP_FSCTL_TRANSACT_RSP_SIZEMAX - sizeof(FSP_FSCTL_TRANSACT_RSP))
#define FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN 16384
#define FSP_FSCTL_TRANSACT_BUFFER_SIZEMIN FSP_FSCTL_TRANSACT_REQ_SIZEMAX
diff --git a/src/dll/fsop.c b/src/dll/fsop.c
index ff6a09a3..f3e11cf0 100644
--- a/src/dll/fsop.c
+++ b/src/dll/fsop.c
@@ -1064,9 +1064,7 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
union
{
REPARSE_DATA_BUFFER V;
- UINT8 B[FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
- /* assumption: the substitute and print paths fit in the same buffer */
- FSP_FSCTL_TRANSACT_PATH_SIZEMAX];
+ UINT8 B[FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX];
} ReparseDataBuf;
PREPARSE_DATA_BUFFER ReparseData = &ReparseDataBuf.V;
SIZE_T Size, MaxTries = 32;
@@ -1151,7 +1149,7 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
if (IO_REPARSE_TAG_SYMLINK == ReparseData->ReparseTag)
{
TargetLink = ReparseData->SymbolicLinkReparseBuffer.PathBuffer +
- ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset;
+ ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
Size = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
}
else
diff --git a/src/shared/minimal.h b/src/shared/minimal.h
index 3499d4d7..d0bfdd7a 100644
--- a/src/shared/minimal.h
+++ b/src/shared/minimal.h
@@ -26,6 +26,7 @@
* - "C/C++ > Code Generation > Basic Runtime Checks" must be set to "Default"
* - "C/C++ > Code Generation > Runtime Library" must be set to "Multi-threaded (/MT)".
* - "C/C++ > Code Generation > Security Check" must be disabled (/GS-).
+ * - "C/C++ > Command Line > Additional Options" add "/Gs16384" to disable __chkstk probes.
* - "Linker > Input > Ignore All Default Libraries" must be "Yes".
*
*
diff --git a/src/sys/fsctl.c b/src/sys/fsctl.c
index 86fe7839..62da25ec 100644
--- a/src/sys/fsctl.c
+++ b/src/sys/fsctl.c
@@ -118,8 +118,8 @@ static NTSTATUS FspFsvolFileSystemControlReparsePoint(
if (IsWrite)
{
if (0 == InputBuffer || 0 == InputBufferLength ||
- FSP_FSCTL_TRANSACT_REQ_SIZEMAX - FIELD_OFFSET(FSP_FSCTL_TRANSACT_REQ, Buffer) -
- (FileNode->FileName.Length + sizeof(WCHAR)) < InputBufferLength)
+ FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMAX - (FileNode->FileName.Length + sizeof(WCHAR)) <
+ InputBufferLength)
return STATUS_INVALID_PARAMETER;
Result = FsRtlValidateReparsePointBuffer(InputBufferLength, InputBuffer);
@@ -134,9 +134,9 @@ static NTSTATUS FspFsvolFileSystemControlReparsePoint(
if (FsvolDeviceExtension->VolumeParams.ReparsePointsAccessCheck)
{
if (KernelMode != Irp->RequestorMode &&
- SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_CREATE_SYMBOLIC_LINK_PRIVILEGE),
+ !SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_CREATE_SYMBOLIC_LINK_PRIVILEGE),
UserMode))
- return STATUS_ACCESS_DENIED;
+ return STATUS_PRIVILEGE_NOT_HELD;
}
/* determine if target resides on same device as link (convenience for user mode) */
diff --git a/tst/memfs/memfs.cpp b/tst/memfs/memfs.cpp
index 25d6a28d..092a23f3 100644
--- a/tst/memfs/memfs.cpp
+++ b/tst/memfs/memfs.cpp
@@ -1153,6 +1153,7 @@ NTSTATUS MemfsCreate(
VolumeParams.UnicodeOnDisk = 1;
VolumeParams.PersistentAcls = 1;
VolumeParams.ReparsePoints = 1;
+ VolumeParams.ReparsePointsAccessCheck = 1;
if (0 != VolumePrefix)
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix);
diff --git a/tst/winfsp-tests/reparse-test.c b/tst/winfsp-tests/reparse-test.c
index 1c34f16e..58eaceb1 100644
--- a/tst/winfsp-tests/reparse-test.c
+++ b/tst/winfsp-tests/reparse-test.c
@@ -219,8 +219,89 @@ void reparse_nfs_test(void)
}
}
+static void reparse_symlink_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
+{
+ void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
+
+ HANDLE Handle;
+ BOOL Success;
+ WCHAR FilePath[MAX_PATH], LinkPath[MAX_PATH];
+ PUINT8 NameInfoBuf[sizeof(FILE_NAME_INFO) + MAX_PATH];
+ PFILE_NAME_INFO PNameInfo = (PVOID)NameInfoBuf;
+
+ StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
+ Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
+
+ StringCbPrintfW(LinkPath, sizeof LinkPath, L"%s%s\\link0",
+ Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
+
+ Success = CreateSymbolicLinkW(LinkPath, FilePath, 0);
+ if (Success)
+ {
+ Handle = CreateFileW(FilePath,
+ FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
+ ASSERT(INVALID_HANDLE_VALUE != Handle);
+ CloseHandle(Handle);
+
+ Handle = CreateFileW(LinkPath,
+ FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ 0, OPEN_EXISTING, 0, 0);
+ ASSERT(INVALID_HANDLE_VALUE != Handle);
+
+ Success = GetFileInformationByHandleEx(Handle, FileNameInfo, PNameInfo, sizeof NameInfoBuf);
+ ASSERT(Success);
+ if (-1 == Flags)
+ ASSERT(PNameInfo->FileNameLength == wcslen(FilePath + 6) * sizeof(WCHAR));
+ else if (0 == Prefix)
+ ASSERT(PNameInfo->FileNameLength == wcslen(L"\\file0") * sizeof(WCHAR));
+ else
+ ASSERT(PNameInfo->FileNameLength == wcslen(FilePath + 1) * sizeof(WCHAR));
+ if (-1 == Flags)
+ ASSERT(0 == memcmp(FilePath + 6, PNameInfo->FileName, PNameInfo->FileNameLength));
+ else if (0 == Prefix)
+ ASSERT(0 == memcmp(L"\\file0", PNameInfo->FileName, PNameInfo->FileNameLength));
+ else
+ ASSERT(0 == memcmp(FilePath + 1, PNameInfo->FileName, PNameInfo->FileNameLength));
+
+ CloseHandle(Handle);
+
+ Success = DeleteFileW(LinkPath);
+ ASSERT(Success);
+
+ Success = DeleteFileW(FilePath);
+ ASSERT(Success);
+ }
+ else
+ {
+ ASSERT(ERROR_PRIVILEGE_NOT_HELD == GetLastError());
+ FspDebugLog(__FUNCTION__ ": need SE_CREATE_SYMBOLIC_LINK_PRIVILEGE\n");
+ }
+
+ memfs_stop(memfs);
+}
+
+void reparse_symlink_test(void)
+{
+ if (NtfsTests)
+ {
+ WCHAR DirBuf[MAX_PATH] = L"\\\\?\\";
+ GetCurrentDirectoryW(MAX_PATH - 4, DirBuf + 4);
+ reparse_symlink_dotest(-1, DirBuf, 0);
+ }
+ if (WinFspDiskTests)
+ {
+ reparse_symlink_dotest(MemfsDisk, 0, 0);
+ }
+ if (WinFspNetTests)
+ {
+ reparse_symlink_dotest(MemfsNet, L"\\\\memfs\\share", 0);
+ }
+}
+
void reparse_tests(void)
{
TEST(reparse_guid_test);
TEST(reparse_nfs_test);
+ TEST(reparse_symlink_test);
}