[winpr,file] fix issues with FindFirstFile

This commit is contained in:
Armin Novak 2023-07-25 10:19:15 +02:00 committed by Martin Fleisz
parent c4f93891fd
commit 14d5cbeacb
9 changed files with 421 additions and 182 deletions

View File

@ -80,6 +80,7 @@ extern "C"
WINPR_API char* strtok_s(char* strToken, const char* strDelimit, char** context); 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* wcstok_s(WCHAR* strToken, const WCHAR* strDelimit, WCHAR** context);
WINPR_API WCHAR* _wcsncat(WCHAR* dst, const WCHAR* src, size_t sz);
#else #else
#define _wcscmp wcscmp #define _wcscmp wcscmp
@ -89,6 +90,7 @@ extern "C"
#define _wcsstr wcsstr #define _wcsstr wcsstr
#define _wcschr wcschr #define _wcschr wcschr
#define _wcsrchr wcsrchr #define _wcsrchr wcsrchr
#define _wcsncat wcsncat
#endif /* _WIN32 */ #endif /* _WIN32 */

View File

@ -388,7 +388,6 @@ static BOOL add_file_to_list(wClipboard* clipboard, const WCHAR* local_name,
WINPR_ASSERT(remote_name); WINPR_ASSERT(remote_name);
WINPR_ASSERT(files); WINPR_ASSERT(files);
WLog_VRB(TAG, "adding file: %s", local_name);
file = make_synthetic_file(local_name, remote_name); file = make_synthetic_file(local_name, remote_name);
if (!file) if (!file)

View File

@ -203,6 +203,19 @@ WCHAR* _wcsdup(const WCHAR* strSource)
return strDestination; 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) int _stricmp(const char* string1, const char* string2)
{ {
return strcasecmp(string1, string2); return strcasecmp(string1, string2);

View File

@ -873,12 +873,47 @@ BOOL WINAPI SetFileTime(HANDLE hFile, const FILETIME* lpCreationTime,
typedef struct typedef struct
{ {
DIR* pDir; char magic[16];
LPSTR lpPath; LPSTR lpPath;
LPSTR lpPattern; LPSTR lpPattern;
struct dirent* pDirent; DIR* pDir;
} WIN32_FILE_SEARCH; } 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, static BOOL FindDataFromStat(const char* path, const struct stat* fileStat,
LPWIN32_FIND_DATAA lpFindFileData) 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) HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
{ {
BOOL isDir = FALSE;
struct stat fileStat;
WIN32_FILE_SEARCH* pFileSearch;
if (!lpFindFileData || !lpFileName) if (!lpFindFileData || !lpFileName)
{ {
SetLastError(ERROR_BAD_ARGUMENTS); SetLastError(ERROR_BAD_ARGUMENTS);
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA)); const WIN32_FIND_DATAA empty = { 0 };
pFileSearch = (WIN32_FILE_SEARCH*)calloc(1, sizeof(WIN32_FILE_SEARCH)); *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) if (!pFileSearch)
{ {
@ -945,101 +989,10 @@ HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
return INVALID_HANDLE_VALUE; 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 (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; return (HANDLE)pFileSearch;
}
fail:
FindClose(pFileSearch); FindClose(pFileSearch);
return INVALID_HANDLE_VALUE; 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) BOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)
{ {
if (!hFindFile || !lpFindFileData) if (!lpFindFileData)
return FALSE;
if (hFindFile == INVALID_HANDLE_VALUE)
return FALSE; return FALSE;
const WIN32_FIND_DATAA empty = { 0 }; const WIN32_FIND_DATAA empty = { 0 };
*lpFindFileData = empty; *lpFindFileData = empty;
if (!is_valid_file_search_handle(hFindFile))
return FALSE;
WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)hFindFile; 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; 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); const size_t namelen = strnlen(lpFindFileData->cFileName, MAX_PATH);
size_t pathlen = strlen(pFileSearch->lpPath); size_t pathlen = strlen(pFileSearch->lpPath);
char* fullpath = (char*)malloc(pathlen + namelen + 2); char* fullpath = (char*)malloc(pathlen + namelen + 2);
@ -1156,7 +1110,7 @@ BOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)
* duplicate separators */ * duplicate separators */
if (fullpath[pathlen - 1] != '/') if (fullpath[pathlen - 1] != '/')
fullpath[pathlen++] = '/'; fullpath[pathlen++] = '/';
memcpy(fullpath + pathlen, pFileSearch->pDirent->d_name, namelen); memcpy(fullpath + pathlen, pDirent->d_name, namelen);
fullpath[pathlen + namelen] = 0; fullpath[pathlen + namelen] = 0;
struct stat fileStat = { 0 }; struct stat fileStat = { 0 };
@ -1220,7 +1174,7 @@ BOOL FindClose(HANDLE hFindFile)
* is a initialized HANDLE that is not freed properly. * is a initialized HANDLE that is not freed properly.
* Disable this return to stop confusing the analyzer. */ * Disable this return to stop confusing the analyzer. */
#ifndef __clang_analyzer__ #ifndef __clang_analyzer__
if (!pFileSearch || (pFileSearch == INVALID_HANDLE_VALUE)) if (!is_valid_file_search_handle(hFindFile))
return FALSE; return FALSE;
#endif #endif

View File

@ -1,66 +1,325 @@
#include <stdio.h> #include <stdio.h>
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/handle.h>
#include <winpr/file.h> #include <winpr/file.h>
#include <winpr/path.h> #include <winpr/path.h>
#include <winpr/tchar.h> #include <winpr/tchar.h>
#include <winpr/collections.h>
#include <winpr/windows.h> #include <winpr/windows.h>
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; for (size_t x = 0; x < 10; x++)
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)
{ {
_tprintf(_T("Unable to allocate memory\n")); CHAR FilePath[PATHCCH_MAX_CCH] = { 0 };
return -1; 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 return TRUE;
BasePath = _strdup(str); }
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"); CHAR CurFilePath[PATHCCH_MAX_CCH] = { 0 };
return -1; 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); printf("FindFirstFile: %s", FindData.cFileName);
#endif
CopyMemory(FilePath, BasePath, length * sizeof(TCHAR)); if (strcmp(FindData.cFileName, testFile1A) != 0)
FilePath[length] = 0; {
PathCchConvertStyle(BasePath, length, PATH_STYLE_WINDOWS); printf("FindFirstFile failure: Expected: %s, Actual: %s\n", testFile1A, FindData.cFileName);
NativePathCchAppend(FilePath, PATHCCH_MAX_CCH, _T("TestFile1")); goto fail;
free(BasePath); }
_tprintf(_T("Finding file: %s\n"), FilePath); rc = TRUE;
hFind = FindFirstFile(FilePath, &FindData); 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) if (hFind == INVALID_HANDLE_VALUE)
{ {
_tprintf(_T("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n"), FilePath); printf("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n", FilePathA);
return -1; 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, printf("FindFirstFile failure: Expected: %s, Actual: %s\n", testFile1A, cFileName);
FindData.cFileName); goto fail;
return -1;
} }
rc = 0;
fail:
DeleteFileW(FilePath);
FindClose(hFind); 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;
} }

