diff --git a/tst/winfsp-tests/reparse-test.c b/tst/winfsp-tests/reparse-test.c index c405d554..e577fd3c 100644 --- a/tst/winfsp-tests/reparse-test.c +++ b/tst/winfsp-tests/reparse-test.c @@ -314,9 +314,171 @@ void reparse_symlink_test(void) } } +static BOOL my_mkdir_fn(PWSTR Prefix, void *memfs, PWSTR FileName) +{ + WCHAR FilePath[MAX_PATH]; + + StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s%s", + Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), FileName); + + return CreateDirectoryW(FilePath, 0); +} + +static BOOL my_rmdir_fn(PWSTR Prefix, void *memfs, PWSTR FileName) +{ + WCHAR FilePath[MAX_PATH]; + + StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s%s", + Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), FileName); + + return RemoveDirectoryW(FilePath); +} + +static BOOL my_make_fn(PWSTR Prefix, void *memfs, PWSTR FileName) +{ + WCHAR FilePath[MAX_PATH]; + HANDLE Handle; + + StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s%s", + Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), FileName); + + Handle = CreateFileW(FilePath, 0, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); + if (INVALID_HANDLE_VALUE == Handle) + return FALSE; + CloseHandle(Handle); + return TRUE; +} + +static BOOL my_unlink_fn(PWSTR Prefix, void *memfs, PWSTR FileName) +{ + WCHAR FilePath[MAX_PATH]; + + StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s%s", + Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), FileName); + + return DeleteFileW(FilePath); +} + +static BOOL my_symlink_fn(PWSTR Prefix, void *memfs, PWSTR LinkName, PWSTR FileName, DWORD Flags) +{ + WCHAR LinkPath[MAX_PATH]; + + StringCbPrintfW(LinkPath, sizeof LinkPath, L"%s%s%s", + Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), LinkName); + + return CreateSymbolicLinkW(LinkPath, FileName, Flags); +} + +static BOOL my_namecheck_fn(ULONG Flags, PWSTR Prefix, void *memfs, PWSTR FileName, PWSTR Expected) +{ + WCHAR FilePath[MAX_PATH], ExpectedPath[MAX_PATH]; + HANDLE Handle; + PUINT8 NameInfoBuf[sizeof(FILE_NAME_INFO) + MAX_PATH]; + PFILE_NAME_INFO PNameInfo = (PVOID)NameInfoBuf; + + StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s%s", + Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), FileName); + StringCbPrintfW(ExpectedPath, sizeof ExpectedPath, L"%s%s%s", + Prefix ? Prefix : L"", Prefix ? L"\\" : L"", Expected); + + Handle = CreateFileW(FilePath, FILE_READ_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); + if (INVALID_HANDLE_VALUE == Handle) + return FALSE; + + if (GetFileInformationByHandleEx(Handle, FileNameInfo, PNameInfo, sizeof NameInfoBuf)) + { + if (-1 == Flags) + ASSERT(PNameInfo->FileNameLength == wcslen(ExpectedPath + 6) * sizeof(WCHAR)); + else if (0 == Prefix) + ASSERT(PNameInfo->FileNameLength == wcslen(ExpectedPath) * sizeof(WCHAR)); + else + ASSERT(PNameInfo->FileNameLength == wcslen(ExpectedPath + 1) * sizeof(WCHAR)); + if (-1 == Flags) + ASSERT(0 == memcmp(ExpectedPath + 6, PNameInfo->FileName, PNameInfo->FileNameLength)); + else if (0 == Prefix) + ASSERT(0 == memcmp(ExpectedPath, PNameInfo->FileName, PNameInfo->FileNameLength)); + else + ASSERT(0 == memcmp(ExpectedPath + 1, PNameInfo->FileName, PNameInfo->FileNameLength)); + } + + CloseHandle(Handle); + return TRUE; +} + +#define my_mkdir(FileName) ASSERT(my_mkdir_fn(Prefix, memfs, FileName)) +#define my_rmdir(FileName) ASSERT(my_rmdir_fn(Prefix, memfs, FileName)) +#define my_make(FileName) ASSERT(my_make_fn(Prefix, memfs, FileName)) +#define my_unlink(FileName) ASSERT(my_unlink_fn(Prefix, memfs, FileName)) +#define my_symlinkd(LinkName, FileName) ASSERT(my_symlink_fn(Prefix, memfs, LinkName, FileName,\ + SYMBOLIC_LINK_FLAG_DIRECTORY)) +#define my_symlink(LinkName, FileName) ASSERT(my_symlink_fn(Prefix, memfs, LinkName, FileName, 0)) +#define my_namecheck(FileName, Expected)ASSERT(my_namecheck_fn(Flags, Prefix, memfs, FileName, Expected)) + +static void reparse_symlink_large_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout) +{ + void *memfs = memfs_start_ex(Flags, FileInfoTimeout); + + my_mkdir(L"\\1"); + my_mkdir(L"\\1\\1.1"); + my_make(L"\\1\\1.2"); + my_make(L"\\1\\1.3"); + my_make(L"\\1\\1.1\\1.1.1"); + my_mkdir(L"\\2"); + my_make(L"\\2\\2.1"); + + my_symlink(L"\\l0", L"NON-EXISTANT"); + my_symlink(L"\\loop", L"loop"); + my_symlink(L"\\1\\1.1\\l1.1.1", L"1.1.1"); + my_symlinkd(L"\\2\\l1", L"..\\1"); + my_symlinkd(L"\\1\\l2", L"..\\2"); + my_symlinkd(L"\\2\\a1", L"\\1"); + my_symlinkd(L"\\1\\a2", L"\\2"); + + my_rmdir(L"\\1\\a2"); + my_rmdir(L"\\2\\a1"); + my_rmdir(L"\\1\\l2"); + my_rmdir(L"\\2\\l1"); + my_unlink(L"\\1\\1.1\\l1.1.1"); + my_unlink(L"\\loop"); + my_unlink(L"\\l0"); + + my_unlink(L"\\2\\2.1"); + my_rmdir(L"\\2"); + my_unlink(L"\\1\\1.1\\1.1.1"); + my_unlink(L"\\1\\1.3"); + my_unlink(L"\\1\\1.2"); + my_rmdir(L"\\1\\1.1"); + my_rmdir(L"\\1"); + + memfs_stop(memfs); +} + +void reparse_symlink_large_test(void) +{ + if (NtfsTests) + { + WCHAR DirBuf[MAX_PATH] = L"\\\\?\\"; + GetCurrentDirectoryW(MAX_PATH - 4, DirBuf + 4); + reparse_symlink_large_dotest(-1, DirBuf, 0); + } + if (WinFspDiskTests) + { + reparse_symlink_large_dotest(MemfsDisk, 0, 0); + } + if (WinFspNetTests) + { + reparse_symlink_large_dotest(MemfsNet, L"\\\\memfs\\share", 0); + } +} + void reparse_tests(void) { TEST(reparse_guid_test); TEST(reparse_nfs_test); TEST(reparse_symlink_test); + TEST(reparse_symlink_large_test); }