From 14d5cbeacb9ca224769865b31ed1382d10693a81 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 25 Jul 2023 10:19:15 +0200 Subject: [PATCH] [winpr,file] fix issues with FindFirstFile --- winpr/include/winpr/string.h | 2 + winpr/libwinpr/clipboard/synthetic_file.c | 1 - winpr/libwinpr/crt/string.c | 13 + winpr/libwinpr/file/generic.c | 172 ++++----- .../file/test/TestFileFindFirstFile.c | 337 ++++++++++++++++-- .../libwinpr/path/include/PathAllocCombine.c | 27 +- .../path/include/PathCchAddExtension.c | 18 +- winpr/libwinpr/path/include/PathCchAppend.c | 17 +- winpr/libwinpr/path/path.c | 16 +- 9 files changed, 421 insertions(+), 182 deletions(-) diff --git a/winpr/include/winpr/string.h b/winpr/include/winpr/string.h index 89d879e43..01bd074e8 100644 --- a/winpr/include/winpr/string.h +++ b/winpr/include/winpr/string.h @@ -80,6 +80,7 @@ extern "C" WINPR_API char* strtok_s(char* strToken, const char* strDelimit, char** context); WINPR_API WCHAR* wcstok_s(WCHAR* strToken, const WCHAR* strDelimit, WCHAR** context); + WINPR_API WCHAR* _wcsncat(WCHAR* dst, const WCHAR* src, size_t sz); #else #define _wcscmp wcscmp @@ -89,6 +90,7 @@ extern "C" #define _wcsstr wcsstr #define _wcschr wcschr #define _wcsrchr wcsrchr +#define _wcsncat wcsncat #endif /* _WIN32 */ diff --git a/winpr/libwinpr/clipboard/synthetic_file.c b/winpr/libwinpr/clipboard/synthetic_file.c index 8476373aa..1feb557b4 100644 --- a/winpr/libwinpr/clipboard/synthetic_file.c +++ b/winpr/libwinpr/clipboard/synthetic_file.c @@ -388,7 +388,6 @@ static BOOL add_file_to_list(wClipboard* clipboard, const WCHAR* local_name, WINPR_ASSERT(remote_name); WINPR_ASSERT(files); - WLog_VRB(TAG, "adding file: %s", local_name); file = make_synthetic_file(local_name, remote_name); if (!file) diff --git a/winpr/libwinpr/crt/string.c b/winpr/libwinpr/crt/string.c index 794294b35..c2c74ac7a 100644 --- a/winpr/libwinpr/crt/string.c +++ b/winpr/libwinpr/crt/string.c @@ -203,6 +203,19 @@ WCHAR* _wcsdup(const WCHAR* strSource) return strDestination; } +WCHAR* _wcsncat(WCHAR* dst, const WCHAR* src, size_t sz) +{ + WINPR_ASSERT(dst); + WINPR_ASSERT(src || (sz == 0)); + + const size_t dlen = _wcslen(dst); + const size_t slen = _wcsnlen(src, sz); + for (size_t x = 0; x < slen; x++) + dst[dlen + x] = src[x]; + dst[dlen + slen] = '\0'; + return dst; +} + int _stricmp(const char* string1, const char* string2) { return strcasecmp(string1, string2); diff --git a/winpr/libwinpr/file/generic.c b/winpr/libwinpr/file/generic.c index acf65daf0..46adeea51 100644 --- a/winpr/libwinpr/file/generic.c +++ b/winpr/libwinpr/file/generic.c @@ -873,12 +873,47 @@ BOOL WINAPI SetFileTime(HANDLE hFile, const FILETIME* lpCreationTime, typedef struct { - DIR* pDir; + char magic[16]; LPSTR lpPath; LPSTR lpPattern; - struct dirent* pDirent; + DIR* pDir; } WIN32_FILE_SEARCH; +static const char file_search_magic[] = "file_srch_magic"; + +static WIN32_FILE_SEARCH* file_search_new(const char* name, size_t namelen, const char* pattern, + size_t patternlen) +{ + WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)calloc(1, sizeof(WIN32_FILE_SEARCH)); + if (!pFileSearch) + return NULL; + strncpy(pFileSearch->magic, file_search_magic, sizeof(pFileSearch->magic)); + + pFileSearch->lpPath = strndup(name, namelen); + pFileSearch->lpPattern = strndup(pattern, patternlen); + if (!pFileSearch->lpPath || !pFileSearch->lpPattern) + goto fail; + + pFileSearch->pDir = opendir(pFileSearch->lpPath); + if (!pFileSearch->pDir) + goto fail; + return pFileSearch; +fail: + FindClose(pFileSearch); + return NULL; +} + +static BOOL is_valid_file_search_handle(HANDLE handle) +{ + WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)handle; + if (!pFileSearch) + return FALSE; + if (pFileSearch == INVALID_HANDLE_VALUE) + return FALSE; + if (strcmp(file_search_magic, pFileSearch->magic) != 0) + return FALSE; + return TRUE; +} static BOOL FindDataFromStat(const char* path, const struct stat* fileStat, LPWIN32_FIND_DATAA lpFindFileData) { @@ -926,18 +961,27 @@ static BOOL FindDataFromStat(const char* path, const struct stat* fileStat, HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData) { - BOOL isDir = FALSE; - struct stat fileStat; - WIN32_FILE_SEARCH* pFileSearch; - if (!lpFindFileData || !lpFileName) { SetLastError(ERROR_BAD_ARGUMENTS); return INVALID_HANDLE_VALUE; } - ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA)); - pFileSearch = (WIN32_FILE_SEARCH*)calloc(1, sizeof(WIN32_FILE_SEARCH)); + const WIN32_FIND_DATAA empty = { 0 }; + *lpFindFileData = empty; + + WIN32_FILE_SEARCH* pFileSearch = NULL; + size_t patternlen = 0; + const size_t flen = strlen(lpFileName); + const char sep = PathGetSeparatorA(PATH_STYLE_NATIVE); + const char* ptr = strrchr(lpFileName, sep); + if (!ptr) + goto fail; + patternlen = strlen(ptr + 1); + if (patternlen == 0) + goto fail; + + pFileSearch = file_search_new(lpFileName, flen - patternlen, ptr + 1, patternlen); if (!pFileSearch) { @@ -945,101 +989,10 @@ HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData) return INVALID_HANDLE_VALUE; } - if (stat(lpFileName, &fileStat) >= 0) - { - isDir = (S_ISDIR(fileStat.st_mode) != 0); - } - else - errno = 0; - - if (isDir) - { - pFileSearch->lpPath = _strdup(lpFileName); - pFileSearch->lpPattern = _strdup("*"); - } - else - { - LPSTR p; - size_t index; - size_t length; - /* Separate lpFileName into path and pattern components */ - p = strrchr(lpFileName, '/'); - - if (!p) - p = strrchr(lpFileName, '\\'); - - index = (p - lpFileName); - length = (p - lpFileName) + 1; - pFileSearch->lpPath = (LPSTR)malloc(length + 1); - - if (!pFileSearch->lpPath) - { - free(pFileSearch); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return INVALID_HANDLE_VALUE; - } - - CopyMemory(pFileSearch->lpPath, lpFileName, length); - pFileSearch->lpPath[length] = '\0'; - length = strlen(lpFileName) - index; - pFileSearch->lpPattern = (LPSTR)malloc(length + 1); - - if (!pFileSearch->lpPattern) - { - free(pFileSearch->lpPath); - free(pFileSearch); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return INVALID_HANDLE_VALUE; - } - - CopyMemory(pFileSearch->lpPattern, &lpFileName[index + 1], length); - pFileSearch->lpPattern[length] = '\0'; - - /* Check if the path is a directory */ - - if (stat(pFileSearch->lpPath, &fileStat) < 0) - { - FindClose(pFileSearch); - SetLastError(map_posix_err(errno)); - errno = 0; - return INVALID_HANDLE_VALUE; /* stat error */ - } - - if (S_ISDIR(fileStat.st_mode) == 0) - { - FindClose(pFileSearch); - return INVALID_HANDLE_VALUE; /* not a directory */ - } - } - - /* Open directory for reading */ - pFileSearch->pDir = opendir(pFileSearch->lpPath); - - if (!pFileSearch->pDir) - { - FindClose(pFileSearch); - SetLastError(map_posix_err(errno)); - errno = 0; - return INVALID_HANDLE_VALUE; /* failed to open directory */ - } - if (FindNextFileA((HANDLE)pFileSearch, lpFindFileData)) - { - if (isDir) - { - const char* name = strrchr(lpFileName, '/'); - - if (!name) - name = lpFileName; - else - name++; - - sprintf_s(lpFindFileData->cFileName, ARRAYSIZE(lpFindFileData->cFileName), "%s", name); - } - return (HANDLE)pFileSearch; - } +fail: FindClose(pFileSearch); return INVALID_HANDLE_VALUE; } @@ -1124,23 +1077,24 @@ HANDLE FindFirstFileExW(LPCWSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPV BOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData) { - if (!hFindFile || !lpFindFileData) - return FALSE; - - if (hFindFile == INVALID_HANDLE_VALUE) + if (!lpFindFileData) return FALSE; const WIN32_FIND_DATAA empty = { 0 }; *lpFindFileData = empty; + if (!is_valid_file_search_handle(hFindFile)) + return FALSE; + WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)hFindFile; - while ((pFileSearch->pDirent = readdir(pFileSearch->pDir)) != NULL) + struct dirent* pDirent = NULL; + while ((pDirent = readdir(pFileSearch->pDir)) != NULL) { - if (FilePatternMatchA(pFileSearch->pDirent->d_name, pFileSearch->lpPattern)) + if (FilePatternMatchA(pDirent->d_name, pFileSearch->lpPattern)) { BOOL success = FALSE; - strncpy(lpFindFileData->cFileName, pFileSearch->pDirent->d_name, MAX_PATH); + strncpy(lpFindFileData->cFileName, pDirent->d_name, MAX_PATH); const size_t namelen = strnlen(lpFindFileData->cFileName, MAX_PATH); size_t pathlen = strlen(pFileSearch->lpPath); char* fullpath = (char*)malloc(pathlen + namelen + 2); @@ -1156,7 +1110,7 @@ BOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData) * duplicate separators */ if (fullpath[pathlen - 1] != '/') fullpath[pathlen++] = '/'; - memcpy(fullpath + pathlen, pFileSearch->pDirent->d_name, namelen); + memcpy(fullpath + pathlen, pDirent->d_name, namelen); fullpath[pathlen + namelen] = 0; struct stat fileStat = { 0 }; @@ -1220,7 +1174,7 @@ BOOL FindClose(HANDLE hFindFile) * is a initialized HANDLE that is not freed properly. * Disable this return to stop confusing the analyzer. */ #ifndef __clang_analyzer__ - if (!pFileSearch || (pFileSearch == INVALID_HANDLE_VALUE)) + if (!is_valid_file_search_handle(hFindFile)) return FALSE; #endif diff --git a/winpr/libwinpr/file/test/TestFileFindFirstFile.c b/winpr/libwinpr/file/test/TestFileFindFirstFile.c index afd60721f..02aea9919 100644 --- a/winpr/libwinpr/file/test/TestFileFindFirstFile.c +++ b/winpr/libwinpr/file/test/TestFileFindFirstFile.c @@ -1,66 +1,325 @@ #include #include +#include #include #include #include +#include #include -static TCHAR testFile1[] = _T("TestFile1"); +static const CHAR testFile1A[] = "TestFile1A"; +static const WCHAR testFile1W[] = { 'T', 'e', 's', 't', 'F', 'i', 'l', 'e', '1', 'W', '\0' }; -int TestFileFindFirstFile(int argc, char* argv[]) +static BOOL create_layout_files(size_t level, const char* BasePath, wArrayList* files) { - char* str; - size_t length = 0; - HANDLE hFind; - LPTSTR BasePath; - WIN32_FIND_DATA FindData; - TCHAR FilePath[PATHCCH_MAX_CCH] = { 0 }; - WINPR_UNUSED(argc); - - str = argv[1]; -#ifdef UNICODE - BasePath = ConvertUtf8ToWChar(str, &length); - - if (!BasePath) + for (size_t x = 0; x < 10; x++) { - _tprintf(_T("Unable to allocate memory\n")); - return -1; + 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); } -#else - BasePath = _strdup(str); + return TRUE; +} - if (!BasePath) +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++) { - printf("Unable to allocate memory\n"); - return -1; + 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; } - length = strlen(BasePath); -#endif - CopyMemory(FilePath, BasePath, length * sizeof(TCHAR)); - FilePath[length] = 0; - PathCchConvertStyle(BasePath, length, PATH_STYLE_WINDOWS); - NativePathCchAppend(FilePath, PATHCCH_MAX_CCH, _T("TestFile1")); - free(BasePath); - _tprintf(_T("Finding file: %s\n"), FilePath); - hFind = FindFirstFile(FilePath, &FindData); + 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 = free; + obj->fnObjectNew = _strdup; + + 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) +{ + 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) { - _tprintf(_T("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n"), FilePath); - return -1; + printf("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n", FilePathA); + goto fail; } - _tprintf(_T("FindFirstFile: %s"), FindData.cFileName); + CHAR cFileName[MAX_PATH] = { 0 }; + ConvertWCharNToUtf8(FindData.cFileName, ARRAYSIZE(FindData.cFileName), cFileName, + ARRAYSIZE(cFileName)); - if (_tcscmp(FindData.cFileName, testFile1) != 0) + printf("FindFirstFile: %s", cFileName); + + if (_wcscmp(FindData.cFileName, testFile1W) != 0) { - _tprintf(_T("FindFirstFile failure: Expected: %s, Actual: %s\n"), testFile1, - FindData.cFileName); - return -1; + printf("FindFirstFile failure: Expected: %s, Actual: %s\n", testFile1A, cFileName); + goto fail; } + rc = 0; +fail: + DeleteFileW(FilePath); FindClose(hFind); - return 0; + 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/path/include/PathAllocCombine.c b/winpr/libwinpr/path/include/PathAllocCombine.c index ea3198a23..aaa567159 100644 --- a/winpr/libwinpr/path/include/PathAllocCombine.c +++ b/winpr/libwinpr/path/include/PathAllocCombine.c @@ -23,7 +23,6 @@ HRESULT PATH_ALLOC_COMBINE(PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFlags, PWSTR* ppszPathOut) { -#ifdef _WIN32 PWSTR pszPathOut; BOOL backslashIn; BOOL backslashMore; @@ -44,8 +43,8 @@ HRESULT PATH_ALLOC_COMBINE(PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFla if (!pszPathIn) return E_FAIL; /* valid but not implemented, see top comment */ - pszPathInLength = wcslen(pszPathIn); - pszMoreLength = wcslen(pszMore); + pszPathInLength = _wcslen(pszPathIn); + pszMoreLength = _wcslen(pszMore); /* prevent segfaults - the complete implementation below is buggy */ if (pszPathInLength < 3) @@ -58,21 +57,25 @@ HRESULT PATH_ALLOC_COMBINE(PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFla { if ((pszPathIn[1] == ':') && (pszPathIn[2] == CUR_PATH_SEPARATOR_CHR)) { + const WCHAR colon[] = { ':', '\0' }; size_t sizeOfBuffer; - pszPathOutLength = 2 + pszMoreLength; - sizeOfBuffer = (pszPathOutLength + 1) * 2; - pszPathOut = (PWSTR)calloc(sizeOfBuffer, 2); + pszPathOutLength = sizeof(WCHAR) + pszMoreLength; + sizeOfBuffer = (pszPathOutLength + 1) * sizeof(WCHAR); + pszPathOut = (PWSTR)calloc(sizeOfBuffer, sizeof(WCHAR)); if (!pszPathOut) return E_OUTOFMEMORY; - swprintf_s(pszPathOut, sizeOfBuffer, L"%c:%s", pszPathIn[0], pszMore); + _wcsncat(pszPathOut, &pszPathIn[0], 1); + _wcsncat(pszPathOut, colon, ARRAYSIZE(colon)); + _wcsncat(pszPathOut, pszMore, pszMoreLength); *ppszPathOut = pszPathOut; return S_OK; } } else { + const WCHAR sep[] = CUR_PATH_SEPARATOR_STR; size_t sizeOfBuffer; pszPathOutLength = pszPathInLength + pszMoreLength; sizeOfBuffer = (pszPathOutLength + 1) * 2; @@ -81,17 +84,15 @@ HRESULT PATH_ALLOC_COMBINE(PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFla if (!pszPathOut) return E_OUTOFMEMORY; - if (backslashIn) - swprintf_s(pszPathOut, sizeOfBuffer, L"%s%s", pszPathIn, pszMore); - else - swprintf_s(pszPathOut, sizeOfBuffer, L"%s" CUR_PATH_SEPARATOR_STR L"%s", pszPathIn, - pszMore); + _wcsncat(pszPathOut, pszPathIn, pszPathInLength); + if (!backslashIn) + _wcsncat(pszPathOut, sep, ARRAYSIZE(sep)); + _wcsncat(pszPathOut, pszMore, pszMoreLength); *ppszPathOut = pszPathOut; return S_OK; } -#endif return E_FAIL; } diff --git a/winpr/libwinpr/path/include/PathCchAddExtension.c b/winpr/libwinpr/path/include/PathCchAddExtension.c index a78e229fc..62f0b747c 100644 --- a/winpr/libwinpr/path/include/PathCchAddExtension.c +++ b/winpr/libwinpr/path/include/PathCchAddExtension.c @@ -9,7 +9,6 @@ HRESULT PATH_CCH_ADD_EXTENSION(PWSTR pszPath, size_t cchPath, PCWSTR pszExt) { -#ifdef _WIN32 LPWSTR pDot; BOOL bExtDot; LPWSTR pBackslash; @@ -26,8 +25,8 @@ HRESULT PATH_CCH_ADD_EXTENSION(PWSTR pszPath, size_t cchPath, PCWSTR pszExt) pszPathLength = lstrlenW(pszPath); bExtDot = (pszExt[0] == '.') ? TRUE : FALSE; - pDot = wcsrchr(pszPath, '.'); - pBackslash = wcsrchr(pszPath, CUR_PATH_SEPARATOR_CHR); + pDot = _wcsrchr(pszPath, '.'); + pBackslash = _wcsrchr(pszPath, CUR_PATH_SEPARATOR_CHR); if (pDot && pBackslash) { @@ -37,14 +36,17 @@ HRESULT PATH_CCH_ADD_EXTENSION(PWSTR pszPath, size_t cchPath, PCWSTR pszExt) if (cchPath > pszPathLength + pszExtLength + ((bExtDot) ? 0 : 1)) { - if (bExtDot) - swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L"%s", pszExt); - else - swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L".%s", pszExt); + const WCHAR dot[] = { '.', '\0' }; + WCHAR* ptr = &pszPath[pszPathLength]; + *ptr = '\0'; + + if (!bExtDot) + _wcsncat(ptr, dot, _wcslen(dot)); + _wcsncat(ptr, pszExt, pszExtLength); return S_OK; } -#endif + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } diff --git a/winpr/libwinpr/path/include/PathCchAppend.c b/winpr/libwinpr/path/include/PathCchAppend.c index 2e7507b6d..02777770f 100644 --- a/winpr/libwinpr/path/include/PathCchAppend.c +++ b/winpr/libwinpr/path/include/PathCchAppend.c @@ -10,7 +10,6 @@ HRESULT PATH_CCH_APPEND(PWSTR pszPath, size_t cchPath, PCWSTR pszMore) { -#ifdef _WIN32 BOOL pathBackslash; BOOL moreBackslash; size_t pszMoreLength; @@ -35,7 +34,9 @@ HRESULT PATH_CCH_APPEND(PWSTR pszPath, size_t cchPath, PCWSTR pszMore) { if ((pszPathLength + pszMoreLength - 1) < cchPath) { - swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L"%s", &pszMore[1]); + WCHAR* ptr = &pszPath[pszPathLength]; + *ptr = '\0'; + _wcsncat(ptr, &pszMore[1], _wcslen(&pszMore[1])); return S_OK; } } @@ -43,7 +44,9 @@ HRESULT PATH_CCH_APPEND(PWSTR pszPath, size_t cchPath, PCWSTR pszMore) { if ((pszPathLength + pszMoreLength) < cchPath) { - swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L"%s", pszMore); + WCHAR* ptr = &pszPath[pszPathLength]; + *ptr = '\0'; + _wcsncat(ptr, pszMore, _wcslen(pszMore)); return S_OK; } } @@ -51,12 +54,14 @@ HRESULT PATH_CCH_APPEND(PWSTR pszPath, size_t cchPath, PCWSTR pszMore) { if ((pszPathLength + pszMoreLength + 1) < cchPath) { - swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, - CUR_PATH_SEPARATOR_STR L"%s", pszMore); + const WCHAR sep[] = CUR_PATH_SEPARATOR_STR; + WCHAR* ptr = &pszPath[pszPathLength]; + *ptr = '\0'; + _wcsncat(ptr, sep, _wcslen(sep)); + _wcsncat(ptr, pszMore, _wcslen(pszMore)); return S_OK; } } -#endif return HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); } diff --git a/winpr/libwinpr/path/path.c b/winpr/libwinpr/path/path.c index 9a65dfc3f..3fdabc6f9 100644 --- a/winpr/libwinpr/path/path.c +++ b/winpr/libwinpr/path/path.c @@ -35,8 +35,14 @@ #define PATH_SLASH_STR_W L"/" #define PATH_BACKSLASH_STR_W L"\\" #else -#define PATH_SLASH_STR_W "/" -#define PATH_BACKSLASH_STR_W "\\" +#define PATH_SLASH_STR_W \ + { \ + '/', '\0' \ + } +#define PATH_BACKSLASH_STR_W \ + { \ + '\\', '\0' \ + } #endif #ifdef _WIN32 @@ -1109,15 +1115,13 @@ BOOL winpr_RemoveDirectory_RecursiveW(LPCWSTR lpPathName) return FALSE; const size_t pathnamelen = _wcslen(lpPathName); - const size_t path_slash_len = pathnamelen + 2; - WCHAR* path_slash = calloc(pathnamelen + 3, sizeof(WCHAR)); + const size_t path_slash_len = pathnamelen + 3; + WCHAR* path_slash = calloc(pathnamelen + 4, sizeof(WCHAR)); if (!path_slash) return FALSE; memcpy(path_slash, lpPathName, pathnamelen * sizeof(WCHAR)); - const WCHAR sep[] = { PathGetSeparatorW(PATH_STYLE_NATIVE), '\0' }; const WCHAR star[] = { '*', '\0' }; - PathCchAppendW(path_slash, path_slash_len, sep); PathCchAppendW(path_slash, path_slash_len, star); WIN32_FIND_DATAW findFileData = { 0 };