View File

@ -23,7 +23,6 @@
HRESULT PATH_ALLOC_COMBINE(PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFlags, HRESULT PATH_ALLOC_COMBINE(PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFlags,
PWSTR* ppszPathOut) PWSTR* ppszPathOut)
{ {
#ifdef _WIN32
PWSTR pszPathOut; PWSTR pszPathOut;
BOOL backslashIn; BOOL backslashIn;
BOOL backslashMore; BOOL backslashMore;
@ -44,8 +43,8 @@ HRESULT PATH_ALLOC_COMBINE(PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFla
if (!pszPathIn) if (!pszPathIn)
return E_FAIL; /* valid but not implemented, see top comment */ return E_FAIL; /* valid but not implemented, see top comment */
pszPathInLength = wcslen(pszPathIn); pszPathInLength = _wcslen(pszPathIn);
pszMoreLength = wcslen(pszMore); pszMoreLength = _wcslen(pszMore);
/* prevent segfaults - the complete implementation below is buggy */ /* prevent segfaults - the complete implementation below is buggy */
if (pszPathInLength < 3) 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)) if ((pszPathIn[1] == ':') && (pszPathIn[2] == CUR_PATH_SEPARATOR_CHR))
{ {
const WCHAR colon[] = { ':', '\0' };
size_t sizeOfBuffer; size_t sizeOfBuffer;
pszPathOutLength = 2 + pszMoreLength; pszPathOutLength = sizeof(WCHAR) + pszMoreLength;
sizeOfBuffer = (pszPathOutLength + 1) * 2; sizeOfBuffer = (pszPathOutLength + 1) * sizeof(WCHAR);
pszPathOut = (PWSTR)calloc(sizeOfBuffer, 2); pszPathOut = (PWSTR)calloc(sizeOfBuffer, sizeof(WCHAR));
if (!pszPathOut) if (!pszPathOut)
return E_OUTOFMEMORY; 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; *ppszPathOut = pszPathOut;
return S_OK; return S_OK;
} }
} }
else else
{ {
const WCHAR sep[] = CUR_PATH_SEPARATOR_STR;
size_t sizeOfBuffer; size_t sizeOfBuffer;
pszPathOutLength = pszPathInLength + pszMoreLength; pszPathOutLength = pszPathInLength + pszMoreLength;
sizeOfBuffer = (pszPathOutLength + 1) * 2; sizeOfBuffer = (pszPathOutLength + 1) * 2;
@ -81,17 +84,15 @@ HRESULT PATH_ALLOC_COMBINE(PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFla
if (!pszPathOut) if (!pszPathOut)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (backslashIn) _wcsncat(pszPathOut, pszPathIn, pszPathInLength);
swprintf_s(pszPathOut, sizeOfBuffer, L"%s%s", pszPathIn, pszMore); if (!backslashIn)
else _wcsncat(pszPathOut, sep, ARRAYSIZE(sep));
swprintf_s(pszPathOut, sizeOfBuffer, L"%s" CUR_PATH_SEPARATOR_STR L"%s", pszPathIn, _wcsncat(pszPathOut, pszMore, pszMoreLength);
pszMore);
*ppszPathOut = pszPathOut; *ppszPathOut = pszPathOut;
return S_OK; return S_OK;
} }
#endif
return E_FAIL; return E_FAIL;
} }

