Milestone 5: deliver embedded RDP sessions and lifecycle hardening

This commit is contained in:
Keith Smith
2026-03-03 18:59:26 -07:00
parent 230a401386
commit 36006bd4aa
2941 changed files with 724359 additions and 77 deletions

View File

@@ -0,0 +1,57 @@
if(NOT WIN32)
set(MODULE_NAME "TestFile")
set(MODULE_PREFIX "TEST_FILE")
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
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()

View File

@@ -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 = nullptr;
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 = nullptr;
int rc = 0;
SYSTEMTIME systemTime;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
GetSystemTime(&systemTime);
(void)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 separator.
* 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, nullptr, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (!handle)
{
free(name);
return -1;
}
if (!winpr_PathFileExists(name))
rc = -1;
if (!WriteFile(handle, buffer, sizeof(buffer), &written, nullptr))
rc = -1;
if (written != sizeof(buffer))
rc = -1;
written = SetFilePointer(handle, 5, nullptr, FILE_BEGIN);
if (written != 5)
rc = -1;
written = SetFilePointer(handle, 0, nullptr, FILE_CURRENT);
if (written != 5)
rc = -1;
written = SetFilePointer(handle, -5, nullptr, FILE_CURRENT);
if (written != 0)
rc = -1;
if (!ReadFile(handle, cmp, sizeof(cmp), &written, nullptr))
rc = -1;
if (written != sizeof(cmp))
rc = -1;
if (memcmp(buffer, cmp, sizeof(buffer)) != 0)
rc = -1;
if (!CloseHandle(handle))
rc = -1;
if (!winpr_DeleteFile(name))
rc = -1;
if (winpr_PathFileExists(name))
rc = -1;
free(name);
return rc;
}

View File

@@ -0,0 +1,67 @@
#include <stdio.h>
#include <stdlib.h>
#include <winpr/crt.h>
#include <winpr/file.h>
#include <winpr/path.h>
#include <winpr/windows.h>
#if !defined(_WIN32)
#include <sys/stat.h>
#endif
static int secure_mkstemp(char* tmpname)
{
#if !defined(_WIN32)
const mode_t mask = umask(S_IRWXU);
#endif
int fd = mkstemp(tmpname);
#if !defined(_WIN32)
(void)umask(mask);
#endif
return fd;
}
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 = nullptr;
const char invalidA[] = "/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
WCHAR invalidW[sizeof(invalidA)] = WINPR_C_ARRAY_INIT;
(void)ConvertUtf8NToWChar(invalidA, ARRAYSIZE(invalidA), invalidW, ARRAYSIZE(invalidW));
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
rc = winpr_DeleteFile(invalidA);
if (rc)
return -1;
rc = DeleteFileW(invalidW);
if (rc)
return -1;
fd = secure_mkstemp(validA);
if (fd < 0)
return -1;
rc = winpr_DeleteFile(validA);
if (!rc)
return -1;
fd = secure_mkstemp(validW);
if (fd < 0)
return -1;
validWW = ConvertUtf8NToWCharAlloc(validW, ARRAYSIZE(validW), nullptr);
if (validWW)
rc = DeleteFileW(validWW);
free(validWW);
if (!rc)
return -1;
return 0;
}

View File

