summaryrefslogtreecommitdiffstats
path: root/winpr/libwinpr/file/test
diff options
context:
space:
mode:
Diffstat (limited to 'winpr/libwinpr/file/test')
-rw-r--r--winpr/libwinpr/file/test/CMakeLists.txt58
-rw-r--r--winpr/libwinpr/file/test/TestFileCreateFile.c94
-rw-r--r--winpr/libwinpr/file/test/TestFileDeleteFile.c50
-rw-r--r--winpr/libwinpr/file/test/TestFileFindFirstFile.c326
-rw-r--r--winpr/libwinpr/file/test/TestFileFindFirstFileEx.c10
-rw-r--r--winpr/libwinpr/file/test/TestFileFindNextFile.c99
-rw-r--r--winpr/libwinpr/file/test/TestFileGetStdHandle.c49
-rw-r--r--winpr/libwinpr/file/test/TestFilePatternMatch.c182
-rw-r--r--winpr/libwinpr/file/test/TestFileReadFile.c10
-rw-r--r--winpr/libwinpr/file/test/TestFileWriteFile.c10
-rw-r--r--winpr/libwinpr/file/test/TestSetFileAttributes.c152
11 files changed, 1040 insertions, 0 deletions
diff --git a/winpr/libwinpr/file/test/CMakeLists.txt b/winpr/libwinpr/file/test/CMakeLists.txt
new file mode 100644
index 0000000..3999271
--- /dev/null
+++ b/winpr/libwinpr/file/test/CMakeLists.txt
@@ -0,0 +1,58 @@
+
+if (NOT WIN32)
+ set(MODULE_NAME "TestFile")
+ set(MODULE_PREFIX "TEST_FILE")
+
+ set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
+
+ set(${MODULE_PREFIX}_TESTS
+ TestFileCreateFile.c
+ TestFileDeleteFile.c
+ TestFileReadFile.c
+ TestSetFileAttributes.c
+ TestFileWriteFile.c
+ TestFilePatternMatch.c
+ TestFileFindFirstFile.c
+ TestFileFindFirstFileEx.c
+ TestFileFindNextFile.c
+ TestFileGetStdHandle.c
+ )
+
+ create_test_sourcelist(${MODULE_PREFIX}_SRCS
+ ${${MODULE_PREFIX}_DRIVER}
+ ${${MODULE_PREFIX}_TESTS})
+
+ add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
+
+ target_link_libraries(${MODULE_NAME} winpr)
+
+ set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
+
+ if(NOT MSVC)
+ set(TEST_AREA "${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME}Area")
+ else()
+ set(TEST_AREA "${TESTING_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE}/${MODULE_NAME}Area")
+ endif()
+
+ file(MAKE_DIRECTORY "${TEST_AREA}")
+ file(WRITE "${TEST_AREA}/TestFile1" "TestFile1")
+ file(WRITE "${TEST_AREA}/TestFile2" "TestFile2")
+ file(WRITE "${TEST_AREA}/TestFile3" "TestFile3")
+ file(MAKE_DIRECTORY "${TEST_AREA}/TestDirectory1")
+ file(WRITE "${TEST_AREA}/TestDirectory1/TestDirectory1File1" "TestDirectory1File1")
+ file(MAKE_DIRECTORY "${TEST_AREA}/TestDirectory2")
+ file(WRITE "${TEST_AREA}/TestDirectory2/TestDirectory2File1" "TestDirectory2File1")
+ file(WRITE "${TEST_AREA}/TestDirectory2/TestDirectory2File2" "TestDirectory2File2")
+ file(MAKE_DIRECTORY "${TEST_AREA}/TestDirectory3")
+ file(WRITE "${TEST_AREA}/TestDirectory3/TestDirectory3File1" "TestDirectory3File1")
+ file(WRITE "${TEST_AREA}/TestDirectory3/TestDirectory3File2" "TestDirectory3File2")
+ file(WRITE "${TEST_AREA}/TestDirectory3/TestDirectory3File3" "TestDirectory3File3")
+
+ foreach(test ${${MODULE_PREFIX}_TESTS})
+ get_filename_component(TestName ${test} NAME_WE)
+ add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName} ${TEST_AREA})
+ endforeach()
+
+ set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")
+
+endif()
diff --git a/winpr/libwinpr/file/test/TestFileCreateFile.c b/winpr/libwinpr/file/test/TestFileCreateFile.c
new file mode 100644
index 0000000..a939416
--- /dev/null
+++ b/winpr/libwinpr/file/test/TestFileCreateFile.c
@@ -0,0 +1,94 @@
+
+#include <stdio.h>
+#include <winpr/crt.h>
+#include <winpr/file.h>
+#include <winpr/path.h>
+#include <winpr/handle.h>
+#include <winpr/windows.h>
+#include <winpr/sysinfo.h>
+
+int TestFileCreateFile(int argc, char* argv[])
+{
+ HANDLE handle = NULL;
+ HRESULT hr = 0;
+ DWORD written = 0;
+ const char buffer[] = "Some random text\r\njust want it done.";
+ char cmp[sizeof(buffer)];
+ char sname[8192];
+ LPSTR name = NULL;
+ int rc = 0;
+ SYSTEMTIME systemTime;
+ WINPR_UNUSED(argc);
+ WINPR_UNUSED(argv);
+ GetSystemTime(&systemTime);
+ sprintf_s(sname, sizeof(sname),
+ "CreateFile-%04" PRIu16 "%02" PRIu16 "%02" PRIu16 "%02" PRIu16 "%02" PRIu16
+ "%02" PRIu16 "%04" PRIu16,
+ systemTime.wYear, systemTime.wMonth, systemTime.wDay, systemTime.wHour,
+ systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds);
+ name = GetKnownSubPath(KNOWN_PATH_TEMP, sname);
+
+ if (!name)
+ return -1;
+
+ /* On windows we would need '\\' or '/' as seperator.
+ * Single '\' do not work. */
+ hr = PathCchConvertStyleA(name, strlen(name), PATH_STYLE_UNIX);
+
+ if (FAILED(hr))
+ rc = -1;
+
+ handle = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (!handle)
+ {
+ free(name);
+ return -1;
+ }
+
+ if (!winpr_PathFileExists(name))
+ rc = -1;
+
+ if (!WriteFile(handle, buffer, sizeof(buffer), &written, NULL))
+ rc = -1;
+
+ if (written != sizeof(buffer))
+ rc = -1;
+
+ written = SetFilePointer(handle, 5, NULL, FILE_BEGIN);
+
+ if (written != 5)
+ rc = -1;
+
+ written = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
+
+ if (written != 5)
+ rc = -1;
+
+ written = SetFilePointer(handle, -5, NULL, FILE_CURRENT);
+
+ if (written != 0)
+ rc = -1;
+
+ if (!ReadFile(handle, cmp, sizeof(cmp), &written, NULL))
+ rc = -1;
+
+ if (written != sizeof(cmp))
+ rc = -1;
+
+ if (memcmp(buffer, cmp, sizeof(buffer)))
+ rc = -1;
+
+ if (!CloseHandle(handle))
+ rc = -1;
+
+ if (!winpr_DeleteFile(name))
+ rc = -1;
+
+ if (winpr_PathFileExists(name))
+ rc = -1;
+
+ free(name);
+ return rc;
+}
diff --git a/winpr/libwinpr/file/test/TestFileDeleteFile.c b/winpr/libwinpr/file/test/TestFileDeleteFile.c
new file mode 100644
index 0000000..81f0599
--- /dev/null
+++ b/winpr/libwinpr/file/test/TestFileDeleteFile.c
@@ -0,0 +1,50 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <winpr/crt.h>
+#include <winpr/file.h>
+#include <winpr/windows.h>
+
+int TestFileDeleteFile(int argc, char* argv[])
+{
+ BOOL rc = FALSE;
+ int fd = 0;
+ char validA[] = "/tmp/valid-test-file-XXXXXX";
+ char validW[] = "/tmp/valid-test-file-XXXXXX";
+ WCHAR* validWW = NULL;
+ const char invalidA[] = "/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+ WCHAR invalidW[sizeof(invalidA)] = { 0 };
+
+ ConvertUtf8NToWChar(invalidA, ARRAYSIZE(invalidA), invalidW, ARRAYSIZE(invalidW));
+
+ WINPR_UNUSED(argc);
+ WINPR_UNUSED(argv);
+
+ rc = DeleteFileA(invalidA);
+ if (rc)
+ return -1;
+
+ rc = DeleteFileW(invalidW);
+ if (rc)
+ return -1;
+
+ fd = mkstemp(validA);
+ if (fd < 0)
+ return -1;
+
+ rc = DeleteFileA(validA);
+ if (!rc)
+ return -1;
+
+ fd = mkstemp(validW);
+ if (fd < 0)
+ return -1;
+
+ validWW = ConvertUtf8NToWCharAlloc(validW, ARRAYSIZE(validW), NULL);
+ if (validWW)
+ rc = DeleteFileW(validWW);
+ free(validWW);
+ if (!rc)
+ return -1;
+ return 0;
+}
diff --git a/winpr/libwinpr/file/test/TestFileFindFirstFile.c b/winpr/libwinpr/file/test/TestFileFindFirstFile.c
new file mode 100644
index 0000000..04829a3
--- /dev/null
+++ b/winpr/libwinpr/file/test/TestFileFindFirstFile.c
@@ -0,0 +1,326 @@
+
+#include <stdio.h>
+#include <winpr/crt.h>
+#include <winpr/handle.h>
+#include <winpr/file.h>
+#include <winpr/path.h>
+#include <winpr/tchar.h>
+#include <winpr/collections.h>
+#include <winpr/windows.h>
+
+static const CHAR testFile1A[] = "TestFile1A";
+
+static BOOL create_layout_files(size_t level, const char* BasePath, wArrayList* files)
+{
+ for (size_t x = 0; x < 10; x++)
+ {
+ CHAR FilePath[PATHCCH_MAX_CCH] = { 0 };
+ strncpy(FilePath, BasePath, ARRAYSIZE(FilePath));
+
+ CHAR name[64] = { 0 };
+ _snprintf(name, ARRAYSIZE(name), "%zd-TestFile%zd", level, x);
+ NativePathCchAppendA(FilePath, PATHCCH_MAX_CCH, name);
+
+ HANDLE hdl =
+ CreateFileA(FilePath, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hdl == INVALID_HANDLE_VALUE)
+ return FALSE;
+ ArrayList_Append(files, FilePath);
+ CloseHandle(hdl);
+ }
+ return TRUE;
+}
+
+static BOOL create_layout_directories(size_t level, size_t max_level, const char* BasePath,
+ wArrayList* files)
+{
+ if (level >= max_level)
+ return TRUE;
+
+ CHAR FilePath[PATHCCH_MAX_CCH] = { 0 };
+ strncpy(FilePath, BasePath, ARRAYSIZE(FilePath));
+ PathCchConvertStyleA(FilePath, ARRAYSIZE(FilePath), PATH_STYLE_NATIVE);
+ if (!winpr_PathMakePath(FilePath, NULL))
+ return FALSE;
+ ArrayList_Append(files, FilePath);
+
+ if (!create_layout_files(level + 1, BasePath, files))
+ return FALSE;
+
+ for (size_t x = 0; x < 10; x++)
+ {
+ CHAR CurFilePath[PATHCCH_MAX_CCH] = { 0 };
+ strncpy(CurFilePath, FilePath, ARRAYSIZE(CurFilePath));
+
+ PathCchConvertStyleA(CurFilePath, ARRAYSIZE(CurFilePath), PATH_STYLE_NATIVE);
+
+ CHAR name[64] = { 0 };
+ _snprintf(name, ARRAYSIZE(name), "%zd-TestPath%zd", level, x);
+ NativePathCchAppendA(CurFilePath, PATHCCH_MAX_CCH, name);
+
+ if (!create_layout_directories(level + 1, max_level, CurFilePath, files))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static BOOL create_layout(const char* BasePath, wArrayList* files)
+{
+ CHAR BasePathNative[PATHCCH_MAX_CCH] = { 0 };
+ memcpy(BasePathNative, BasePath, sizeof(BasePathNative));
+ PathCchConvertStyleA(BasePathNative, ARRAYSIZE(BasePathNative), PATH_STYLE_NATIVE);
+
+ return create_layout_directories(0, 3, BasePathNative, files);
+}
+
+static void cleanup_layout(const char* BasePath)
+{
+ winpr_RemoveDirectory_RecursiveA(BasePath);
+}
+
+static BOOL find_first_file_success(const char* FilePath)
+{
+ BOOL rc = FALSE;
+ WIN32_FIND_DATAA FindData = { 0 };
+ HANDLE hFind = FindFirstFileA(FilePath, &FindData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ printf("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n", FilePath);
+ goto fail;
+ }
+
+ printf("FindFirstFile: %s", FindData.cFileName);
+
+ if (strcmp(FindData.cFileName, testFile1A) != 0)
+ {
+ printf("FindFirstFile failure: Expected: %s, Actual: %s\n", testFile1A, FindData.cFileName);
+ goto fail;
+ }
+ rc = TRUE;
+fail:
+ FindClose(hFind);
+ return rc;
+}
+
+static BOOL list_directory_dot(const char* BasePath, wArrayList* files)
+{
+ BOOL rc = FALSE;
+ CHAR BasePathDot[PATHCCH_MAX_CCH] = { 0 };
+ memcpy(BasePathDot, BasePath, ARRAYSIZE(BasePathDot));
+ PathCchConvertStyleA(BasePathDot, ARRAYSIZE(BasePathDot), PATH_STYLE_NATIVE);
+ NativePathCchAppendA(BasePathDot, PATHCCH_MAX_CCH, ".");
+ WIN32_FIND_DATAA FindData = { 0 };
+ HANDLE hFind = FindFirstFileA(BasePathDot, &FindData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ return FALSE;
+ size_t count = 0;
+ do
+ {
+ count++;
+ if (strcmp(FindData.cFileName, ".") != 0)
+ goto fail;
+ } while (FindNextFile(hFind, &FindData));
+
+ rc = TRUE;
+fail:
+ FindClose(hFind);
+
+ if (count != 1)
+ return FALSE;
+ return rc;
+}
+
+static BOOL list_directory_star(const char* BasePath, wArrayList* files)
+{
+ CHAR BasePathDot[PATHCCH_MAX_CCH] = { 0 };
+ memcpy(BasePathDot, BasePath, ARRAYSIZE(BasePathDot));
+ PathCchConvertStyleA(BasePathDot, ARRAYSIZE(BasePathDot), PATH_STYLE_NATIVE);
+ NativePathCchAppendA(BasePathDot, PATHCCH_MAX_CCH, "*");
+ WIN32_FIND_DATAA FindData = { 0 };
+ HANDLE hFind = FindFirstFileA(BasePathDot, &FindData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ return FALSE;
+ size_t count = 0;
+ size_t dotcount = 0;
+ size_t dotdotcount = 0;
+ do
+ {
+ if (strcmp(FindData.cFileName, ".") == 0)
+ dotcount++;
+ else if (strcmp(FindData.cFileName, "..") == 0)
+ dotdotcount++;
+ else
+ count++;
+ } while (FindNextFile(hFind, &FindData));
+ FindClose(hFind);
+
+ const char sep = PathGetSeparatorA(PATH_STYLE_NATIVE);
+ size_t fcount = 0;
+ const size_t baselen = strlen(BasePath);
+ const size_t total = ArrayList_Count(files);
+ for (size_t x = 0; x < total; x++)
+ {
+ const char* path = ArrayList_GetItem(files, x);
+ const size_t pathlen = strlen(path);
+ if (pathlen < baselen)
+ continue;
+ const char* skip = &path[baselen];
+ if (*skip == sep)
+ skip++;
+ const char* end = strrchr(skip, sep);
+ if (end)
+ continue;
+ fcount++;
+ }
+
+ if (fcount != count)
+ return FALSE;
+ return TRUE;
+}
+
+static BOOL find_first_file_fail(const char* FilePath)
+{
+ WIN32_FIND_DATAA FindData = { 0 };
+ HANDLE hFind = FindFirstFileA(FilePath, &FindData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ return TRUE;
+
+ FindClose(hFind);
+ return FALSE;
+}
+
+static int TestFileFindFirstFileA(const char* str)
+{
+ int rc = -1;
+ if (!str)
+ return -1;
+
+ CHAR BasePath[PATHCCH_MAX_CCH] = { 0 };
+
+ strncpy(BasePath, str, ARRAYSIZE(BasePath));
+
+ const size_t length = strnlen(BasePath, PATHCCH_MAX_CCH - 1);
+
+ CHAR FilePath[PATHCCH_MAX_CCH] = { 0 };
+ CopyMemory(FilePath, BasePath, length * sizeof(CHAR));
+
+ PathCchConvertStyleA(BasePath, length, PATH_STYLE_WINDOWS);
+
+ wArrayList* files = ArrayList_New(FALSE);
+ if (!files)
+ return -3;
+ wObject* obj = ArrayList_Object(files);
+ obj->fnObjectFree = winpr_ObjectStringFree;
+ obj->fnObjectNew = winpr_ObjectStringClone;
+
+ if (!create_layout(BasePath, files))
+ return -1;
+
+ NativePathCchAppendA(FilePath, PATHCCH_MAX_CCH, testFile1A);
+
+ printf("Finding file: %s\n", FilePath);
+
+ if (!find_first_file_fail(FilePath))
+ goto fail;
+
+ HANDLE hdl =
+ CreateFileA(FilePath, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hdl == INVALID_HANDLE_VALUE)
+ goto fail;
+ CloseHandle(hdl);
+
+ if (!find_first_file_success(FilePath))
+ goto fail;
+
+ CHAR BasePathInvalid[PATHCCH_MAX_CCH] = { 0 };
+ memcpy(BasePathInvalid, BasePath, ARRAYSIZE(BasePathInvalid));
+ PathCchAddBackslashA(BasePathInvalid, PATHCCH_MAX_CCH);
+
+ if (!find_first_file_fail(BasePathInvalid))
+ goto fail;
+
+ if (!list_directory_dot(BasePath, files))
+ goto fail;
+
+ if (!list_directory_star(BasePath, files))
+ goto fail;
+
+ rc = 0;
+fail:
+ DeleteFileA(FilePath);
+ cleanup_layout(BasePath);
+ ArrayList_Free(files);
+ return rc;
+}
+
+static int TestFileFindFirstFileW(const char* str)
+{
+ WCHAR buffer[32] = { 0 };
+ const WCHAR* testFile1W = InitializeConstWCharFromUtf8("TestFile1W", buffer, ARRAYSIZE(buffer));
+ int rc = -1;
+ if (!str)
+ return -1;
+
+ WCHAR BasePath[PATHCCH_MAX_CCH] = { 0 };
+
+ ConvertUtf8ToWChar(str, BasePath, ARRAYSIZE(BasePath));
+
+ const size_t length = _wcsnlen(BasePath, PATHCCH_MAX_CCH - 1);
+
+ WCHAR FilePath[PATHCCH_MAX_CCH] = { 0 };
+ CopyMemory(FilePath, BasePath, length * sizeof(WCHAR));
+
+ PathCchConvertStyleW(BasePath, length, PATH_STYLE_WINDOWS);
+ NativePathCchAppendW(FilePath, PATHCCH_MAX_CCH, testFile1W);
+
+ CHAR FilePathA[PATHCCH_MAX_CCH] = { 0 };
+ ConvertWCharNToUtf8(FilePath, ARRAYSIZE(FilePath), FilePathA, ARRAYSIZE(FilePathA));
+ printf("Finding file: %s\n", FilePathA);
+
+ WIN32_FIND_DATAW FindData = { 0 };
+ HANDLE hFind = FindFirstFileW(FilePath, &FindData);
+
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ printf("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n", FilePathA);
+ goto fail;
+ }
+
+ CHAR cFileName[MAX_PATH] = { 0 };
+ ConvertWCharNToUtf8(FindData.cFileName, ARRAYSIZE(FindData.cFileName), cFileName,
+ ARRAYSIZE(cFileName));
+
+ printf("FindFirstFile: %s", cFileName);
+
+ if (_wcscmp(FindData.cFileName, testFile1W) != 0)
+ {
+ printf("FindFirstFile failure: Expected: %s, Actual: %s\n", testFile1A, cFileName);
+ goto fail;
+ }
+
+ rc = 0;
+fail:
+ DeleteFileW(FilePath);
+ FindClose(hFind);
+ return rc;
+}
+
+int TestFileFindFirstFile(int argc, char* argv[])
+{
+ char* str = GetKnownSubPath(KNOWN_PATH_TEMP, "TestFileFindFirstFile");
+ if (!str)
+ return -23;
+
+ cleanup_layout(str);
+
+ int rc1 = -1;
+ int rc2 = -1;
+ if (winpr_PathMakePath(str, NULL))
+ {
+ rc1 = TestFileFindFirstFileA(str);
+ rc2 = 0; // TestFileFindFirstFileW(str);
+ winpr_RemoveDirectory(str);
+ }
+ free(str);
+ return rc1 + rc2;
+}
diff --git a/winpr/libwinpr/file/test/TestFileFindFirstFileEx.c b/winpr/libwinpr/file/test/TestFileFindFirstFileEx.c
new file mode 100644
index 0000000..b8a7683
--- /dev/null
+++ b/winpr/libwinpr/file/test/TestFileFindFirstFileEx.c
@@ -0,0 +1,10 @@
+
+#include <stdio.h>
+#include <winpr/crt.h>
+#include <winpr/file.h>
+#include <winpr/windows.h>
+
+int TestFileFindFirstFileEx(int argc, char* argv[])
+{
+ return 0;
+}
diff --git a/winpr/libwinpr/file/test/TestFileFindNextFile.c b/winpr/libwinpr/file/test/TestFileFindNextFile.c
new file mode 100644
index 0000000..ebb9bec
--- /dev/null
+++ b/winpr/libwinpr/file/test/TestFileFindNextFile.c
@@ -0,0 +1,99 @@
+
+#include <stdio.h>
+#include <winpr/crt.h>
+#include <winpr/file.h>
+#include <winpr/path.h>
+#include <winpr/tchar.h>
+#include <winpr/windows.h>
+
+static TCHAR testDirectory2File1[] = _T("TestDirectory2File1");
+static TCHAR testDirectory2File2[] = _T("TestDirectory2File2");
+
+int TestFileFindNextFile(int argc, char* argv[])
+{
+ char* str = NULL;
+ size_t length = 0;
+ BOOL status = 0;
+ HANDLE hFind = NULL;
+ LPTSTR BasePath = NULL;
+ WIN32_FIND_DATA FindData;
+ TCHAR FilePath[PATHCCH_MAX_CCH] = { 0 };
+ WINPR_UNUSED(argc);
+ str = argv[1];
+#ifdef UNICODE
+ BasePath = ConvertUtf8ToWChar(str, &length);
+
+ if (!BasePath)
+ {
+ _tprintf(_T("Unable to allocate memory"));
+ return -1;
+ }
+#else
+ BasePath = _strdup(str);
+
+ if (!BasePath)
+ {
+ printf("Unable to allocate memory");
+ return -1;
+ }
+
+ length = strlen(BasePath);
+#endif
+ /* Simple filter matching all files inside current directory */
+ CopyMemory(FilePath, BasePath, length * sizeof(TCHAR));
+ FilePath[length] = 0;
+ PathCchConvertStyle(BasePath, length, PATH_STYLE_WINDOWS);
+ NativePathCchAppend(FilePath, PATHCCH_MAX_CCH, _T("TestDirectory2"));
+ NativePathCchAppend(FilePath, PATHCCH_MAX_CCH, _T("TestDirectory2File*"));
+ free(BasePath);
+ _tprintf(_T("Finding file: %s\n"), FilePath);
+ hFind = FindFirstFile(FilePath, &FindData);
+
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ _tprintf(_T("FindFirstFile failure: %s\n"), FilePath);
+ return -1;
+ }
+
+ _tprintf(_T("FindFirstFile: %s"), FindData.cFileName);
+
+ /**
+ * The current implementation does not enforce a particular order
+ */
+
+ if ((_tcscmp(FindData.cFileName, testDirectory2File1) != 0) &&
+ (_tcscmp(FindData.cFileName, testDirectory2File2) != 0))
+ {
+ _tprintf(_T("FindFirstFile failure: Expected: %s, Actual: %s\n"), testDirectory2File1,
+ FindData.cFileName);
+ return -1;
+ }
+
+ status = FindNextFile(hFind, &FindData);
+
+ if (!status)
+ {
+ _tprintf(_T("FindNextFile failure: Expected: TRUE, Actual: %") _T(PRId32) _T("\n"), status);
+ return -1;
+ }
+
+ if ((_tcscmp(FindData.cFileName, testDirectory2File1) != 0) &&
+ (_tcscmp(FindData.cFileName, testDirectory2File2) != 0))
+ {
+ _tprintf(_T("FindNextFile failure: Expected: %s, Actual: %s\n"), testDirectory2File2,
+ FindData.cFileName);
+ return -1;
+ }
+
+ status = FindNextFile(hFind, &FindData);
+
+ if (status)
+ {
+ _tprintf(_T("FindNextFile failure: Expected: FALSE, Actual: %") _T(PRId32) _T("\n"),
+ status);
+ return -1;
+ }
+
+ FindClose(hFind);
+ return 0;
+}
diff --git a/winpr/libwinpr/file/test/TestFileGetStdHandle.c b/winpr/libwinpr/file/test/TestFileGetStdHandle.c
new file mode 100644
index 0000000..79ce4ae
--- /dev/null
+++ b/winpr/libwinpr/file/test/TestFileGetStdHandle.c
@@ -0,0 +1,49 @@
+
+/**
+ * WinPR: Windows Portable Runtime
+ * File Functions
+ *
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 Bernhard Miklautz <bernhard.miklautz@thincast.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <winpr/file.h>
+#include <winpr/handle.h>
+#include <string.h>
+#include <stdio.h>
+
+int TestFileGetStdHandle(int argc, char* argv[])
+{
+ HANDLE so = NULL;
+ const char buf[] = "happy happy";
+ DWORD bytesWritten = 0;
+ WINPR_UNUSED(argc);
+ WINPR_UNUSED(argv);
+ so = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (so == INVALID_HANDLE_VALUE)
+ {
+ fprintf(stderr, "GetStdHandle failed ;(\n");
+ return -1;
+ }
+ WriteFile(so, buf, strnlen(buf, sizeof(buf)), &bytesWritten, FALSE);
+ if (bytesWritten != strnlen(buf, sizeof(buf)))
+ {
+ fprintf(stderr, "write failed\n");
+ return -1;
+ }
+ CloseHandle(so);
+
+ return 0;
+}
diff --git a/winpr/libwinpr/file/test/TestFilePatternMatch.c b/winpr/libwinpr/file/test/TestFilePatternMatch.c
new file mode 100644
index 0000000..8f7a2fb
--- /dev/null
+++ b/winpr/libwinpr/file/test/TestFilePatternMatch.c
@@ -0,0 +1,182 @@
+
+#include <stdio.h>
+#include <winpr/crt.h>
+#include <winpr/file.h>
+#include <winpr/windows.h>
+
+int TestFilePatternMatch(int argc, char* argv[])
+{
+ /* '*' expression */
+ WINPR_UNUSED(argc);
+ WINPR_UNUSED(argv);
+ if (!FilePatternMatchA("document.txt", "*"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.txt", "*");
+ return -1;
+ }
+
+ /* '*X' expression */
+
+ if (!FilePatternMatchA("document.txt", "*.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.txt", "*.txt");
+ return -1;
+ }
+
+ if (FilePatternMatchA("document.docx", "*.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.docx", "*.txt");
+ return -1;
+ }
+
+ if (FilePatternMatchA("document.txt.bak", "*.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.txt.bak", "*.txt");
+ return -1;
+ }
+
+ if (FilePatternMatchA("bak", "*.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "bak", "*.txt");
+ return -1;
+ }
+
+ /* 'X*' expression */
+
+ if (!FilePatternMatchA("document.txt", "document.*"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.txt", "document.*");
+ return -1;
+ }
+
+ /* 'X?' expression */
+
+ if (!FilePatternMatchA("document.docx", "document.doc?"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.docx",
+ "document.doc?");
+ return -1;
+ }
+
+ if (FilePatternMatchA("document.doc", "document.doc?"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.doc",
+ "document.doc?");
+ return -1;
+ }
+
+ /* no wildcards expression */
+
+ if (!FilePatternMatchA("document.txt", "document.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.txt",
+ "document.txt");
+ return -1;
+ }
+
+ /* 'X * Y' expression */
+
+ if (!FilePatternMatchA("X123Y.txt", "X*Y.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Y.txt", "X*Y.txt");
+ return -1;
+ }
+
+ if (!FilePatternMatchA("XY.txt", "X*Y.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XY.txt", "X*Y.txt");
+ return -1;
+ }
+
+ if (FilePatternMatchA("XZ.txt", "X*Y.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XZ.txt", "X*Y.txt");
+ return -1;
+ }
+
+ if (FilePatternMatchA("X123Z.txt", "X*Y.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Z.txt", "X*Y.txt");
+ return -1;
+ }
+
+ /* 'X * Y * Z' expression */
+
+ if (!FilePatternMatchA("X123Y456Z.txt", "X*Y*Z.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Y456Z.txt", "X*Y*Z.txt");
+ return -1;
+ }
+
+ if (!FilePatternMatchA("XYZ.txt", "X*Y*Z.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XYZ.txt", "X*Y*Z.txt");
+ return -1;
+ }
+
+ if (!FilePatternMatchA("X123Y456W.txt", "X*Y*Z.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Y456W.txt", "X*Y*Z.txt");
+ return -1;
+ }
+
+ if (!FilePatternMatchA("XYW.txt", "X*Y*Z.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XYW.txt", "X*Y*Z.txt");
+ return -1;
+ }
+
+ /* 'X ? Y' expression */
+
+ if (!FilePatternMatchA("X1Y.txt", "X?Y.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X1Y.txt", "X?Y.txt");
+ return -1;
+ }
+
+ if (FilePatternMatchA("XY.txt", "X?Y.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XY.txt", "X?Y.txt");
+ return -1;
+ }
+
+ if (FilePatternMatchA("XZ.txt", "X?Y.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XZ.txt", "X?Y.txt");
+ return -1;
+ }
+
+ if (FilePatternMatchA("X123Z.txt", "X?Y.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Z.txt", "X?Y.txt");
+ return -1;
+ }
+
+ /* 'X ? Y ? Z' expression */
+
+ if (!FilePatternMatchA("X123Y456Z.txt", "X?Y?Z.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Y456Z.txt", "X?Y?Z.txt");
+ return -1;
+ }
+
+ if (FilePatternMatchA("XYZ.txt", "X?Y?Z.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XYZ.txt", "X?Y?Z.txt");
+ return -1;
+ }
+
+ if (!FilePatternMatchA("X123Y456W.txt", "X?Y?Z.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Y456W.txt", "X?Y?Z.txt");
+ return -1;
+ }
+
+ if (FilePatternMatchA("XYW.txt", "X?Y?Z.txt"))
+ {
+ printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XYW.txt", "X?Y?Z.txt");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/winpr/libwinpr/file/test/TestFileReadFile.c b/winpr/libwinpr/file/test/TestFileReadFile.c
new file mode 100644
index 0000000..936881a
--- /dev/null
+++ b/winpr/libwinpr/file/test/TestFileReadFile.c
@@ -0,0 +1,10 @@
+
+#include <stdio.h>
+#include <winpr/crt.h>
+#include <winpr/file.h>
+#include <winpr/windows.h>
+
+int TestFileReadFile(int argc, char* argv[])
+{
+ return 0;
+}
diff --git a/winpr/libwinpr/file/test/TestFileWriteFile.c b/winpr/libwinpr/file/test/TestFileWriteFile.c
new file mode 100644
index 0000000..a8283ee
--- /dev/null
+++ b/winpr/libwinpr/file/test/TestFileWriteFile.c
@@ -0,0 +1,10 @@
+
+#include <stdio.h>
+#include <winpr/crt.h>
+#include <winpr/file.h>
+#include <winpr/windows.h>
+
+int TestFileWriteFile(int argc, char* argv[])
+{
+ return 0;
+}
diff --git a/winpr/libwinpr/file/test/TestSetFileAttributes.c b/winpr/libwinpr/file/test/TestSetFileAttributes.c
new file mode 100644
index 0000000..f423ec2
--- /dev/null
+++ b/winpr/libwinpr/file/test/TestSetFileAttributes.c
@@ -0,0 +1,152 @@
+
+#include <stdio.h>
+#include <winpr/crt.h>
+#include <winpr/file.h>
+#include <winpr/path.h>
+#include <winpr/handle.h>
+#include <winpr/windows.h>
+#include <winpr/sysinfo.h>
+
+static const DWORD allflags[] = {
+ 0,
+ FILE_ATTRIBUTE_READONLY,
+ FILE_ATTRIBUTE_HIDDEN,
+ FILE_ATTRIBUTE_SYSTEM,
+ FILE_ATTRIBUTE_DIRECTORY,
+ FILE_ATTRIBUTE_ARCHIVE,
+ FILE_ATTRIBUTE_DEVICE,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_ATTRIBUTE_TEMPORARY,
+ FILE_ATTRIBUTE_SPARSE_FILE,
+ FILE_ATTRIBUTE_REPARSE_POINT,
+ FILE_ATTRIBUTE_COMPRESSED,
+ FILE_ATTRIBUTE_OFFLINE,
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
+ FILE_ATTRIBUTE_ENCRYPTED,
+ FILE_ATTRIBUTE_VIRTUAL,
+ FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,
+ FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DEVICE |
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_SPARSE_FILE | FILE_ATTRIBUTE_REPARSE_POINT |
+ FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_OFFLINE,
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_VIRTUAL
+};
+
+static BOOL test_SetFileAttributesA(void)
+{
+ BOOL rc = FALSE;
+ HANDLE handle = NULL;
+ const DWORD flags[] = { 0, FILE_ATTRIBUTE_READONLY };
+ char* name = GetKnownSubPath(KNOWN_PATH_TEMP, "afsklhjwe4oq5iu432oijrlkejadlkhjaklhfdkahfd");
+ if (!name)
+ goto fail;
+
+ for (size_t x = 0; x < ARRAYSIZE(allflags); x++)
+ {
+ const DWORD flag = allflags[x];
+ const BOOL brc = SetFileAttributesA(NULL, flag);
+ if (brc)
+ goto fail;
+
+ const BOOL crc = SetFileAttributesA(name, flag);
+ if (crc)
+ goto fail;
+ }
+
+ handle = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (handle == INVALID_HANDLE_VALUE)
+ goto fail;
+ CloseHandle(handle);
+
+ for (size_t x = 0; x < ARRAYSIZE(flags); x++)
+ {
+ DWORD attr = 0;
+ const DWORD flag = flags[x];
+ const BOOL brc = SetFileAttributesA(name, flag);
+ if (!brc)
+ goto fail;
+
+ attr = GetFileAttributesA(name);
+ if (flag != 0)
+ {
+ if ((attr & flag) == 0)
+ goto fail;
+ }
+ }
+
+ rc = TRUE;
+
+fail:
+ DeleteFileA(name);
+ free(name);
+ return rc;
+}
+
+static BOOL test_SetFileAttributesW(void)
+{
+ BOOL rc = FALSE;
+ WCHAR* name = NULL;
+ HANDLE handle = NULL;
+ const DWORD flags[] = { 0, FILE_ATTRIBUTE_READONLY };
+ char* base = GetKnownSubPath(KNOWN_PATH_TEMP, "afsklhjwe4oq5iu432oijrlkejadlkhjaklhfdkahfd");
+ if (!base)
+ goto fail;
+
+ name = ConvertUtf8ToWCharAlloc(base, NULL);
+ if (!name)
+ goto fail;
+
+ for (size_t x = 0; x < ARRAYSIZE(allflags); x++)
+ {
+ const DWORD flag = allflags[x];
+ const BOOL brc = SetFileAttributesW(NULL, flag);
+ if (brc)
+ goto fail;
+
+ const BOOL crc = SetFileAttributesW(name, flag);
+ if (crc)
+ goto fail;
+ }
+
+ handle = CreateFileW(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (handle == INVALID_HANDLE_VALUE)
+ goto fail;
+ CloseHandle(handle);
+
+ for (size_t x = 0; x < ARRAYSIZE(flags); x++)
+ {
+ DWORD attr = 0;
+ const DWORD flag = flags[x];
+ const BOOL brc = SetFileAttributesW(name, flag);
+ if (!brc)
+ goto fail;
+
+ attr = GetFileAttributesW(name);
+ if (flag != 0)
+ {
+ if ((attr & flag) == 0)
+ goto fail;
+ }
+ }
+
+ rc = TRUE;
+fail:
+ DeleteFileW(name);
+ free(name);
+ free(base);
+ return rc;
+}
+
+int TestSetFileAttributes(int argc, char* argv[])
+{
+ WINPR_UNUSED(argc);
+ WINPR_UNUSED(argv);
+
+ if (!test_SetFileAttributesA())
+ return -1;
+ if (!test_SetFileAttributesW())
+ return -1;
+ return 0;
+}