View File

@ -9,7 +9,6 @@
HRESULT PATH_CCH_ADD_EXTENSION(PWSTR pszPath, size_t cchPath, PCWSTR pszExt) HRESULT PATH_CCH_ADD_EXTENSION(PWSTR pszPath, size_t cchPath, PCWSTR pszExt)
{ {
#ifdef _WIN32
LPWSTR pDot; LPWSTR pDot;
BOOL bExtDot; BOOL bExtDot;
LPWSTR pBackslash; LPWSTR pBackslash;
@ -26,8 +25,8 @@ HRESULT PATH_CCH_ADD_EXTENSION(PWSTR pszPath, size_t cchPath, PCWSTR pszExt)
pszPathLength = lstrlenW(pszPath); pszPathLength = lstrlenW(pszPath);
bExtDot = (pszExt[0] == '.') ? TRUE : FALSE; bExtDot = (pszExt[0] == '.') ? TRUE : FALSE;
pDot = wcsrchr(pszPath, '.'); pDot = _wcsrchr(pszPath, '.');
pBackslash = wcsrchr(pszPath, CUR_PATH_SEPARATOR_CHR); pBackslash = _wcsrchr(pszPath, CUR_PATH_SEPARATOR_CHR);
if (pDot && pBackslash) 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 (cchPath > pszPathLength + pszExtLength + ((bExtDot) ? 0 : 1))
{ {
if (bExtDot) const WCHAR dot[] = { '.', '\0' };
swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L"%s", pszExt); WCHAR* ptr = &pszPath[pszPathLength];
else *ptr = '\0';
swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L".%s", pszExt);
if (!bExtDot)
_wcsncat(ptr, dot, _wcslen(dot));
_wcsncat(ptr, pszExt, pszExtLength);
return S_OK; return S_OK;
} }
#endif
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
} }

