From 6b52a2e5cc6a9eb2c76d53cca2205cbd940aa825 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Wed, 9 Sep 2015 16:47:03 +0200 Subject: [PATCH] winpr/file: initial regular file support Add initial support for "regular" files. First implemented call is GetStdHandle to get stdin/stdout/stderr. --- winpr/include/winpr/environment.h | 4 - winpr/include/winpr/file.h | 9 +- winpr/libwinpr/environment/environment.c | 15 -- winpr/libwinpr/file/CMakeLists.txt | 2 +- winpr/libwinpr/file/file.c | 222 ++++++++++++++++++ winpr/libwinpr/file/generic.c | 1 - winpr/libwinpr/file/namedPipeClient.c | 3 +- winpr/libwinpr/file/test/CMakeLists.txt | 4 +- .../libwinpr/file/test/TestFileGetStdHandle.c | 46 ++++ 9 files changed, 281 insertions(+), 25 deletions(-) create mode 100644 winpr/libwinpr/file/file.c create mode 100644 winpr/libwinpr/file/test/TestFileGetStdHandle.c diff --git a/winpr/include/winpr/environment.h b/winpr/include/winpr/environment.h index 71bdc056c..d6329d827 100644 --- a/winpr/include/winpr/environment.h +++ b/winpr/include/winpr/environment.h @@ -40,10 +40,6 @@ WINPR_API BOOL SetCurrentDirectoryW(LPCWSTR lpPathName); WINPR_API DWORD SearchPathA(LPCSTR lpPath, LPCSTR lpFileName, LPCSTR lpExtension, DWORD nBufferLength, LPSTR lpBuffer, LPSTR* lpFilePart); WINPR_API DWORD SearchPathW(LPCWSTR lpPath, LPCWSTR lpFileName, LPCWSTR lpExtension, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR* lpFilePart); -WINPR_API HANDLE GetStdHandle(DWORD nStdHandle); -WINPR_API BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle); -WINPR_API BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle); - WINPR_API LPSTR GetCommandLineA(VOID); WINPR_API LPWSTR GetCommandLineW(VOID); diff --git a/winpr/include/winpr/file.h b/winpr/include/winpr/file.h index 45ec3e698..4d3a3792f 100644 --- a/winpr/include/winpr/file.h +++ b/winpr/include/winpr/file.h @@ -161,6 +161,10 @@ #define FIND_FIRST_EX_CASE_SENSITIVE 0x1 #define FIND_FIRST_EX_LARGE_FETCH 0x2 +#define STD_INPUT_HANDLE (DWORD)-10 +#define STD_OUTPUT_HANDLE (DWORD)-11 +#define STD_ERROR_HANDLE (DWORD)-12 + typedef union _FILE_SEGMENT_ELEMENT { PVOID64 Buffer; @@ -316,7 +320,6 @@ WINPR_API BOOL RemoveDirectoryW(LPCWSTR lpPathName); #define RemoveDirectory RemoveDirectoryA #endif - /* Extra Functions */ typedef BOOL (*pcIsFileHandled)(LPCSTR lpFileName); @@ -329,7 +332,9 @@ typedef struct _HANDLE_CREATOR pcCreateFileA CreateFileA; } HANDLE_CREATOR, *PHANDLE_CREATOR, *LPHANDLE_CREATOR; -BOOL RegisterHandleCreator(PHANDLE_CREATOR pHandleCreator); +WINPR_API HANDLE GetStdHandle(DWORD nStdHandle); +WINPR_API BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle); +WINPR_API BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle); #endif /* _WIN32 */ diff --git a/winpr/libwinpr/environment/environment.c b/winpr/libwinpr/environment/environment.c index d87172679..dcdb24f30 100644 --- a/winpr/libwinpr/environment/environment.c +++ b/winpr/libwinpr/environment/environment.c @@ -111,21 +111,6 @@ DWORD SearchPathW(LPCWSTR lpPath, LPCWSTR lpFileName, LPCWSTR lpExtension, DWORD return 0; } -HANDLE GetStdHandle(DWORD nStdHandle) -{ - return NULL; -} - -BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle) -{ - return TRUE; -} - -BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle) -{ - return TRUE; -} - LPSTR GetCommandLineA(VOID) { return NULL; diff --git a/winpr/libwinpr/file/CMakeLists.txt b/winpr/libwinpr/file/CMakeLists.txt index 55a8e84bb..986c87386 100644 --- a/winpr/libwinpr/file/CMakeLists.txt +++ b/winpr/libwinpr/file/CMakeLists.txt @@ -15,7 +15,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -winpr_module_add(generic.c namedPipeClient.c pattern.c) +winpr_module_add(generic.c namedPipeClient.c pattern.c file.c) if(BUILD_TESTING) add_subdirectory(test) diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c new file mode 100644 index 000000000..b46ee4f06 --- /dev/null +++ b/winpr/libwinpr/file/file.c @@ -0,0 +1,222 @@ +/** + * WinPR: Windows Portable Runtime + * File Functions + * + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 Bernhard Miklautz + * + * 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 _WIN32 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + + +#include "../log.h" +#define TAG WINPR_TAG("file") + +#include +#include + +#include "../handle/handle.h" +#include + +struct winpr_file +{ + WINPR_HANDLE_DEF(); + + int fd; +}; + +typedef struct winpr_file WINPR_FILE; + +static BOOL FileIsHandled(HANDLE handle) +{ + WINPR_FILE* pFile = (WINPR_FILE*) handle; + + if (!pFile || (pFile->Type != HANDLE_TYPE_FILE)) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + return TRUE; +} + +static int FileGetFd(HANDLE handle) +{ + WINPR_FILE *file= (WINPR_FILE*)handle; + + if (!FileIsHandled(handle)) + return -1; + + return file->fd; +} + +static BOOL FileCloseHandle(HANDLE handle) { + WINPR_FILE* file = (WINPR_FILE *)handle; + + if (!FileIsHandled(handle)) + return FALSE; + + if (file->fd != -1) + { + close(file->fd); + file->fd = -1; + } + + free(handle); + return TRUE; +} + +static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) +{ + int io_status; + WINPR_FILE* file; + BOOL status = TRUE; + + if (!Object) + return FALSE; + + if (lpOverlapped) + { + WLog_ERR(TAG, "Overlapping write not supported."); + return FALSE; + } + + file = (WINPR_FILE *)Object; + do + { + io_status = read(file->fd, lpBuffer, nNumberOfBytesToRead); + } + while ((io_status < 0) && (errno == EINTR)); + + if (io_status < 0) + { + status = FALSE; + + switch (errno) + { + case EWOULDBLOCK: + SetLastError(ERROR_NO_DATA); + break; + } + } + + if (lpNumberOfBytesRead) + *lpNumberOfBytesRead = io_status; + + return status; +} + +static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) +{ + int io_status; + WINPR_FILE* file; + + if (!Object) + return FALSE; + + if (lpOverlapped) + { + WLog_ERR(TAG, "Overlapping write not supported."); + return FALSE; + } + + file = (WINPR_FILE *)Object; + + do + { + io_status = write(file->fd, lpBuffer, nNumberOfBytesToWrite); + } + while ((io_status < 0) && (errno == EINTR)); + + if ((io_status < 0) && (errno == EWOULDBLOCK)) + io_status = 0; + + *lpNumberOfBytesWritten = io_status; + return TRUE; +} + + +static HANDLE_OPS ops = { + FileIsHandled, + FileCloseHandle, + FileGetFd, + NULL, /* CleanupHandle */ + FileRead, + FileWrite +}; + +static WINPR_FILE *FileHandle_New() +{ + WINPR_FILE *pFile; + HANDLE hFile; + + pFile = (WINPR_FILE*) calloc(1, sizeof(WINPR_FILE)); + if (!pFile) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + pFile->fd = -1; + pFile->ops = &ops; + + hFile = (HANDLE) pFile; + WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ); + return pFile; +} + +HANDLE GetStdHandle(DWORD nStdHandle) +{ + int fd; + WINPR_FILE *pFile; + switch (nStdHandle) + { + case STD_INPUT_HANDLE: + fd = STDIN_FILENO; + break; + case STD_OUTPUT_HANDLE: + fd = STDOUT_FILENO; + break; + case STD_ERROR_HANDLE: + fd = STDERR_FILENO; + break; + default: + return INVALID_HANDLE_VALUE; + } + pFile = FileHandle_New(); + if (!pFile) + return INVALID_HANDLE_VALUE; + + pFile->fd = fd; + return (HANDLE)pFile; +} + +BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle) +{ + return TRUE; +} + +BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle) +{ + return TRUE; +} + +#endif /* _WIN32 */ + diff --git a/winpr/libwinpr/file/generic.c b/winpr/libwinpr/file/generic.c index c71d17af8..9eac8e165 100644 --- a/winpr/libwinpr/file/generic.c +++ b/winpr/libwinpr/file/generic.c @@ -24,7 +24,6 @@ #include #include -#include #include #ifdef HAVE_UNISTD_H diff --git a/winpr/libwinpr/file/namedPipeClient.c b/winpr/libwinpr/file/namedPipeClient.c index 2941d313e..d2aed74fd 100644 --- a/winpr/libwinpr/file/namedPipeClient.c +++ b/winpr/libwinpr/file/namedPipeClient.c @@ -61,7 +61,8 @@ static BOOL NamedPipeClientIsHandled(HANDLE handle) return TRUE; } -BOOL NamedPipeClientCloseHandle(HANDLE handle) { +BOOL NamedPipeClientCloseHandle(HANDLE handle) +{ WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*) handle; diff --git a/winpr/libwinpr/file/test/CMakeLists.txt b/winpr/libwinpr/file/test/CMakeLists.txt index f23bde6e9..c7015c670 100644 --- a/winpr/libwinpr/file/test/CMakeLists.txt +++ b/winpr/libwinpr/file/test/CMakeLists.txt @@ -12,7 +12,9 @@ set(${MODULE_PREFIX}_TESTS TestFilePatternMatch.c TestFileFindFirstFile.c TestFileFindFirstFileEx.c - TestFileFindNextFile.c) + TestFileFindNextFile.c + TestFileGetStdHandle.c +) create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} diff --git a/winpr/libwinpr/file/test/TestFileGetStdHandle.c b/winpr/libwinpr/file/test/TestFileGetStdHandle.c new file mode 100644 index 000000000..e37dd8cd7 --- /dev/null +++ b/winpr/libwinpr/file/test/TestFileGetStdHandle.c @@ -0,0 +1,46 @@ + +/** + * WinPR: Windows Portable Runtime + * File Functions + * + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 Bernhard Miklautz + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +int TestFileGetStdHandle(int argc, char* argv[]) +{ + HANDLE stdout; + char *buf = "happy happy"; + DWORD bytesWritten; + + stdout = GetStdHandle(STD_OUTPUT_HANDLE); + if (stdout == INVALID_HANDLE_VALUE) + { + fprintf(stderr, "GetStdHandle failed ;(\n"); + return -1; + } + WriteFile(stdout, buf, strlen(buf), &bytesWritten, FALSE); + if (bytesWritten != strlen(buf)) + { + fprintf(stderr, "write failed\n"); + return -1; + } + + return 0; +} \ No newline at end of file