@@ -0,0 +1,360 @@
#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_fileA(const char* FilePath)
{
HANDLE hdl = CreateFileA(FilePath, GENERIC_ALL, 0, nullptr, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (hdl == INVALID_HANDLE_VALUE)
return FALSE;
(void)CloseHandle(hdl);
return TRUE;
}
static BOOL create_fileW(const WCHAR* FilePath)
{
HANDLE hdl = CreateFileW(FilePath, GENERIC_ALL, 0, nullptr, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (hdl == INVALID_HANDLE_VALUE)
return FALSE;
(void)CloseHandle(hdl);
return TRUE;
}
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] = WINPR_C_ARRAY_INIT;
strncpy(FilePath, BasePath, ARRAYSIZE(FilePath));
CHAR name[64] = WINPR_C_ARRAY_INIT;
(void)_snprintf(name, ARRAYSIZE(name), "%zd-TestFile%zd", level, x);
NativePathCchAppendA(FilePath, PATHCCH_MAX_CCH, name);
if (create_fileA(FilePath))
ArrayList_Append(files, FilePath);
}
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] = WINPR_C_ARRAY_INIT;
strncpy(FilePath, BasePath, ARRAYSIZE(FilePath));
PathCchConvertStyleA(FilePath, ARRAYSIZE(FilePath), PATH_STYLE_NATIVE);
if (!winpr_PathMakePath(FilePath, nullptr))
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] = WINPR_C_ARRAY_INIT;
strncpy(CurFilePath, FilePath, ARRAYSIZE(CurFilePath));
PathCchConvertStyleA(CurFilePath, ARRAYSIZE(CurFilePath), PATH_STYLE_NATIVE);
CHAR name[64] = WINPR_C_ARRAY_INIT;
(void)_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] = WINPR_C_ARRAY_INIT;
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 = WINPR_C_ARRAY_INIT;
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\n", FindData.cFileName);
if (strcmp(FindData.cFileName, testFile1A) != 0)
{
printf("FindFirstFile failure: Expected: %s, Actual: %s\n", testFile1A, FindData.cFileName);
goto fail;
}
rc = TRUE;
fail:
if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);
return rc;
}
static BOOL list_directory_dot(const char* BasePath, wArrayList* files)
{
BOOL rc = FALSE;
CHAR BasePathDot[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
memcpy(BasePathDot, BasePath, ARRAYSIZE(BasePathDot));
PathCchConvertStyleA(BasePathDot, ARRAYSIZE(BasePathDot), PATH_STYLE_NATIVE);
NativePathCchAppendA(BasePathDot, PATHCCH_MAX_CCH, ".");
WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
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] = WINPR_C_ARRAY_INIT;
memcpy(BasePathDot, BasePath, ARRAYSIZE(BasePathDot));
PathCchConvertStyleA(BasePathDot, ARRAYSIZE(BasePathDot), PATH_STYLE_NATIVE);
NativePathCchAppendA(BasePathDot, PATHCCH_MAX_CCH, "*");
WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
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++;
}
return (fcount == count);
}
static BOOL find_first_file_fail(const char* FilePath)
{
WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
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;
printf("[%s] basepath: '%s'\n", __func__, str);
if (!str)
return -1;
CHAR BasePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
strncpy(BasePath, str, ARRAYSIZE(BasePath));
const size_t length = strnlen(BasePath, PATHCCH_MAX_CCH - 1);
CHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
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))
goto fail;
NativePathCchAppendA(FilePath, PATHCCH_MAX_CCH, testFile1A);
printf("Finding file: %s\n", FilePath);
if (!find_first_file_fail(FilePath))
goto fail;
if (!create_fileA(FilePath))
goto fail;
if (!find_first_file_success(FilePath))
goto fail;
CHAR BasePathInvalid[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
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:
winpr_DeleteFile(FilePath);
cleanup_layout(BasePath);
ArrayList_Free(files);
return rc;
}
WINPR_ATTR_FORMAT_ARG(1, 0)
static int printf1W(const char* WINPR_FORMAT_ARG fmt, const WCHAR* arg1)
{
char* var1 = ConvertWCharToUtf8Alloc(arg1, nullptr);
const int rc = printf(fmt, var1);
free(var1);
return rc;
}
WINPR_ATTR_FORMAT_ARG(1, 0)
static int printf2W(const char* WINPR_FORMAT_ARG fmt, const WCHAR* arg1, const WCHAR* arg2)
{
char* var1 = ConvertWCharToUtf8Alloc(arg1, nullptr);
char* var2 = ConvertWCharToUtf8Alloc(arg2, nullptr);
const int rc = printf(fmt, var1, var2);
free(var1);
free(var2);
return rc;
}
static int TestFileFindFirstFileW(const char* str)
{
WCHAR buffer[32] = WINPR_C_ARRAY_INIT;
const WCHAR* testFile1W = InitializeConstWCharFromUtf8("TestFile1W", buffer, ARRAYSIZE(buffer));
int rc = -1;
if (!str)
return -1;
WCHAR BasePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
printf("[%s] basepath: '%s'\n", __func__, str);
(void)ConvertUtf8ToWChar(str, BasePath, ARRAYSIZE(BasePath));
const size_t length = _wcsnlen(BasePath, PATHCCH_MAX_CCH - 1);
WCHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
CopyMemory(FilePath, BasePath, length * sizeof(WCHAR));
PathCchConvertStyleW(BasePath, length, PATH_STYLE_WINDOWS);
NativePathCchAppendW(FilePath, PATHCCH_MAX_CCH, testFile1W);
HANDLE hFind = INVALID_HANDLE_VALUE;
if (!create_fileW(FilePath))
goto fail;
printf1W("Finding file: %s\n", FilePath);
WIN32_FIND_DATAW FindData = WINPR_C_ARRAY_INIT;
hFind = FindFirstFileW(FilePath, &FindData);
if (hFind == INVALID_HANDLE_VALUE)
{
printf1W("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n", FilePath);
goto fail;
}
printf1W("FindFirstFile: %s\n", FindData.cFileName);
if (_wcscmp(FindData.cFileName, testFile1W) != 0)
{
printf2W("FindFirstFile failure: Expected: %s, Actual: %s\n", testFile1W,
FindData.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, nullptr))
{
rc1 = TestFileFindFirstFileA(str);
rc2 = TestFileFindFirstFileW(str);
winpr_RemoveDirectory(str);
}
free(str);
return rc1 + rc2;
}