View File

@ -10,7 +10,6 @@
HRESULT PATH_CCH_APPEND(PWSTR pszPath, size_t cchPath, PCWSTR pszMore) HRESULT PATH_CCH_APPEND(PWSTR pszPath, size_t cchPath, PCWSTR pszMore)
{ {
#ifdef _WIN32
BOOL pathBackslash; BOOL pathBackslash;
BOOL moreBackslash; BOOL moreBackslash;
size_t pszMoreLength; size_t pszMoreLength;
@ -35,7 +34,9 @@ HRESULT PATH_CCH_APPEND(PWSTR pszPath, size_t cchPath, PCWSTR pszMore)
{ {
if ((pszPathLength + pszMoreLength - 1) < cchPath) 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; return S_OK;
} }
} }
@ -43,7 +44,9 @@ HRESULT PATH_CCH_APPEND(PWSTR pszPath, size_t cchPath, PCWSTR pszMore)
{ {
if ((pszPathLength + pszMoreLength) < cchPath) 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; return S_OK;
} }
} }
@ -51,12 +54,14 @@ HRESULT PATH_CCH_APPEND(PWSTR pszPath, size_t cchPath, PCWSTR pszMore)
{ {
if ((pszPathLength + pszMoreLength + 1) < cchPath) if ((pszPathLength + pszMoreLength + 1) < cchPath)
{ {
swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, const WCHAR sep[] = CUR_PATH_SEPARATOR_STR;
CUR_PATH_SEPARATOR_STR L"%s", pszMore); WCHAR* ptr = &pszPath[pszPathLength];
*ptr = '\0';
_wcsncat(ptr, sep, _wcslen(sep));
_wcsncat(ptr, pszMore, _wcslen(pszMore));
return S_OK; return S_OK;
} }
} }
#endif
return HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); return HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
} }

View File

@ -35,8 +35,14 @@
#define PATH_SLASH_STR_W L"/" #define PATH_SLASH_STR_W L"/"
#define PATH_BACKSLASH_STR_W L"\\" #define PATH_BACKSLASH_STR_W L"\\"
#else #else
#define PATH_SLASH_STR_W "/" #define PATH_SLASH_STR_W \
#define PATH_BACKSLASH_STR_W "\\" { \
'/', '\0' \
}
#define PATH_BACKSLASH_STR_W \
{ \
'\\', '\0' \
}
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
@ -1109,15 +1115,13 @@ BOOL winpr_RemoveDirectory_RecursiveW(LPCWSTR lpPathName)
return FALSE; return FALSE;
const size_t pathnamelen = _wcslen(lpPathName); const size_t pathnamelen = _wcslen(lpPathName);
const size_t path_slash_len = pathnamelen + 2; const size_t path_slash_len = pathnamelen + 3;
WCHAR* path_slash = calloc(pathnamelen + 3, sizeof(WCHAR)); WCHAR* path_slash = calloc(pathnamelen + 4, sizeof(WCHAR));
if (!path_slash) if (!path_slash)
return FALSE; return FALSE;
memcpy(path_slash, lpPathName, pathnamelen * sizeof(WCHAR)); memcpy(path_slash, lpPathName, pathnamelen * sizeof(WCHAR));
const WCHAR sep[] = { PathGetSeparatorW(PATH_STYLE_NATIVE), '\0' };
const WCHAR star[] = { '*', '\0' }; const WCHAR star[] = { '*', '\0' };
PathCchAppendW(path_slash, path_slash_len, sep);
PathCchAppendW(path_slash, path_slash_len, star); PathCchAppendW(path_slash, path_slash_len, star);
WIN32_FIND_DATAW findFileData = { 0 }; WIN32_FIND_DATAW findFileData = { 0 };