diff --git a/src/port.c b/src/port.c index 3564fa5..e2f536f 100644 --- a/src/port.c +++ b/src/port.c @@ -130,6 +130,133 @@ int wPread(WFD fd, unsigned char* buf, unsigned int sz, long ofst) #endif #endif /* !NO_FILESYSTEM */ + +#ifdef USE_WINDOWS_API + +void* WS_CreateFileA(const char* fileName, unsigned long desiredAccess, + unsigned long shareMode, unsigned long creationDisposition, + unsigned long flags, void* heap) +{ + HANDLE fileHandle; + wchar_t* unicodeFileName; + size_t unicodeFileNameSz = 0; + size_t returnSz = 0; + size_t fileNameSz = 0; + errno_t error; + + fileNameSz = WSTRLEN(fileName); + error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0); + if (error) + return INVALID_HANDLE_VALUE; + + unicodeFileName = (wchar_t*)WMALLOC(unicodeFileNameSz, heap, 0); + if (unicodeFileName == NULL) + return INVALID_HANDLE_VALUE; + + error = mbstowcs_s(&returnSz, unicodeFileName, unicodeFileNameSz, + fileName, fileNameSz); + + if (!error) + fileHandle = CreateFileW(unicodeFileName, desiredAccess, shareMode, + NULL, creationDisposition, flags, NULL); + + WFREE(unicodeFileName, heap, 0); + + return (void*)(error ? INVALID_HANDLE_VALUE : fileHandle); +} + +void* WS_FindFirstFileA(const char* fileName, + char* realFileName, size_t realFileNameSz, int* isDir, void* heap) +{ + HANDLE findHandle; + WIN32_FIND_DATAW findFileData; + wchar_t* unicodeFileName; + size_t unicodeFileNameSz = 0; + size_t returnSz = 0; + size_t fileNameSz = 0; + errno_t error; + + fileNameSz = WSTRLEN(fileName); + error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0); + if (error) + return INVALID_HANDLE_VALUE; + + unicodeFileName = (wchar_t*)WMALLOC(unicodeFileNameSz, heap, 0); + if (unicodeFileName == NULL) + return INVALID_HANDLE_VALUE; + + error = mbstowcs_s(&returnSz, unicodeFileName, unicodeFileNameSz, + fileName, fileNameSz); + + if (!error) + findHandle = FindFirstFileW(unicodeFileName, &findFileData); + + WFREE(unicodeFileName, heap, 0); + + error = wcstombs_s(NULL, realFileName, realFileNameSz, + findFileData.cFileName, realFileNameSz); + + if (isDir != NULL) { + *isDir = + (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + } + + return (void*)findHandle; +} + + +int WS_FindNextFileA(void* findHandle, + char* realFileName, size_t realFileNameSz) +{ + BOOL success; + WIN32_FIND_DATAW findFileData; + errno_t error; + + success = FindNextFileW((HANDLE)findHandle, &findFileData); + + if (success) { + error = wcstombs_s(NULL, realFileName, realFileNameSz, + findFileData.cFileName, realFileNameSz); + } + + return (success != 0) && (error == 0); +} + + +int WS_GetFileAttributesExA(const char* fileName, void* fileInfo, void* heap) +{ + BOOL success = 0; + wchar_t* unicodeFileName; + size_t unicodeFileNameSz = 0; + size_t returnSz = 0; + size_t fileNameSz = 0; + errno_t error; + + fileNameSz = WSTRLEN(fileName); + error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0); + if (error != 0) + return 0; + + unicodeFileName = (wchar_t*)WMALLOC(unicodeFileNameSz, heap, 0); + if (unicodeFileName == NULL) + return 0; + + error = mbstowcs_s(&returnSz, unicodeFileName, unicodeFileNameSz, + fileName, fileNameSz); + + if (error == 0) { + success = GetFileAttributesExW(unicodeFileName, + GetFileExInfoStandard, fileInfo); + } + + WFREE(unicodeFileName, heap, 0); + + return success != 0; +} + +#endif /* USE_WINDOWS_API */ + + #ifndef WSTRING_USER char* wstrnstr(const char* s1, const char* s2, unsigned int n) diff --git a/src/wolfsftp.c b/src/wolfsftp.c index 0daa165..ba46aa2 100644 --- a/src/wolfsftp.c +++ b/src/wolfsftp.c @@ -1637,8 +1637,8 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) #endif clean_path(dir); - fileHandle = CreateFileA(dir, desiredAccess, 0, NULL, creationDisp, - FILE_ATTRIBUTE_NORMAL, NULL); + fileHandle = WS_CreateFileA(dir, desiredAccess, 0, creationDisp, + FILE_ATTRIBUTE_NORMAL, ssh->ctx->heap); if (fileHandle == INVALID_HANDLE_VALUE) { WLOG(WS_LOG_SFTP, "Error opening file %s", dir); res = oer; @@ -1808,7 +1808,8 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) char* dirName; word32 idx = 0; HANDLE findHandle; - WIN32_FIND_DATAA findData; + char realName[MAX_PATH]; + int isDir = 0; int ret = WS_SUCCESS; word32 outSz = sizeof(word64) + WOLFSSH_SFTP_HEADER + UINT32_SZ; @@ -1843,9 +1844,9 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) clean_path(dirName); /* get directory handle */ - findHandle = FindFirstFileA(dirName, &findData); - if (findHandle == INVALID_HANDLE_VALUE || - !(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + findHandle = (HANDLE)WS_FindFirstFileA(dirName, + realName, sizeof(realName), &isDir, ssh->ctx->heap); + if (findHandle == INVALID_HANDLE_VALUE || !isDir) { WLOG(WS_LOG_SFTP, "Error with opening directory"); WFREE(dirName, ssh->ctx->heap, DYNTYPE_BUFFER); @@ -2015,7 +2016,7 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out, { int sz; HANDLE findHandle; - WIN32_FIND_DATAA findData; + char realFileName[MAX_PATH]; if (dir == NULL || ssh == NULL || out == NULL) { return WS_BAD_ARGUMENT; @@ -2032,7 +2033,8 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out, WSTRNCPY(name, dirName, MAX_PATH); WSTRNCAT(name, "\\*", MAX_PATH); - findHandle = FindFirstFileA(name, &findData); + findHandle = (HANDLE)WS_FindFirstFileA(name, + realFileName, sizeof(realFileName), NULL, ssh->ctx->heap); if (findHandle == INVALID_HANDLE_VALUE) return WS_FATAL_ERROR; @@ -2041,12 +2043,13 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out, } else { findHandle = *dir; - if (FindNextFileA(findHandle, &findData) == 0) { + if (WS_FindNextFileA(findHandle, + realFileName, sizeof(realFileName)) == 0) { return WS_FATAL_ERROR; } } - sz = (int)WSTRLEN(findData.cFileName); + sz = (int)WSTRLEN(realFileName); out->fName = (char*)WMALLOC(sz + 1, out->heap, DYNTYPE_SFTP); if (out->fName == NULL) { return WS_MEMORY_E; @@ -2057,8 +2060,8 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out, return WS_MEMORY_E; } - WMEMCPY(out->fName, findData.cFileName, sz); - WMEMCPY(out->lName, findData.cFileName, sz); + WMEMCPY(out->fName, realFileName, sz); + WMEMCPY(out->lName, realFileName, sz); out->fName[sz] = '\0'; out->lName[sz] = '\0'; out->fSz = sz; @@ -3414,7 +3417,7 @@ int SFTP_GetAttributes(const char* fileName, WS_SFTP_FILEATRB* atr, byte link) /* @TODO add proper Windows link support */ /* Note, for windows, we treat WSTAT and WLSTAT the same. */ - error = !GetFileAttributesExA(fileName, GetFileExInfoStandard, &stats); + error = !WS_GetFileAttributesExA(fileName, &stats, NULL); if (error) return WS_BAD_FILE_E; @@ -6798,9 +6801,9 @@ int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from, DWORD desiredAccess = GENERIC_WRITE; if (state->gOfst > 0) desiredAccess |= FILE_APPEND_DATA; - state->fileHandle = CreateFileA(to, desiredAccess, - 0, NULL, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL); + state->fileHandle = WS_CreateFileA(to, desiredAccess, + 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, ssh->ctx->heap); } if (resume) { WMEMSET(&state->offset, 0, sizeof(OVERLAPPED)); @@ -6997,9 +7000,9 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume, WFSEEK(state->fl, state->pOfst, 0); } #else /* USE_WINDOWS_API */ - state->fileHandle = CreateFileA(from, GENERIC_READ, - FILE_SHARE_READ, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); + state->fileHandle = WS_CreateFileA(from, GENERIC_READ, + FILE_SHARE_READ, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, ssh->ctx->heap); if (state->fileHandle == INVALID_HANDLE_VALUE) { ssh->error = WS_SFTP_FILE_DNE; ret = WS_FATAL_ERROR; diff --git a/wolfssh/port.h b/wolfssh/port.h index 01dd3c3..5ff8d18 100644 --- a/wolfssh/port.h +++ b/wolfssh/port.h @@ -146,6 +146,18 @@ extern "C" { !defined(WOLFSSH_SCP_USER_CALLBACKS) #ifdef USE_WINDOWS_API + WOLFSSH_LOCAL void* WS_CreateFileA(const char* fileName, + unsigned long desiredAccess, unsigned long shareMode, + unsigned long creationDisposition, unsigned long flags, + void* heap); + WOLFSSH_LOCAL void* WS_FindFirstFileA(const char* fileName, + char* realFileName, size_t realFileNameSz, int* isDir, + void* heap); + WOLFSSH_LOCAL int WS_FindNextFileA(void* findHandle, + char* realFileName, size_t realFileNameSz); + WOLFSSH_LOCAL int WS_GetFileAttributesExA(const char* fileName, + void* fileInfo, void* heap); + #ifndef _WIN32_WCE #include #define WCHDIR(p) _chdir((p))