From d59976bd5d2b13ec6cf61b1e98a8a277314a803e Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Thu, 14 Mar 2019 21:36:29 -0700 Subject: [PATCH] tst: winfsp-tests: ea_create_test --- build/VStudio/testing/winfsp-tests.vcxproj | 1 + .../testing/winfsp-tests.vcxproj.filters | 3 + src/dll/fsop.c | 15 +- tst/memfs/memfs.cpp | 5 +- tst/winfsp-tests/ea-test.c | 128 ++++++++++++++++++ tst/winfsp-tests/winfsp-tests.c | 1 + 6 files changed, 144 insertions(+), 9 deletions(-) create mode 100644 tst/winfsp-tests/ea-test.c diff --git a/build/VStudio/testing/winfsp-tests.vcxproj b/build/VStudio/testing/winfsp-tests.vcxproj index c1d7825e..d4f78a30 100644 --- a/build/VStudio/testing/winfsp-tests.vcxproj +++ b/build/VStudio/testing/winfsp-tests.vcxproj @@ -185,6 +185,7 @@ + diff --git a/build/VStudio/testing/winfsp-tests.vcxproj.filters b/build/VStudio/testing/winfsp-tests.vcxproj.filters index 493a812a..26eb09a9 100644 --- a/build/VStudio/testing/winfsp-tests.vcxproj.filters +++ b/build/VStudio/testing/winfsp-tests.vcxproj.filters @@ -94,6 +94,9 @@ Source + + Source + diff --git a/src/dll/fsop.c b/src/dll/fsop.c index 54b25822..7621e565 100644 --- a/src/dll/fsop.c +++ b/src/dll/fsop.c @@ -1826,18 +1826,19 @@ FSP_API BOOLEAN FspFileSystemAddEa(PFILE_FULL_EA_INFORMATION SingleEa, { if (0 != SingleEa) { + PUINT8 EaPtr = (PUINT8)Ea + FSP_FSCTL_ALIGN_UP(*PBytesTransferred, sizeof(ULONG)); PUINT8 EaEnd = (PUINT8)Ea + Length; - ULONG EaLength = sizeof *SingleEa + SingleEa->EaNameLength + SingleEa->EaValueLength; + ULONG EaLen = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) + + SingleEa->EaNameLength + 1 + SingleEa->EaValueLength; - Ea = (PVOID)((PUINT8)Ea + *PBytesTransferred); - if ((PUINT8)Ea + EaLength > EaEnd) + if (EaEnd < EaPtr + EaLen) return FALSE; - memcpy(Ea, SingleEa, EaLength); - Ea->NextEntryOffset = FSP_FSCTL_ALIGN_UP(EaLength, sizeof(ULONG)); - *PBytesTransferred += EaLength; + memcpy(EaPtr, SingleEa, EaLen); + ((PFILE_FULL_EA_INFORMATION)EaPtr)->NextEntryOffset = FSP_FSCTL_ALIGN_UP(EaLen, sizeof(ULONG)); + *PBytesTransferred = (ULONG)(EaPtr + EaLen - (PUINT8)Ea); } - else if (sizeof *SingleEa <= *PBytesTransferred) + else if ((ULONG)FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) <= *PBytesTransferred) { PUINT8 EaEnd = (PUINT8)Ea + *PBytesTransferred; diff --git a/tst/memfs/memfs.cpp b/tst/memfs/memfs.cpp index a3bb6b64..b3fa297b 100644 --- a/tst/memfs/memfs.cpp +++ b/tst/memfs/memfs.cpp @@ -441,10 +441,11 @@ NTSTATUS MemfsFileNodeSetEa( if (0 != Ea->EaValueLength) { FileNodeEa = (FILE_FULL_EA_INFORMATION *)malloc( - sizeof *FileNodeEa + Ea->EaNameLength + Ea->EaValueLength); + FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) + Ea->EaNameLength + 1 + Ea->EaValueLength); if (0 == FileNodeEa) return STATUS_INSUFFICIENT_RESOURCES; - memcpy(FileNodeEa, Ea, sizeof *FileNodeEa + Ea->EaNameLength + Ea->EaValueLength); + memcpy(FileNodeEa, Ea, + FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) + Ea->EaNameLength + 1 + Ea->EaValueLength); FileNodeEa->NextEntryOffset = 0; } diff --git a/tst/winfsp-tests/ea-test.c b/tst/winfsp-tests/ea-test.c new file mode 100644 index 00000000..6966b2fe --- /dev/null +++ b/tst/winfsp-tests/ea-test.c @@ -0,0 +1,128 @@ +/** + * @file ea-test.c + * + * @copyright 2015-2019 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 software + * in accordance with the commercial license agreement provided in + * conjunction with the software. The terms and conditions of any such + * commercial license agreement shall govern, supersede, and render + * ineffective any application of the GPLv3 license to this software, + * notwithstanding of any reference thereto in the software or + * associated repository. + */ + +#include +#include +#include +#include "memfs.h" + +#include "winfsp-tests.h" + +static void ea_create_dotest(ULONG Flags, PWSTR Prefix) +{ + void *memfs = memfs_start(Flags); + + HANDLE DirHandle, FileHandle; + NTSTATUS Result; + BOOLEAN Success; + WCHAR FilePath[MAX_PATH]; + WCHAR UnicodePathBuf[MAX_PATH] = L"file2"; + UNICODE_STRING UnicodePath; + OBJECT_ATTRIBUTES Obja; + IO_STATUS_BLOCK Iosb; + LARGE_INTEGER LargeZero = { 0 }; + union + { + FILE_FULL_EA_INFORMATION V; + UINT8 B[128]; + } SingleEa; + union + { + FILE_FULL_EA_INFORMATION V; + UINT8 B[512]; + } Ea; + ULONG EaLength = 0; + + StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir1", + Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); + + Success = CreateDirectoryW(FilePath, 0); + ASSERT(Success); + + DirHandle = CreateFileW(FilePath, + GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE, 0); + ASSERT(INVALID_HANDLE_VALUE != DirHandle); + + memset(&SingleEa, 0, sizeof SingleEa); + SingleEa.V.EaNameLength = (UCHAR)strlen("name1"); + SingleEa.V.EaValueLength = (USHORT)strlen("first"); + lstrcpyA(SingleEa.V.EaName, "name1"); + memcpy(SingleEa.V.EaName + SingleEa.V.EaNameLength + 1, "first", SingleEa.V.EaValueLength); + FspFileSystemAddEa(&SingleEa.V, &Ea.V, sizeof Ea, &EaLength); + + memset(&SingleEa, 0, sizeof SingleEa); + SingleEa.V.EaNameLength = (UCHAR)strlen("nameTwo"); + SingleEa.V.EaValueLength = (USHORT)strlen("second"); + lstrcpyA(SingleEa.V.EaName, "nameTwo"); + memcpy(SingleEa.V.EaName + SingleEa.V.EaNameLength + 1, "second", SingleEa.V.EaValueLength); + FspFileSystemAddEa(&SingleEa.V, &Ea.V, sizeof Ea, &EaLength); + + memset(&SingleEa, 0, sizeof SingleEa); + SingleEa.V.EaNameLength = (UCHAR)strlen("n3"); + SingleEa.V.EaValueLength = (USHORT)strlen("third"); + lstrcpyA(SingleEa.V.EaName, "n3"); + memcpy(SingleEa.V.EaName + SingleEa.V.EaNameLength + 1, "third", SingleEa.V.EaValueLength); + FspFileSystemAddEa(&SingleEa.V, &Ea.V, sizeof Ea, &EaLength); + + FspFileSystemAddEa(0, &Ea.V, sizeof Ea, &EaLength); + + UnicodePath.Length = (USHORT)wcslen(UnicodePathBuf) * sizeof(WCHAR); + UnicodePath.MaximumLength = sizeof UnicodePathBuf; + UnicodePath.Buffer = UnicodePathBuf; + InitializeObjectAttributes(&Obja, &UnicodePath, 0, DirHandle, 0); + Result = NtCreateFile(&FileHandle, + FILE_GENERIC_READ | FILE_GENERIC_WRITE | DELETE, &Obja, &Iosb, + &LargeZero, FILE_ATTRIBUTE_NORMAL, 0, + FILE_CREATE, FILE_DELETE_ON_CLOSE, + &Ea, EaLength); + ASSERT(STATUS_SUCCESS == Result); + CloseHandle(FileHandle); + + CloseHandle(DirHandle); + + DirHandle = CreateFileW(FilePath, + GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE, 0); + ASSERT(INVALID_HANDLE_VALUE == DirHandle); + ASSERT(ERROR_FILE_NOT_FOUND == GetLastError()); + + memfs_stop(memfs); +} + +static void ea_create_test(void) +{ + if (NtfsTests) + { + WCHAR DirBuf[MAX_PATH]; + GetTestDirectory(DirBuf); + ea_create_dotest(-1, DirBuf); + } + if (WinFspDiskTests) + ea_create_dotest(MemfsDisk, 0); + if (WinFspNetTests) + ea_create_dotest(MemfsNet, L"\\\\memfs\\share"); +} + +void ea_tests(void) +{ + TEST(ea_create_test); +} diff --git a/tst/winfsp-tests/winfsp-tests.c b/tst/winfsp-tests/winfsp-tests.c index 8e934338..e8be476c 100644 --- a/tst/winfsp-tests/winfsp-tests.c +++ b/tst/winfsp-tests/winfsp-tests.c @@ -206,6 +206,7 @@ int main(int argc, char *argv[]) TESTSUITE(exec_tests); TESTSUITE(devctl_tests); TESTSUITE(reparse_tests); + TESTSUITE(ea_tests); TESTSUITE(stream_tests); TESTSUITE(oplock_tests);