View File

@@ -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;
}

View File

@@ -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 = nullptr;
size_t length = 0;
BOOL status = 0;
HANDLE hFind = nullptr;
LPTSTR BasePath = nullptr;
WIN32_FIND_DATA FindData;
TCHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
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 ((_tcsncmp(FindData.cFileName, testDirectory2File1, ARRAYSIZE(testDirectory2File1)) != 0) &&
(_tcsncmp(FindData.cFileName, testDirectory2File2, ARRAYSIZE(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 ((_tcsncmp(FindData.cFileName, testDirectory2File1, ARRAYSIZE(testDirectory2File1)) != 0) &&
(_tcsncmp(FindData.cFileName, testDirectory2File2, ARRAYSIZE(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;
}

View File

@@ -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 = nullptr;
const char buf[] = "happy happy";
DWORD bytesWritten = 0;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
so = GetStdHandle(STD_OUTPUT_HANDLE);
if (so == INVALID_HANDLE_VALUE)
{
(void)fprintf(stderr, "GetStdHandle failed ;(\n");
return -1;
}
WriteFile(so, buf, strnlen(buf, sizeof(buf)), &bytesWritten, nullptr);
if (bytesWritten != strnlen(buf, sizeof(buf)))
{
(void)fprintf(stderr, "write failed\n");
return -1;
}
(void)CloseHandle(so);
return 0;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,128 @@
#include <stdio.h>
#include <winpr/crt.h>
#include <winpr/file.h>
#include <winpr/windows.h>
static const char* get_dir(char* filename, size_t len)
{
#if defined(WIN32)
if ((len == 0) || (strnlen_s(filename, len) == len))
return nullptr;
char* ptr = strrchr(filename, '\\');
#else
if ((len == 0) || (strnlen(filename, len) == len))
return nullptr;
char* ptr = strrchr(filename, '/');
#endif
if (!ptr)
return nullptr;
*ptr = '\0';
return filename;
}
static BOOL get_tmp(char* path, size_t len)
{
#if defined(WIN32)
const char template[] = "tmpdir.XXXXXX";
strncmp(path, template, strnlen_s(template, len) + 1);
if (!mktemp_s(path))
return FALSE;
return winpr_str_append("testfile", path, len, "\\");
#else
const char template[] = "/tmp/tmpdir.XXXXXX";
if (!strncpy(path, template, strnlen(template, len) + 1))
return FALSE;
if (!mkdtemp(path))
return FALSE;
return winpr_str_append("testfile", path, len, "/");
#endif
}
static BOOL test_write(const char* filename, const char* data, size_t datalen)
{
BOOL rc = FALSE;
WINPR_ASSERT(filename);
WINPR_ASSERT(data);
WINPR_ASSERT(datalen > 0);
HANDLE hdl = CreateFileA(filename, GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL,
nullptr);
if (!hdl || (hdl == INVALID_HANDLE_VALUE))
goto fail;
DWORD written = 0;
if (!WriteFile(hdl, data, datalen, &written, nullptr))
goto fail;
if (written != datalen)
goto fail;
if (!FlushFileBuffers(hdl))
goto fail;
rc = TRUE;
fail:
CloseHandle(hdl);
return rc;
}
static BOOL test_read(const char* filename, const char* data, size_t datalen)
{
BOOL rc = FALSE;
WINPR_ASSERT(filename);
WINPR_ASSERT(data);
WINPR_ASSERT(datalen > 0);
char* cmp = calloc(datalen + 1, sizeof(char));
HANDLE hdl = CreateFileA(filename, GENERIC_READ, 0, nullptr, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (!hdl || (hdl == INVALID_HANDLE_VALUE) || !cmp)
goto fail;
DWORD read = 0;
if (!ReadFile(hdl, cmp, datalen, &read, nullptr))
goto fail;
if (read != datalen)
goto fail;
if (memcmp(data, cmp, datalen) != 0)
goto fail;
if (FlushFileBuffers(hdl))
goto fail;
rc = TRUE;
fail:
free(cmp);
CloseHandle(hdl);
return rc;
}
int TestFileWriteFile(int argc, char* argv[])
{
const char data[] = "sometesttext\nanother line\r\ngogogo\r\tfoo\t\r\n\r";
char filename[MAX_PATH] = WINPR_C_ARRAY_INIT;
int rc = -1;
if (!get_tmp(filename, sizeof(filename)))
goto fail;
if (!test_write(filename, data, sizeof(data)))
goto fail;
if (!test_read(filename, data, sizeof(data)))
goto fail;
rc = 0;
fail:
if (!DeleteFile(filename))
rc = -2;
const char* d = get_dir(filename, sizeof(filename));
if (d)
{
if (!RemoveDirectory(d))
rc = -3;
}
return rc;
}

View File

@@ -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 = nullptr;
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(nullptr, flag);
if (brc)
goto fail;
const BOOL crc = SetFileAttributesA(name, flag);
if (crc)
goto fail;
}
handle = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (handle == INVALID_HANDLE_VALUE)
goto fail;
(void)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:
winpr_DeleteFile(name);
free(name);
return rc;
}
static BOOL test_SetFileAttributesW(void)
{
BOOL rc = FALSE;
WCHAR* name = nullptr;
HANDLE handle = nullptr;
const DWORD flags[] = { 0, FILE_ATTRIBUTE_READONLY };
char* base = GetKnownSubPath(KNOWN_PATH_TEMP, "afsklhjwe4oq5iu432oijrlkejadlkhjaklhfdkahfd");
if (!base)
goto fail;
name = ConvertUtf8ToWCharAlloc(base, nullptr);
if (!name)
goto fail;
for (size_t x = 0; x < ARRAYSIZE(allflags); x++)
{
const DWORD flag = allflags[x];
const BOOL brc = SetFileAttributesW(nullptr, flag);
if (brc)
goto fail;
const BOOL crc = SetFileAttributesW(name, flag);
if (crc)
goto fail;
}
handle = CreateFileW(name, GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (handle == INVALID_HANDLE_VALUE)
goto fail;
(void)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;
}