From a04f1f8fc59a72ce7330c4dbbe6d4be3f3ff698d Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 9 Dec 2015 18:27:05 +0100 Subject: [PATCH 01/12] Added missing _snprintf define. --- winpr/include/winpr/string.h | 1 + 1 file changed, 1 insertion(+) diff --git a/winpr/include/winpr/string.h b/winpr/include/winpr/string.h index ddcaeaf46..555d05306 100644 --- a/winpr/include/winpr/string.h +++ b/winpr/include/winpr/string.h @@ -153,6 +153,7 @@ WINPR_API int lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2); #endif #define sprintf_s snprintf +#define _snprintf snprintf #define _scprintf(_fmt, ...) snprintf(NULL, 0, _fmt, ## __VA_ARGS__) #define _scprintf(_fmt, ...) snprintf(NULL, 0, _fmt, ## __VA_ARGS__) From d0e3528c8e07124964f873a733ab9b37f3ed0a0a Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 9 Dec 2015 18:27:37 +0100 Subject: [PATCH 02/12] Added winpr_strerror function. --- winpr/include/winpr/debug.h | 1 + winpr/libwinpr/utils/debug.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/winpr/include/winpr/debug.h b/winpr/include/winpr/debug.h index 3d2cde68a..362bafd5a 100644 --- a/winpr/include/winpr/debug.h +++ b/winpr/include/winpr/debug.h @@ -32,6 +32,7 @@ WINPR_API void* winpr_backtrace(DWORD size); WINPR_API void winpr_backtrace_free(void* buffer); WINPR_API char** winpr_backtrace_symbols(void* buffer, size_t* used); WINPR_API void winpr_backtrace_symbols_fd(void* buffer, int fd); +WINPR_API char* winpr_strerror(DWORD dw, char* dmsg, size_t size); #ifdef __cplusplus } diff --git a/winpr/libwinpr/utils/debug.c b/winpr/libwinpr/utils/debug.c index d90d1e021..0b3150e05 100644 --- a/winpr/libwinpr/utils/debug.c +++ b/winpr/libwinpr/utils/debug.c @@ -471,3 +471,29 @@ void winpr_log_backtrace(const char* tag, DWORD level, DWORD size) winpr_backtrace_free(stack); } +char* winpr_strerror(DWORD dw, char* dmsg, size_t size) { + LPTSTR msg = NULL; + DWORD rc; + +#if defined(_WIN32) + rc = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dw, 0, (LPTSTR)&msg, 0, NULL); + if (rc) { +#if defined(UNICODE) + WideCharToMultiByte(CP_ACP, 0, msg, rc, dmsg, size - 1, NULL, NULL); +#else + memcpy(dmsg, msg, min(rc, size - 1)); +#endif + dmsg[min(rc, size - 1)] = 0; + LocalFree(msg); + } else { + _snprintf(dmsg, size, "FAILURE: %08X", GetLastError()); + } +#else + _snprintf(dmsg, size, "%s", strerror(dw)); +#endif + + return dmsg; +} From 19744f3bb865e1fde2b33155a96b2379244a9edf Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 9 Dec 2015 18:29:16 +0100 Subject: [PATCH 03/12] Added additional file functions and tests. --- winpr/include/winpr/file.h | 9 + winpr/libwinpr/file/file.c | 429 +++++++++++++++++- winpr/libwinpr/file/file.h | 61 +++ winpr/libwinpr/file/generic.c | 271 ++++++++++- winpr/libwinpr/file/namedPipeClient.c | 15 +- winpr/libwinpr/file/test/TestFileCreateFile.c | 63 ++- winpr/libwinpr/handle/handle.h | 41 +- winpr/libwinpr/pipe/pipe.c | 17 +- 8 files changed, 853 insertions(+), 53 deletions(-) create mode 100644 winpr/libwinpr/file/file.h diff --git a/winpr/include/winpr/file.h b/winpr/include/winpr/file.h index afe858878..f0129e212 100644 --- a/winpr/include/winpr/file.h +++ b/winpr/include/winpr/file.h @@ -165,6 +165,13 @@ #define STD_OUTPUT_HANDLE (DWORD)-11 #define STD_ERROR_HANDLE (DWORD)-12 +#define FILE_BEGIN 0 +#define FILE_CURRENT 1 +#define FILE_END 2 + +#define LOCKFILE_FAIL_IMMEDIATELY 1 +#define LOCKFILE_EXCLUSIVE_LOCK 2 + typedef union _FILE_SEGMENT_ELEMENT { PVOID64 Buffer; @@ -261,6 +268,8 @@ WINPR_API BOOL FlushFileBuffers(HANDLE hFile); WINPR_API BOOL SetEndOfFile(HANDLE hFile); +WINPR_API DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh); + WINPR_API DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod); diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index 49d6a5d96..a0f197670 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -30,19 +30,12 @@ #define TAG WINPR_TAG("file") #include +#include -#include "../handle/handle.h" +#include "file.h" #include #include - -struct winpr_file -{ - WINPR_HANDLE_DEF(); - - int fd; -}; - -typedef struct winpr_file WINPR_FILE; +#include static BOOL FileIsHandled(HANDLE handle) { @@ -84,10 +77,81 @@ static BOOL FileCloseHandle(HANDLE handle) { } } - free(handle); + free(file->lpFileName); + free(file); return TRUE; } +static BOOL FileSetEndOfFile(HANDLE hFile) +{ + WINPR_FILE* pFile = (WINPR_FILE*) hFile; + DWORD lowSize, highSize; + off_t size; + + if (!hFile) + return FALSE; + + lowSize = GetFileSize(hFile, &highSize); + if (lowSize == INVALID_FILE_SIZE) + return FALSE; + + size = lowSize | ((off_t)highSize << 32); + if (ftruncate(pFile->fd, size) < 0) + { + WLog_ERR(TAG, "ftruncate %d failed with %s [%08X]", + pFile->fd, strerror(errno), errno); + return FALSE; + } + + return TRUE; +} + + +static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove, + PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) +{ + WINPR_FILE* pFile = (WINPR_FILE*) hFile; + long offset = lDistanceToMove; + int whence; + FILE* fp; + + if (!hFile) + return INVALID_SET_FILE_POINTER; + + fp = fdopen(pFile->fd, "w"); + + if (!fp) + { + WLog_ERR(TAG, "fdopen(%d) failed with %s [%08X]", pFile->fd, + strerror(errno), errno); + return INVALID_SET_FILE_POINTER; + } + + switch(dwMoveMethod) + { + case FILE_BEGIN: + whence = SEEK_SET; + break; + case FILE_END: + whence = SEEK_END; + break; + case FILE_CURRENT: + whence = SEEK_CUR; + break; + default: + return INVALID_SET_FILE_POINTER; + } + + if (fseek(fp, offset, whence)) + { + WLog_ERR(TAG, "fseek(%d) failed with %s [%08X]", pFile->fd, + strerror(errno), errno); + return INVALID_SET_FILE_POINTER; + } + + return ftell(fp); +} + static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) { @@ -159,29 +223,347 @@ static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrit return TRUE; } +static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh) +{ + WINPR_FILE* file; + FILE* fp; + long cur, size; -static HANDLE_OPS ops = { - FileIsHandled, - FileCloseHandle, - FileGetFd, - NULL, /* CleanupHandle */ - FileRead, - FileWrite + if (!Object) + return 0; + + file = (WINPR_FILE *)Object; + fp = fdopen(file->fd, "r"); + + if (!fp) + { + WLog_ERR(TAG, "fdopen(%d) failed with %s [%08X]", file->fd, + strerror(errno), errno); + return INVALID_FILE_SIZE; + } + + cur = ftell(fp); + + if (cur < 0) + { + WLog_ERR(TAG, "ftell(%d) failed with %s [%08X]", file->fd, + strerror(errno), errno); + return INVALID_FILE_SIZE; + } + + if (fseek(fp, 0, SEEK_END) != 0) + { + WLog_ERR(TAG, "fseek(%d) failed with %s [%08X]", file->fd, + strerror(errno), errno); + return INVALID_FILE_SIZE; + } + + size = ftell(fp); + + if (size < 0) + { + WLog_ERR(TAG, "ftell(%d) failed with %s [%08X]", file->fd, + strerror(errno), errno); + return INVALID_FILE_SIZE; + } + + if (fseek(fp, cur, SEEK_SET) != 0) + { + WLog_ERR(TAG, "ftell(%d) failed with %s [%08X]", file->fd, + strerror(errno), errno); + return INVALID_FILE_SIZE; + } + + if (lpFileSizeHigh) + *lpFileSizeHigh = 0; + + return size; +} + +static BOOL FileLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, + DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, + LPOVERLAPPED lpOverlapped) + { + int lock; + WINPR_FILE* pFile = (WINPR_FILE*)hFile; + + if (!hFile) + return FALSE; + + if (pFile->bLocked) + { + WLog_ERR(TAG, "File %d already locked!", pFile->fd); + return FALSE; + } + + if (lpOverlapped) + { + WLog_ERR(TAG, "lpOverlapped not implemented!"); + return FALSE; + } + + if (dwFlags & LOCKFILE_EXCLUSIVE_LOCK) + lock = LOCK_EX; + else + lock = LOCK_SH; + + if (dwFlags & LOCKFILE_FAIL_IMMEDIATELY) + lock |= LOCK_NB; + + if (flock(pFile->fd, lock) < 0) + { + WLog_ERR(TAG, "flock failed with %s [%08X]", + strerror(errno), errno); + return FALSE; + } + + pFile->bLocked = TRUE; + + return TRUE; +} + +static BOOL FileUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh) +{ + WINPR_FILE* pFile = (WINPR_FILE*)hFile; + + if (!hFile) + return FALSE; + + if (!pFile->bLocked) + { + WLog_ERR(TAG, "File %d is not locked!", pFile->fd); + return FALSE; + } + + if (flock(pFile->fd, LOCK_UN) < 0) + { + WLog_ERR(TAG, "flock(LOCK_UN) %d failed with %s [%08X]", + pFile->fd, strerror(errno), errno); + return FALSE; + } + + return TRUE; +} + +static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped) +{ + WINPR_FILE* pFile = (WINPR_FILE*)hFile; + + if (!hFile) + return FALSE; + + if (!pFile->bLocked) + { + WLog_ERR(TAG, "File %d is not locked!", pFile->fd); + return FALSE; + } + + if (lpOverlapped) + { + WLog_ERR(TAG, "lpOverlapped not implemented!"); + return FALSE; + } + + if (flock(pFile->fd, LOCK_UN) < 0) + { + WLog_ERR(TAG, "flock(LOCK_UN) %d failed with %s [%08X]", + pFile->fd, strerror(errno), errno); + return FALSE; + } + + return TRUE; +} + +static HANDLE_OPS fileOps = { + FileIsHandled, + FileCloseHandle, + FileGetFd, + NULL, /* CleanupHandle */ + FileRead, + NULL, /* FileReadEx */ + NULL, /* FileReadScatter */ + FileWrite, + NULL, /* FileWriteEx */ + NULL, /* FileWriteGather */ + FileGetFileSize, + NULL, /* FlushFileBuffers */ + FileSetEndOfFile, + FileSetFilePointer, + NULL, /* SetFilePointerEx */ + NULL, /* FileLockFile */ + FileLockFileEx, + FileUnlockFile, + FileUnlockFileEx }; -static WINPR_FILE *FileHandle_New() +static HANDLE_OPS pipeOps = { + FileIsHandled, + FileCloseHandle, + FileGetFd, + NULL, /* CleanupHandle */ + FileRead, + NULL, /* FileReadEx */ + NULL, /* FileReadScatter */ + FileWrite, + NULL, /* FileWriteEx */ + NULL, /* FileWriteGather */ + NULL, /* FileGetFileSize */ + NULL, /* FlushFileBuffers */ + NULL, /* FileSetEndOfFile */ + NULL, /* FileSetFilePointer */ + NULL, /* SetFilePointerEx */ + NULL, /* FileLockFile */ + NULL, /* FileLockFileEx */ + NULL, /* FileUnlockFile */ + NULL /* FileUnlockFileEx */ + +}; + + +static const char* FileGetMode(DWORD dwDesiredAccess, DWORD dwCreationDisposition, BOOL* create) +{ + BOOL writeable = dwDesiredAccess & GENERIC_WRITE; + + switch(dwCreationDisposition) + { + case CREATE_ALWAYS: + *create = TRUE; + return (writeable) ? "wb+" : "rwb"; + case CREATE_NEW: + *create = TRUE; + return "wb+"; + case OPEN_ALWAYS: + *create = TRUE; + return "rb+"; + case OPEN_EXISTING: + *create = FALSE; + return "rb+"; + case TRUNCATE_EXISTING: + *create = FALSE; + return "wb+"; + default: + *create = FALSE; + return ""; + } +} + +static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) +{ + WINPR_FILE* pFile; + BOOL create; + const char* mode = FileGetMode(dwDesiredAccess, dwCreationDisposition, &create); + int lock; + + pFile = (WINPR_FILE*) calloc(1, sizeof(WINPR_FILE)); + if (!pFile) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return INVALID_HANDLE_VALUE; + } + + WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ); + pFile->ops = &fileOps; + + pFile->lpFileName = _strdup(lpFileName); + if (!pFile->lpFileName) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + free(pFile); + return INVALID_HANDLE_VALUE; + } + + pFile->dwOpenMode = dwDesiredAccess; + pFile->dwShareMode = dwShareMode; + pFile->dwFlagsAndAttributes = dwFlagsAndAttributes; + pFile->lpSecurityAttributes = lpSecurityAttributes; + pFile->dwCreationDisposition = dwCreationDisposition; + pFile->hTemplateFile = hTemplateFile; + + if (create) + { + FILE* fp = fopen(pFile->lpFileName, "ab"); + if (!fp) + { + free(pFile->lpFileName); + free(pFile); + return INVALID_HANDLE_VALUE; + } + fclose(fp); + } + + { + FILE* fp = fopen(pFile->lpFileName, mode); + pFile->fd = fileno(fp); + } + if (pFile->fd < 0) + { + WLog_ERR(TAG, "Failed to open file %s with mode %s", + pFile->lpFileName, mode); + + free(pFile->lpFileName); + free(pFile); + return INVALID_HANDLE_VALUE; + } + + if (dwShareMode & FILE_SHARE_READ) + lock = LOCK_SH; + if (dwShareMode & FILE_SHARE_WRITE) + lock = LOCK_EX; + + if (dwShareMode & (FILE_SHARE_READ | FILE_SHARE_WRITE)) + { + if (flock(pFile->fd, lock) < 0) + { + WLog_ERR(TAG, "flock failed with %s [%08X]", + strerror(errno), errno); + close(pFile->fd); + free(pFile->lpFileName); + free(pFile); + return INVALID_HANDLE_VALUE; + } + + pFile->bLocked = TRUE; + } + + return pFile; +} + +BOOL IsFileDevice(LPCTSTR lpDeviceName) +{ + return TRUE; +} + +HANDLE_CREATOR _FileHandleCreator = +{ + IsFileDevice, + FileCreateFileA +}; + +HANDLE_CREATOR *GetFileHandleCreator(void) +{ + return &_FileHandleCreator; +} + + +static WINPR_FILE *FileHandle_New(int fd) { WINPR_FILE *pFile; HANDLE hFile; + char name[MAX_PATH]; + _snprintf(name, sizeof(name), "pipe_device_%d", fd); pFile = (WINPR_FILE*) calloc(1, sizeof(WINPR_FILE)); if (!pFile) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } - pFile->fd = -1; - pFile->ops = &ops; + pFile->fd = fd; + pFile->ops = &pipeOps; + pFile->lpFileName = _strdup(name); hFile = (HANDLE) pFile; WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ); @@ -206,11 +588,10 @@ HANDLE GetStdHandle(DWORD nStdHandle) default: return INVALID_HANDLE_VALUE; } - pFile = FileHandle_New(); + pFile = FileHandle_New(fd); if (!pFile) return INVALID_HANDLE_VALUE; - pFile->fd = fd; return (HANDLE)pFile; } @@ -239,7 +620,7 @@ HANDLE GetFileHandleForFileDescriptor(int fd) if (fcntl(fd, F_GETFD) == -1 && errno == EBADF) return INVALID_HANDLE_VALUE; - pFile = FileHandle_New(); + pFile = FileHandle_New(fd); if (!pFile) return INVALID_HANDLE_VALUE; pFile->fd = fd; diff --git a/winpr/libwinpr/file/file.h b/winpr/libwinpr/file/file.h new file mode 100644 index 000000000..fc2879366 --- /dev/null +++ b/winpr/libwinpr/file/file.h @@ -0,0 +1,61 @@ +/** + * WinPR: Windows Portable Runtime + * File Functions + * + * Copyright 2015 Armin Novak + * Copyright 2015 Thincast Technologies GmbH + * + * 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. + */ + +#ifndef WINPR_FILE_PRIV_H +#define WINPR_FILE_PRIV_H + +#include +#include + +#include +#include +#include + +#ifndef _WIN32 + +#include +#include "../handle/handle.h" + +struct winpr_file +{ + WINPR_HANDLE_DEF(); + + int fd; + + char* lpFileName; + + DWORD dwOpenMode; + DWORD dwShareMode; + DWORD dwFlagsAndAttributes; + + LPSECURITY_ATTRIBUTES lpSecurityAttributes; + DWORD dwCreationDisposition; + HANDLE hTemplateFile; + + BOOL bLocked; +}; +typedef struct winpr_file WINPR_FILE; + +HANDLE_CREATOR *GetFileHandleCreator(void); + +#endif /* _WIN32 */ + +#endif /* WINPR_FILE_PRIV_H */ + diff --git a/winpr/libwinpr/file/generic.c b/winpr/libwinpr/file/generic.c index 6a8a265c6..8719787ad 100644 --- a/winpr/libwinpr/file/generic.c +++ b/winpr/libwinpr/file/generic.c @@ -65,6 +65,8 @@ #include "../pipe/pipe.h" +#include "file.h" + /** * api-ms-win-core-file-l1-2-0.dll: * @@ -195,6 +197,7 @@ static void _HandleCreatorsInit() #if defined __linux__ && !defined ANDROID ArrayList_Add(_HandleCreators, GetCommHandleCreator()); #endif /* __linux__ && !defined ANDROID */ + ArrayList_Add(_HandleCreators, GetFileHandleCreator()); } @@ -253,8 +256,9 @@ HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, if (creator && creator->IsHandled(lpFileName)) { - HANDLE newHandle = creator->CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, - dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + HANDLE newHandle = creator->CreateFileA(lpFileName, dwDesiredAccess, + dwShareMode, lpSecurityAttributes, dwCreationDisposition, + dwFlagsAndAttributes, hTemplateFile); ArrayList_Unlock(_HandleCreators); return newHandle; } @@ -267,7 +271,17 @@ HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { - return NULL; + LPSTR lpFileNameA = NULL; + HANDLE hdl; + + if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameA, 0, NULL, NULL)) + return NULL; + + hdl= CreateFileA(lpFileNameA, dwDesiredAccess, dwShareMode, lpSecurityAttributes, + dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + free (lpFileNameA); + + return hdl; } BOOL DeleteFileA(LPCSTR lpFileName) @@ -279,7 +293,15 @@ BOOL DeleteFileA(LPCSTR lpFileName) BOOL DeleteFileW(LPCWSTR lpFileName) { - return TRUE; + LPSTR lpFileNameA = NULL; + BOOL rc = FALSE; + + if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameA, 0, NULL, NULL)) + return FALSE; + rc = DeleteFileA(lpFileNameA); + free (lpFileNameA); + + return rc; } BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, @@ -304,22 +326,55 @@ BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, handle = (WINPR_HANDLE *)hFile; if (handle->ops->ReadFile) - return handle->ops->ReadFile(handle, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); + return handle->ops->ReadFile(handle, lpBuffer, nNumberOfBytesToRead, + lpNumberOfBytesRead, lpOverlapped); WLog_ERR(TAG, "ReadFile operation not implemented"); return FALSE; } BOOL ReadFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, - LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) + LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) { + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->ReadFileEx) + return handle->ops->ReadFileEx(handle, lpBuffer, nNumberOfBytesToRead, + lpOverlapped, lpCompletionRoutine); + + WLog_ERR(TAG, "ReadFileEx operation not implemented"); + return FALSE; + return TRUE; } BOOL ReadFileScatter(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[], - DWORD nNumberOfBytesToRead, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped) + DWORD nNumberOfBytesToRead, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped) { - return TRUE; + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->ReadFileScatter) + return handle->ops->ReadFileScatter(handle, aSegmentArray, nNumberOfBytesToRead, + lpReserved, lpOverlapped); + + WLog_ERR(TAG, "ReadFileScatter operation not implemented"); + return FALSE; } BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, @@ -336,68 +391,236 @@ BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, handle = (WINPR_HANDLE *)hFile; if (handle->ops->WriteFile) - return handle->ops->WriteFile(handle, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped); + return handle->ops->WriteFile(handle, lpBuffer, nNumberOfBytesToWrite, + lpNumberOfBytesWritten, lpOverlapped); - WLog_ERR(TAG, "ReadFile operation not implemented"); + WLog_ERR(TAG, "WriteFile operation not implemented"); return FALSE; } BOOL WriteFileEx(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, - LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) + LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) { - return TRUE; + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->WriteFileEx) + return handle->ops->WriteFileEx(handle, lpBuffer, nNumberOfBytesToWrite, + lpOverlapped, lpCompletionRoutine); + + WLog_ERR(TAG, "WriteFileEx operation not implemented"); + return FALSE; } BOOL WriteFileGather(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[], - DWORD nNumberOfBytesToWrite, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped) + DWORD nNumberOfBytesToWrite, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped) { - return TRUE; + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->WriteFileGather) + return handle->ops->WriteFileGather(handle, aSegmentArray, nNumberOfBytesToWrite, + lpReserved, lpOverlapped); + + WLog_ERR(TAG, "WriteFileGather operation not implemented"); + return FALSE; } BOOL FlushFileBuffers(HANDLE hFile) { - return TRUE; + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->FlushFileBuffers) + return handle->ops->FlushFileBuffers(handle); + + WLog_ERR(TAG, "FlushFileBuffers operation not implemented"); + return FALSE; } BOOL SetEndOfFile(HANDLE hFile) { - return TRUE; + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->SetEndOfFile) + return handle->ops->SetEndOfFile(handle); + + WLog_ERR(TAG, "SetEndOfFile operation not implemented"); + return FALSE; +} + +DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) +{ + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->GetFileSize) + return handle->ops->GetFileSize(handle, lpFileSizeHigh); + + WLog_ERR(TAG, "GetFileSize operation not implemented"); + return 0; } DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) { - return TRUE; + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->SetFilePointer) + return handle->ops->SetFilePointer(handle, lDistanceToMove, + lpDistanceToMoveHigh, dwMoveMethod); + + WLog_ERR(TAG, "SetFilePointer operation not implemented"); + return 0; } BOOL SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, - PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod) + PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod) { - return TRUE; + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->SetFilePointerEx) + return handle->ops->SetFilePointerEx(handle, liDistanceToMove, + lpNewFilePointer, dwMoveMethod); + + WLog_ERR(TAG, "SetFilePointerEx operation not implemented"); + return 0; } BOOL LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh) { - return TRUE; + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->LockFile) + return handle->ops->LockFile(handle, dwFileOffsetLow, dwFileOffsetHigh, + nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh); + + WLog_ERR(TAG, "LockFile operation not implemented"); + return FALSE; } BOOL LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, - DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped) + DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped) { - return TRUE; + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->LockFileEx) + return handle->ops->LockFileEx(handle, dwFlags, dwReserved, + nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh, lpOverlapped); + + WLog_ERR(TAG, "LockFileEx operation not implemented"); + return FALSE; } BOOL UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh) { - return TRUE; + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->UnlockFile) + return handle->ops->UnlockFile(handle, dwFileOffsetLow, dwFileOffsetHigh, + nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh); + + WLog_ERR(TAG, "UnLockFile operation not implemented"); + return FALSE; } BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped) { - return TRUE; + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->UnlockFileEx) + return handle->ops->UnlockFileEx(handle, dwReserved, + nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh, lpOverlapped); + + WLog_ERR(TAG, "UnLockFileEx operation not implemented"); + return FALSE; } struct _WIN32_FILE_SEARCH diff --git a/winpr/libwinpr/file/namedPipeClient.c b/winpr/libwinpr/file/namedPipeClient.c index d2aed74fd..b78f8eb7c 100644 --- a/winpr/libwinpr/file/namedPipeClient.c +++ b/winpr/libwinpr/file/namedPipeClient.c @@ -111,7 +111,20 @@ static HANDLE_OPS ops = { NamedPipeClientGetFd, NULL, /* CleanupHandle */ NamedPipeRead, - NamedPipeWrite + NULL, /* FileReadEx */ + NULL, /* FileReadScatter */ + NamedPipeWrite, + NULL, /* FileWriteEx */ + NULL, /* FileWriteGather */ + NULL, /* FileGetFileSize */ + NULL, /* FlushFileBuffers */ + NULL, /* FileSetEndOfFile */ + NULL, /* FileSetFilePointer */ + NULL, /* SetFilePointerEx */ + NULL, /* FileLockFile */ + NULL, /* FileLockFileEx */ + NULL, /* FileUnlockFile */ + NULL /* FileUnlockFileEx */ }; static HANDLE NamedPipeClientCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, diff --git a/winpr/libwinpr/file/test/TestFileCreateFile.c b/winpr/libwinpr/file/test/TestFileCreateFile.c index 39b6a26c7..96281060d 100644 --- a/winpr/libwinpr/file/test/TestFileCreateFile.c +++ b/winpr/libwinpr/file/test/TestFileCreateFile.c @@ -2,9 +2,70 @@ #include #include #include +#include #include int TestFileCreateFile(int argc, char* argv[]) { - return 0; + HANDLE handle; + HRESULT hr; + DWORD written; + const char buffer[] = "Some random text\r\njust want it done."; + char cmp[sizeof(buffer)]; + LPSTR name = GetKnownSubPath(KNOWN_PATH_TEMP, "CreateFile.testfile"); + + int rc = 0; + + 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 (!PathFileExistsA(name)) + rc = -1; + + if (!WriteFile(handle, buffer, sizeof(buffer), &written, NULL)) + rc = -1; + + if (written != sizeof(buffer)) + rc = -1; + + written = SetFilePointer(handle, 0, NULL, FILE_BEGIN); + + 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 (!DeleteFileA(name)) + rc = -1; + + if (PathFileExistsA(name)) + rc = -1; + + free(name); + + return rc; } diff --git a/winpr/libwinpr/handle/handle.h b/winpr/libwinpr/handle/handle.h index 7dd620062..d2669baa7 100644 --- a/winpr/libwinpr/handle/handle.h +++ b/winpr/libwinpr/handle/handle.h @@ -50,9 +50,33 @@ typedef BOOL (*pcCloseHandle)(HANDLE handle); typedef int (*pcGetFd)(HANDLE handle); typedef DWORD (*pcCleanupHandle)(HANDLE handle); typedef BOOL (*pcReadFile)(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, - LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); + LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); +typedef BOOL (*pcReadFileEx)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, + LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); +typedef BOOL (*pcReadFileScatter)(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[], + DWORD nNumberOfBytesToRead, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped); typedef BOOL (*pcWriteFile)(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, - LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped); + LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped); +typedef BOOL (*pcWriteFileEx)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, + LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); +typedef BOOL (*pcWriteFileGather)(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[], + DWORD nNumberOfBytesToWrite, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped); +typedef DWORD (*pcGetFileSize)(HANDLE handle, LPDWORD lpFileSizeHigh); +typedef BOOL (*pcFlushFileBuffers)(HANDLE hFile); +typedef BOOL (*pcSetEndOfFile)(HANDLE handle); +typedef DWORD(*pcSetFilePointer)(HANDLE handle, LONG lDistanceToMove, + PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod); +typedef BOOL (*pcSetFilePointerEx)(HANDLE hFile, LARGE_INTEGER liDistanceToMove, + PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod); +typedef BOOL (*pcLockFile)(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh); +typedef BOOL (*pcLockFileEx)(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, + DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, + LPOVERLAPPED lpOverlapped); +typedef BOOL (*pcUnlockFile)(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh); +typedef BOOL (*pcUnlockFileEx)(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped); typedef struct _HANDLE_OPS { @@ -61,7 +85,20 @@ typedef struct _HANDLE_OPS pcGetFd GetFd; pcCleanupHandle CleanupHandle; pcReadFile ReadFile; + pcReadFileEx ReadFileEx; + pcReadFileScatter ReadFileScatter; pcWriteFile WriteFile; + pcWriteFileEx WriteFileEx; + pcWriteFileGather WriteFileGather; + pcGetFileSize GetFileSize; + pcFlushFileBuffers FlushFileBuffers; + pcSetEndOfFile SetEndOfFile; + pcSetFilePointer SetFilePointer; + pcSetFilePointerEx SetFilePointerEx; + pcLockFile LockFile; + pcLockFileEx LockFileEx; + pcUnlockFile UnlockFile; + pcUnlockFileEx UnlockFileEx; } HANDLE_OPS; struct winpr_handle diff --git a/winpr/libwinpr/pipe/pipe.c b/winpr/libwinpr/pipe/pipe.c index 28d9eede3..02beb5d5b 100644 --- a/winpr/libwinpr/pipe/pipe.c +++ b/winpr/libwinpr/pipe/pipe.c @@ -178,7 +178,20 @@ static HANDLE_OPS ops = { PipeGetFd, NULL, /* CleanupHandle */ PipeRead, - PipeWrite + NULL, /* FileReadEx */ + NULL, /* FileReadScatter */ + PipeWrite, + NULL, /* FileWriteEx */ + NULL, /* FileWriteGather */ + NULL, /* FileGetFileSize */ + NULL, /* FlushFileBuffers */ + NULL, /* FileSetEndOfFile */ + NULL, /* FileSetFilePointer */ + NULL, /* SetFilePointerEx */ + NULL, /* FileLockFile */ + NULL, /* FileLockFileEx */ + NULL, /* FileUnlockFile */ + NULL /* FileUnlockFileEx */ }; @@ -409,6 +422,8 @@ static HANDLE_OPS namedOps = { NamedPipeGetFd, NULL, /* CleanupHandle */ NamedPipeRead, + NULL, + NULL, NamedPipeWrite }; From df528cefc57a5355fd071c1e03a555fd719bca19 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 9 Dec 2015 18:29:41 +0100 Subject: [PATCH 04/12] Using locking winpr file functions for known hosts. --- libfreerdp/crypto/certificate.c | 241 +++++++++++++++++--------------- 1 file changed, 131 insertions(+), 110 deletions(-) diff --git a/libfreerdp/crypto/certificate.c b/libfreerdp/crypto/certificate.c index e8d292377..7665677e5 100644 --- a/libfreerdp/crypto/certificate.c +++ b/libfreerdp/crypto/certificate.c @@ -116,63 +116,55 @@ fail: static int certificate_data_match_legacy(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data) { - FILE* fp; + HANDLE fp; int match = 1; char* data; char* mdata; char* pline; char* hostname; - long size; + DWORD lowSize, highSize; + UINT64 size; size_t length; + DWORD read; - fp = fopen(certificate_store->legacy_file, "rb"); - if (!fp) + /* Assure POSIX style paths, CreateFile expects either '/' or '\\' */ + PathCchConvertStyleA(certificate_store->legacy_file, strlen(certificate_store->legacy_file), PATH_STYLE_UNIX); + fp = CreateFileA(certificate_store->legacy_file, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (fp == INVALID_HANDLE_VALUE) return match; - if (fseek(fp, 0, SEEK_END) < 0) + if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE) { - WLog_ERR(TAG, "fseek(%s) returned %s [%08X]", - certificate_store->legacy_file, strerror(errno), errno); - fclose(fp); - return match; - } - if ((size = ftell(fp)) < 0) - { - WLog_ERR(TAG, "ftell(%s) returned %s [%08X]", - certificate_store->legacy_file, strerror(errno), errno); - fclose(fp); - return match; - } - if (fseek(fp, 0, SEEK_SET) < 0) - { - WLog_ERR(TAG, "fseek(%s) returned %s [%08X]", - certificate_store->legacy_file, strerror(errno), errno); - fclose(fp); + WLog_ERR(TAG, "GetFileSize(%s) returned %s [%08X]", + certificate_store->legacy_file, strerror(errno), GetLastError()); + CloseHandle(fp); return match; } + size = (UINT64)lowSize | ((UINT64)highSize << 32); if (size < 1) { - fclose(fp); + CloseHandle(fp); return match; } mdata = (char*) malloc(size + 2); if (!mdata) { - fclose(fp); + CloseHandle(fp); return match; } data = mdata; - if (fread(data, size, 1, fp) != 1) + if (!ReadFile(fp, data, size, &read, NULL) || (read != size)) { free(data); - fclose(fp); + CloseHandle(fp); return match; } - fclose(fp); + CloseHandle(fp); data[size] = '\n'; data[size + 1] = '\0'; @@ -243,67 +235,59 @@ static int certificate_data_match_raw(rdpCertificateStore* certificate_store, char** fprint) { BOOL found = FALSE; - FILE* fp; + HANDLE fp; size_t length; char* data; char* mdata; char* pline; int match = 1; - long int size; + DWORD lowSize, highSize; + UINT64 size; char* hostname = NULL; char* subject = NULL; char* issuer = NULL; char* fingerprint = NULL; unsigned short port = 0; + DWORD read; - fp = fopen(certificate_store->file, "rb"); + /* Assure POSIX style paths, CreateFile expects either '/' or '\\' */ + PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX); + fp = CreateFileA(certificate_store->file, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL, NULL); - if (!fp) + if (fp == INVALID_HANDLE_VALUE) return match; - if (fseek(fp, 0, SEEK_END) < 0) + if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE) { - WLog_ERR(TAG, "fseek(%s) returned %s [%08X]", - certificate_store->file, strerror(errno), errno); - fclose(fp); - return match; - } - if ((size = ftell(fp)) < 0) - { - WLog_ERR(TAG, "ftell(%s) returned %s [%08X]", - certificate_store->file, strerror(errno), errno); - fclose(fp); - return match; - } - if (fseek(fp, 0, SEEK_SET) < 0) - { - WLog_ERR(TAG, "fseek(%s) returned %s [%08X]", - certificate_store->file, strerror(errno), errno); - fclose(fp); + WLog_ERR(TAG, "GetFileSize(%s) returned %s [%08X]", + certificate_store->legacy_file, strerror(errno), GetLastError()); + CloseHandle(fp); return match; } + size = (UINT64)lowSize | ((UINT64)highSize << 32); if (size < 1) { - fclose(fp); + CloseHandle(fp); return match; } mdata = (char*) malloc(size + 2); if (!mdata) { - fclose(fp); + CloseHandle(fp); return match; } data = mdata; - if (fread(data, size, 1, fp) != 1) + if (!ReadFile(fp, data, size, &read, NULL) || (read != size)) { - fclose(fp); free(data); + CloseHandle(fp); return match; } - fclose(fp); + CloseHandle(fp); data[size] = '\n'; data[size + 1] = '\0'; @@ -371,40 +355,36 @@ int certificate_data_match(rdpCertificateStore* certificate_store, BOOL certificate_data_replace(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data) { - FILE* fp; + HANDLE fp; BOOL rc = FALSE; size_t length; char* data; char* sdata; char* pline; - long int size; + UINT64 size; + DWORD read, written; + DWORD lowSize, highSize; - fp = fopen(certificate_store->file, "rb"); + /* Assure POSIX style paths, CreateFile expects either '/' or '\\' */ + PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX); + fp = CreateFileA(certificate_store->file, GENERIC_READ | GENERIC_WRITE, 0, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (!fp) + if (fp == INVALID_HANDLE_VALUE) return FALSE; - /* Read the current contents of the file. */ - if (fseek(fp, 0, SEEK_END) < 0) + + if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE) { - WLog_ERR(TAG, "fseek(%s) returned %s [%08X]", - certificate_store->file, strerror(errno), errno); - fclose(fp); + WLog_ERR(TAG, "GetFileSize(%s) returned %s [%08X]", + certificate_store->legacy_file, strerror(errno), GetLastError()); + CloseHandle(fp); return FALSE; } + size = (UINT64)lowSize | ((UINT64)highSize << 32); - if ((size = ftell(fp)) < 0) + if (size < 1) { - WLog_ERR(TAG, "ftell(%s) returned %s [%08X]", - certificate_store->file, strerror(errno), errno); - fclose(fp); - return FALSE; - } - - if (fseek(fp, 0, SEEK_SET) < 0) - { - WLog_ERR(TAG, "fseek(%s) returned %s [%08X]", - certificate_store->file, strerror(errno), errno); - fclose(fp); + CloseHandle(fp); return FALSE; } @@ -415,22 +395,26 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store, return FALSE; } - if (fread(data, size, 1, fp) != 1) + if (!ReadFile(fp, data, size, &read, NULL) || (read != size)) { - fclose(fp); free(data); + CloseHandle(fp); return FALSE; } - fclose(fp); - - fp = fopen(certificate_store->file, "wb"); - - if (fp == NULL) + if (SetFilePointer(fp, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { - WLog_ERR(TAG, "freopen(%s) returned %s [%08X]", - certificate_store->file, strerror(errno), errno); - free(data); + WLog_ERR(TAG, "SetFilePointer(%s) returned %s [%08X]", + certificate_store->file, strerror(errno), GetLastError()); + CloseHandle(fp); + return FALSE; + } + + if (!SetEndOfFile(fp)) + { + WLog_ERR(TAG, "SetEndOfFile(%s) returned %s [%08X]", + certificate_store->file, strerror(errno), GetLastError()); + CloseHandle(fp); return FALSE; } @@ -451,6 +435,7 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store, char* fingerprint = NULL; char* subject = NULL; char* issuer = NULL; + char* tdata; if (!certificate_split_line(pline, &hostname, &port, &subject, &issuer, &fingerprint)) WLog_WARN(TAG, "Skipping invalid %s entry %s!", @@ -464,26 +449,41 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store, fingerprint = certificate_data->fingerprint; rc = TRUE; } - if (fprintf(fp, "%s %hu %s %s %s\n", hostname, port, fingerprint, subject, issuer) < 0) + + size = _snprintf(NULL, 0, "%s %hu %s %s %s\n", hostname, port, fingerprint, subject, issuer); + tdata = malloc(size + 1); + if (!tdata) { - WLog_ERR(TAG, "fprintf(%s) returned %s [%08X]", + WLog_ERR(TAG, "malloc(%s) returned %s [%08X]", certificate_store->file, strerror(errno), errno); - fclose(fp); + CloseHandle(fp); return FALSE; } + + if (_snprintf(tdata, size + 1, "%s %hu %s %s %s\n", hostname, port, fingerprint, subject, issuer) != size) + { + WLog_ERR(TAG, "_snprintf(%s) returned %s [%08X]", + certificate_store->file, strerror(errno), errno); + free(tdata); + CloseHandle(fp); + return FALSE; + } + if (!WriteFile(fp, tdata, size, &written, NULL) || (written != size)) + { + WLog_ERR(TAG, "WriteFile(%s) returned %s [%08X]", + certificate_store->file, strerror(errno), errno); + free(tdata); + CloseHandle(fp); + return FALSE; + } + free(tdata); } } pline = StrSep(&sdata, "\r\n"); } - if (fflush(fp) != 0) - { - WLog_WARN(TAG, "fflush(%s) returned %s [%08X]", - certificate_store->file, strerror(errno), errno); - } - - fclose(fp); + CloseHandle(fp); free(data); return rc; @@ -533,39 +533,60 @@ BOOL certificate_split_line(char* line, char** host, UINT16* port, char** subjec BOOL certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data) { - FILE* fp; + HANDLE fp; + char* tdata; + UINT64 size; + DWORD written; /* reopen in append mode */ - fp = fopen(certificate_store->file, "ab"); + /* Assure POSIX style paths, CreateFile expects either '/' or '\\' */ + PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX); + fp = CreateFileA(certificate_store->file, GENERIC_WRITE, 0, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (!fp) + if (fp == INVALID_HANDLE_VALUE) return FALSE; - if (fseek(fp, 0, SEEK_END) < 0) + if (SetFilePointer(fp, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) { - WLog_ERR(TAG, "fseek(%s) returned %s [%08X]", - certificate_store->file, strerror(errno), errno); - fclose(fp); + WLog_ERR(TAG, "SetFilePointer(%s) returned %s [%08X]", + certificate_store->file, strerror(errno), GetLastError()); + CloseHandle(fp); return FALSE; } - if (fprintf(fp, "%s %hu %s %s %s\n", certificate_data->hostname, certificate_data->port, + size = _snprintf(NULL, 0, "%s %hu %s %s %s\n", certificate_data->hostname, certificate_data->port, certificate_data->fingerprint, certificate_data->subject, - certificate_data->issuer) < 0) + certificate_data->issuer); + tdata = malloc(size + 1); + if (!tdata) { - WLog_ERR(TAG, "fprintf(%s) returned %s [%08X]", + WLog_ERR(TAG, "malloc(%s) returned %s [%08X]", certificate_store->file, strerror(errno), errno); - fclose(fp); + CloseHandle(fp); return FALSE; } - - if (fflush(fp) != 0) + if (_snprintf(tdata, size + 1, "%s %hu %s %s %s\n", certificate_data->hostname, certificate_data->port, + certificate_data->fingerprint, certificate_data->subject, + certificate_data->issuer) != size) { - WLog_WARN(TAG, "fflush(%s) returned %s [%08X]", + WLog_ERR(TAG, "_snprintf(%s) returned %s [%08X]", certificate_store->file, strerror(errno), errno); + free(tdata); + CloseHandle(fp); + return FALSE; } + if (!WriteFile(fp, tdata, size, &written, NULL) || (written != size)) + { + WLog_ERR(TAG, "WriteFile(%s) returned %s [%08X]", + certificate_store->file, strerror(errno), errno); + free(tdata); + CloseHandle(fp); + return FALSE; + } + free(tdata); - fclose(fp); + CloseHandle(fp); return TRUE; } From 400d1b8b9666a138142399966f7d7db57683a904 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 10 Dec 2015 10:37:44 +0100 Subject: [PATCH 05/12] Fixed open mode for fdopen. --- winpr/libwinpr/file/file.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index a0f197670..ac618a024 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -118,7 +118,7 @@ static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove, if (!hFile) return INVALID_SET_FILE_POINTER; - fp = fdopen(pFile->fd, "w"); + fp = fdopen(pFile->fd, "wb"); if (!fp) { @@ -233,7 +233,7 @@ static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh) return 0; file = (WINPR_FILE *)Object; - fp = fdopen(file->fd, "r"); + fp = fdopen(file->fd, "wb"); if (!fp) { @@ -496,7 +496,9 @@ static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw { FILE* fp = fopen(pFile->lpFileName, mode); - pFile->fd = fileno(fp); + pFile->fd = -1; + if (fp) + pFile->fd = fileno(fp); } if (pFile->fd < 0) { From fe51dd1e108f8ae2eced90f4d269d52c03ea24fb Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 10 Dec 2015 10:39:37 +0100 Subject: [PATCH 06/12] Fixed logging, added file name. --- winpr/libwinpr/file/file.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index ac618a024..6cd848280 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -122,7 +122,7 @@ static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove, if (!fp) { - WLog_ERR(TAG, "fdopen(%d) failed with %s [%08X]", pFile->fd, + WLog_ERR(TAG, "fdopen(%s) failed with %s [%08X]", pFile->lpFileName, strerror(errno), errno); return INVALID_SET_FILE_POINTER; } @@ -144,7 +144,7 @@ static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove, if (fseek(fp, offset, whence)) { - WLog_ERR(TAG, "fseek(%d) failed with %s [%08X]", pFile->fd, + WLog_ERR(TAG, "fseek(%s) failed with %s [%08X]", pFile->lpFileName, strerror(errno), errno); return INVALID_SET_FILE_POINTER; } @@ -237,7 +237,7 @@ static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh) if (!fp) { - WLog_ERR(TAG, "fdopen(%d) failed with %s [%08X]", file->fd, + WLog_ERR(TAG, "fopen(%s) failed with %s [%08X]", file->lpFileName, strerror(errno), errno); return INVALID_FILE_SIZE; } @@ -246,14 +246,14 @@ static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh) if (cur < 0) { - WLog_ERR(TAG, "ftell(%d) failed with %s [%08X]", file->fd, + WLog_ERR(TAG, "ftell(%s) failed with %s [%08X]", file->lpFileName, strerror(errno), errno); return INVALID_FILE_SIZE; } if (fseek(fp, 0, SEEK_END) != 0) { - WLog_ERR(TAG, "fseek(%d) failed with %s [%08X]", file->fd, + WLog_ERR(TAG, "fseek(%s) failed with %s [%08X]", file->lpFileName, strerror(errno), errno); return INVALID_FILE_SIZE; } @@ -262,14 +262,14 @@ static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh) if (size < 0) { - WLog_ERR(TAG, "ftell(%d) failed with %s [%08X]", file->fd, + WLog_ERR(TAG, "ftell(%s) failed with %s [%08X]", file->lpFileName, strerror(errno), errno); return INVALID_FILE_SIZE; } if (fseek(fp, cur, SEEK_SET) != 0) { - WLog_ERR(TAG, "ftell(%d) failed with %s [%08X]", file->fd, + WLog_ERR(TAG, "ftell(%s) failed with %s [%08X]", file->lpFileName, strerror(errno), errno); return INVALID_FILE_SIZE; } @@ -292,7 +292,7 @@ static BOOL FileLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, if (pFile->bLocked) { - WLog_ERR(TAG, "File %d already locked!", pFile->fd); + WLog_ERR(TAG, "File %s already locked!", pFile->lpFileName); return FALSE; } @@ -332,14 +332,14 @@ static BOOL FileUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffs if (!pFile->bLocked) { - WLog_ERR(TAG, "File %d is not locked!", pFile->fd); + WLog_ERR(TAG, "File %s is not locked!", pFile->lpFileName); return FALSE; } if (flock(pFile->fd, LOCK_UN) < 0) { - WLog_ERR(TAG, "flock(LOCK_UN) %d failed with %s [%08X]", - pFile->fd, strerror(errno), errno); + WLog_ERR(TAG, "flock(LOCK_UN) %s failed with %s [%08X]", + pFile->lpFileName, strerror(errno), errno); return FALSE; } @@ -356,7 +356,7 @@ static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfByte if (!pFile->bLocked) { - WLog_ERR(TAG, "File %d is not locked!", pFile->fd); + WLog_ERR(TAG, "File %s is not locked!", pFile->lpFileName); return FALSE; } @@ -368,8 +368,8 @@ static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfByte if (flock(pFile->fd, LOCK_UN) < 0) { - WLog_ERR(TAG, "flock(LOCK_UN) %d failed with %s [%08X]", - pFile->fd, strerror(errno), errno); + WLog_ERR(TAG, "flock(LOCK_UN) %s failed with %s [%08X]", + pFile->lpFileName, strerror(errno), errno); return FALSE; } @@ -398,7 +398,7 @@ static HANDLE_OPS fileOps = { FileUnlockFileEx }; -static HANDLE_OPS pipeOps = { +static HANDLE_OPS shmOps = { FileIsHandled, FileCloseHandle, FileGetFd, @@ -556,7 +556,7 @@ static WINPR_FILE *FileHandle_New(int fd) HANDLE hFile; char name[MAX_PATH]; - _snprintf(name, sizeof(name), "pipe_device_%d", fd); + _snprintf(name, sizeof(name), "device_%d", fd); pFile = (WINPR_FILE*) calloc(1, sizeof(WINPR_FILE)); if (!pFile) { @@ -564,7 +564,7 @@ static WINPR_FILE *FileHandle_New(int fd) return NULL; } pFile->fd = fd; - pFile->ops = &pipeOps; + pFile->ops = &shmOps; pFile->lpFileName = _strdup(name); hFile = (HANDLE) pFile; From f0e3a2d8454a179222a073132cb49fb8492fc5c1 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 10 Dec 2015 10:40:14 +0100 Subject: [PATCH 07/12] Added extended file seek tests. --- winpr/libwinpr/file/test/TestFileCreateFile.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/winpr/libwinpr/file/test/TestFileCreateFile.c b/winpr/libwinpr/file/test/TestFileCreateFile.c index 96281060d..547d322af 100644 --- a/winpr/libwinpr/file/test/TestFileCreateFile.c +++ b/winpr/libwinpr/file/test/TestFileCreateFile.c @@ -3,6 +3,7 @@ #include #include #include +#include #include int TestFileCreateFile(int argc, char* argv[]) @@ -42,7 +43,17 @@ int TestFileCreateFile(int argc, char* argv[]) if (written != sizeof(buffer)) rc = -1; - written = SetFilePointer(handle, 0, NULL, FILE_BEGIN); + 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; From 65062633c2156642cf093bb7f4dfc50c8687a478 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 10 Dec 2015 13:57:05 +0100 Subject: [PATCH 08/12] Fixed memory leak. --- libfreerdp/crypto/certificate.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libfreerdp/crypto/certificate.c b/libfreerdp/crypto/certificate.c index 7665677e5..4e2618dfa 100644 --- a/libfreerdp/crypto/certificate.c +++ b/libfreerdp/crypto/certificate.c @@ -406,6 +406,7 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store, { WLog_ERR(TAG, "SetFilePointer(%s) returned %s [%08X]", certificate_store->file, strerror(errno), GetLastError()); + free(data); CloseHandle(fp); return FALSE; } @@ -414,6 +415,7 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store, { WLog_ERR(TAG, "SetEndOfFile(%s) returned %s [%08X]", certificate_store->file, strerror(errno), GetLastError()); + free(data); CloseHandle(fp); return FALSE; } @@ -456,6 +458,7 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store, { WLog_ERR(TAG, "malloc(%s) returned %s [%08X]", certificate_store->file, strerror(errno), errno); + free(data); CloseHandle(fp); return FALSE; } @@ -465,6 +468,7 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store, WLog_ERR(TAG, "_snprintf(%s) returned %s [%08X]", certificate_store->file, strerror(errno), errno); free(tdata); + free(data); CloseHandle(fp); return FALSE; } @@ -473,6 +477,7 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store, WLog_ERR(TAG, "WriteFile(%s) returned %s [%08X]", certificate_store->file, strerror(errno), errno); free(tdata); + free(data); CloseHandle(fp); return FALSE; } From 60109329847c0455a64f19443bff92f281092889 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 14 Dec 2015 09:23:42 +0100 Subject: [PATCH 09/12] Fixed possible race on file creation. --- winpr/libwinpr/file/file.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index 6cd848280..b0eb565b8 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -456,6 +456,7 @@ static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw BOOL create; const char* mode = FileGetMode(dwDesiredAccess, dwCreationDisposition, &create); int lock; + FILE* fp = NULL; pFile = (WINPR_FILE*) calloc(1, sizeof(WINPR_FILE)); if (!pFile) @@ -484,22 +485,24 @@ static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw if (create) { - FILE* fp = fopen(pFile->lpFileName, "ab"); + fp = fopen(pFile->lpFileName, "ab"); if (!fp) { free(pFile->lpFileName); free(pFile); return INVALID_HANDLE_VALUE; } - fclose(fp); + + fp = freopen(pFile->lpFileName, mode, fp); } - { - FILE* fp = fopen(pFile->lpFileName, mode); - pFile->fd = -1; - if (fp) - pFile->fd = fileno(fp); - } + if (NULL == fp) + fp = fopen(pFile->lpFileName, mode); + + pFile->fd = -1; + if (fp) + pFile->fd = fileno(fp); + if (pFile->fd < 0) { WLog_ERR(TAG, "Failed to open file %s with mode %s", From 03a1ff814d8983b3a6076cc41cdb654585153066 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 16 Dec 2015 15:15:46 +0100 Subject: [PATCH 10/12] Fixed unused warnings. --- winpr/libwinpr/utils/debug.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/winpr/libwinpr/utils/debug.c b/winpr/libwinpr/utils/debug.c index 0b3150e05..a911f424c 100644 --- a/winpr/libwinpr/utils/debug.c +++ b/winpr/libwinpr/utils/debug.c @@ -472,10 +472,10 @@ void winpr_log_backtrace(const char* tag, DWORD level, DWORD size) } char* winpr_strerror(DWORD dw, char* dmsg, size_t size) { +#if defined(_WIN32) LPTSTR msg = NULL; DWORD rc; -#if defined(_WIN32) rc = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, @@ -483,17 +483,17 @@ char* winpr_strerror(DWORD dw, char* dmsg, size_t size) { if (rc) { #if defined(UNICODE) WideCharToMultiByte(CP_ACP, 0, msg, rc, dmsg, size - 1, NULL, NULL); -#else +#else /* defined(UNICODE) */ memcpy(dmsg, msg, min(rc, size - 1)); -#endif +#endif /* defined(UNICODE) */ dmsg[min(rc, size - 1)] = 0; LocalFree(msg); } else { _snprintf(dmsg, size, "FAILURE: %08X", GetLastError()); } -#else +#else /* defined(_WIN32) */ _snprintf(dmsg, size, "%s", strerror(dw)); -#endif +#endif /* defined(_WIN32) */ return dmsg; } From 5b2f4f50a0d0e0b64a54df49aa32007d967f18ca Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 16 Dec 2015 17:35:59 +0100 Subject: [PATCH 11/12] Fixed FILE* leak and EndOfFile settings. --- winpr/libwinpr/file/file.c | 111 ++++++++++++++++++------------------- winpr/libwinpr/file/file.h | 2 +- 2 files changed, 54 insertions(+), 59 deletions(-) diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index b0eb565b8..e58b2249b 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -57,7 +57,7 @@ static int FileGetFd(HANDLE handle) if (!FileIsHandled(handle)) return -1; - return file->fd; + return fileno(file->fp); } static BOOL FileCloseHandle(HANDLE handle) { @@ -66,14 +66,13 @@ static BOOL FileCloseHandle(HANDLE handle) { if (!FileIsHandled(handle)) return FALSE; - if (file->fd != -1) + if (file->fp) { - /* Don't close stdin/stdout/stderr */ - if (file->fd > 2) + if (fileno(file->fp) > 2) { - close(file->fd); - file->fd = -1; + fclose(file->fp); + file->fp = NULL; } } @@ -85,21 +84,16 @@ static BOOL FileCloseHandle(HANDLE handle) { static BOOL FileSetEndOfFile(HANDLE hFile) { WINPR_FILE* pFile = (WINPR_FILE*) hFile; - DWORD lowSize, highSize; off_t size; if (!hFile) return FALSE; - lowSize = GetFileSize(hFile, &highSize); - if (lowSize == INVALID_FILE_SIZE) - return FALSE; - - size = lowSize | ((off_t)highSize << 32); - if (ftruncate(pFile->fd, size) < 0) + size = ftell(pFile->fp); + if (ftruncate(fileno(pFile->fp), size) < 0) { - WLog_ERR(TAG, "ftruncate %d failed with %s [%08X]", - pFile->fd, strerror(errno), errno); + WLog_ERR(TAG, "ftruncate %s failed with %s [%08X]", + pFile->lpFileName, strerror(errno), errno); return FALSE; } @@ -118,12 +112,11 @@ static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove, if (!hFile) return INVALID_SET_FILE_POINTER; - fp = fdopen(pFile->fd, "wb"); + fp = pFile->fp; if (!fp) { - WLog_ERR(TAG, "fdopen(%s) failed with %s [%08X]", pFile->lpFileName, - strerror(errno), errno); + WLog_ERR(TAG, "No file pointer for(%s)", pFile->lpFileName); return INVALID_SET_FILE_POINTER; } @@ -155,7 +148,7 @@ static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove, static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) { - int io_status; + size_t io_status; WINPR_FILE* file; BOOL status = TRUE; @@ -169,13 +162,9 @@ static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, } file = (WINPR_FILE *)Object; - do - { - io_status = read(file->fd, lpBuffer, nNumberOfBytesToRead); - } - while ((io_status < 0) && (errno == EINTR)); + io_status = fread(lpBuffer, nNumberOfBytesToRead, 1, file->fp); - if (io_status < 0) + if (io_status != 1) { status = FALSE; @@ -188,7 +177,7 @@ static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, } if (lpNumberOfBytesRead) - *lpNumberOfBytesRead = io_status; + *lpNumberOfBytesRead = nNumberOfBytesToRead; return status; } @@ -196,7 +185,7 @@ static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) { - int io_status; + size_t io_status; WINPR_FILE* file; if (!Object) @@ -210,16 +199,14 @@ static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrit file = (WINPR_FILE *)Object; - do - { - io_status = write(file->fd, lpBuffer, nNumberOfBytesToWrite); - } - while ((io_status < 0) && (errno == EINTR)); + io_status = fwrite(lpBuffer, nNumberOfBytesToWrite, 1, file->fp); + if (io_status != 1) + return FALSE; if ((io_status < 0) && (errno == EWOULDBLOCK)) io_status = 0; - *lpNumberOfBytesWritten = io_status; + *lpNumberOfBytesWritten = nNumberOfBytesToWrite; return TRUE; } @@ -233,7 +220,7 @@ static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh) return 0; file = (WINPR_FILE *)Object; - fp = fdopen(file->fd, "wb"); + fp = file->fp; if (!fp) { @@ -310,7 +297,7 @@ static BOOL FileLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, if (dwFlags & LOCKFILE_FAIL_IMMEDIATELY) lock |= LOCK_NB; - if (flock(pFile->fd, lock) < 0) + if (flock(fileno(pFile->fp), lock) < 0) { WLog_ERR(TAG, "flock failed with %s [%08X]", strerror(errno), errno); @@ -336,7 +323,7 @@ static BOOL FileUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffs return FALSE; } - if (flock(pFile->fd, LOCK_UN) < 0) + if (flock(fileno(pFile->fp), LOCK_UN) < 0) { WLog_ERR(TAG, "flock(LOCK_UN) %s failed with %s [%08X]", pFile->lpFileName, strerror(errno), errno); @@ -366,7 +353,7 @@ static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfByte return FALSE; } - if (flock(pFile->fd, LOCK_UN) < 0) + if (flock(fileno(pFile->fp), LOCK_UN) < 0) { WLog_ERR(TAG, "flock(LOCK_UN) %s failed with %s [%08X]", pFile->lpFileName, strerror(errno), errno); @@ -499,14 +486,11 @@ static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw if (NULL == fp) fp = fopen(pFile->lpFileName, mode); - pFile->fd = -1; - if (fp) - pFile->fd = fileno(fp); - - if (pFile->fd < 0) + pFile->fp = fp; + if (!pFile->fp) { - WLog_ERR(TAG, "Failed to open file %s with mode %s", - pFile->lpFileName, mode); + WLog_ERR(TAG, "Failed to open file pointer for %s", + pFile->lpFileName); free(pFile->lpFileName); free(pFile); @@ -520,13 +504,11 @@ static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw if (dwShareMode & (FILE_SHARE_READ | FILE_SHARE_WRITE)) { - if (flock(pFile->fd, lock) < 0) + if (flock(fileno(pFile->fp), lock) < 0) { WLog_ERR(TAG, "flock failed with %s [%08X]", strerror(errno), errno); - close(pFile->fd); - free(pFile->lpFileName); - free(pFile); + FileCloseHandle(pFile); return INVALID_HANDLE_VALUE; } @@ -553,20 +535,20 @@ HANDLE_CREATOR *GetFileHandleCreator(void) } -static WINPR_FILE *FileHandle_New(int fd) +static WINPR_FILE *FileHandle_New(FILE* fp) { WINPR_FILE *pFile; HANDLE hFile; char name[MAX_PATH]; - _snprintf(name, sizeof(name), "device_%d", fd); + _snprintf(name, sizeof(name), "device_%d", fileno(fp)); pFile = (WINPR_FILE*) calloc(1, sizeof(WINPR_FILE)); if (!pFile) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } - pFile->fd = fd; + pFile->fp = fp; pFile->ops = &shmOps; pFile->lpFileName = _strdup(name); @@ -577,23 +559,24 @@ static WINPR_FILE *FileHandle_New(int fd) HANDLE GetStdHandle(DWORD nStdHandle) { - int fd; + FILE* fp; WINPR_FILE *pFile; + switch (nStdHandle) { case STD_INPUT_HANDLE: - fd = STDIN_FILENO; + fp = stdin; break; case STD_OUTPUT_HANDLE: - fd = STDOUT_FILENO; + fp = stdout; break; case STD_ERROR_HANDLE: - fd = STDERR_FILENO; + fp = stderr; break; default: return INVALID_HANDLE_VALUE; } - pFile = FileHandle_New(fd); + pFile = FileHandle_New(fp); if (!pFile) return INVALID_HANDLE_VALUE; @@ -620,16 +603,28 @@ HANDLE GetFileHandleForFileDescriptor(int fd) return (HANDLE)_get_osfhandle(fd); #else /* WIN32 */ WINPR_FILE *pFile; + FILE* fp; + int flags; /* Make sure it's a valid fd */ if (fcntl(fd, F_GETFD) == -1 && errno == EBADF) return INVALID_HANDLE_VALUE; - pFile = FileHandle_New(fd); + flags = fcntl(fd, F_GETFL); + if (flags == -1) + return INVALID_HANDLE_VALUE; + + if (flags & O_WRONLY) + fp = fdopen(fd, "wb"); + else + fp = fdopen(fd, "rb"); + + pFile = FileHandle_New(fp); if (!pFile) return INVALID_HANDLE_VALUE; - pFile->fd = fd; + return (HANDLE)pFile; #endif /* WIN32 */ } + diff --git a/winpr/libwinpr/file/file.h b/winpr/libwinpr/file/file.h index fc2879366..af0916753 100644 --- a/winpr/libwinpr/file/file.h +++ b/winpr/libwinpr/file/file.h @@ -37,7 +37,7 @@ struct winpr_file { WINPR_HANDLE_DEF(); - int fd; + FILE* fp; char* lpFileName; From 06307f1ac142355f8cde14fd9f52b833db148116 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Wed, 16 Dec 2015 18:33:19 +0100 Subject: [PATCH 12/12] winpr/file: disable buffering When FILE streams are used per default buffering is enabled but WriteFile/ReadFile shouldn't do any extra buffering. --- winpr/libwinpr/file/file.c | 44 +++++++++++++------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index e58b2249b..066a76e16 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -107,19 +107,10 @@ static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove, WINPR_FILE* pFile = (WINPR_FILE*) hFile; long offset = lDistanceToMove; int whence; - FILE* fp; if (!hFile) return INVALID_SET_FILE_POINTER; - fp = pFile->fp; - - if (!fp) - { - WLog_ERR(TAG, "No file pointer for(%s)", pFile->lpFileName); - return INVALID_SET_FILE_POINTER; - } - switch(dwMoveMethod) { case FILE_BEGIN: @@ -135,14 +126,14 @@ static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove, return INVALID_SET_FILE_POINTER; } - if (fseek(fp, offset, whence)) + if (fseek(pFile->fp, offset, whence)) { WLog_ERR(TAG, "fseek(%s) failed with %s [%08X]", pFile->lpFileName, strerror(errno), errno); return INVALID_SET_FILE_POINTER; } - return ftell(fp); + return ftell(pFile->fp); } static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, @@ -213,23 +204,14 @@ static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrit static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh) { WINPR_FILE* file; - FILE* fp; long cur, size; if (!Object) return 0; file = (WINPR_FILE *)Object; - fp = file->fp; - if (!fp) - { - WLog_ERR(TAG, "fopen(%s) failed with %s [%08X]", file->lpFileName, - strerror(errno), errno); - return INVALID_FILE_SIZE; - } - - cur = ftell(fp); + cur = ftell(file->fp); if (cur < 0) { @@ -238,14 +220,14 @@ static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh) return INVALID_FILE_SIZE; } - if (fseek(fp, 0, SEEK_END) != 0) + if (fseek(file->fp, 0, SEEK_END) != 0) { WLog_ERR(TAG, "fseek(%s) failed with %s [%08X]", file->lpFileName, strerror(errno), errno); return INVALID_FILE_SIZE; } - size = ftell(fp); + size = ftell(file->fp); if (size < 0) { @@ -254,7 +236,7 @@ static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh) return INVALID_FILE_SIZE; } - if (fseek(fp, cur, SEEK_SET) != 0) + if (fseek(file->fp, cur, SEEK_SET) != 0) { WLog_ERR(TAG, "ftell(%s) failed with %s [%08X]", file->lpFileName, strerror(errno), errno); @@ -489,14 +471,15 @@ static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw pFile->fp = fp; if (!pFile->fp) { - WLog_ERR(TAG, "Failed to open file pointer for %s", - pFile->lpFileName); - + /* This case can occur when trying to open a + * not existing file without create flag. */ free(pFile->lpFileName); free(pFile); return INVALID_HANDLE_VALUE; } + setvbuf(fp, NULL, _IONBF, 0); + if (dwShareMode & FILE_SHARE_READ) lock = LOCK_SH; if (dwShareMode & FILE_SHARE_WRITE) @@ -538,7 +521,6 @@ HANDLE_CREATOR *GetFileHandleCreator(void) static WINPR_FILE *FileHandle_New(FILE* fp) { WINPR_FILE *pFile; - HANDLE hFile; char name[MAX_PATH]; _snprintf(name, sizeof(name), "device_%d", fileno(fp)); @@ -552,7 +534,6 @@ static WINPR_FILE *FileHandle_New(FILE* fp) pFile->ops = &shmOps; pFile->lpFileName = _strdup(name); - hFile = (HANDLE) pFile; WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ); return pFile; } @@ -619,6 +600,11 @@ HANDLE GetFileHandleForFileDescriptor(int fd) else fp = fdopen(fd, "rb"); + if (!fp) + return INVALID_HANDLE_VALUE; + + setvbuf(fp, NULL, _IONBF, 0); + pFile = FileHandle_New(fp); if (!pFile) return INVALID_HANDLE_VALUE;