From cb17b7e2e0349d998f797ce97bffc41360a87a26 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Tue, 18 Oct 2016 14:08:58 -0700 Subject: [PATCH] dll: FspFileSystemSetMountPoint: testing --- inc/winfsp/winfsp.h | 10 +++++-- src/dll/fs.c | 18 +++++++++-- tools/run-tests.bat | 12 ++++++++ tst/winfsp-tests/create-test.c | 22 +++++++++----- tst/winfsp-tests/memfs-test.c | 12 ++++++++ tst/winfsp-tests/reparse-test.c | 3 +- tst/winfsp-tests/winfsp-tests.c | 53 ++++++++++++++++++++++++++++++++- tst/winfsp-tests/winfsp-tests.h | 17 ++++++----- 8 files changed, 125 insertions(+), 22 deletions(-) diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index db7020ea..f1438968 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -855,9 +855,13 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem); /** * Set the mount point for a file system. * - * This function currently only supports drive letters (X:) as mount points. Refer to the - * documentation of the DefineDosDevice Windows API to better understand how drive letters are - * created. + * This function supports drive letters (X:) or directories as mount points: + * * * @param FileSystem * The file system object. diff --git a/src/dll/fs.c b/src/dll/fs.c index e8f950e1..6d695faf 100644 --- a/src/dll/fs.c +++ b/src/dll/fs.c @@ -126,10 +126,24 @@ static NTSTATUS FspFileSystemSetMountPoint_CreateDirectory(PWSTR MountPoint, PWS NTSTATUS Result; HANDLE DirHandle; BOOL Success; - DWORD Bytes; + DWORD Backslashes, Bytes; USHORT VolumeNameLength, BackslashLength, ReparseDataLength; PREPARSE_DATA_BUFFER ReparseData = 0; - PWSTR PathBuffer; + PWSTR P, PathBuffer; + + /* + * Windows does not allow mount points (junctions) to point to network file systems. + * + * Count how many backslashes our VolumeName. If it is 3 or more this is a network + * file system. Preemptively return STATUS_NETWORK_ACCESS_DENIED. + */ + for (P = VolumeName, Backslashes = 0; *P; P++) + if (L'\\' == *P) + if (3 == ++Backslashes) + { + Result = STATUS_NETWORK_ACCESS_DENIED; + goto exit; + } if (!CreateDirectoryW(MountPoint, 0)) { diff --git a/tools/run-tests.bat b/tools/run-tests.bat index 38a4ea52..6923fef0 100644 --- a/tools/run-tests.bat +++ b/tools/run-tests.bat @@ -78,6 +78,12 @@ if errorlevel 1 goto fail echo winfsp-tests-x64 --case-randomize winfsp-tests-x64 --case-randomize if errorlevel 1 goto fail +echo winfsp-tests-x64 --mountpoint=X: +winfsp-tests-x64 --mountpoint=X: +if errorlevel 1 goto fail +echo winfsp-tests-x64 --mountpoint=mymnt +winfsp-tests-x64 --mountpoint=mymnt +if errorlevel 1 goto fail exit /b 0 :winfsp-tests-x86 @@ -87,6 +93,12 @@ if errorlevel 1 goto fail echo winfsp-tests-x86 --case-randomize winfsp-tests-x86 --case-randomize if errorlevel 1 goto fail +echo winfsp-tests-x86 --mountpoint=X: +winfsp-tests-x86 --mountpoint=X: +if errorlevel 1 goto fail +echo winfsp-tests-x86 --mountpoint=mymnt +winfsp-tests-x86 --mountpoint=mymnt +if errorlevel 1 goto fail exit /b 0 :fsx-memfs-x64 diff --git a/tst/winfsp-tests/create-test.c b/tst/winfsp-tests/create-test.c index d0c4c08f..713be4b4 100644 --- a/tst/winfsp-tests/create-test.c +++ b/tst/winfsp-tests/create-test.c @@ -62,10 +62,13 @@ void create_dotest(ULONG Flags, PWSTR Prefix) StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\\\\\file0", Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); - Handle = CreateFileW(FilePath, - GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); - ASSERT(INVALID_HANDLE_VALUE == Handle); - ASSERT(ERROR_INVALID_NAME == GetLastError()); + if (0 == OptMountPoint) + { + Handle = CreateFileW(FilePath, + GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); + ASSERT(INVALID_HANDLE_VALUE == Handle); + ASSERT(ERROR_INVALID_NAME == GetLastError()); + } } /* invalid chars (wildcards) not allowed */ @@ -146,10 +149,13 @@ void create_dotest(ULONG Flags, PWSTR Prefix) StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0\\", Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); - Handle = CreateFileW(FilePath, - GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); - ASSERT(INVALID_HANDLE_VALUE == Handle); - ASSERT(ERROR_INVALID_NAME == GetLastError()); + if (0 == OptMountPoint) + { + Handle = CreateFileW(FilePath, + GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); + ASSERT(INVALID_HANDLE_VALUE == Handle); + ASSERT(ERROR_INVALID_NAME == GetLastError()); + } StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir1\\\\", Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); diff --git a/tst/winfsp-tests/memfs-test.c b/tst/winfsp-tests/memfs-test.c index 2e740328..3c2714a9 100644 --- a/tst/winfsp-tests/memfs-test.c +++ b/tst/winfsp-tests/memfs-test.c @@ -5,6 +5,8 @@ #include "winfsp-tests.h" +int memfs_running; + void *memfs_start_ex(ULONG Flags, ULONG FileInfoTimeout) { if (-1 == Flags) @@ -24,9 +26,17 @@ void *memfs_start_ex(ULONG Flags, ULONG FileInfoTimeout) ASSERT(NT_SUCCESS(Result)); ASSERT(0 != Memfs); + if (OptMountPoint) + { + Result = FspFileSystemSetMountPoint(MemfsFileSystem(Memfs), OptMountPoint); + ASSERT(NT_SUCCESS(Result)); + } + Result = MemfsStart(Memfs); ASSERT(NT_SUCCESS(Result)); + memfs_running = 1; + return Memfs; } @@ -40,6 +50,8 @@ void memfs_stop(void *data) if (0 == data) return; + memfs_running = 0; + MEMFS *Memfs = data; MemfsStop(Memfs); diff --git a/tst/winfsp-tests/reparse-test.c b/tst/winfsp-tests/reparse-test.c index 8bcc74ac..3d6beaaa 100644 --- a/tst/winfsp-tests/reparse-test.c +++ b/tst/winfsp-tests/reparse-test.c @@ -434,7 +434,7 @@ static void reparse_symlink_relative_dotest(ULONG Flags, PWSTR Prefix, ULONG Fil { ASSERT(ERROR_PRIVILEGE_NOT_HELD == GetLastError()); FspDebugLog(__FUNCTION__ ": need SE_CREATE_SYMBOLIC_LINK_PRIVILEGE\n"); - return; + goto exit; } my_mkdir(L"\\1"); @@ -491,6 +491,7 @@ static void reparse_symlink_relative_dotest(ULONG Flags, PWSTR Prefix, ULONG Fil my_rmdir(L"\\1\\1.1"); my_rmdir(L"\\1"); +exit: memfs_stop(memfs); } diff --git a/tst/winfsp-tests/winfsp-tests.c b/tst/winfsp-tests/winfsp-tests.c index 41a5fa81..827a02fe 100644 --- a/tst/winfsp-tests/winfsp-tests.c +++ b/tst/winfsp-tests/winfsp-tests.c @@ -9,6 +9,7 @@ int WinFspNetTests = 1; BOOLEAN OptCaseInsensitive = FALSE; BOOLEAN OptCaseRandomize = FALSE; +WCHAR OptMountPointBuf[MAX_PATH], *OptMountPoint; int mywcscmp(PWSTR a, int alen, PWSTR b, int blen) { @@ -57,12 +58,16 @@ HANDLE HookCreateFileW( HANDLE hTemplateFile) { static WCHAR DevicePrefix[] = - L"\\\\?\\GLOBALROOT\\Device\\Volume{01234567-0123-0123-0101-010101010101}\\"; + L"\\\\?\\GLOBALROOT\\Device\\Volume{01234567-0123-0123-0101-010101010101}"; + static WCHAR MemfsSharePrefix[] = + L"\\\\memfs\\share"; static const TogglePercent = 25; WCHAR FileNameBuf[1024]; PWSTR P, EndP; + size_t L1, L2; wcscpy_s(FileNameBuf, sizeof FileNameBuf / sizeof(WCHAR), lpFileName); + if (OptCaseRandomize) { if (L'\\' == FileNameBuf[0] && L'\\' == FileNameBuf[1] && @@ -83,6 +88,37 @@ HANDLE HookCreateFileW( *P = togglealpha(*P); } + if (OptMountPoint && memfs_running) + { + if (L'\\' == FileNameBuf[0] && L'\\' == FileNameBuf[1] && + L'?' == FileNameBuf[2] && L'\\' == FileNameBuf[3] && + testalpha(FileNameBuf[4]) && L':' == FileNameBuf[5] && L'\\' == FileNameBuf[6]) + ; + else if (0 == wcsncmp(FileNameBuf, DevicePrefix, wcschr(DevicePrefix, L'{') - DevicePrefix)) + { + P = FileNameBuf + wcslen(DevicePrefix); + L1 = wcslen(P) + 1; + L2 = wcslen(OptMountPoint); + memmove(FileNameBuf + 1024 - L1, P, L1 * sizeof(WCHAR)); + memmove(FileNameBuf, OptMountPoint, L2 * sizeof(WCHAR)); + memmove(FileNameBuf + L2, P, L1 * sizeof(WCHAR)); + } + else if (0 == mywcscmp( + FileNameBuf, (int)wcslen(MemfsSharePrefix), MemfsSharePrefix, (int)wcslen(MemfsSharePrefix))) + { + P = FileNameBuf + wcslen(MemfsSharePrefix); + L1 = wcslen(P) + 1; + L2 = wcslen(OptMountPoint); + memmove(FileNameBuf + 1024 - L1, P, L1 * sizeof(WCHAR)); + memmove(FileNameBuf, OptMountPoint, L2 * sizeof(WCHAR)); + memmove(FileNameBuf + L2, P, L1 * sizeof(WCHAR)); + } + else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2]) + ; + else + abort(); + } + HANDLE h = CreateFileW( FileNameBuf, dwDesiredAccess, @@ -149,6 +185,21 @@ int main(int argc, char *argv[]) OptCaseInsensitive = TRUE; rmarg(argv, argc, argi); } + else if (0 == strncmp("--mountpoint=", a, sizeof "--mountpoint=" - 1)) + { + if (0 != MultiByteToWideChar(CP_UTF8, 0, + a + sizeof "--mountpoint=" - 1, -1, OptMountPointBuf, MAX_PATH)) + { + OptMountPoint = OptMountPointBuf; + rmarg(argv, argc, argi); + + NtfsTests = 0; + if (!(testalpha(OptMountPoint[0]) && + L':' == OptMountPoint[1] && + L'\0' == OptMountPoint[2])) + WinFspNetTests = 0; + } + } } } diff --git a/tst/winfsp-tests/winfsp-tests.h b/tst/winfsp-tests/winfsp-tests.h index 16952d03..87268eca 100644 --- a/tst/winfsp-tests/winfsp-tests.h +++ b/tst/winfsp-tests/winfsp-tests.h @@ -5,13 +5,6 @@ void *memfs_start(ULONG Flags); void memfs_stop(void *data); PWSTR memfs_volumename(void *data); -extern int NtfsTests; -extern int WinFspDiskTests; -extern int WinFspNetTests; - -extern BOOLEAN OptCaseInsensitive; -extern BOOLEAN OptCaseRandomize; - int mywcscmp(PWSTR a, int alen, PWSTR b, int blen); #define CreateFileW HookCreateFileW @@ -23,3 +16,13 @@ HANDLE HookCreateFileW( DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); + +extern int NtfsTests; +extern int WinFspDiskTests; +extern int WinFspNetTests; + +extern BOOLEAN OptCaseInsensitive; +extern BOOLEAN OptCaseRandomize; +extern WCHAR OptMountPointBuf[], *OptMountPoint; + +extern int memfs_running;