diff --git a/build/VStudio/testing/winfsp-tests.vcxproj b/build/VStudio/testing/winfsp-tests.vcxproj index 5e494520..55cd2848 100644 --- a/build/VStudio/testing/winfsp-tests.vcxproj +++ b/build/VStudio/testing/winfsp-tests.vcxproj @@ -186,6 +186,7 @@ + diff --git a/build/VStudio/testing/winfsp-tests.vcxproj.filters b/build/VStudio/testing/winfsp-tests.vcxproj.filters index dd1e6352..d4443b26 100644 --- a/build/VStudio/testing/winfsp-tests.vcxproj.filters +++ b/build/VStudio/testing/winfsp-tests.vcxproj.filters @@ -70,6 +70,9 @@ Source + + Source + diff --git a/tst/winfsp-tests/hooks.c b/tst/winfsp-tests/hooks.c new file mode 100644 index 00000000..0e692509 --- /dev/null +++ b/tst/winfsp-tests/hooks.c @@ -0,0 +1,194 @@ +/** + * @file hooks.c + * + * @copyright 2015-2016 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 "winfsp-tests.h" + +#undef CreateFileW +#undef CloseHandle +#undef DeleteFileW + +#define FILENAMEBUF_SIZE 1024 + +static VOID PrepareFileName(PCWSTR FileName, PWSTR FileNameBuf) +{ + static WCHAR DevicePrefix[] = + L"\\\\?\\GLOBALROOT\\Device\\Volume{01234567-0123-0123-0101-010101010101}"; + static WCHAR MemfsSharePrefix[] = + L"\\\\memfs\\share"; + static const int TogglePercent = 25; + PWSTR P, EndP; + size_t L1, L2, L3; + + wcscpy_s(FileNameBuf, FILENAMEBUF_SIZE, FileName); + + if (OptCaseRandomize) + { + if (L'\\' == FileNameBuf[0] && L'\\' == FileNameBuf[1] && + L'?' == FileNameBuf[2] && L'\\' == FileNameBuf[3] && + testalpha(FileNameBuf[4]) && L':' == FileNameBuf[5] && L'\\' == FileNameBuf[6]) + P = FileNameBuf + 6; + else if (0 == wcsncmp(FileNameBuf, DevicePrefix, wcschr(DevicePrefix, L'{') - DevicePrefix)) + P = FileNameBuf + wcslen(DevicePrefix); + else if (L'\\' == FileNameBuf[0] && L'\\' == FileNameBuf[1]) + P = FileNameBuf + 2; + else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2]) + P = FileNameBuf + 2; + else + ABORT("unknown filename format"); + + for (EndP = P + wcslen(P); EndP > P; P++) + if (testalpha(*P) && myrand() <= (TogglePercent) * 0x7fff / 100) + *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]) + ABORT("--mountpoint not supported with NTFS"); + else if (0 == wcsncmp(FileNameBuf, DevicePrefix, wcschr(DevicePrefix, L'{') - DevicePrefix)) + P = FileNameBuf + wcslen(DevicePrefix); + else if (0 == mywcscmp( + FileNameBuf, (int)wcslen(MemfsSharePrefix), MemfsSharePrefix, (int)wcslen(MemfsSharePrefix))) + P = FileNameBuf + wcslen(MemfsSharePrefix); + else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2]) + ABORT("--mountpoint not supported with NTFS"); + else + ABORT("unknown filename format"); + + L1 = wcslen(P) + 1; + L2 = wcslen(OptMountPoint); + memmove(FileNameBuf + FILENAMEBUF_SIZE - L1, P, L1 * sizeof(WCHAR)); + memmove(FileNameBuf, OptMountPoint, L2 * sizeof(WCHAR)); + memmove(FileNameBuf + L2, FileNameBuf + FILENAMEBUF_SIZE - L1, L1 * sizeof(WCHAR)); + } + + if (OptShareName && memfs_running) + { + if (L'\\' == FileNameBuf[0] && L'\\' == FileNameBuf[1] && + L'?' == FileNameBuf[2] && L'\\' == FileNameBuf[3] && + testalpha(FileNameBuf[4]) && L':' == FileNameBuf[5] && L'\\' == FileNameBuf[6]) + /* NTFS testing can only been done when the whole drive is being shared */ + P = FileNameBuf + 6; + else if (0 == wcsncmp(FileNameBuf, DevicePrefix, wcschr(DevicePrefix, L'{') - DevicePrefix)) + P = FileNameBuf + wcslen(DevicePrefix); + else if (0 == mywcscmp( + FileNameBuf, (int)wcslen(MemfsSharePrefix), MemfsSharePrefix, (int)wcslen(MemfsSharePrefix))) + P = FileNameBuf + wcslen(MemfsSharePrefix); + else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2]) + /* NTFS testing can only been done when the whole drive is being shared */ + P = FileNameBuf + 2; + else + ABORT("unknown filename format"); + + L1 = wcslen(P) + 1; + L2 = wcslen(OptShareComputer); + L3 = wcslen(OptShareName); + memmove(FileNameBuf + FILENAMEBUF_SIZE - L1, P, L1 * sizeof(WCHAR)); + memmove(FileNameBuf, OptShareComputer, L2 * sizeof(WCHAR)); + memmove(FileNameBuf + L2, OptShareName, L3 * sizeof(WCHAR)); + memmove(FileNameBuf + L2 + L3, FileNameBuf + FILENAMEBUF_SIZE - L1, L1 * sizeof(WCHAR)); + } +} + +HANDLE HookCreateFileW( + LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile) +{ + WCHAR FileNameBuf[FILENAMEBUF_SIZE]; + TOKEN_PRIVILEGES Privileges; + + PrepareFileName(lpFileName, FileNameBuf); + + if (OptNoTraverseToken) + { + Privileges.PrivilegeCount = 1; + Privileges.Privileges[0].Attributes = 0; + Privileges.Privileges[0].Luid = OptNoTraverseLuid; + if (!AdjustTokenPrivileges(OptNoTraverseToken, FALSE, &Privileges, 0, 0, 0)) + ABORT("cannot disable traverse privilege"); + } + + HANDLE h; + if (!OptResilient) + h = CreateFileW( + FileNameBuf, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + else + h = ResilientCreateFileW( + FileNameBuf, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + DWORD LastError = GetLastError(); + + if (OptNoTraverseToken) + { + Privileges.PrivilegeCount = 1; + Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + Privileges.Privileges[0].Luid = OptNoTraverseLuid; + if (!AdjustTokenPrivileges(OptNoTraverseToken, FALSE, &Privileges, 0, 0, 0)) + ABORT("cannot enable traverse privilege"); + } + +#if 0 + FspDebugLog("CreateFileW(\"%S\", %#lx, %#lx, %p, %#lx, %#lx, %p) = %p[%#lx]\n", + FileNameBuf, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile, + h, INVALID_HANDLE_VALUE != h ? 0 : LastError); +#endif + + SetLastError(LastError); + return h; +} + +BOOL HookCloseHandle( + HANDLE hObject) +{ + if (!OptResilient) + return CloseHandle(hObject); + else + return ResilientCloseHandle(hObject); +} + +BOOL HookDeleteFileW( + LPCWSTR lpFileName) +{ + if (!OptResilient) + return DeleteFileW(lpFileName); + else + return ResilientDeleteFileW(lpFileName); +} diff --git a/tst/winfsp-tests/winfsp-tests.c b/tst/winfsp-tests/winfsp-tests.c index 33cc4cee..68d44207 100644 --- a/tst/winfsp-tests/winfsp-tests.c +++ b/tst/winfsp-tests/winfsp-tests.c @@ -23,12 +23,9 @@ #include "winfsp-tests.h" -#define ABORT(s)\ - do\ - {\ - tlib_printf("ABORT: %s: %s\n", __func__, s);\ - abort();\ - } while (0,0) +#undef CreateFileW +#undef CloseHandle +#undef DeleteFileW int NtfsTests = 0; int WinFspDiskTests = 1; @@ -69,11 +66,8 @@ int mywcscmp(PWSTR a, int alen, PWSTR b, int blen) return res; } -#define testalpha(c) ('a' <= ((c) | 0x20) && ((c) | 0x20) <= 'z') -#define togglealpha(c) ((c) ^ 0x20) -#undef CreateFileW static unsigned myrandseed = 1; -static int myrand(void) +int myrand(void) { /* * This mimics MSVCRT rand(); we need our own version @@ -83,172 +77,6 @@ static int myrand(void) myrandseed = myrandseed * 214013 + 2531011; return (myrandseed >> 16) & RAND_MAX; } -HANDLE HookCreateFileW( - LPCWSTR lpFileName, - DWORD dwDesiredAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreationDisposition, - DWORD dwFlagsAndAttributes, - HANDLE hTemplateFile) -{ - static WCHAR DevicePrefix[] = - L"\\\\?\\GLOBALROOT\\Device\\Volume{01234567-0123-0123-0101-010101010101}"; - static WCHAR MemfsSharePrefix[] = - L"\\\\memfs\\share"; - static const TogglePercent = 25; - WCHAR FileNameBuf[1024]; - TOKEN_PRIVILEGES Privileges; - PWSTR P, EndP; - size_t L1, L2; - - wcscpy_s(FileNameBuf, sizeof FileNameBuf / sizeof(WCHAR), lpFileName); - - if (OptCaseRandomize) - { - if (L'\\' == FileNameBuf[0] && L'\\' == FileNameBuf[1] && - L'?' == FileNameBuf[2] && L'\\' == FileNameBuf[3] && - testalpha(FileNameBuf[4]) && L':' == FileNameBuf[5] && L'\\' == FileNameBuf[6]) - P = FileNameBuf + 7; - else if (0 == wcsncmp(FileNameBuf, DevicePrefix, wcschr(DevicePrefix, L'{') - DevicePrefix)) - P = FileNameBuf + wcslen(DevicePrefix); - else if (L'\\' == FileNameBuf[0] && L'\\' == FileNameBuf[1]) - P = FileNameBuf + 2; - else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2]) - P = FileNameBuf + 3; - else - ABORT("unknown filename format"); - - for (EndP = P + wcslen(P); EndP > P; P++) - if (testalpha(*P) && myrand() <= (TogglePercent) * 0x7fff / 100) - *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]) - ABORT("--mountpoint not supported with NTFS"); - else if (0 == wcsncmp(FileNameBuf, DevicePrefix, wcschr(DevicePrefix, L'{') - DevicePrefix)) - P = FileNameBuf + wcslen(DevicePrefix); - else if (0 == mywcscmp( - FileNameBuf, (int)wcslen(MemfsSharePrefix), MemfsSharePrefix, (int)wcslen(MemfsSharePrefix))) - P = FileNameBuf + wcslen(MemfsSharePrefix); - else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2]) - ABORT("--mountpoint not supported with NTFS"); - else - ABORT("unknown filename format"); - - L1 = wcslen(P) + 1; - L2 = wcslen(OptMountPoint); - memmove(FileNameBuf + 1024 - L1, P, L1 * sizeof(WCHAR)); - memmove(FileNameBuf, OptMountPoint, L2 * sizeof(WCHAR)); - memmove(FileNameBuf + L2, FileNameBuf + 1024 - L1, L1 * sizeof(WCHAR)); - } - - if (OptShareName && memfs_running) - { - if (L'\\' == FileNameBuf[0] && L'\\' == FileNameBuf[1] && - L'?' == FileNameBuf[2] && L'\\' == FileNameBuf[3] && - testalpha(FileNameBuf[4]) && L':' == FileNameBuf[5] && L'\\' == FileNameBuf[6]) - /* NTFS testing can only been done when the whole drive is being shared */ - P = FileNameBuf + 6; - else if (0 == wcsncmp(FileNameBuf, DevicePrefix, wcschr(DevicePrefix, L'{') - DevicePrefix)) - P = FileNameBuf + wcslen(DevicePrefix); - else if (0 == mywcscmp( - FileNameBuf, (int)wcslen(MemfsSharePrefix), MemfsSharePrefix, (int)wcslen(MemfsSharePrefix))) - P = FileNameBuf + wcslen(MemfsSharePrefix); - else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2]) - /* NTFS testing can only been done when the whole drive is being shared */ - P = FileNameBuf + 2; - else - ABORT("unknown filename format"); - - L1 = wcslen(P) + 1; - L2 = wcslen(OptShareName); - memmove(FileNameBuf + 1024 - L1, P, L1 * sizeof(WCHAR)); - memmove(FileNameBuf, OptShareComputer, sizeof OptShareComputer - sizeof(WCHAR)); - memmove(FileNameBuf + (sizeof OptShareComputer - sizeof(WCHAR)) / sizeof(WCHAR), - OptShareName, L2 * sizeof(WCHAR)); - memmove(FileNameBuf + (sizeof OptShareComputer - sizeof(WCHAR)) / sizeof(WCHAR) + L2, - FileNameBuf + 1024 - L1, L1 * sizeof(WCHAR)); - } - - if (OptNoTraverseToken) - { - Privileges.PrivilegeCount = 1; - Privileges.Privileges[0].Attributes = 0; - Privileges.Privileges[0].Luid = OptNoTraverseLuid; - if (!AdjustTokenPrivileges(OptNoTraverseToken, FALSE, &Privileges, 0, 0, 0)) - ABORT("cannot disable traverse privilege"); - } - - HANDLE h; - if (!OptResilient) - h = CreateFileW( - FileNameBuf, - dwDesiredAccess, - dwShareMode, - lpSecurityAttributes, - dwCreationDisposition, - dwFlagsAndAttributes, - hTemplateFile); - else - h = ResilientCreateFileW( - FileNameBuf, - dwDesiredAccess, - dwShareMode, - lpSecurityAttributes, - dwCreationDisposition, - dwFlagsAndAttributes, - hTemplateFile); - DWORD LastError = GetLastError(); - - if (OptNoTraverseToken) - { - Privileges.PrivilegeCount = 1; - Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - Privileges.Privileges[0].Luid = OptNoTraverseLuid; - if (!AdjustTokenPrivileges(OptNoTraverseToken, FALSE, &Privileges, 0, 0, 0)) - ABORT("cannot enable traverse privilege"); - } - -#if 0 - FspDebugLog("CreateFileW(\"%S\", %#lx, %#lx, %p, %#lx, %#lx, %p) = %p[%#lx]\n", - FileNameBuf, - dwDesiredAccess, - dwShareMode, - lpSecurityAttributes, - dwCreationDisposition, - dwFlagsAndAttributes, - hTemplateFile, - h, INVALID_HANDLE_VALUE != h ? 0 : LastError); -#endif - - SetLastError(LastError); - return h; -} - -#undef CloseHandle -BOOL HookCloseHandle( - HANDLE hObject) -{ - if (!OptResilient) - return CloseHandle(hObject); - else - return ResilientCloseHandle(hObject); -} - -#undef DeleteFileW -BOOL HookDeleteFileW( - LPCWSTR lpFileName) -{ - if (!OptResilient) - return DeleteFileW(lpFileName); - else - return ResilientDeleteFileW(lpFileName); -} static VOID DisableBackupRestorePrivileges(VOID) { diff --git a/tst/winfsp-tests/winfsp-tests.h b/tst/winfsp-tests/winfsp-tests.h index d94c6c97..c215e6c9 100644 --- a/tst/winfsp-tests/winfsp-tests.h +++ b/tst/winfsp-tests/winfsp-tests.h @@ -17,12 +17,16 @@ #include -void *memfs_start_ex(ULONG Flags, ULONG FileInfoTimeout); -void *memfs_start(ULONG Flags); -void memfs_stop(void *data); -PWSTR memfs_volumename(void *data); +#define ABORT(s)\ + do\ + {\ + void tlib_printf(const char *fmt, ...);\ + tlib_printf("ABORT: %s: %s\n", __func__, s);\ + abort();\ + } while (0,0) -int mywcscmp(PWSTR a, int alen, PWSTR b, int blen); +#define testalpha(c) ('a' <= ((c) | 0x20) && ((c) | 0x20) <= 'z') +#define togglealpha(c) ((c) ^ 0x20) #define CreateFileW HookCreateFileW #define CloseHandle HookCloseHandle @@ -58,6 +62,14 @@ typedef struct BOOLEAN Disposition; } MY_FILE_DISPOSITION_INFO; +void *memfs_start_ex(ULONG Flags, ULONG FileInfoTimeout); +void *memfs_start(ULONG Flags); +void memfs_stop(void *data); +PWSTR memfs_volumename(void *data); + +int mywcscmp(PWSTR a, int alen, PWSTR b, int blen); +int myrand(void); + extern int NtfsTests; extern int WinFspDiskTests; extern int WinFspNetTests;