From c0bc9a2a67015b1cad8d87dac5b6e111843f086b Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Thu, 5 Mar 2015 14:58:25 -0800 Subject: [PATCH 001/298] initial commit --- .gitmodules | 3 + ext-src/gtest | 1 + src/CMakeLists.txt | 17 + src/impl/getcurrentprocessorid.cpp | 9 + src/impl/getcurrentprocessorid.h | 10 + src/impl/pal.h | 587 +++++++++++++++++++++++++ src/main.cpp | 7 + src/tests/test-getcurrentprocessid.cpp | 16 + 8 files changed, 650 insertions(+) create mode 100644 .gitmodules create mode 160000 ext-src/gtest create mode 100644 src/CMakeLists.txt create mode 100644 src/impl/getcurrentprocessorid.cpp create mode 100644 src/impl/getcurrentprocessorid.h create mode 100644 src/impl/pal.h create mode 100644 src/main.cpp create mode 100644 src/tests/test-getcurrentprocessid.cpp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..63ba77f861 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ext-src/gtest"] + path = ext-src/gtest + url = https://msostc.visualstudio.com/DefaultCollection/PS/_git/ext-gtest diff --git a/ext-src/gtest b/ext-src/gtest new file mode 160000 index 0000000000..2196edcdb7 --- /dev/null +++ b/ext-src/gtest @@ -0,0 +1 @@ +Subproject commit 2196edcdb71dc8ff99f693e9e43332c143fe59d3 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000000..4355f98d04 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8.4) +project(monad_native) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +#include gtest +include_directories(../ext-src/gtest/fused-src impl) + +set(SOURCE_FILES main.cpp tests/test-getcurrentprocessid.cpp impl/getcurrentprocessorid.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) +add_executable(monad_native ${SOURCE_FILES}) + +# add pthread +find_package(Threads) +target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT}) + + + diff --git a/src/impl/getcurrentprocessorid.cpp b/src/impl/getcurrentprocessorid.cpp new file mode 100644 index 0000000000..409f2c258f --- /dev/null +++ b/src/impl/getcurrentprocessorid.cpp @@ -0,0 +1,9 @@ +#include "getcurrentprocessorid.h" +#include + +HANDLE GetCurrentProcessId() +{ + pid_t pid = getpid(); + return reinterpret_cast(pid); +} + diff --git a/src/impl/getcurrentprocessorid.h b/src/impl/getcurrentprocessorid.h new file mode 100644 index 0000000000..fa3f35534e --- /dev/null +++ b/src/impl/getcurrentprocessorid.h @@ -0,0 +1,10 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +HANDLE GetCurrentProcessId(); + +PAL_END_EXTERNC + diff --git a/src/impl/pal.h b/src/impl/pal.h new file mode 100644 index 0000000000..659afd4f61 --- /dev/null +++ b/src/impl/pal.h @@ -0,0 +1,587 @@ +/* +**============================================================================== +** +** Open Management Infrastructure (OMI) +** +** Copyright (c) Microsoft Corporation +** +** 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 +** +** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +** MERCHANTABLITY OR NON-INFRINGEMENT. +** +** See the Apache 2 License for the specific language governing permissions +** and limitations under the License. +** +**============================================================================== +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#ifndef NAME_MAX +# define NAME_MAX 255 +#endif + +/* +**============================================================================== +** +** Windows-specific types. Defined here for PAL on Non-Windows platforms. +** +**============================================================================== +*/ + +#ifdef _MSC_VER + #ifndef WIN32_FROM_HRESULT + #define WIN32_FROM_HRESULT(hr) (HRESULT_FACILITY(hr) == FACILITY_WIN32 ? HRESULT_CODE(hr) : hr) + #endif +#else + #define WIN32_FROM_HRESULT(hr) hr + #define HRESULT_FROM_WIN32(error) error + typedef unsigned long DWORD, *LPDWORD; + typedef int BOOL; + typedef unsigned long HRESULT; + typedef const wchar_t *PCWSTR; + typedef wchar_t *PWSTR; + typedef const char *PCSTR; + typedef char *PSTR; + typedef void *PVOID; + typedef PVOID HANDLE; + #define NO_ERROR 0 + #define INFINITE 0xFFFFFFFF + #define WINAPI + #define S_OK 0 + #define ERROR_GEN_FAILURE 31 + #define TRUE 1 + #define FALSE 0 + #define ERROR_INVALID_PARAMETER 87 + #define ERROR_OUTOFMEMORY 14 + #define MAX_PATH 0x00000104 + typedef unsigned long long uint64; +#endif + +/* +**============================================================================== +** +** __FUNCTION__ +** +**============================================================================== +*/ + +#if !defined(CONFIG_HAVE_FUNCTION_MACRO) +# if !defined(_MSC_VER) && !defined(__FUNCTION__) +# define __FUNCTION__ "" +# endif +#endif + +/* +**============================================================================== +** +** PAL_32BIT +** PAL_64BIT +** +**============================================================================== +*/ +#if defined(__GNUC__) +# if defined(__i386__) +# define PAL_32BIT +# elif defined(__x86_64__) +# define PAL_64BIT +# elif defined(__ppc__) +# define PAL_32BIT +# elif defined(__ppc64__) +# define PAL_64BIT +# elif ((ULONG_MAX) == (UINT_MAX) && (ULONG_MAX == 0xFFFFFFFF)) +# define PAL_32BIT +# else +# define PAL_64BIT +# endif +#elif defined(_MSC_VER) +# if defined(_WIN64) +# define PAL_64BIT +# else +# define PAL_32BIT +# endif +#elif ((ULONG_MAX) == (UINT_MAX) && (ULONG_MAX == 0xFFFFFFFF)) +# define PAL_32BIT +#else +# define PAL_64BIT +#endif + +/* +**============================================================================== +** +** PAL_CALL macro +** +**============================================================================== +*/ +#ifdef _MSC_VER +# define PAL_CALL __stdcall +#else +# define PAL_CALL +#endif + +/* +**============================================================================== +** +** PAL_EXPORT_API, PAL_IMPORT_API macros +** +**============================================================================== +*/ + +#if defined(_MSC_VER) +# define PAL_EXPORT_API __declspec(dllexport) +# define PAL_IMPORT_API __declspec(dllimport) +#elif defined(__GNUC__) +# define PAL_EXPORT_API __attribute__((visibility("default"))) +# define PAL_IMPORT_API /* empty */ +#elif defined(sun) +# define PAL_EXPORT_API __global +# define PAL_IMPORT_API /* empty */ +#else +# define PAL_EXPORT_API /* empty */ +# define PAL_IMPORT_API /* empty */ +#endif + +/* +**============================================================================== +** +** PAL_BEGIN_EXTERNC +** PAL_END_EXTERNC +** +**============================================================================== +*/ + +#if defined(__cplusplus) +# define PAL_BEGIN_EXTERNC extern "C" { +# define PAL_END_EXTERNC } +#else +# define PAL_BEGIN_EXTERNC +# define PAL_END_EXTERNC +#endif + +/* +**============================================================================== +** +** PAL_EXTERN_C +** +**============================================================================== +*/ +#ifdef __cplusplus +# define PAL_EXTERN_C extern "C" +#else +# define PAL_EXTERN_C extern +#endif /* __cplusplus */ + +/* +**============================================================================== +** +** PAL_INLINE macro +** +**============================================================================== +*/ + +#if defined(_MSC_VER) +# define PAL_INLINE static __inline +#elif defined(__GNUC__) +# define PAL_INLINE static __inline +#elif defined(sun) +# define PAL_INLINE static inline +#elif defined(__PPC) +# define PAL_INLINE __inline__ +#else +# define PAL_INLINE static __inline +#endif + +/* +**============================================================================== +** +** PAL string +** +**============================================================================== +*/ + +#if defined(CONFIG_ENABLE_WCHAR) +typedef wchar_t PAL_Char; +#else +typedef char PAL_Char; +#endif + +typedef PAL_Char TChar; + +/* +**============================================================================== +** +** PAL_T() +** +**============================================================================== +*/ + +#if defined(CONFIG_ENABLE_WCHAR) +# define __PAL_T(STR) L ## STR +# define PAL_T(STR) __PAL_T(STR) +#else +# define PAL_T(STR) STR +#endif + +/* +**============================================================================== +** +** PAL_UNUSED +** +**============================================================================== +*/ + +#define PAL_UNUSED(X) ((void)X) + +/* +**============================================================================== +** +** PAL_HAVE_POSIX +** +**============================================================================== +*/ + +#if defined(linux) || defined(sun) || defined(hpux) || defined(aix) +# define PAL_HAVE_POSIX +#endif + +/* +**============================================================================== +** +** PAL_HAVE_PTHREADS +** +**============================================================================== +*/ + +#if defined(linux) | defined(sun) | defined(hpux) | defined(aix) +# define PAL_HAVE_PTHREADS +#endif + +/* +**============================================================================== +** +** Basic types +** +**============================================================================== +*/ + +typedef unsigned char PAL_Uint8; +#define PAL_UINT8_MAX (UCHAR_MAX) + +typedef signed char PAL_Sint8; +#define PAL_SINT8_MIN (SCHAR_MIN) +#define PAL_SINT8_MAX (SCHAR_MAX) + +typedef unsigned short PAL_Uint16; +#define PAL_UINT16_MAX (USHRT_MAX) + +typedef signed short PAL_Sint16; +#define PAL_SINT16_MIN (SHRT_MIN) +#define PAL_SINT16_MAX (SHRT_MAX) + +typedef unsigned int PAL_Uint32; +#define PAL_UINT32_MAX (UINT_MAX) + +typedef signed int PAL_Sint32; +#define PAL_SINT32_MIN (INT_MIN) +#define PAL_SINT32_MAX (INT_MAX) + +#if defined(_MSC_VER) +typedef unsigned __int64 PAL_Uint64; +typedef signed __int64 PAL_Sint64; +#else +typedef unsigned long long PAL_Uint64; +typedef signed long long PAL_Sint64; +#endif +#define PAL_UINT64_MIN ((PAL_Uint64) 0ULL) +#define PAL_UINT64_MAX ((PAL_Uint64) 18446744073709551615ULL) +#define PAL_SINT64_MIN ((PAL_Sint64) (-9223372036854775807LL - 1LL)) +#define PAL_SINT64_MAX ((PAL_Sint64) 9223372036854775807LL ) + +typedef unsigned char PAL_Boolean; + +#define PAL_TRUE ((PAL_Boolean)1) +#define PAL_FALSE ((PAL_Boolean)0) + +/* +**============================================================================== +** +** Function calling conventions +** +**============================================================================== +*/ + +#ifdef _MSC_VER +# define PAL_CDECLAPI __cdecl +#else +# define PAL_CDECLAPI +#endif + +#define ATEXIT_API PAL_CDECLAPI + +/* +**============================================================================== +** +** SAL Notation for non-Windows platforms +** +**============================================================================== +*/ + +#if !defined(_MSC_VER) + +# ifndef _In_ +# define _In_ +# endif + +# ifndef _Out_ +# define _Out_ +# endif + +# ifndef _Inout_ +# define _Inout_ +# endif + +# ifndef _Return_type_success_ +# define _Return_type_success_(x) +# endif + +# ifndef _Acquires_lock_ +# define _Acquires_lock_(x) +# endif + +# ifndef _Releases_lock_ +# define _Releases_lock_(x) +# endif + +# ifndef _In_z_ +# define _In_z_ +# endif + +# ifndef _Post_z_ +# define _Post_z_ +# endif + +# ifndef _Out_writes_ +# define _Out_writes_(size) +# endif + +# ifndef _Out_writes_z_ +# define _Out_writes_z_(size) +# endif + +# ifndef _Null_terminated_ +# define _Null_terminated_ +# endif + +# ifndef _Use_decl_annotations_ +# define _Use_decl_annotations_ +# endif + +# ifndef _Out_opt_ +# define _Out_opt_ +# endif + +# ifndef _Deref_post_z_ +# define _Deref_post_z_ +# endif + +# ifndef _Inout_updates_z_ +# define _Inout_updates_z_(count) +# endif + +# ifndef _Inout_opt_z_ +# define _Inout_opt_z_ +# endif + +# ifndef _Deref_prepost_opt_z_ +# define _Deref_prepost_opt_z_ +# endif + +# ifndef _In_opt_ +# define _In_opt_ +# endif + +# ifndef _In_opt_z_ +# define _In_opt_z_ +# endif + +# ifndef _Ret_maybenull_ +# define _Ret_maybenull_ +# endif + +# ifndef _Check_return_ +# define _Check_return_ +# endif + +# ifndef _Must_inspect_result_ +# define _Must_inspect_result_ +# endif + +# ifndef _Frees_ptr_opt_ +# define _Frees_ptr_opt_ +# endif + +# ifndef _Frees_ptr_ +# define _Frees_ptr_ +# endif + +# ifndef _Const_ +# define _Const_ +# endif + +# ifndef _Post_writable_byte_size +# define _Post_writable_byte_size(size) +# endif + +# ifndef _Analysis_assume_ +# define _Analysis_assume_(expr) +# endif + +# ifndef _Always_ +# define _Always_(expr) +# endif + +# ifndef _Outptr_ +# define _Outptr_ +# endif + +# ifndef _Outptr_result_buffer_ +# define _Outptr_result_buffer_(size) +# endif + +# ifndef _Outptr_result_nullonfailure_ +# define _Outptr_result_nullonfailure_ +# endif + +# ifndef _Maybenull_ +# define _Maybenull_ +# endif + +# ifndef _Notnull_ +# define _Notnull_ +# endif + +# ifndef _Valid_ +# define _Valid_ +# endif + +# ifndef _Analysis_noreturn_ +# define _Analysis_noreturn_ +# endif + +# ifndef _Ret_writes_maybenull_z_ +# define _Ret_writes_maybenull_z_(count) +# endif + +# ifndef _String_length_ +# define _String_length_(str) +# endif + +# ifndef _Success_ +# define _Success_ +# endif + +# ifndef _Field_range_ +# define _Field_range_(min, max) +# endif + +# ifndef _In_range_ +# define _In_range_(min, max) +# endif + +# ifndef _Field_size_ +# define _Field_size_(count) +# endif + +# ifndef _Field_size_opt_ +# define _Field_size_opt_(count) +# endif + +# ifndef _Field_size_full_opt_ +# define _Field_size_full_opt_(count) +# endif + +# ifndef _Field_size_bytes_opt_ +# define _Field_size_bytes_opt_(size) +# endif + +# ifndef _Readable_elements_ +# define _Readable_elements_(count) +# endif + +# ifndef _Writable_elements_ +# define _Writable_elements_(count) +# endif + +# ifndef _Struct_size_bytes_ +# define _Struct_size_bytes_(size) +# endif + +# ifndef _At_ +# define _At_(target, annotation) +# endif + +# ifndef _Pre_satisfies_ +# define _Pre_satisfies_(expr) +# endif + +# ifndef _On_failure_ +# define _On_failure_(expr) +# endif + +# ifndef _In_bytecount_ +# define _In_bytecount_(size) +# endif + +# ifndef _Out_writes_bytes_to_opt_ +# define _Out_writes_bytes_to_opt_(buffLen, bufferNeeded) +# endif + +# ifndef _When_ +# define _When_(expr, annotation) +# endif + +# ifndef _Analysis_assume_nullterminated_ +# define _Analysis_assume_nullterminated_(expr) +# endif + + +#endif /* !defined(_MSC_VER) */ + +/* +**============================================================================== +** +** PAL_MAX_PATH_SIZE +** +**============================================================================== +*/ + +#define PAL_MAX_PATH_SIZE 1024 + +/* +**============================================================================== +** +** PAL_COUNT +** +**============================================================================== +*/ + +#ifdef _MSC_VER +# define PAL_COUNT(ARR) _countof(ARR) +#else +# define PAL_COUNT(ARR) (sizeof(ARR) / sizeof(ARR[0])) +#endif + diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000000..e59bea0572 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,7 @@ +#include + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/src/tests/test-getcurrentprocessid.cpp b/src/tests/test-getcurrentprocessid.cpp new file mode 100644 index 0000000000..9803b6612c --- /dev/null +++ b/src/tests/test-getcurrentprocessid.cpp @@ -0,0 +1,16 @@ +#include +#include "getcurrentprocessorid.h" + +// This is a very simple test case to show how tests can be written +TEST(GetCurrentProcessId,simple) +{ + const HANDLE currentProcessId = GetCurrentProcessId(); + const pid_t pid = getpid(); + + // first make sure that on this platform those types are of the same size + ASSERT_TRUE(sizeof(HANDLE) >= sizeof(pid_t)); + + // now compare the actual values + ASSERT_EQ(currentProcessId,reinterpret_cast(pid)); +} + From beb5be9ffaac1ee032fb091a83f9e28ddb6d1110 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Thu, 5 Mar 2015 14:58:25 -0800 Subject: [PATCH 002/298] initial commit --- CMakeLists.txt | 17 + impl/getcurrentprocessorid.cpp | 9 + impl/getcurrentprocessorid.h | 10 + impl/pal.h | 587 +++++++++++++++++++++++++++++ main.cpp | 7 + tests/test-getcurrentprocessid.cpp | 16 + 6 files changed, 646 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 impl/getcurrentprocessorid.cpp create mode 100644 impl/getcurrentprocessorid.h create mode 100644 impl/pal.h create mode 100644 main.cpp create mode 100644 tests/test-getcurrentprocessid.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..4355f98d04 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8.4) +project(monad_native) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +#include gtest +include_directories(../ext-src/gtest/fused-src impl) + +set(SOURCE_FILES main.cpp tests/test-getcurrentprocessid.cpp impl/getcurrentprocessorid.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) +add_executable(monad_native ${SOURCE_FILES}) + +# add pthread +find_package(Threads) +target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT}) + + + diff --git a/impl/getcurrentprocessorid.cpp b/impl/getcurrentprocessorid.cpp new file mode 100644 index 0000000000..409f2c258f --- /dev/null +++ b/impl/getcurrentprocessorid.cpp @@ -0,0 +1,9 @@ +#include "getcurrentprocessorid.h" +#include + +HANDLE GetCurrentProcessId() +{ + pid_t pid = getpid(); + return reinterpret_cast(pid); +} + diff --git a/impl/getcurrentprocessorid.h b/impl/getcurrentprocessorid.h new file mode 100644 index 0000000000..fa3f35534e --- /dev/null +++ b/impl/getcurrentprocessorid.h @@ -0,0 +1,10 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +HANDLE GetCurrentProcessId(); + +PAL_END_EXTERNC + diff --git a/impl/pal.h b/impl/pal.h new file mode 100644 index 0000000000..659afd4f61 --- /dev/null +++ b/impl/pal.h @@ -0,0 +1,587 @@ +/* +**============================================================================== +** +** Open Management Infrastructure (OMI) +** +** Copyright (c) Microsoft Corporation +** +** 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 +** +** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +** MERCHANTABLITY OR NON-INFRINGEMENT. +** +** See the Apache 2 License for the specific language governing permissions +** and limitations under the License. +** +**============================================================================== +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#ifndef NAME_MAX +# define NAME_MAX 255 +#endif + +/* +**============================================================================== +** +** Windows-specific types. Defined here for PAL on Non-Windows platforms. +** +**============================================================================== +*/ + +#ifdef _MSC_VER + #ifndef WIN32_FROM_HRESULT + #define WIN32_FROM_HRESULT(hr) (HRESULT_FACILITY(hr) == FACILITY_WIN32 ? HRESULT_CODE(hr) : hr) + #endif +#else + #define WIN32_FROM_HRESULT(hr) hr + #define HRESULT_FROM_WIN32(error) error + typedef unsigned long DWORD, *LPDWORD; + typedef int BOOL; + typedef unsigned long HRESULT; + typedef const wchar_t *PCWSTR; + typedef wchar_t *PWSTR; + typedef const char *PCSTR; + typedef char *PSTR; + typedef void *PVOID; + typedef PVOID HANDLE; + #define NO_ERROR 0 + #define INFINITE 0xFFFFFFFF + #define WINAPI + #define S_OK 0 + #define ERROR_GEN_FAILURE 31 + #define TRUE 1 + #define FALSE 0 + #define ERROR_INVALID_PARAMETER 87 + #define ERROR_OUTOFMEMORY 14 + #define MAX_PATH 0x00000104 + typedef unsigned long long uint64; +#endif + +/* +**============================================================================== +** +** __FUNCTION__ +** +**============================================================================== +*/ + +#if !defined(CONFIG_HAVE_FUNCTION_MACRO) +# if !defined(_MSC_VER) && !defined(__FUNCTION__) +# define __FUNCTION__ "" +# endif +#endif + +/* +**============================================================================== +** +** PAL_32BIT +** PAL_64BIT +** +**============================================================================== +*/ +#if defined(__GNUC__) +# if defined(__i386__) +# define PAL_32BIT +# elif defined(__x86_64__) +# define PAL_64BIT +# elif defined(__ppc__) +# define PAL_32BIT +# elif defined(__ppc64__) +# define PAL_64BIT +# elif ((ULONG_MAX) == (UINT_MAX) && (ULONG_MAX == 0xFFFFFFFF)) +# define PAL_32BIT +# else +# define PAL_64BIT +# endif +#elif defined(_MSC_VER) +# if defined(_WIN64) +# define PAL_64BIT +# else +# define PAL_32BIT +# endif +#elif ((ULONG_MAX) == (UINT_MAX) && (ULONG_MAX == 0xFFFFFFFF)) +# define PAL_32BIT +#else +# define PAL_64BIT +#endif + +/* +**============================================================================== +** +** PAL_CALL macro +** +**============================================================================== +*/ +#ifdef _MSC_VER +# define PAL_CALL __stdcall +#else +# define PAL_CALL +#endif + +/* +**============================================================================== +** +** PAL_EXPORT_API, PAL_IMPORT_API macros +** +**============================================================================== +*/ + +#if defined(_MSC_VER) +# define PAL_EXPORT_API __declspec(dllexport) +# define PAL_IMPORT_API __declspec(dllimport) +#elif defined(__GNUC__) +# define PAL_EXPORT_API __attribute__((visibility("default"))) +# define PAL_IMPORT_API /* empty */ +#elif defined(sun) +# define PAL_EXPORT_API __global +# define PAL_IMPORT_API /* empty */ +#else +# define PAL_EXPORT_API /* empty */ +# define PAL_IMPORT_API /* empty */ +#endif + +/* +**============================================================================== +** +** PAL_BEGIN_EXTERNC +** PAL_END_EXTERNC +** +**============================================================================== +*/ + +#if defined(__cplusplus) +# define PAL_BEGIN_EXTERNC extern "C" { +# define PAL_END_EXTERNC } +#else +# define PAL_BEGIN_EXTERNC +# define PAL_END_EXTERNC +#endif + +/* +**============================================================================== +** +** PAL_EXTERN_C +** +**============================================================================== +*/ +#ifdef __cplusplus +# define PAL_EXTERN_C extern "C" +#else +# define PAL_EXTERN_C extern +#endif /* __cplusplus */ + +/* +**============================================================================== +** +** PAL_INLINE macro +** +**============================================================================== +*/ + +#if defined(_MSC_VER) +# define PAL_INLINE static __inline +#elif defined(__GNUC__) +# define PAL_INLINE static __inline +#elif defined(sun) +# define PAL_INLINE static inline +#elif defined(__PPC) +# define PAL_INLINE __inline__ +#else +# define PAL_INLINE static __inline +#endif + +/* +**============================================================================== +** +** PAL string +** +**============================================================================== +*/ + +#if defined(CONFIG_ENABLE_WCHAR) +typedef wchar_t PAL_Char; +#else +typedef char PAL_Char; +#endif + +typedef PAL_Char TChar; + +/* +**============================================================================== +** +** PAL_T() +** +**============================================================================== +*/ + +#if defined(CONFIG_ENABLE_WCHAR) +# define __PAL_T(STR) L ## STR +# define PAL_T(STR) __PAL_T(STR) +#else +# define PAL_T(STR) STR +#endif + +/* +**============================================================================== +** +** PAL_UNUSED +** +**============================================================================== +*/ + +#define PAL_UNUSED(X) ((void)X) + +/* +**============================================================================== +** +** PAL_HAVE_POSIX +** +**============================================================================== +*/ + +#if defined(linux) || defined(sun) || defined(hpux) || defined(aix) +# define PAL_HAVE_POSIX +#endif + +/* +**============================================================================== +** +** PAL_HAVE_PTHREADS +** +**============================================================================== +*/ + +#if defined(linux) | defined(sun) | defined(hpux) | defined(aix) +# define PAL_HAVE_PTHREADS +#endif + +/* +**============================================================================== +** +** Basic types +** +**============================================================================== +*/ + +typedef unsigned char PAL_Uint8; +#define PAL_UINT8_MAX (UCHAR_MAX) + +typedef signed char PAL_Sint8; +#define PAL_SINT8_MIN (SCHAR_MIN) +#define PAL_SINT8_MAX (SCHAR_MAX) + +typedef unsigned short PAL_Uint16; +#define PAL_UINT16_MAX (USHRT_MAX) + +typedef signed short PAL_Sint16; +#define PAL_SINT16_MIN (SHRT_MIN) +#define PAL_SINT16_MAX (SHRT_MAX) + +typedef unsigned int PAL_Uint32; +#define PAL_UINT32_MAX (UINT_MAX) + +typedef signed int PAL_Sint32; +#define PAL_SINT32_MIN (INT_MIN) +#define PAL_SINT32_MAX (INT_MAX) + +#if defined(_MSC_VER) +typedef unsigned __int64 PAL_Uint64; +typedef signed __int64 PAL_Sint64; +#else +typedef unsigned long long PAL_Uint64; +typedef signed long long PAL_Sint64; +#endif +#define PAL_UINT64_MIN ((PAL_Uint64) 0ULL) +#define PAL_UINT64_MAX ((PAL_Uint64) 18446744073709551615ULL) +#define PAL_SINT64_MIN ((PAL_Sint64) (-9223372036854775807LL - 1LL)) +#define PAL_SINT64_MAX ((PAL_Sint64) 9223372036854775807LL ) + +typedef unsigned char PAL_Boolean; + +#define PAL_TRUE ((PAL_Boolean)1) +#define PAL_FALSE ((PAL_Boolean)0) + +/* +**============================================================================== +** +** Function calling conventions +** +**============================================================================== +*/ + +#ifdef _MSC_VER +# define PAL_CDECLAPI __cdecl +#else +# define PAL_CDECLAPI +#endif + +#define ATEXIT_API PAL_CDECLAPI + +/* +**============================================================================== +** +** SAL Notation for non-Windows platforms +** +**============================================================================== +*/ + +#if !defined(_MSC_VER) + +# ifndef _In_ +# define _In_ +# endif + +# ifndef _Out_ +# define _Out_ +# endif + +# ifndef _Inout_ +# define _Inout_ +# endif + +# ifndef _Return_type_success_ +# define _Return_type_success_(x) +# endif + +# ifndef _Acquires_lock_ +# define _Acquires_lock_(x) +# endif + +# ifndef _Releases_lock_ +# define _Releases_lock_(x) +# endif + +# ifndef _In_z_ +# define _In_z_ +# endif + +# ifndef _Post_z_ +# define _Post_z_ +# endif + +# ifndef _Out_writes_ +# define _Out_writes_(size) +# endif + +# ifndef _Out_writes_z_ +# define _Out_writes_z_(size) +# endif + +# ifndef _Null_terminated_ +# define _Null_terminated_ +# endif + +# ifndef _Use_decl_annotations_ +# define _Use_decl_annotations_ +# endif + +# ifndef _Out_opt_ +# define _Out_opt_ +# endif + +# ifndef _Deref_post_z_ +# define _Deref_post_z_ +# endif + +# ifndef _Inout_updates_z_ +# define _Inout_updates_z_(count) +# endif + +# ifndef _Inout_opt_z_ +# define _Inout_opt_z_ +# endif + +# ifndef _Deref_prepost_opt_z_ +# define _Deref_prepost_opt_z_ +# endif + +# ifndef _In_opt_ +# define _In_opt_ +# endif + +# ifndef _In_opt_z_ +# define _In_opt_z_ +# endif + +# ifndef _Ret_maybenull_ +# define _Ret_maybenull_ +# endif + +# ifndef _Check_return_ +# define _Check_return_ +# endif + +# ifndef _Must_inspect_result_ +# define _Must_inspect_result_ +# endif + +# ifndef _Frees_ptr_opt_ +# define _Frees_ptr_opt_ +# endif + +# ifndef _Frees_ptr_ +# define _Frees_ptr_ +# endif + +# ifndef _Const_ +# define _Const_ +# endif + +# ifndef _Post_writable_byte_size +# define _Post_writable_byte_size(size) +# endif + +# ifndef _Analysis_assume_ +# define _Analysis_assume_(expr) +# endif + +# ifndef _Always_ +# define _Always_(expr) +# endif + +# ifndef _Outptr_ +# define _Outptr_ +# endif + +# ifndef _Outptr_result_buffer_ +# define _Outptr_result_buffer_(size) +# endif + +# ifndef _Outptr_result_nullonfailure_ +# define _Outptr_result_nullonfailure_ +# endif + +# ifndef _Maybenull_ +# define _Maybenull_ +# endif + +# ifndef _Notnull_ +# define _Notnull_ +# endif + +# ifndef _Valid_ +# define _Valid_ +# endif + +# ifndef _Analysis_noreturn_ +# define _Analysis_noreturn_ +# endif + +# ifndef _Ret_writes_maybenull_z_ +# define _Ret_writes_maybenull_z_(count) +# endif + +# ifndef _String_length_ +# define _String_length_(str) +# endif + +# ifndef _Success_ +# define _Success_ +# endif + +# ifndef _Field_range_ +# define _Field_range_(min, max) +# endif + +# ifndef _In_range_ +# define _In_range_(min, max) +# endif + +# ifndef _Field_size_ +# define _Field_size_(count) +# endif + +# ifndef _Field_size_opt_ +# define _Field_size_opt_(count) +# endif + +# ifndef _Field_size_full_opt_ +# define _Field_size_full_opt_(count) +# endif + +# ifndef _Field_size_bytes_opt_ +# define _Field_size_bytes_opt_(size) +# endif + +# ifndef _Readable_elements_ +# define _Readable_elements_(count) +# endif + +# ifndef _Writable_elements_ +# define _Writable_elements_(count) +# endif + +# ifndef _Struct_size_bytes_ +# define _Struct_size_bytes_(size) +# endif + +# ifndef _At_ +# define _At_(target, annotation) +# endif + +# ifndef _Pre_satisfies_ +# define _Pre_satisfies_(expr) +# endif + +# ifndef _On_failure_ +# define _On_failure_(expr) +# endif + +# ifndef _In_bytecount_ +# define _In_bytecount_(size) +# endif + +# ifndef _Out_writes_bytes_to_opt_ +# define _Out_writes_bytes_to_opt_(buffLen, bufferNeeded) +# endif + +# ifndef _When_ +# define _When_(expr, annotation) +# endif + +# ifndef _Analysis_assume_nullterminated_ +# define _Analysis_assume_nullterminated_(expr) +# endif + + +#endif /* !defined(_MSC_VER) */ + +/* +**============================================================================== +** +** PAL_MAX_PATH_SIZE +** +**============================================================================== +*/ + +#define PAL_MAX_PATH_SIZE 1024 + +/* +**============================================================================== +** +** PAL_COUNT +** +**============================================================================== +*/ + +#ifdef _MSC_VER +# define PAL_COUNT(ARR) _countof(ARR) +#else +# define PAL_COUNT(ARR) (sizeof(ARR) / sizeof(ARR[0])) +#endif + diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000000..e59bea0572 --- /dev/null +++ b/main.cpp @@ -0,0 +1,7 @@ +#include + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/tests/test-getcurrentprocessid.cpp b/tests/test-getcurrentprocessid.cpp new file mode 100644 index 0000000000..9803b6612c --- /dev/null +++ b/tests/test-getcurrentprocessid.cpp @@ -0,0 +1,16 @@ +#include +#include "getcurrentprocessorid.h" + +// This is a very simple test case to show how tests can be written +TEST(GetCurrentProcessId,simple) +{ + const HANDLE currentProcessId = GetCurrentProcessId(); + const pid_t pid = getpid(); + + // first make sure that on this platform those types are of the same size + ASSERT_TRUE(sizeof(HANDLE) >= sizeof(pid_t)); + + // now compare the actual values + ASSERT_EQ(currentProcessId,reinterpret_cast(pid)); +} + From 7acaf3a0930adb4d6f019ded1986d3f30c502cc6 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Thu, 5 Mar 2015 14:59:16 -0800 Subject: [PATCH 003/298] added .idea to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..485dee64bc --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea From 8c27f6eb801b1c8923422c301749590aaeb7d3c1 Mon Sep 17 00:00:00 2001 From: Pete Baker Date: Thu, 19 Mar 2015 13:09:36 -0700 Subject: [PATCH 004/298] built and tested - pass --- src/impl/getcurrentthreadid.cpp | 9 +++++++++ src/impl/getcurrentthreadid.h | 10 ++++++++++ src/tests/test-getcurrentthreadid.cpp | 16 ++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 src/impl/getcurrentthreadid.cpp create mode 100644 src/impl/getcurrentthreadid.h create mode 100644 src/tests/test-getcurrentthreadid.cpp diff --git a/src/impl/getcurrentthreadid.cpp b/src/impl/getcurrentthreadid.cpp new file mode 100644 index 0000000000..efd7a31361 --- /dev/null +++ b/src/impl/getcurrentthreadid.cpp @@ -0,0 +1,9 @@ +#include "getcurrentthreadid.h" +#include +#include + +HANDLE GetCurrentThreadId() +{ + pid_t tid = pthread_self(); + return reinterpret_cast(tid); +} diff --git a/src/impl/getcurrentthreadid.h b/src/impl/getcurrentthreadid.h new file mode 100644 index 0000000000..258c3c397f --- /dev/null +++ b/src/impl/getcurrentthreadid.h @@ -0,0 +1,10 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +HANDLE GetCurrentThreadId(); + +PAL_END_EXTERNC + diff --git a/src/tests/test-getcurrentthreadid.cpp b/src/tests/test-getcurrentthreadid.cpp new file mode 100644 index 0000000000..7488d192dd --- /dev/null +++ b/src/tests/test-getcurrentthreadid.cpp @@ -0,0 +1,16 @@ +#include +#include "getcurrentthreadid.h" +#include + +TEST(GetCurrentThreadId,simple) +{ + const HANDLE currentThreadId = GetCurrentThreadId(); + const pid_t tid = pthread_self(); + + // first make sure that on this platform those types are of the same size + ASSERT_TRUE(sizeof(HANDLE) >= sizeof(pid_t)); + + // now compare the actual values + ASSERT_EQ(currentThreadId,reinterpret_cast(tid)); +} + From 0c5f78a223210371576a5c5ec7cda2ae035196bc Mon Sep 17 00:00:00 2001 From: Pete Baker Date: Thu, 19 Mar 2015 13:09:36 -0700 Subject: [PATCH 005/298] built and tested - pass --- impl/getcurrentthreadid.cpp | 9 +++++++++ impl/getcurrentthreadid.h | 10 ++++++++++ tests/test-getcurrentthreadid.cpp | 16 ++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 impl/getcurrentthreadid.cpp create mode 100644 impl/getcurrentthreadid.h create mode 100644 tests/test-getcurrentthreadid.cpp diff --git a/impl/getcurrentthreadid.cpp b/impl/getcurrentthreadid.cpp new file mode 100644 index 0000000000..efd7a31361 --- /dev/null +++ b/impl/getcurrentthreadid.cpp @@ -0,0 +1,9 @@ +#include "getcurrentthreadid.h" +#include +#include + +HANDLE GetCurrentThreadId() +{ + pid_t tid = pthread_self(); + return reinterpret_cast(tid); +} diff --git a/impl/getcurrentthreadid.h b/impl/getcurrentthreadid.h new file mode 100644 index 0000000000..258c3c397f --- /dev/null +++ b/impl/getcurrentthreadid.h @@ -0,0 +1,10 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +HANDLE GetCurrentThreadId(); + +PAL_END_EXTERNC + diff --git a/tests/test-getcurrentthreadid.cpp b/tests/test-getcurrentthreadid.cpp new file mode 100644 index 0000000000..7488d192dd --- /dev/null +++ b/tests/test-getcurrentthreadid.cpp @@ -0,0 +1,16 @@ +#include +#include "getcurrentthreadid.h" +#include + +TEST(GetCurrentThreadId,simple) +{ + const HANDLE currentThreadId = GetCurrentThreadId(); + const pid_t tid = pthread_self(); + + // first make sure that on this platform those types are of the same size + ASSERT_TRUE(sizeof(HANDLE) >= sizeof(pid_t)); + + // now compare the actual values + ASSERT_EQ(currentThreadId,reinterpret_cast(tid)); +} + From ac95206250ac27740a9b91fdde8d6afe682bdb57 Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Fri, 20 Mar 2015 10:07:06 -0700 Subject: [PATCH 006/298] code for cpinfo --- src/CMakeLists.txt | 3 ++- src/impl/getcpinfo.cpp | 27 ++++++++++++++++++++++++ src/impl/getcpinfo.h | 22 ++++++++++++++++++++ src/tests/test-getcpinfo.cpp | 40 ++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 src/impl/getcpinfo.cpp create mode 100644 src/impl/getcpinfo.h create mode 100644 src/tests/test-getcpinfo.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4355f98d04..018b963fcd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,7 +6,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest include_directories(../ext-src/gtest/fused-src impl) -set(SOURCE_FILES main.cpp tests/test-getcurrentprocessid.cpp impl/getcurrentprocessorid.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) +set(SOURCE_FILES main.cpp tests/test-getcurrentprocessid.cpp impl/getcurrentprocessorid.cpp tests/test-getcpinfo.cpp impl/getcpinfo.cpp +../ext-src/gtest/fused-src/gtest/gtest-all.cc) add_executable(monad_native ${SOURCE_FILES}) # add pthread diff --git a/src/impl/getcpinfo.cpp b/src/impl/getcpinfo.cpp new file mode 100644 index 0000000000..1392f79709 --- /dev/null +++ b/src/impl/getcpinfo.cpp @@ -0,0 +1,27 @@ +#include "getcpinfo.h" +#include + +bool GetCPInfo(unsigned int codepage, LPCPINFO cpinfo) +{ + switch(codepage) + { + case 65000: + cpinfo->DefaultChar[0]= '?'; + cpinfo->DefaultChar[1]= '0'; + cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = '0'; + cpinfo->MaxCharSize = 5; + return true; + break; + case 65001: + cpinfo->DefaultChar[0]= '?'; + cpinfo->DefaultChar[1]= '0'; + cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = '0'; + cpinfo->MaxCharSize = 4; + return true; + break; + default: + return false; + } + +} + diff --git a/src/impl/getcpinfo.h b/src/impl/getcpinfo.h new file mode 100644 index 0000000000..2e11196bde --- /dev/null +++ b/src/impl/getcpinfo.h @@ -0,0 +1,22 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + + + const int MAX_DEFAULTCHAR = 2; + + const int MAX_LEADBYTES = 12; + + +typedef struct _cpinfo { + unsigned int MaxCharSize; + char DefaultChar[MAX_DEFAULTCHAR]; + char LeadByte[MAX_LEADBYTES]; +} CPINFO, *LPCPINFO; + + +bool GetCPInfo(unsigned int codepage, LPCPINFO cpinfo); + +PAL_END_EXTERNC diff --git a/src/tests/test-getcpinfo.cpp b/src/tests/test-getcpinfo.cpp new file mode 100644 index 0000000000..2a23121ecc --- /dev/null +++ b/src/tests/test-getcpinfo.cpp @@ -0,0 +1,40 @@ +#include +#include "getcpinfo.h" + +// This is a very simple test case to show how tests can be written +TEST(GetCPInfo,utf8) +{ + + LPCPINFO cpinfo = new CPINFO(); + bool utf8 = GetCPInfo(65001, cpinfo); + + + // first make sure that on this platform those types are of the same size + ASSERT_TRUE(utf8 == 1); + + // now compare the actual values + ASSERT_EQ(cpinfo->DefaultChar[0],'?'); + ASSERT_EQ(cpinfo->DefaultChar[1],'0'); + ASSERT_EQ(cpinfo->LeadByte[0] ,'0'); + ASSERT_EQ(cpinfo->LeadByte[1] ,'0'); + ASSERT_EQ(cpinfo->MaxCharSize ,4); + +} + + +TEST(GetCPInfo,utf7) +{ + LPCPINFO cpinfo = new CPINFO(); + bool utf7 = GetCPInfo(65000, cpinfo); + + + // first make sure that on this platform those types are of the same size + ASSERT_TRUE(utf7 == 1); + + // now compare the actual values + ASSERT_EQ(cpinfo->DefaultChar[0],'?'); + ASSERT_EQ(cpinfo->DefaultChar[1],'0'); + ASSERT_EQ(cpinfo->LeadByte[0] ,'0'); + ASSERT_EQ(cpinfo->LeadByte[1] ,'0'); + ASSERT_EQ(cpinfo->MaxCharSize ,5); +} \ No newline at end of file From 82c111c6c248bb08fded0ec079c3de919c5c30a4 Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Fri, 20 Mar 2015 10:07:06 -0700 Subject: [PATCH 007/298] code for cpinfo --- CMakeLists.txt | 3 ++- impl/getcpinfo.cpp | 27 +++++++++++++++++++++++++++ impl/getcpinfo.h | 22 ++++++++++++++++++++++ tests/test-getcpinfo.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 impl/getcpinfo.cpp create mode 100644 impl/getcpinfo.h create mode 100644 tests/test-getcpinfo.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4355f98d04..018b963fcd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest include_directories(../ext-src/gtest/fused-src impl) -set(SOURCE_FILES main.cpp tests/test-getcurrentprocessid.cpp impl/getcurrentprocessorid.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) +set(SOURCE_FILES main.cpp tests/test-getcurrentprocessid.cpp impl/getcurrentprocessorid.cpp tests/test-getcpinfo.cpp impl/getcpinfo.cpp +../ext-src/gtest/fused-src/gtest/gtest-all.cc) add_executable(monad_native ${SOURCE_FILES}) # add pthread diff --git a/impl/getcpinfo.cpp b/impl/getcpinfo.cpp new file mode 100644 index 0000000000..1392f79709 --- /dev/null +++ b/impl/getcpinfo.cpp @@ -0,0 +1,27 @@ +#include "getcpinfo.h" +#include + +bool GetCPInfo(unsigned int codepage, LPCPINFO cpinfo) +{ + switch(codepage) + { + case 65000: + cpinfo->DefaultChar[0]= '?'; + cpinfo->DefaultChar[1]= '0'; + cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = '0'; + cpinfo->MaxCharSize = 5; + return true; + break; + case 65001: + cpinfo->DefaultChar[0]= '?'; + cpinfo->DefaultChar[1]= '0'; + cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = '0'; + cpinfo->MaxCharSize = 4; + return true; + break; + default: + return false; + } + +} + diff --git a/impl/getcpinfo.h b/impl/getcpinfo.h new file mode 100644 index 0000000000..2e11196bde --- /dev/null +++ b/impl/getcpinfo.h @@ -0,0 +1,22 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + + + const int MAX_DEFAULTCHAR = 2; + + const int MAX_LEADBYTES = 12; + + +typedef struct _cpinfo { + unsigned int MaxCharSize; + char DefaultChar[MAX_DEFAULTCHAR]; + char LeadByte[MAX_LEADBYTES]; +} CPINFO, *LPCPINFO; + + +bool GetCPInfo(unsigned int codepage, LPCPINFO cpinfo); + +PAL_END_EXTERNC diff --git a/tests/test-getcpinfo.cpp b/tests/test-getcpinfo.cpp new file mode 100644 index 0000000000..2a23121ecc --- /dev/null +++ b/tests/test-getcpinfo.cpp @@ -0,0 +1,40 @@ +#include +#include "getcpinfo.h" + +// This is a very simple test case to show how tests can be written +TEST(GetCPInfo,utf8) +{ + + LPCPINFO cpinfo = new CPINFO(); + bool utf8 = GetCPInfo(65001, cpinfo); + + + // first make sure that on this platform those types are of the same size + ASSERT_TRUE(utf8 == 1); + + // now compare the actual values + ASSERT_EQ(cpinfo->DefaultChar[0],'?'); + ASSERT_EQ(cpinfo->DefaultChar[1],'0'); + ASSERT_EQ(cpinfo->LeadByte[0] ,'0'); + ASSERT_EQ(cpinfo->LeadByte[1] ,'0'); + ASSERT_EQ(cpinfo->MaxCharSize ,4); + +} + + +TEST(GetCPInfo,utf7) +{ + LPCPINFO cpinfo = new CPINFO(); + bool utf7 = GetCPInfo(65000, cpinfo); + + + // first make sure that on this platform those types are of the same size + ASSERT_TRUE(utf7 == 1); + + // now compare the actual values + ASSERT_EQ(cpinfo->DefaultChar[0],'?'); + ASSERT_EQ(cpinfo->DefaultChar[1],'0'); + ASSERT_EQ(cpinfo->LeadByte[0] ,'0'); + ASSERT_EQ(cpinfo->LeadByte[1] ,'0'); + ASSERT_EQ(cpinfo->MaxCharSize ,5); +} \ No newline at end of file From 9f4c6d3e02313f84e6878b6266b0d11a43d9d431 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Fri, 3 Apr 2015 10:19:17 -0700 Subject: [PATCH 008/298] added build files and folders to gitignore --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 485dee64bc..45c8b7d406 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,7 @@ .idea +src/.kdev4/ +src/CMakeFiles/ +src/build/ +src/monad_native +src/src.kdev4 + From 70645d5bc1f8d039a240f3753b656a1cdfc7ca70 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Fri, 3 Apr 2015 10:22:05 -0700 Subject: [PATCH 009/298] fetched changes from branch feature/GetComputerName --- CMakeLists.txt | 3 ++- impl/getcomputername.cpp | 8 ++++++++ impl/getcomputername.h | 9 +++++++++ tests/test-getcomputername.cpp | 23 +++++++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 impl/getcomputername.cpp create mode 100644 impl/getcomputername.h create mode 100644 tests/test-getcomputername.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4355f98d04..868a006fa9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest include_directories(../ext-src/gtest/fused-src impl) -set(SOURCE_FILES main.cpp tests/test-getcurrentprocessid.cpp impl/getcurrentprocessorid.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) +set(SOURCE_FILES main.cpp tests/test-getcurrentprocessid.cpp impl/getcurrentprocessorid.cpp tests/test-getcomputername.cpp impl/getcomputername.cpp +../ext-src/gtest/fused-src/gtest/gtest-all.cc) add_executable(monad_native ${SOURCE_FILES}) # add pthread diff --git a/impl/getcomputername.cpp b/impl/getcomputername.cpp new file mode 100644 index 0000000000..f67adab0b5 --- /dev/null +++ b/impl/getcomputername.cpp @@ -0,0 +1,8 @@ +#include "getcomputername.h" +#include + +int GetComputerName(char *name, size_t len) +{ + int host = gethostname(name, len); + return host; +} diff --git a/impl/getcomputername.h b/impl/getcomputername.h new file mode 100644 index 0000000000..a1d6cefe21 --- /dev/null +++ b/impl/getcomputername.h @@ -0,0 +1,9 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +int GetComputerName(char * name, size_t len); + +PAL_END_EXTERNC \ No newline at end of file diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp new file mode 100644 index 0000000000..c2c152ed54 --- /dev/null +++ b/tests/test-getcomputername.cpp @@ -0,0 +1,23 @@ +#include +#include "getcomputername.h" + +TEST(GetComputerName,simple) +{ + + char hostname[128]; + char hostnameFunctionTest[128]; + + int getComputerName = GetComputerName(hostnameFunctionTest, sizeof hostnameFunctionTest); + int host = gethostname(hostname, sizeof hostname); + + // first make sure that on this platform those types are of the same size + + ASSERT_TRUE(getComputerName == 0); + ASSERT_TRUE(host == 0); + + // now compare the actual values + for(int i =0; hostname[i] != '\0'; i++) + { + ASSERT_EQ(hostnameFunctionTest[i],hostname[i]); + } +} \ No newline at end of file From e46e44d701fcc0de19d3c30e2cd26a516ed25fb4 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Fri, 3 Apr 2015 10:22:05 -0700 Subject: [PATCH 010/298] fetched changes from branch feature/GetComputerName --- src/CMakeLists.txt | 3 ++- src/impl/getcomputername.cpp | 8 ++++++++ src/impl/getcomputername.h | 9 +++++++++ src/tests/test-getcomputername.cpp | 23 +++++++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/impl/getcomputername.cpp create mode 100644 src/impl/getcomputername.h create mode 100644 src/tests/test-getcomputername.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4355f98d04..868a006fa9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,7 +6,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest include_directories(../ext-src/gtest/fused-src impl) -set(SOURCE_FILES main.cpp tests/test-getcurrentprocessid.cpp impl/getcurrentprocessorid.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) +set(SOURCE_FILES main.cpp tests/test-getcurrentprocessid.cpp impl/getcurrentprocessorid.cpp tests/test-getcomputername.cpp impl/getcomputername.cpp +../ext-src/gtest/fused-src/gtest/gtest-all.cc) add_executable(monad_native ${SOURCE_FILES}) # add pthread diff --git a/src/impl/getcomputername.cpp b/src/impl/getcomputername.cpp new file mode 100644 index 0000000000..f67adab0b5 --- /dev/null +++ b/src/impl/getcomputername.cpp @@ -0,0 +1,8 @@ +#include "getcomputername.h" +#include + +int GetComputerName(char *name, size_t len) +{ + int host = gethostname(name, len); + return host; +} diff --git a/src/impl/getcomputername.h b/src/impl/getcomputername.h new file mode 100644 index 0000000000..a1d6cefe21 --- /dev/null +++ b/src/impl/getcomputername.h @@ -0,0 +1,9 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +int GetComputerName(char * name, size_t len); + +PAL_END_EXTERNC \ No newline at end of file diff --git a/src/tests/test-getcomputername.cpp b/src/tests/test-getcomputername.cpp new file mode 100644 index 0000000000..c2c152ed54 --- /dev/null +++ b/src/tests/test-getcomputername.cpp @@ -0,0 +1,23 @@ +#include +#include "getcomputername.h" + +TEST(GetComputerName,simple) +{ + + char hostname[128]; + char hostnameFunctionTest[128]; + + int getComputerName = GetComputerName(hostnameFunctionTest, sizeof hostnameFunctionTest); + int host = gethostname(hostname, sizeof hostname); + + // first make sure that on this platform those types are of the same size + + ASSERT_TRUE(getComputerName == 0); + ASSERT_TRUE(host == 0); + + // now compare the actual values + for(int i =0; hostname[i] != '\0'; i++) + { + ASSERT_EQ(hostnameFunctionTest[i],hostname[i]); + } +} \ No newline at end of file From 6194094244805ddd7950c256b7e5ccd486712787 Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Fri, 3 Apr 2015 11:06:30 -0700 Subject: [PATCH 011/298] Changes from notes --- src/impl/getcpinfo.cpp | 31 +++++++++++++++--------------- src/impl/getcpinfo.h | 15 +-------------- src/impl/pal.h | 29 ++++++++++++++++++++++++++++ src/tests/test-getcpinfo.cpp | 37 ++++++++++++++++++------------------ 4 files changed, 64 insertions(+), 48 deletions(-) diff --git a/src/impl/getcpinfo.cpp b/src/impl/getcpinfo.cpp index 1392f79709..0ad41c0a2f 100644 --- a/src/impl/getcpinfo.cpp +++ b/src/impl/getcpinfo.cpp @@ -1,27 +1,28 @@ #include "getcpinfo.h" #include +#include -bool GetCPInfo(unsigned int codepage, LPCPINFO cpinfo) +BOOL GetCPInfo(UINT codepage, CPINFO &cpinfo) { + std::string test; switch(codepage) { case 65000: - cpinfo->DefaultChar[0]= '?'; - cpinfo->DefaultChar[1]= '0'; - cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = '0'; - cpinfo->MaxCharSize = 5; - return true; - break; + cpinfo.DefaultChar[0]= '?'; + cpinfo.DefaultChar[1]= '0'; + cpinfo.LeadByte[0] = '0'; + cpinfo.LeadByte[1] = '0'; + cpinfo.MaxCharSize = 5; + return TRUE; case 65001: - cpinfo->DefaultChar[0]= '?'; - cpinfo->DefaultChar[1]= '0'; - cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = '0'; - cpinfo->MaxCharSize = 4; - return true; - break; + cpinfo.DefaultChar[0]= '?'; + cpinfo.DefaultChar[1]= '0'; + cpinfo.LeadByte[0] = '0'; + cpinfo.LeadByte[1] = '0'; + cpinfo.MaxCharSize = 4; + return TRUE; default: - return false; + return FALSE; } - } diff --git a/src/impl/getcpinfo.h b/src/impl/getcpinfo.h index 2e11196bde..0e5d574628 100644 --- a/src/impl/getcpinfo.h +++ b/src/impl/getcpinfo.h @@ -4,19 +4,6 @@ PAL_BEGIN_EXTERNC - - const int MAX_DEFAULTCHAR = 2; - - const int MAX_LEADBYTES = 12; - - -typedef struct _cpinfo { - unsigned int MaxCharSize; - char DefaultChar[MAX_DEFAULTCHAR]; - char LeadByte[MAX_LEADBYTES]; -} CPINFO, *LPCPINFO; - - -bool GetCPInfo(unsigned int codepage, LPCPINFO cpinfo); +BOOL GetCPInfo(UINT codepage, CPINFO &cpinfo); PAL_END_EXTERNC diff --git a/src/impl/pal.h b/src/impl/pal.h index 659afd4f61..c86ba79b05 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -30,6 +30,7 @@ #include #include #include +#include #ifndef NAME_MAX # define NAME_MAX 255 @@ -59,6 +60,8 @@ typedef char *PSTR; typedef void *PVOID; typedef PVOID HANDLE; + typedef uint32_t UINT; + typedef char BYTE; #define NO_ERROR 0 #define INFINITE 0xFFFFFFFF #define WINAPI @@ -585,3 +588,29 @@ typedef unsigned char PAL_Boolean; # define PAL_COUNT(ARR) (sizeof(ARR) / sizeof(ARR[0])) #endif +/* +**============================================================================== +** +** NameSpace +** +**============================================================================== +*/ + +namespace const_cpinfo{ + constexpr int MAX_DEFAULTCHAR = 2; + constexpr int MAX_LEADBYTES = 12; +} + +/* +**============================================================================== +** +** Structs +** +**============================================================================== +*/ + +typedef struct _cpinfo { + UINT MaxCharSize; + BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; + BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; +} CPINFO; \ No newline at end of file diff --git a/src/tests/test-getcpinfo.cpp b/src/tests/test-getcpinfo.cpp index 2a23121ecc..428261f20f 100644 --- a/src/tests/test-getcpinfo.cpp +++ b/src/tests/test-getcpinfo.cpp @@ -4,37 +4,36 @@ // This is a very simple test case to show how tests can be written TEST(GetCPInfo,utf8) { - - LPCPINFO cpinfo = new CPINFO(); - bool utf8 = GetCPInfo(65001, cpinfo); + CPINFO cpinfo; + BOOL utf8 = GetCPInfo(65001, cpinfo); - // first make sure that on this platform those types are of the same size - ASSERT_TRUE(utf8 == 1); + // first make sure that the function worked + ASSERT_TRUE(utf8 == TRUE); // now compare the actual values - ASSERT_EQ(cpinfo->DefaultChar[0],'?'); - ASSERT_EQ(cpinfo->DefaultChar[1],'0'); - ASSERT_EQ(cpinfo->LeadByte[0] ,'0'); - ASSERT_EQ(cpinfo->LeadByte[1] ,'0'); - ASSERT_EQ(cpinfo->MaxCharSize ,4); + ASSERT_EQ(cpinfo.DefaultChar[0],'?'); + ASSERT_EQ(cpinfo.DefaultChar[1],'0'); + ASSERT_EQ(cpinfo.LeadByte[0] ,'0'); + ASSERT_EQ(cpinfo.LeadByte[1] ,'0'); + ASSERT_EQ(cpinfo.MaxCharSize ,4); } TEST(GetCPInfo,utf7) { - LPCPINFO cpinfo = new CPINFO(); - bool utf7 = GetCPInfo(65000, cpinfo); + CPINFO cpinfo; + BOOL utf7 = GetCPInfo(65000, cpinfo); - // first make sure that on this platform those types are of the same size - ASSERT_TRUE(utf7 == 1); + // first make sure that the function worked + ASSERT_TRUE(utf7 == TRUE); // now compare the actual values - ASSERT_EQ(cpinfo->DefaultChar[0],'?'); - ASSERT_EQ(cpinfo->DefaultChar[1],'0'); - ASSERT_EQ(cpinfo->LeadByte[0] ,'0'); - ASSERT_EQ(cpinfo->LeadByte[1] ,'0'); - ASSERT_EQ(cpinfo->MaxCharSize ,5); + ASSERT_EQ(cpinfo.DefaultChar[0],'?'); + ASSERT_EQ(cpinfo.DefaultChar[1],'0'); + ASSERT_EQ(cpinfo.LeadByte[0] ,'0'); + ASSERT_EQ(cpinfo.LeadByte[1] ,'0'); + ASSERT_EQ(cpinfo.MaxCharSize ,5); } \ No newline at end of file From c84dfa9b63056325345d303d22de631c79a13584 Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Fri, 3 Apr 2015 11:06:30 -0700 Subject: [PATCH 012/298] Changes from notes --- impl/getcpinfo.cpp | 31 ++++++++++++++++--------------- impl/getcpinfo.h | 15 +-------------- impl/pal.h | 29 +++++++++++++++++++++++++++++ tests/test-getcpinfo.cpp | 37 ++++++++++++++++++------------------- 4 files changed, 64 insertions(+), 48 deletions(-) diff --git a/impl/getcpinfo.cpp b/impl/getcpinfo.cpp index 1392f79709..0ad41c0a2f 100644 --- a/impl/getcpinfo.cpp +++ b/impl/getcpinfo.cpp @@ -1,27 +1,28 @@ #include "getcpinfo.h" #include +#include -bool GetCPInfo(unsigned int codepage, LPCPINFO cpinfo) +BOOL GetCPInfo(UINT codepage, CPINFO &cpinfo) { + std::string test; switch(codepage) { case 65000: - cpinfo->DefaultChar[0]= '?'; - cpinfo->DefaultChar[1]= '0'; - cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = '0'; - cpinfo->MaxCharSize = 5; - return true; - break; + cpinfo.DefaultChar[0]= '?'; + cpinfo.DefaultChar[1]= '0'; + cpinfo.LeadByte[0] = '0'; + cpinfo.LeadByte[1] = '0'; + cpinfo.MaxCharSize = 5; + return TRUE; case 65001: - cpinfo->DefaultChar[0]= '?'; - cpinfo->DefaultChar[1]= '0'; - cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = '0'; - cpinfo->MaxCharSize = 4; - return true; - break; + cpinfo.DefaultChar[0]= '?'; + cpinfo.DefaultChar[1]= '0'; + cpinfo.LeadByte[0] = '0'; + cpinfo.LeadByte[1] = '0'; + cpinfo.MaxCharSize = 4; + return TRUE; default: - return false; + return FALSE; } - } diff --git a/impl/getcpinfo.h b/impl/getcpinfo.h index 2e11196bde..0e5d574628 100644 --- a/impl/getcpinfo.h +++ b/impl/getcpinfo.h @@ -4,19 +4,6 @@ PAL_BEGIN_EXTERNC - - const int MAX_DEFAULTCHAR = 2; - - const int MAX_LEADBYTES = 12; - - -typedef struct _cpinfo { - unsigned int MaxCharSize; - char DefaultChar[MAX_DEFAULTCHAR]; - char LeadByte[MAX_LEADBYTES]; -} CPINFO, *LPCPINFO; - - -bool GetCPInfo(unsigned int codepage, LPCPINFO cpinfo); +BOOL GetCPInfo(UINT codepage, CPINFO &cpinfo); PAL_END_EXTERNC diff --git a/impl/pal.h b/impl/pal.h index 659afd4f61..c86ba79b05 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -30,6 +30,7 @@ #include #include #include +#include #ifndef NAME_MAX # define NAME_MAX 255 @@ -59,6 +60,8 @@ typedef char *PSTR; typedef void *PVOID; typedef PVOID HANDLE; + typedef uint32_t UINT; + typedef char BYTE; #define NO_ERROR 0 #define INFINITE 0xFFFFFFFF #define WINAPI @@ -585,3 +588,29 @@ typedef unsigned char PAL_Boolean; # define PAL_COUNT(ARR) (sizeof(ARR) / sizeof(ARR[0])) #endif +/* +**============================================================================== +** +** NameSpace +** +**============================================================================== +*/ + +namespace const_cpinfo{ + constexpr int MAX_DEFAULTCHAR = 2; + constexpr int MAX_LEADBYTES = 12; +} + +/* +**============================================================================== +** +** Structs +** +**============================================================================== +*/ + +typedef struct _cpinfo { + UINT MaxCharSize; + BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; + BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; +} CPINFO; \ No newline at end of file diff --git a/tests/test-getcpinfo.cpp b/tests/test-getcpinfo.cpp index 2a23121ecc..428261f20f 100644 --- a/tests/test-getcpinfo.cpp +++ b/tests/test-getcpinfo.cpp @@ -4,37 +4,36 @@ // This is a very simple test case to show how tests can be written TEST(GetCPInfo,utf8) { - - LPCPINFO cpinfo = new CPINFO(); - bool utf8 = GetCPInfo(65001, cpinfo); + CPINFO cpinfo; + BOOL utf8 = GetCPInfo(65001, cpinfo); - // first make sure that on this platform those types are of the same size - ASSERT_TRUE(utf8 == 1); + // first make sure that the function worked + ASSERT_TRUE(utf8 == TRUE); // now compare the actual values - ASSERT_EQ(cpinfo->DefaultChar[0],'?'); - ASSERT_EQ(cpinfo->DefaultChar[1],'0'); - ASSERT_EQ(cpinfo->LeadByte[0] ,'0'); - ASSERT_EQ(cpinfo->LeadByte[1] ,'0'); - ASSERT_EQ(cpinfo->MaxCharSize ,4); + ASSERT_EQ(cpinfo.DefaultChar[0],'?'); + ASSERT_EQ(cpinfo.DefaultChar[1],'0'); + ASSERT_EQ(cpinfo.LeadByte[0] ,'0'); + ASSERT_EQ(cpinfo.LeadByte[1] ,'0'); + ASSERT_EQ(cpinfo.MaxCharSize ,4); } TEST(GetCPInfo,utf7) { - LPCPINFO cpinfo = new CPINFO(); - bool utf7 = GetCPInfo(65000, cpinfo); + CPINFO cpinfo; + BOOL utf7 = GetCPInfo(65000, cpinfo); - // first make sure that on this platform those types are of the same size - ASSERT_TRUE(utf7 == 1); + // first make sure that the function worked + ASSERT_TRUE(utf7 == TRUE); // now compare the actual values - ASSERT_EQ(cpinfo->DefaultChar[0],'?'); - ASSERT_EQ(cpinfo->DefaultChar[1],'0'); - ASSERT_EQ(cpinfo->LeadByte[0] ,'0'); - ASSERT_EQ(cpinfo->LeadByte[1] ,'0'); - ASSERT_EQ(cpinfo->MaxCharSize ,5); + ASSERT_EQ(cpinfo.DefaultChar[0],'?'); + ASSERT_EQ(cpinfo.DefaultChar[1],'0'); + ASSERT_EQ(cpinfo.LeadByte[0] ,'0'); + ASSERT_EQ(cpinfo.LeadByte[1] ,'0'); + ASSERT_EQ(cpinfo.MaxCharSize ,5); } \ No newline at end of file From ea7b78ef1c00106b03a1cfd2bf4b4aa049415e27 Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Mon, 6 Apr 2015 09:57:16 -0700 Subject: [PATCH 013/298] changes based on comments --- impl/getcomputername.cpp | 10 ++++++--- impl/getcomputername.h | 2 +- impl/pal.h | 3 +++ tests/test-getcomputername.cpp | 37 +++++++++++++++++++--------------- 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/impl/getcomputername.cpp b/impl/getcomputername.cpp index f67adab0b5..66a34e67ef 100644 --- a/impl/getcomputername.cpp +++ b/impl/getcomputername.cpp @@ -1,8 +1,12 @@ #include "getcomputername.h" #include -int GetComputerName(char *name, size_t len) +BOOL GetComputerName(LPTSTR name, LPDWORD len) { - int host = gethostname(name, len); - return host; + int host = gethostname(name, HOST_NAME_MAX); + if(host == 0) + { + return TRUE; + } + return FALSE; } diff --git a/impl/getcomputername.h b/impl/getcomputername.h index a1d6cefe21..7f8dd8eb5a 100644 --- a/impl/getcomputername.h +++ b/impl/getcomputername.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -int GetComputerName(char * name, size_t len); +BOOL GetComputerName(LPTSTR name, LPDWORD len); PAL_END_EXTERNC \ No newline at end of file diff --git a/impl/pal.h b/impl/pal.h index 659afd4f61..defde3b1fb 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -59,6 +59,9 @@ typedef char *PSTR; typedef void *PVOID; typedef PVOID HANDLE; + typedef char TCHAR; + typedef TCHAR *LPTSTR; + typedef DWORD *LPDWORD; #define NO_ERROR 0 #define INFINITE 0xFFFFFFFF #define WINAPI diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index c2c152ed54..f4ce811fc4 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -2,22 +2,27 @@ #include "getcomputername.h" TEST(GetComputerName,simple) -{ - - char hostname[128]; - char hostnameFunctionTest[128]; +{ + char hostname[HOST_NAME_MAX]; + TCHAR hostnameFunctionTest[HOST_NAME_MAX]; + DWORD hostSize = HOST_NAME_MAX; - int getComputerName = GetComputerName(hostnameFunctionTest, sizeof hostnameFunctionTest); - int host = gethostname(hostname, sizeof hostname); + BOOL getComputerName = GetComputerName(hostnameFunctionTest, &hostSize); + BOOL host = gethostname(hostname, sizeof hostname); - // first make sure that on this platform those types are of the same size - - ASSERT_TRUE(getComputerName == 0); - ASSERT_TRUE(host == 0); - - // now compare the actual values - for(int i =0; hostname[i] != '\0'; i++) - { - ASSERT_EQ(hostnameFunctionTest[i],hostname[i]); - } + if(host == 0) + { + host = TRUE; + } + else + { + host = FALSE; + } + + std::string hostnameSting(hostname); + std::string hostnameStingTest(hostnameFunctionTest); + + ASSERT_TRUE(getComputerName == TRUE); + ASSERT_EQ(host,TRUE); + ASSERT_EQ(hostnameSting,hostnameFunctionTest); } \ No newline at end of file From 03eae4653ad64151ef5d978a630e322de699f4ce Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Mon, 6 Apr 2015 09:57:16 -0700 Subject: [PATCH 014/298] changes based on comments --- src/impl/getcomputername.cpp | 10 +++++--- src/impl/getcomputername.h | 2 +- src/impl/pal.h | 3 +++ src/tests/test-getcomputername.cpp | 37 +++++++++++++++++------------- 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/impl/getcomputername.cpp b/src/impl/getcomputername.cpp index f67adab0b5..66a34e67ef 100644 --- a/src/impl/getcomputername.cpp +++ b/src/impl/getcomputername.cpp @@ -1,8 +1,12 @@ #include "getcomputername.h" #include -int GetComputerName(char *name, size_t len) +BOOL GetComputerName(LPTSTR name, LPDWORD len) { - int host = gethostname(name, len); - return host; + int host = gethostname(name, HOST_NAME_MAX); + if(host == 0) + { + return TRUE; + } + return FALSE; } diff --git a/src/impl/getcomputername.h b/src/impl/getcomputername.h index a1d6cefe21..7f8dd8eb5a 100644 --- a/src/impl/getcomputername.h +++ b/src/impl/getcomputername.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -int GetComputerName(char * name, size_t len); +BOOL GetComputerName(LPTSTR name, LPDWORD len); PAL_END_EXTERNC \ No newline at end of file diff --git a/src/impl/pal.h b/src/impl/pal.h index 659afd4f61..defde3b1fb 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -59,6 +59,9 @@ typedef char *PSTR; typedef void *PVOID; typedef PVOID HANDLE; + typedef char TCHAR; + typedef TCHAR *LPTSTR; + typedef DWORD *LPDWORD; #define NO_ERROR 0 #define INFINITE 0xFFFFFFFF #define WINAPI diff --git a/src/tests/test-getcomputername.cpp b/src/tests/test-getcomputername.cpp index c2c152ed54..f4ce811fc4 100644 --- a/src/tests/test-getcomputername.cpp +++ b/src/tests/test-getcomputername.cpp @@ -2,22 +2,27 @@ #include "getcomputername.h" TEST(GetComputerName,simple) -{ - - char hostname[128]; - char hostnameFunctionTest[128]; +{ + char hostname[HOST_NAME_MAX]; + TCHAR hostnameFunctionTest[HOST_NAME_MAX]; + DWORD hostSize = HOST_NAME_MAX; - int getComputerName = GetComputerName(hostnameFunctionTest, sizeof hostnameFunctionTest); - int host = gethostname(hostname, sizeof hostname); + BOOL getComputerName = GetComputerName(hostnameFunctionTest, &hostSize); + BOOL host = gethostname(hostname, sizeof hostname); - // first make sure that on this platform those types are of the same size - - ASSERT_TRUE(getComputerName == 0); - ASSERT_TRUE(host == 0); - - // now compare the actual values - for(int i =0; hostname[i] != '\0'; i++) - { - ASSERT_EQ(hostnameFunctionTest[i],hostname[i]); - } + if(host == 0) + { + host = TRUE; + } + else + { + host = FALSE; + } + + std::string hostnameSting(hostname); + std::string hostnameStingTest(hostnameFunctionTest); + + ASSERT_TRUE(getComputerName == TRUE); + ASSERT_EQ(host,TRUE); + ASSERT_EQ(hostnameSting,hostnameFunctionTest); } \ No newline at end of file From a0f238906bb9a964e8c7af8367bf375d1a5d1d30 Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Thu, 9 Apr 2015 14:51:10 -0700 Subject: [PATCH 015/298] Changes to spacing --- src/impl/.getcpinfo.cpp.kate-swp | Bin 0 -> 1435 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/impl/.getcpinfo.cpp.kate-swp diff --git a/src/impl/.getcpinfo.cpp.kate-swp b/src/impl/.getcpinfo.cpp.kate-swp new file mode 100644 index 0000000000000000000000000000000000000000..91e90a6f3b104a0b2f013e4b582b5deea2b7eeba GIT binary patch literal 1435 zcmZ9LIZgvX5JlU&0q+~m7$8R$5=Sr+B7y-qHj)D*0sD zC6(;w{`KcicRQstx?aC*vV6OK&MqIHHre^vBBeA~y?(xbKYZ-ny?xzW{QPe7EBUo4 zU6rn6%YUu~Zk5*IxZWfumGWs9pR7$q$JI~d~}xiNfgv9l@_`{ANLjw2<{QW_5|!KFg0`KO zUBMAE(zekcWi}(VVfIvQTu`zZGb3#_AZ0dVwPDt5Tu`!^Fe7a?AZ0cawPE&H)3~5y zGi65FY(UCvrfS2i*|?x&GZRHP9xxma7>)-F#{-54AY~C|8iD891$IFx!dw&~0vIBI bAp#g8fFS}%S%kSpIFw)Hugwi{K@s5(Su1(; literal 0 HcmV?d00001 From 6c716b6fa03b4999a5fb587faf317c609c939ad0 Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Thu, 9 Apr 2015 14:51:10 -0700 Subject: [PATCH 016/298] Changes to spacing --- impl/.getcpinfo.cpp.kate-swp | Bin 0 -> 1435 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 impl/.getcpinfo.cpp.kate-swp diff --git a/impl/.getcpinfo.cpp.kate-swp b/impl/.getcpinfo.cpp.kate-swp new file mode 100644 index 0000000000000000000000000000000000000000..91e90a6f3b104a0b2f013e4b582b5deea2b7eeba GIT binary patch literal 1435 zcmZ9LIZgvX5JlU&0q+~m7$8R$5=Sr+B7y-qHj)D*0sD zC6(;w{`KcicRQstx?aC*vV6OK&MqIHHre^vBBeA~y?(xbKYZ-ny?xzW{QPe7EBUo4 zU6rn6%YUu~Zk5*IxZWfumGWs9pR7$q$JI~d~}xiNfgv9l@_`{ANLjw2<{QW_5|!KFg0`KO zUBMAE(zekcWi}(VVfIvQTu`zZGb3#_AZ0dVwPDt5Tu`!^Fe7a?AZ0cawPE&H)3~5y zGi65FY(UCvrfS2i*|?x&GZRHP9xxma7>)-F#{-54AY~C|8iD891$IFx!dw&~0vIBI bAp#g8fFS}%S%kSpIFw)Hugwi{K@s5(Su1(; literal 0 HcmV?d00001 From 299e362d112d6c6a403e91e44754c21ec04e3591 Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Thu, 9 Apr 2015 15:16:37 -0700 Subject: [PATCH 017/298] changed spacing and using std::string instead of TCHAR --- impl/getcomputername.cpp | 12 ++++++------ tests/test-getcomputername.cpp | 15 +++++++-------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/impl/getcomputername.cpp b/impl/getcomputername.cpp index 66a34e67ef..1ec69110c2 100644 --- a/impl/getcomputername.cpp +++ b/impl/getcomputername.cpp @@ -3,10 +3,10 @@ BOOL GetComputerName(LPTSTR name, LPDWORD len) { - int host = gethostname(name, HOST_NAME_MAX); - if(host == 0) - { - return TRUE; - } - return FALSE; + int host = gethostname(name, HOST_NAME_MAX); + if(host == 0) + { + return TRUE; + } + return FALSE; } diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index f4ce811fc4..8b0f19f5d7 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -4,25 +4,24 @@ TEST(GetComputerName,simple) { char hostname[HOST_NAME_MAX]; - TCHAR hostnameFunctionTest[HOST_NAME_MAX]; + std::string hostnameFunctionTest; DWORD hostSize = HOST_NAME_MAX; - - BOOL getComputerName = GetComputerName(hostnameFunctionTest, &hostSize); + BOOL getComputerName = GetComputerName(&hostnameFunctionTest[0], &hostSize); BOOL host = gethostname(hostname, sizeof hostname); if(host == 0) { - host = TRUE; + host = TRUE; } else { - host = FALSE; + host = FALSE; } - std::string hostnameSting(hostname); - std::string hostnameStingTest(hostnameFunctionTest); + std::string hostnameString(hostname); + std::string hostnameStringTest(&hostnameFunctionTest[0]); ASSERT_TRUE(getComputerName == TRUE); ASSERT_EQ(host,TRUE); - ASSERT_EQ(hostnameSting,hostnameFunctionTest); + ASSERT_EQ(hostnameString,hostnameStringTest); } \ No newline at end of file From 0245ab771ee6d460e859ed59acc05095bbbc6e05 Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Thu, 9 Apr 2015 15:16:37 -0700 Subject: [PATCH 018/298] changed spacing and using std::string instead of TCHAR --- src/impl/getcomputername.cpp | 12 ++++++------ src/tests/test-getcomputername.cpp | 15 +++++++-------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/impl/getcomputername.cpp b/src/impl/getcomputername.cpp index 66a34e67ef..1ec69110c2 100644 --- a/src/impl/getcomputername.cpp +++ b/src/impl/getcomputername.cpp @@ -3,10 +3,10 @@ BOOL GetComputerName(LPTSTR name, LPDWORD len) { - int host = gethostname(name, HOST_NAME_MAX); - if(host == 0) - { - return TRUE; - } - return FALSE; + int host = gethostname(name, HOST_NAME_MAX); + if(host == 0) + { + return TRUE; + } + return FALSE; } diff --git a/src/tests/test-getcomputername.cpp b/src/tests/test-getcomputername.cpp index f4ce811fc4..8b0f19f5d7 100644 --- a/src/tests/test-getcomputername.cpp +++ b/src/tests/test-getcomputername.cpp @@ -4,25 +4,24 @@ TEST(GetComputerName,simple) { char hostname[HOST_NAME_MAX]; - TCHAR hostnameFunctionTest[HOST_NAME_MAX]; + std::string hostnameFunctionTest; DWORD hostSize = HOST_NAME_MAX; - - BOOL getComputerName = GetComputerName(hostnameFunctionTest, &hostSize); + BOOL getComputerName = GetComputerName(&hostnameFunctionTest[0], &hostSize); BOOL host = gethostname(hostname, sizeof hostname); if(host == 0) { - host = TRUE; + host = TRUE; } else { - host = FALSE; + host = FALSE; } - std::string hostnameSting(hostname); - std::string hostnameStingTest(hostnameFunctionTest); + std::string hostnameString(hostname); + std::string hostnameStringTest(&hostnameFunctionTest[0]); ASSERT_TRUE(getComputerName == TRUE); ASSERT_EQ(host,TRUE); - ASSERT_EQ(hostnameSting,hostnameFunctionTest); + ASSERT_EQ(hostnameString,hostnameStringTest); } \ No newline at end of file From e9a2a2d8a237c5b67bffa824045cfcd1cf991699 Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Thu, 9 Apr 2015 15:23:57 -0700 Subject: [PATCH 019/298] changed spacing --- src/impl/getcpinfo.cpp | 32 ++++++++++++------------ src/tests/test-getcpinfo.cpp | 48 +++++++++++++++++------------------- 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/src/impl/getcpinfo.cpp b/src/impl/getcpinfo.cpp index 0ad41c0a2f..857b00de71 100644 --- a/src/impl/getcpinfo.cpp +++ b/src/impl/getcpinfo.cpp @@ -4,25 +4,25 @@ BOOL GetCPInfo(UINT codepage, CPINFO &cpinfo) { - std::string test; - switch(codepage) - { + std::string test; + switch(codepage) + { case 65000: - cpinfo.DefaultChar[0]= '?'; - cpinfo.DefaultChar[1]= '0'; - cpinfo.LeadByte[0] = '0'; - cpinfo.LeadByte[1] = '0'; - cpinfo.MaxCharSize = 5; - return TRUE; + cpinfo.DefaultChar[0] = '?'; + cpinfo.DefaultChar[1] = '0'; + cpinfo.LeadByte[0] = '0'; + cpinfo.LeadByte[1] = '0'; + cpinfo.MaxCharSize = 5; + return TRUE; case 65001: - cpinfo.DefaultChar[0]= '?'; - cpinfo.DefaultChar[1]= '0'; - cpinfo.LeadByte[0] = '0'; - cpinfo.LeadByte[1] = '0'; - cpinfo.MaxCharSize = 4; - return TRUE; + cpinfo.DefaultChar[0] = '?'; + cpinfo.DefaultChar[1] = '0'; + cpinfo.LeadByte[0] = '0'; + cpinfo.LeadByte[1] = '0'; + cpinfo.MaxCharSize = 4; + return TRUE; default: - return FALSE; + return FALSE; } } diff --git a/src/tests/test-getcpinfo.cpp b/src/tests/test-getcpinfo.cpp index 428261f20f..0a8d110e9b 100644 --- a/src/tests/test-getcpinfo.cpp +++ b/src/tests/test-getcpinfo.cpp @@ -4,36 +4,32 @@ // This is a very simple test case to show how tests can be written TEST(GetCPInfo,utf8) { - CPINFO cpinfo; - BOOL utf8 = GetCPInfo(65001, cpinfo); - + CPINFO cpinfo; + BOOL utf8 = GetCPInfo(65001, cpinfo); - // first make sure that the function worked - ASSERT_TRUE(utf8 == TRUE); - - // now compare the actual values - ASSERT_EQ(cpinfo.DefaultChar[0],'?'); - ASSERT_EQ(cpinfo.DefaultChar[1],'0'); - ASSERT_EQ(cpinfo.LeadByte[0] ,'0'); - ASSERT_EQ(cpinfo.LeadByte[1] ,'0'); - ASSERT_EQ(cpinfo.MaxCharSize ,4); - + // first make sure that the function worked + ASSERT_TRUE(utf8 == TRUE); + + // now compare the actual values + ASSERT_EQ(cpinfo.DefaultChar[0],'?'); + ASSERT_EQ(cpinfo.DefaultChar[1],'0'); + ASSERT_EQ(cpinfo.LeadByte[0],'0'); + ASSERT_EQ(cpinfo.LeadByte[1],'0'); + ASSERT_EQ(cpinfo.MaxCharSize,4); } - TEST(GetCPInfo,utf7) { - CPINFO cpinfo; - BOOL utf7 = GetCPInfo(65000, cpinfo); - + CPINFO cpinfo; + BOOL utf7 = GetCPInfo(65000, cpinfo); + + // first make sure that the function worked + ASSERT_TRUE(utf7 == TRUE); - // first make sure that the function worked - ASSERT_TRUE(utf7 == TRUE); - - // now compare the actual values - ASSERT_EQ(cpinfo.DefaultChar[0],'?'); - ASSERT_EQ(cpinfo.DefaultChar[1],'0'); - ASSERT_EQ(cpinfo.LeadByte[0] ,'0'); - ASSERT_EQ(cpinfo.LeadByte[1] ,'0'); - ASSERT_EQ(cpinfo.MaxCharSize ,5); + // now compare the actual values + ASSERT_EQ(cpinfo.DefaultChar[0],'?'); + ASSERT_EQ(cpinfo.DefaultChar[1],'0'); + ASSERT_EQ(cpinfo.LeadByte[0],'0'); + ASSERT_EQ(cpinfo.LeadByte[1],'0'); + ASSERT_EQ(cpinfo.MaxCharSize,5); } \ No newline at end of file From 439381cbf6710893da4809efcae0848af6f62828 Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Thu, 9 Apr 2015 15:23:57 -0700 Subject: [PATCH 020/298] changed spacing --- impl/getcpinfo.cpp | 32 +++++++++++++-------------- tests/test-getcpinfo.cpp | 48 ++++++++++++++++++---------------------- 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/impl/getcpinfo.cpp b/impl/getcpinfo.cpp index 0ad41c0a2f..857b00de71 100644 --- a/impl/getcpinfo.cpp +++ b/impl/getcpinfo.cpp @@ -4,25 +4,25 @@ BOOL GetCPInfo(UINT codepage, CPINFO &cpinfo) { - std::string test; - switch(codepage) - { + std::string test; + switch(codepage) + { case 65000: - cpinfo.DefaultChar[0]= '?'; - cpinfo.DefaultChar[1]= '0'; - cpinfo.LeadByte[0] = '0'; - cpinfo.LeadByte[1] = '0'; - cpinfo.MaxCharSize = 5; - return TRUE; + cpinfo.DefaultChar[0] = '?'; + cpinfo.DefaultChar[1] = '0'; + cpinfo.LeadByte[0] = '0'; + cpinfo.LeadByte[1] = '0'; + cpinfo.MaxCharSize = 5; + return TRUE; case 65001: - cpinfo.DefaultChar[0]= '?'; - cpinfo.DefaultChar[1]= '0'; - cpinfo.LeadByte[0] = '0'; - cpinfo.LeadByte[1] = '0'; - cpinfo.MaxCharSize = 4; - return TRUE; + cpinfo.DefaultChar[0] = '?'; + cpinfo.DefaultChar[1] = '0'; + cpinfo.LeadByte[0] = '0'; + cpinfo.LeadByte[1] = '0'; + cpinfo.MaxCharSize = 4; + return TRUE; default: - return FALSE; + return FALSE; } } diff --git a/tests/test-getcpinfo.cpp b/tests/test-getcpinfo.cpp index 428261f20f..0a8d110e9b 100644 --- a/tests/test-getcpinfo.cpp +++ b/tests/test-getcpinfo.cpp @@ -4,36 +4,32 @@ // This is a very simple test case to show how tests can be written TEST(GetCPInfo,utf8) { - CPINFO cpinfo; - BOOL utf8 = GetCPInfo(65001, cpinfo); - + CPINFO cpinfo; + BOOL utf8 = GetCPInfo(65001, cpinfo); - // first make sure that the function worked - ASSERT_TRUE(utf8 == TRUE); - - // now compare the actual values - ASSERT_EQ(cpinfo.DefaultChar[0],'?'); - ASSERT_EQ(cpinfo.DefaultChar[1],'0'); - ASSERT_EQ(cpinfo.LeadByte[0] ,'0'); - ASSERT_EQ(cpinfo.LeadByte[1] ,'0'); - ASSERT_EQ(cpinfo.MaxCharSize ,4); - + // first make sure that the function worked + ASSERT_TRUE(utf8 == TRUE); + + // now compare the actual values + ASSERT_EQ(cpinfo.DefaultChar[0],'?'); + ASSERT_EQ(cpinfo.DefaultChar[1],'0'); + ASSERT_EQ(cpinfo.LeadByte[0],'0'); + ASSERT_EQ(cpinfo.LeadByte[1],'0'); + ASSERT_EQ(cpinfo.MaxCharSize,4); } - TEST(GetCPInfo,utf7) { - CPINFO cpinfo; - BOOL utf7 = GetCPInfo(65000, cpinfo); - + CPINFO cpinfo; + BOOL utf7 = GetCPInfo(65000, cpinfo); + + // first make sure that the function worked + ASSERT_TRUE(utf7 == TRUE); - // first make sure that the function worked - ASSERT_TRUE(utf7 == TRUE); - - // now compare the actual values - ASSERT_EQ(cpinfo.DefaultChar[0],'?'); - ASSERT_EQ(cpinfo.DefaultChar[1],'0'); - ASSERT_EQ(cpinfo.LeadByte[0] ,'0'); - ASSERT_EQ(cpinfo.LeadByte[1] ,'0'); - ASSERT_EQ(cpinfo.MaxCharSize ,5); + // now compare the actual values + ASSERT_EQ(cpinfo.DefaultChar[0],'?'); + ASSERT_EQ(cpinfo.DefaultChar[1],'0'); + ASSERT_EQ(cpinfo.LeadByte[0],'0'); + ASSERT_EQ(cpinfo.LeadByte[1],'0'); + ASSERT_EQ(cpinfo.MaxCharSize,5); } \ No newline at end of file From 95450a16ed4eede74fa20b7d975094a2709f2d73 Mon Sep 17 00:00:00 2001 From: Aditya Mandaleeka Date: Tue, 21 Apr 2015 23:47:33 -0700 Subject: [PATCH 021/298] Add Unix version of coreconsole. Created a Unix version of coreconsole which, like the Windows version, is similar to corerun but runs the managed binary with the same name as the executable (but with the DLL extension). Moved code that is common between corerun and coreconsole to coreruncommon. Remove the workaround for the XCode 6.3 SDK issue wherein some of the system headers that we reference try to include a __debug header which does not exist. The 6.3.1 update fixed that issue so the workaround is no longer required. Fix #747 --- .gitmirror | 1 + coreruncommon.cpp | 311 ++++++++++++++++++++++++++++++++++++++++++++++ coreruncommon.h | 46 +++++++ 3 files changed, 358 insertions(+) create mode 100644 .gitmirror create mode 100644 coreruncommon.cpp create mode 100644 coreruncommon.h diff --git a/.gitmirror b/.gitmirror new file mode 100644 index 0000000000..f507630f94 --- /dev/null +++ b/.gitmirror @@ -0,0 +1 @@ +Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror. \ No newline at end of file diff --git a/coreruncommon.cpp b/coreruncommon.cpp new file mode 100644 index 0000000000..1294038664 --- /dev/null +++ b/coreruncommon.cpp @@ -0,0 +1,311 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +// +// Code that is used by both the Unix corerun and coreconsole. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +// The name of the CoreCLR native runtime DLL +#if defined(__APPLE__) +static const char * const coreClrDll = "libcoreclr.dylib"; +#else +static const char * const coreClrDll = "libcoreclr.so"; +#endif + +// Windows types used by the ExecuteAssembly function +typedef unsigned int DWORD; +typedef const char16_t* LPCWSTR; +typedef const char* LPCSTR; +typedef int32_t HRESULT; + +#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0) + +// Prototype of the ExecuteAssembly function from the libcoreclr.do +typedef HRESULT (*ExecuteAssemblyFunction)( + LPCSTR exePath, + LPCSTR coreClrPath, + LPCSTR appDomainFriendlyName, + int propertyCount, + LPCSTR* propertyKeys, + LPCSTR* propertyValues, + int argc, + LPCSTR* argv, + LPCSTR managedAssemblyPath, + LPCSTR entryPointAssemblyName, + LPCSTR entryPointTypeName, + LPCSTR entryPointMethodsName, + DWORD* exitCode); + +bool GetAbsolutePath(const char* path, std::string& absolutePath) +{ + bool result = false; + + char realPath[PATH_MAX]; + if (realpath(path, realPath) != nullptr && realPath[0] != '\0') + { + absolutePath.assign(realPath); + // realpath should return canonicalized path without the trailing slash + assert(absolutePath.back() != '/'); + + result = true; + } + + return result; +} + +bool GetDirectory(const char* absolutePath, std::string& directory) +{ + directory.assign(absolutePath); + size_t lastSlash = directory.rfind('/'); + if (lastSlash != std::string::npos) + { + directory.erase(lastSlash); + return true; + } + + return false; +} + +bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) +{ + std::string clrFilesRelativePath; + const char* clrFilesPathLocal = clrFilesPath; + if (clrFilesPathLocal == nullptr) + { + // There was no CLR files path specified, use the folder of the corerun/coreconsole + if (!GetDirectory(currentExePath, clrFilesRelativePath)) + { + perror("Failed to get directory from argv[0]"); + return false; + } + + clrFilesPathLocal = clrFilesRelativePath.c_str(); + + // TODO: consider using an env variable (if defined) as a fall-back. + // The windows version of the corerun uses core_root env variable + } + + if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) + { + perror("Failed to convert CLR files path to absolute path"); + return false; + } + + return true; +} + +void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) +{ + const char * const tpaExtensions[] = { + ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir + ".dll", + ".ni.exe", + ".exe", + }; + + DIR* dir = opendir(directory); + if (dir == nullptr) + { + return; + } + + std::set addedAssemblies; + + // Walk the directory for each extension separately so that we first get files with .ni.dll extension, + // then files with .dll extension, etc. + for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + { + const char* ext = tpaExtensions[extIndex]; + int extLength = strlen(ext); + + struct dirent* entry; + + // For all entries in the directory + while ((entry = readdir(dir)) != nullptr) + { + // We are interested in files only + switch (entry->d_type) + { + case DT_REG: + break; + + // Handle symlinks and file systems that do not support d_type + case DT_LNK: + case DT_UNKNOWN: + { + std::string fullFilename; + + fullFilename.append(directory); + fullFilename.append("/"); + fullFilename.append(entry->d_name); + + struct stat sb; + if (stat(fullFilename.c_str(), &sb) == -1) + { + continue; + } + + if (!S_ISREG(sb.st_mode)) + { + continue; + } + } + break; + + default: + continue; + } + + std::string filename(entry->d_name); + + // Check if the extension matches the one we are looking for + int extPos = filename.length() - extLength; + if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) + { + continue; + } + + std::string filenameWithoutExt(filename.substr(0, extPos)); + + // Make sure if we have an assembly with multiple extensions present, + // we insert only one version of it. + if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) + { + addedAssemblies.insert(filenameWithoutExt); + + tpaList.append(directory); + tpaList.append("/"); + tpaList.append(filename); + tpaList.append(":"); + } + } + + // Rewind the directory stream to be able to iterate over it for the next extension + rewinddir(dir); + } + + closedir(dir); +} + +int ExecuteManagedAssembly( + const char* currentExeAbsolutePath, + const char* clrFilesAbsolutePath, + const char* managedAssemblyAbsolutePath, + int managedAssemblyArgc, + const char** managedAssemblyArgv) +{ + // Indicates failure + int exitCode = -1; + + std::string coreClrDllPath(clrFilesAbsolutePath); + coreClrDllPath.append("/"); + coreClrDllPath.append(coreClrDll); + + if (coreClrDllPath.length() >= PATH_MAX) + { + fprintf(stderr, "Absolute path to libcoreclr.so too long\n"); + return -1; + } + + // Get just the path component of the managed assembly path + std::string appPath; + GetDirectory(managedAssemblyAbsolutePath, appPath); + + std::string nativeDllSearchDirs(appPath); + nativeDllSearchDirs.append(":"); + nativeDllSearchDirs.append(clrFilesAbsolutePath); + + std::string tpaList; + AddFilesFromDirectoryToTpaList(clrFilesAbsolutePath, tpaList); + + void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW | RTLD_LOCAL); + if (coreclrLib != nullptr) + { + ExecuteAssemblyFunction executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib, "ExecuteAssembly"); + if (executeAssembly != nullptr) + { + // Allowed property names: + // APPBASE + // - The base path of the application from which the exe and other assemblies will be loaded + // + // TRUSTED_PLATFORM_ASSEMBLIES + // - The list of complete paths to each of the fully trusted assemblies + // + // APP_PATHS + // - The list of paths which will be probed by the assembly loader + // + // APP_NI_PATHS + // - The list of additional paths that the assembly loader will probe for ngen images + // + // NATIVE_DLL_SEARCH_DIRECTORIES + // - The list of paths that will be probed for native DLLs called by PInvoke + // + const char *propertyKeys[] = { + "TRUSTED_PLATFORM_ASSEMBLIES", + "APP_PATHS", + "APP_NI_PATHS", + "NATIVE_DLL_SEARCH_DIRECTORIES", + "AppDomainCompatSwitch" + }; + const char *propertyValues[] = { + // TRUSTED_PLATFORM_ASSEMBLIES + tpaList.c_str(), + // APP_PATHS + appPath.c_str(), + // APP_NI_PATHS + appPath.c_str(), + // NATIVE_DLL_SEARCH_DIRECTORIES + nativeDllSearchDirs.c_str(), + // AppDomainCompatSwitch + "UseLatestBehaviorWhenTFMNotSpecified" + }; + + HRESULT st = executeAssembly( + currentExeAbsolutePath, + coreClrDllPath.c_str(), + "unixcorerun", + sizeof(propertyKeys) / sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + managedAssemblyArgc, + managedAssemblyArgv, + managedAssemblyAbsolutePath, + NULL, + NULL, + NULL, + (DWORD*)&exitCode); + + if (!SUCCEEDED(st)) + { + fprintf(stderr, "ExecuteAssembly failed - status: 0x%08x\n", st); + } + } + else + { + fprintf(stderr, "Function ExecuteAssembly not found in the libcoreclr.so\n"); + } + + if (dlclose(coreclrLib) != 0) + { + fprintf(stderr, "Warning - dlclose failed\n"); + } + } + else + { + char* error = dlerror(); + fprintf(stderr, "dlopen failed to open the libcoreclr.so with error %s\n", error); + } + + return exitCode; +} diff --git a/coreruncommon.h b/coreruncommon.h new file mode 100644 index 0000000000..b587e407fc --- /dev/null +++ b/coreruncommon.h @@ -0,0 +1,46 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +#include + +// Get absolute path from the specified path. +// Return true in case of a success, false otherwise. +bool GetAbsolutePath(const char* path, std::string& absolutePath); + +// Get directory of the specified path. +// Return true in case of a success, false otherwise. +bool GetDirectory(const char* absolutePath, std::string& directory); + +// +// Get the absolute path to use to locate libcoreclr.so and the CLR assemblies are stored. If clrFilesPath is provided, +// this function will return the absolute path to it. Otherwise, the directory of the current executable is used. +// +// Return true in case of a success, false otherwise. +// +bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); + +// Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. +void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); + +// +// Execute the specified managed assembly. +// +// Parameters: +// currentExePath - Path to the current executable +// clrFilesAbsolutePath - Absolute path to the folder where the libcoreclr.so and CLR managed assemblies are stored +// managedAssemblyPath - Path to the managed assembly to execute +// managedAssemblyArgc - Number of arguments passed to the executed assembly +// managedAssemblyArgv - Array of arguments passed to the executed assembly +// +// Returns: +// ExitCode of the assembly +// +int ExecuteManagedAssembly( + const char* currentExeAbsolutePath, + const char* clrFilesAbsolutePath, + const char* managedAssemblyAbsolutePath, + int managedAssemblyArgc, + const char** managedAssemblyArgv); + From accac3138edc494b1466b4c4642b2b820755dcba Mon Sep 17 00:00:00 2001 From: Anders Jensen-Waud Date: Fri, 1 May 2015 11:16:53 +1000 Subject: [PATCH 022/298] Fix unixcoreruncommon build error on FreeBSD Needed cstdlib to build properly --- coreruncommon.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/coreruncommon.cpp b/coreruncommon.cpp index 1294038664..e7323c177a 100644 --- a/coreruncommon.cpp +++ b/coreruncommon.cpp @@ -7,6 +7,7 @@ // Code that is used by both the Unix corerun and coreconsole. // +#include #include #include #include From 1c6cd1d37e89e22169535e1c65edb7d7b0f1eabc Mon Sep 17 00:00:00 2001 From: stephentoub Date: Thu, 28 May 2015 15:02:40 -0400 Subject: [PATCH 023/298] Fix exitCode from ExecuteAssembly ExecuteAssembly is initializing exitCode to 0 on entrance to the function. If it then fails prior to exitCode being set when invoking the entry point, the exitCode remains 0 even though there was a failure, and corerun ends up returning a successful exit code. --- coreruncommon.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/coreruncommon.cpp b/coreruncommon.cpp index e7323c177a..4f6ffa0330 100644 --- a/coreruncommon.cpp +++ b/coreruncommon.cpp @@ -290,6 +290,7 @@ int ExecuteManagedAssembly( if (!SUCCEEDED(st)) { fprintf(stderr, "ExecuteAssembly failed - status: 0x%08x\n", st); + exitCode = -1; } } else From f8f4b5e380a222332793c1005d425de02bf1817e Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Tue, 16 Jun 2015 14:02:19 -0700 Subject: [PATCH 024/298] added libps.so, added stub for GetUserName --- src/CMakeLists.txt | 13 +++++++++---- src/impl/getusername.cpp | 8 ++++++++ src/impl/getusername.h | 10 ++++++++++ src/impl/pal.h | 4 +++- 4 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 src/impl/getusername.cpp create mode 100644 src/impl/getusername.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4355f98d04..967a6f0049 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,13 +5,18 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest include_directories(../ext-src/gtest/fused-src impl) +link_directories(${monad_native_BINARY_DIR}) -set(SOURCE_FILES main.cpp tests/test-getcurrentprocessid.cpp impl/getcurrentprocessorid.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) -add_executable(monad_native ${SOURCE_FILES}) +set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp) +set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) -# add pthread +add_library(ps SHARED ${LIB_SOURCE_FILES}) +add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) + +# add pthread and other libs find_package(Threads) -target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp new file mode 100644 index 0000000000..b37b1cffc6 --- /dev/null +++ b/src/impl/getusername.cpp @@ -0,0 +1,8 @@ +#include "getusername.h" +#include + +BOOL GetUserName(WCHAR_T* userName, UINT32* maxLength) +{ + return 0; +} + diff --git a/src/impl/getusername.h b/src/impl/getusername.h new file mode 100644 index 0000000000..922a4e96ad --- /dev/null +++ b/src/impl/getusername.h @@ -0,0 +1,10 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +BOOL GetUserName(WCHAR_T* userName, UINT32* maxLength); + +PAL_END_EXTERNC + diff --git a/src/impl/pal.h b/src/impl/pal.h index 659afd4f61..1cfc776302 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -51,7 +51,9 @@ #define WIN32_FROM_HRESULT(hr) hr #define HRESULT_FROM_WIN32(error) error typedef unsigned long DWORD, *LPDWORD; - typedef int BOOL; + typedef char BOOL; + typedef unsigned short WCHAR_T; + typedef unsigned int UINT32; typedef unsigned long HRESULT; typedef const wchar_t *PCWSTR; typedef wchar_t *PWSTR; From 1b02619b2d513916106c8a0e1a827c92fcdd2bc3 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Tue, 16 Jun 2015 14:02:19 -0700 Subject: [PATCH 025/298] added libps.so, added stub for GetUserName --- CMakeLists.txt | 13 +++++++++---- impl/getusername.cpp | 8 ++++++++ impl/getusername.h | 10 ++++++++++ impl/pal.h | 4 +++- 4 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 impl/getusername.cpp create mode 100644 impl/getusername.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4355f98d04..967a6f0049 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,13 +5,18 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest include_directories(../ext-src/gtest/fused-src impl) +link_directories(${monad_native_BINARY_DIR}) -set(SOURCE_FILES main.cpp tests/test-getcurrentprocessid.cpp impl/getcurrentprocessorid.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) -add_executable(monad_native ${SOURCE_FILES}) +set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp) +set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) -# add pthread +add_library(ps SHARED ${LIB_SOURCE_FILES}) +add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) + +# add pthread and other libs find_package(Threads) -target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) diff --git a/impl/getusername.cpp b/impl/getusername.cpp new file mode 100644 index 0000000000..b37b1cffc6 --- /dev/null +++ b/impl/getusername.cpp @@ -0,0 +1,8 @@ +#include "getusername.h" +#include + +BOOL GetUserName(WCHAR_T* userName, UINT32* maxLength) +{ + return 0; +} + diff --git a/impl/getusername.h b/impl/getusername.h new file mode 100644 index 0000000000..922a4e96ad --- /dev/null +++ b/impl/getusername.h @@ -0,0 +1,10 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +BOOL GetUserName(WCHAR_T* userName, UINT32* maxLength); + +PAL_END_EXTERNC + diff --git a/impl/pal.h b/impl/pal.h index 659afd4f61..1cfc776302 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -51,7 +51,9 @@ #define WIN32_FROM_HRESULT(hr) hr #define HRESULT_FROM_WIN32(error) error typedef unsigned long DWORD, *LPDWORD; - typedef int BOOL; + typedef char BOOL; + typedef unsigned short WCHAR_T; + typedef unsigned int UINT32; typedef unsigned long HRESULT; typedef const wchar_t *PCWSTR; typedef wchar_t *PWSTR; From a756ecaadfa486b77032e7cefeb75ac0f479b403 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Tue, 7 Jul 2015 18:04:23 -0700 Subject: [PATCH 026/298] added pinvoke functions to query terminal size --- src/CMakeLists.txt | 2 +- src/impl/pal.h | 1 + src/impl/terminal.cpp | 21 +++++++++++++++++++++ src/impl/terminal.h | 11 +++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/impl/terminal.cpp create mode 100644 src/impl/terminal.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 967a6f0049..f23a2b711d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") include_directories(../ext-src/gtest/fused-src impl) link_directories(${monad_native_BINARY_DIR}) -set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp) +set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp) set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) diff --git a/src/impl/pal.h b/src/impl/pal.h index 1cfc776302..f981088843 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -54,6 +54,7 @@ typedef char BOOL; typedef unsigned short WCHAR_T; typedef unsigned int UINT32; + typedef int INT32; typedef unsigned long HRESULT; typedef const wchar_t *PCWSTR; typedef wchar_t *PWSTR; diff --git a/src/impl/terminal.cpp b/src/impl/terminal.cpp new file mode 100644 index 0000000000..c321928020 --- /dev/null +++ b/src/impl/terminal.cpp @@ -0,0 +1,21 @@ +#include "terminal.h" +#include + +INT32 GetTerminalWidth() +{ + struct winsize ws; + if (-1 == ioctl(0,TIOCGWINSZ,&ws)) + return -1; + + return ws.ws_col; +} + +INT32 GetTerminalHeight() +{ + struct winsize ws; + if (-1 == ioctl(0,TIOCGWINSZ,&ws)) + return -1; + + return ws.ws_row; +} + diff --git a/src/impl/terminal.h b/src/impl/terminal.h new file mode 100644 index 0000000000..00332e9bf5 --- /dev/null +++ b/src/impl/terminal.h @@ -0,0 +1,11 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +INT32 GetTerminalWidth(); +INT32 GetTerminalHeight(); + +PAL_END_EXTERNC + From 39e939ce0f7bfd1c90e949cd447ad71dc91fa8b1 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Tue, 7 Jul 2015 18:04:23 -0700 Subject: [PATCH 027/298] added pinvoke functions to query terminal size --- CMakeLists.txt | 2 +- impl/pal.h | 1 + impl/terminal.cpp | 21 +++++++++++++++++++++ impl/terminal.h | 11 +++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 impl/terminal.cpp create mode 100644 impl/terminal.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 967a6f0049..f23a2b711d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") include_directories(../ext-src/gtest/fused-src impl) link_directories(${monad_native_BINARY_DIR}) -set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp) +set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp) set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) diff --git a/impl/pal.h b/impl/pal.h index 1cfc776302..f981088843 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -54,6 +54,7 @@ typedef char BOOL; typedef unsigned short WCHAR_T; typedef unsigned int UINT32; + typedef int INT32; typedef unsigned long HRESULT; typedef const wchar_t *PCWSTR; typedef wchar_t *PWSTR; diff --git a/impl/terminal.cpp b/impl/terminal.cpp new file mode 100644 index 0000000000..c321928020 --- /dev/null +++ b/impl/terminal.cpp @@ -0,0 +1,21 @@ +#include "terminal.h" +#include + +INT32 GetTerminalWidth() +{ + struct winsize ws; + if (-1 == ioctl(0,TIOCGWINSZ,&ws)) + return -1; + + return ws.ws_col; +} + +INT32 GetTerminalHeight() +{ + struct winsize ws; + if (-1 == ioctl(0,TIOCGWINSZ,&ws)) + return -1; + + return ws.ws_row; +} + diff --git a/impl/terminal.h b/impl/terminal.h new file mode 100644 index 0000000000..00332e9bf5 --- /dev/null +++ b/impl/terminal.h @@ -0,0 +1,11 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +INT32 GetTerminalWidth(); +INT32 GetTerminalHeight(); + +PAL_END_EXTERNC + From a566a181a076f4fa49f4874934c080309424bd6c Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Wed, 15 Jul 2015 23:08:09 +0200 Subject: [PATCH 028/298] Extend the Unix hosting API This change modifies the Unix hosting API so that the hosting app can create as many managed delegates as it needs and execute them as many times it wants. The new API contains separate functions to initialize and shutdown CoreCLR and a function to create a delegate. The current ExecuteAssembly function behavior stays unmodified for now to ensure that dnx that uses that API and that pulls the binary libcoreclr is not broken. After the dnx is updated to use the new coreclr_create_delegate API, I'll remove the ExecuteAssembly. Also done: 1) Added support for comments and skipping empty lines in the mscorwks_unixexports.src. 2) Restructured the mscorwks_unixexports.src 3) Added coreclr_execute_assembly to the unixinterface.cpp / exports 4) Modified coreruncommon.cpp to use the new hosting API --- coreruncommon.cpp | 117 +++++++++++++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 42 deletions(-) diff --git a/coreruncommon.cpp b/coreruncommon.cpp index 4f6ffa0330..ecbbf39290 100644 --- a/coreruncommon.cpp +++ b/coreruncommon.cpp @@ -24,29 +24,31 @@ static const char * const coreClrDll = "libcoreclr.dylib"; static const char * const coreClrDll = "libcoreclr.so"; #endif -// Windows types used by the ExecuteAssembly function -typedef unsigned int DWORD; -typedef const char16_t* LPCWSTR; -typedef const char* LPCSTR; -typedef int32_t HRESULT; +#define SUCCEEDED(Status) ((Status) >= 0) -#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0) +// Prototype of the coreclr_initialize function from the libcoreclr.so +typedef int (*InitializeCoreCLRFunction)( + const char* exePath, + const char* appDomainFriendlyName, + int propertyCount, + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId); -// Prototype of the ExecuteAssembly function from the libcoreclr.do -typedef HRESULT (*ExecuteAssemblyFunction)( - LPCSTR exePath, - LPCSTR coreClrPath, - LPCSTR appDomainFriendlyName, - int propertyCount, - LPCSTR* propertyKeys, - LPCSTR* propertyValues, - int argc, - LPCSTR* argv, - LPCSTR managedAssemblyPath, - LPCSTR entryPointAssemblyName, - LPCSTR entryPointTypeName, - LPCSTR entryPointMethodsName, - DWORD* exitCode); +// Prototype of the coreclr_shutdown function from the libcoreclr.so +typedef int (*ShutdownCoreCLRFunction)( + void* hostHandle, + unsigned int domainId); + +// Prototype of the coreclr_execute_assembly function from the libcoreclr.so +typedef int (*ExecuteAssemblyFunction)( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode); bool GetAbsolutePath(const char* path, std::string& absolutePath) { @@ -233,8 +235,23 @@ int ExecuteManagedAssembly( void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW | RTLD_LOCAL); if (coreclrLib != nullptr) { - ExecuteAssemblyFunction executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib, "ExecuteAssembly"); - if (executeAssembly != nullptr) + InitializeCoreCLRFunction initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib, "coreclr_initialize"); + ExecuteAssemblyFunction executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib, "coreclr_execute_assembly"); + ShutdownCoreCLRFunction shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib, "coreclr_shutdown"); + + if (initializeCoreCLR == nullptr) + { + fprintf(stderr, "Function coreclr_initialize not found in the libcoreclr.so\n"); + } + else if (executeAssembly == nullptr) + { + fprintf(stderr, "Function coreclr_execute_assembly not found in the libcoreclr.so\n"); + } + else if (shutdownCoreCLR == nullptr) + { + fprintf(stderr, "Function coreclr_shutdown not found in the libcoreclr.so\n"); + } + else { // Allowed property names: // APPBASE @@ -272,30 +289,46 @@ int ExecuteManagedAssembly( "UseLatestBehaviorWhenTFMNotSpecified" }; - HRESULT st = executeAssembly( - currentExeAbsolutePath, - coreClrDllPath.c_str(), - "unixcorerun", - sizeof(propertyKeys) / sizeof(propertyKeys[0]), - propertyKeys, - propertyValues, - managedAssemblyArgc, - managedAssemblyArgv, - managedAssemblyAbsolutePath, - NULL, - NULL, - NULL, - (DWORD*)&exitCode); + void* hostHandle; + unsigned int domainId; + + int st = initializeCoreCLR( + currentExeAbsolutePath, + "unixcorerun", + sizeof(propertyKeys) / sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + &hostHandle, + &domainId); if (!SUCCEEDED(st)) { - fprintf(stderr, "ExecuteAssembly failed - status: 0x%08x\n", st); + fprintf(stderr, "coreclr_initialize failed - status: 0x%08x\n", st); exitCode = -1; } - } - else - { - fprintf(stderr, "Function ExecuteAssembly not found in the libcoreclr.so\n"); + else + { + st = executeAssembly( + hostHandle, + domainId, + managedAssemblyArgc, + managedAssemblyArgv, + managedAssemblyAbsolutePath, + (unsigned int*)&exitCode); + + if (!SUCCEEDED(st)) + { + fprintf(stderr, "coreclr_execute_assembly failed - status: 0x%08x\n", st); + exitCode = -1; + } + + st = shutdownCoreCLR(hostHandle, domainId); + if (!SUCCEEDED(st)) + { + fprintf(stderr, "coreclr_shutdown failed - status: 0x%08x\n", st); + exitCode = -1; + } + } } if (dlclose(coreclrLib) != 0) From 371115999686e0580a9faf35b4c008223ae602ea Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Mon, 27 Jul 2015 17:38:11 +0200 Subject: [PATCH 029/298] added first version of custom PS hosting code --- src/CMakeLists.txt | 5 + src/host/cmdline/coreclrutil.cpp | 163 ++++++++++++++++++++++++++ src/host/cmdline/coreclrutil.h | 63 ++++++++++ src/host/cmdline/main.cpp | 194 +++++++++++++++++++++++++++++++ 4 files changed, 425 insertions(+) create mode 100644 src/host/cmdline/coreclrutil.cpp create mode 100644 src/host/cmdline/coreclrutil.h create mode 100644 src/host/cmdline/main.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f23a2b711d..98053e3cc7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,16 +7,21 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") include_directories(../ext-src/gtest/fused-src impl) link_directories(${monad_native_BINARY_DIR}) +# source file definitions set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp) set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) +SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp host/cmdline/coreclrutil.cpp) +# target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) +add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) # add pthread and other libs find_package(Threads) target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) +target_link_libraries(host_cmdline dl) diff --git a/src/host/cmdline/coreclrutil.cpp b/src/host/cmdline/coreclrutil.cpp new file mode 100644 index 0000000000..d67a1057f8 --- /dev/null +++ b/src/host/cmdline/coreclrutil.cpp @@ -0,0 +1,163 @@ +#include "coreclrutil.h" +#include +#include +#include +#include +#include + +namespace CoreCLRUtil +{ + +bool GetAbsolutePath(const char* path, std::string& absolutePath) +{ + bool result = false; + + char realPath[PATH_MAX]; + if (realpath(path, realPath) != nullptr && realPath[0] != '\0') + { + absolutePath.assign(realPath); + // realpath should return canonicalized path without the trailing slash + assert(absolutePath.back() != '/'); + + result = true; + } + + return result; +} + +bool GetDirectory(const char* absolutePath, std::string& directory) +{ + directory.assign(absolutePath); + size_t lastSlash = directory.rfind('/'); + if (lastSlash != std::string::npos) + { + directory.erase(lastSlash); + return true; + } + + return false; +} + +bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) +{ + std::string clrFilesRelativePath; + const char* clrFilesPathLocal = clrFilesPath; + if (clrFilesPathLocal == nullptr) + { + // There was no CLR files path specified, use the folder of the corerun/coreconsole + if (!GetDirectory(currentExePath, clrFilesRelativePath)) + { + perror("Failed to get directory from argv[0]"); + return false; + } + + clrFilesPathLocal = clrFilesRelativePath.c_str(); + + // TODO: consider using an env variable (if defined) as a fall-back. + // The windows version of the corerun uses core_root env variable + } + + if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) + { + perror("Failed to convert CLR files path to absolute path"); + return false; + } + + return true; +} + +void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) +{ + const char * const tpaExtensions[] = { + ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir + ".dll", + ".ni.exe", + ".exe", + }; + + DIR* dir = opendir(directory); + if (dir == nullptr) + { + return; + } + + std::set addedAssemblies; + + // Walk the directory for each extension separately so that we first get files with .ni.dll extension, + // then files with .dll extension, etc. + for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + { + const char* ext = tpaExtensions[extIndex]; + int extLength = strlen(ext); + + struct dirent* entry; + + // For all entries in the directory + while ((entry = readdir(dir)) != nullptr) + { + // We are interested in files only + switch (entry->d_type) + { + case DT_REG: + break; + + // Handle symlinks and file systems that do not support d_type + case DT_LNK: + case DT_UNKNOWN: + { + std::string fullFilename; + + fullFilename.append(directory); + fullFilename.append("/"); + fullFilename.append(entry->d_name); + + struct stat sb; + if (stat(fullFilename.c_str(), &sb) == -1) + { + continue; + } + + if (!S_ISREG(sb.st_mode)) + { + continue; + } + } + break; + + default: + continue; + } + + std::string filename(entry->d_name); + + // Check if the extension matches the one we are looking for + int extPos = filename.length() - extLength; + if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) + { + continue; + } + + std::string filenameWithoutExt(filename.substr(0, extPos)); + + // Make sure if we have an assembly with multiple extensions present, + // we insert only one version of it. + if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) + { + addedAssemblies.insert(filenameWithoutExt); + + tpaList.append(directory); + tpaList.append("/"); + tpaList.append(filename); + tpaList.append(":"); + } + } + + // Rewind the directory stream to be able to iterate over it for the next extension + rewinddir(dir); + } + + closedir(dir); +} + +} // namespace CoreCLRUtil + diff --git a/src/host/cmdline/coreclrutil.h b/src/host/cmdline/coreclrutil.h new file mode 100644 index 0000000000..49a45ab6e1 --- /dev/null +++ b/src/host/cmdline/coreclrutil.h @@ -0,0 +1,63 @@ +#pragma once + +#include + +namespace CoreCLRUtil +{ + +// +// This code is mostly copied and modified from original CoreCLR project's +// code on github: https://github.com/dotnet/coreclr +// + +// +// these function signatures are the entry point API for CoreCLR +// + +// Prototype of the coreclr_initialize function from the libcoreclr.so +typedef int (*InitializeCoreCLRFunction)( + const char* exePath, + const char* appDomainFriendlyName, + int propertyCount, + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId); + +// Prototype of the coreclr_shutdown function from the libcoreclr.so +typedef int (*ShutdownCoreCLRFunction)( + void* hostHandle, + unsigned int domainId); + +// Prototype of the coreclr_execute_assembly function from the libcoreclr.so +typedef int (*ExecuteAssemblyFunction)( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode); + +// Prototype of coreclr_create_delegate function from the libcoreclr.so +typedef int (*CreateDelegateFunction)( + void* hostHandle, + unsigned int domainId, + const char* entryPointAssemblyName, + const char* entryPointTypeName, + const char* entryPointMethodName, + void** delegate); + +// The name of the CoreCLR native runtime DLL +#if defined(__APPLE__) +constexpr char coreClrDll[] = "libcoreclr.dylib"; +#else +constexpr char coreClrDll[] = "libcoreclr.so"; +#endif + +bool GetAbsolutePath(const char* path, std::string& absolutePath); +bool GetDirectory(const char* absolutePath, std::string& directory); +bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); +void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); + +} // namespace CoreCLRUtil + diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp new file mode 100644 index 0000000000..29fbfb938c --- /dev/null +++ b/src/host/cmdline/main.cpp @@ -0,0 +1,194 @@ +#include +#include +#include "coreclrutil.h" +#include +#include + +int main(int argc, char** argv) +{ + // TODO: read from command line args + std::string clrAbsolutePath = "/home/peter/gitwd/monad-linux/scripts/exec_env/app_base"; + + // managed assembly arguments + int managedAssemblyArgc = 0; + const char* managedAssemblyArgv[] = { "" }; + + // there are two assemblies involved in hosting PowerShell: + // - Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll + // + this assembly has to be listed as platform assembly + // - System.Management.Automation.dll + std::string powershellBaseAbsolutePath = "/home/peter/gitwd/monad-linux/scripts/exec_env/app_base"; + std::string assemblyLoadContextAssemblyName = "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext"; + std::string assemblyLoadContextAbsolutePath = powershellBaseAbsolutePath + "/" + assemblyLoadContextAssemblyName + ".dll"; + std::string systemManagementAutomationAssemblyName = "System.Management.Automation"; + std::string systemManagementAutomationAbsolutePath = powershellBaseAbsolutePath + "/" + systemManagementAutomationAssemblyName + ".dll"; + + std::string coreClrDllPath = clrAbsolutePath + "/" + CoreCLRUtil::coreClrDll; + if (coreClrDllPath.size() >= PATH_MAX) + { + std::cerr << "Absolute path to CoreCLR library too long" << std::endl; + return 1; + } + std::cout << "coreClrDllPath: " << coreClrDllPath << std::endl; + + // TPA list + // + // The list of platform assemblies must include all CoreCLR assemblies + // and the Microsoft.PowerShell.CoreCLR.AssemblyLoadContext + // + // TODO: move CLR assemblies to separate path during build&run make steps + // TODO: only add assembly load context to TPA list, not any other PS dll + + std::string tpaList; + CoreCLRUtil::AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); + std::cout << "tpaList: " << tpaList << std::endl; + + // assembly load paths + // + // All PowerShell assemblies are assumed to be in the same path + + std::string appPath; + if (!CoreCLRUtil::GetDirectory(assemblyLoadContextAbsolutePath.c_str(),appPath)) + { + std::cerr << "failed to get assembly search directory from assembly absolute path" << std::endl; + return 1; + } + std::cout << "appPath: " << appPath << std::endl; + + // search paths for native dlls + // + // Add both the CoreCLR directory and the PowerShell directory to this list + std::string nativeDllSearchDirs = appPath + ":" + clrAbsolutePath; + + // get the absolute path of the current executable + std::string currentExeAbsolutePath; + if (!CoreCLRUtil::GetAbsolutePath(argv[0],currentExeAbsolutePath)) + { + std::cerr << "could not get absolute path of current executable" << std::endl; + return 1; + } + + // open the shared library + void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); + if (coreclrLib == nullptr) + { + char* error = dlerror(); + std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; + return 2; + } + + // query the function pointers + CoreCLRUtil::InitializeCoreCLRFunction initializeCoreCLR = (CoreCLRUtil::InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); + CoreCLRUtil::ExecuteAssemblyFunction executeAssembly = (CoreCLRUtil::ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); + CoreCLRUtil::ShutdownCoreCLRFunction shutdownCoreCLR = (CoreCLRUtil::ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); + CoreCLRUtil::CreateDelegateFunction createDelegate = (CoreCLRUtil::CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); + + if (initializeCoreCLR == nullptr) + { + std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; + return 3; + } + if (executeAssembly == nullptr) + { + std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; + return 3; + } + if (shutdownCoreCLR == nullptr) + { + std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; + return 3; + } + if (createDelegate == nullptr) + { + std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; + return 3; + } + + // create list of properties to initialize CoreCLR + const char* propertyKeys[] = { + "TRUSTED_PLATFORM_ASSEMBLIES", + "APP_PATHS", + "APP_NI_PATHS", + "NATIVE_DLL_SEARCH_DIRECTORIES", + "AppDomainCompatSwitch" + }; + + const char* propertyValues[] = { + tpaList.c_str(), + appPath.c_str(), + appPath.c_str(), + nativeDllSearchDirs.c_str(), + "UseLatestBehaviorWhenTFMNotSpecified" + }; + + + // initialize CoreCLR + void* hostHandle; + unsigned int domainId; + int status = initializeCoreCLR( + currentExeAbsolutePath.c_str(), + "ps_cmdline_host", + sizeof(propertyKeys)/sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + &hostHandle, + &domainId); + + if (0 > status) + { + std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; + return 4; + } + + // initialize the PS's custom assembly load context + typedef void (*LoaderRunHelperFp)(const char16_t* appPath); + LoaderRunHelperFp loaderDelegate = nullptr; + status = createDelegate( + hostHandle, + domainId, + "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "System.Management.Automation.PowerShellAssemblyLoadContextInitializer", + "SetPowerShellAssemblyLoadContext", + (void**)&loaderDelegate); + if (0 > status) + { + std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; + return 4; + } + + loaderDelegate(u"/home/peter/gitwd/monad-linux/scripts/exec_env/app_base"); + + + typedef int (*TestDelegate)(); + TestDelegate testDelegate = nullptr; + status = createDelegate( + hostHandle, + domainId, + "System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "System.Management.Automation.Platform", + "IsLinux", + (void**)&testDelegate); + int returnValue = testDelegate(); + std::cout << "returnValue=" << returnValue << std::endl; + + + typedef void (*UnmanagedEntry)(); + UnmanagedEntry unmanagedEntry = nullptr; + status = createDelegate( + hostHandle, + domainId, + "powershell-simple, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "ps_hello_world.Program", + "UnmanagedEntry", + (void**)&unmanagedEntry); + if (0 > status) + { + std::cerr << "could not create delegate for UnmanagedEntry - status: " << std::hex << status << std::endl; + return 4; + } + + unmanagedEntry(); + + return 0; +} + From b9784906f4d71d4d4a4f36f6667d6ed8e1d2aff9 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Mon, 27 Jul 2015 17:38:11 +0200 Subject: [PATCH 030/298] added first version of custom PS hosting code --- CMakeLists.txt | 5 + host/cmdline/coreclrutil.cpp | 163 +++++++++++++++++++++++++++++ host/cmdline/coreclrutil.h | 63 ++++++++++++ host/cmdline/main.cpp | 194 +++++++++++++++++++++++++++++++++++ 4 files changed, 425 insertions(+) create mode 100644 host/cmdline/coreclrutil.cpp create mode 100644 host/cmdline/coreclrutil.h create mode 100644 host/cmdline/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f23a2b711d..98053e3cc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,16 +7,21 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") include_directories(../ext-src/gtest/fused-src impl) link_directories(${monad_native_BINARY_DIR}) +# source file definitions set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp) set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) +SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp host/cmdline/coreclrutil.cpp) +# target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) +add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) # add pthread and other libs find_package(Threads) target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) +target_link_libraries(host_cmdline dl) diff --git a/host/cmdline/coreclrutil.cpp b/host/cmdline/coreclrutil.cpp new file mode 100644 index 0000000000..d67a1057f8 --- /dev/null +++ b/host/cmdline/coreclrutil.cpp @@ -0,0 +1,163 @@ +#include "coreclrutil.h" +#include +#include +#include +#include +#include + +namespace CoreCLRUtil +{ + +bool GetAbsolutePath(const char* path, std::string& absolutePath) +{ + bool result = false; + + char realPath[PATH_MAX]; + if (realpath(path, realPath) != nullptr && realPath[0] != '\0') + { + absolutePath.assign(realPath); + // realpath should return canonicalized path without the trailing slash + assert(absolutePath.back() != '/'); + + result = true; + } + + return result; +} + +bool GetDirectory(const char* absolutePath, std::string& directory) +{ + directory.assign(absolutePath); + size_t lastSlash = directory.rfind('/'); + if (lastSlash != std::string::npos) + { + directory.erase(lastSlash); + return true; + } + + return false; +} + +bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) +{ + std::string clrFilesRelativePath; + const char* clrFilesPathLocal = clrFilesPath; + if (clrFilesPathLocal == nullptr) + { + // There was no CLR files path specified, use the folder of the corerun/coreconsole + if (!GetDirectory(currentExePath, clrFilesRelativePath)) + { + perror("Failed to get directory from argv[0]"); + return false; + } + + clrFilesPathLocal = clrFilesRelativePath.c_str(); + + // TODO: consider using an env variable (if defined) as a fall-back. + // The windows version of the corerun uses core_root env variable + } + + if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) + { + perror("Failed to convert CLR files path to absolute path"); + return false; + } + + return true; +} + +void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) +{ + const char * const tpaExtensions[] = { + ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir + ".dll", + ".ni.exe", + ".exe", + }; + + DIR* dir = opendir(directory); + if (dir == nullptr) + { + return; + } + + std::set addedAssemblies; + + // Walk the directory for each extension separately so that we first get files with .ni.dll extension, + // then files with .dll extension, etc. + for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + { + const char* ext = tpaExtensions[extIndex]; + int extLength = strlen(ext); + + struct dirent* entry; + + // For all entries in the directory + while ((entry = readdir(dir)) != nullptr) + { + // We are interested in files only + switch (entry->d_type) + { + case DT_REG: + break; + + // Handle symlinks and file systems that do not support d_type + case DT_LNK: + case DT_UNKNOWN: + { + std::string fullFilename; + + fullFilename.append(directory); + fullFilename.append("/"); + fullFilename.append(entry->d_name); + + struct stat sb; + if (stat(fullFilename.c_str(), &sb) == -1) + { + continue; + } + + if (!S_ISREG(sb.st_mode)) + { + continue; + } + } + break; + + default: + continue; + } + + std::string filename(entry->d_name); + + // Check if the extension matches the one we are looking for + int extPos = filename.length() - extLength; + if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) + { + continue; + } + + std::string filenameWithoutExt(filename.substr(0, extPos)); + + // Make sure if we have an assembly with multiple extensions present, + // we insert only one version of it. + if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) + { + addedAssemblies.insert(filenameWithoutExt); + + tpaList.append(directory); + tpaList.append("/"); + tpaList.append(filename); + tpaList.append(":"); + } + } + + // Rewind the directory stream to be able to iterate over it for the next extension + rewinddir(dir); + } + + closedir(dir); +} + +} // namespace CoreCLRUtil + diff --git a/host/cmdline/coreclrutil.h b/host/cmdline/coreclrutil.h new file mode 100644 index 0000000000..49a45ab6e1 --- /dev/null +++ b/host/cmdline/coreclrutil.h @@ -0,0 +1,63 @@ +#pragma once + +#include + +namespace CoreCLRUtil +{ + +// +// This code is mostly copied and modified from original CoreCLR project's +// code on github: https://github.com/dotnet/coreclr +// + +// +// these function signatures are the entry point API for CoreCLR +// + +// Prototype of the coreclr_initialize function from the libcoreclr.so +typedef int (*InitializeCoreCLRFunction)( + const char* exePath, + const char* appDomainFriendlyName, + int propertyCount, + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId); + +// Prototype of the coreclr_shutdown function from the libcoreclr.so +typedef int (*ShutdownCoreCLRFunction)( + void* hostHandle, + unsigned int domainId); + +// Prototype of the coreclr_execute_assembly function from the libcoreclr.so +typedef int (*ExecuteAssemblyFunction)( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode); + +// Prototype of coreclr_create_delegate function from the libcoreclr.so +typedef int (*CreateDelegateFunction)( + void* hostHandle, + unsigned int domainId, + const char* entryPointAssemblyName, + const char* entryPointTypeName, + const char* entryPointMethodName, + void** delegate); + +// The name of the CoreCLR native runtime DLL +#if defined(__APPLE__) +constexpr char coreClrDll[] = "libcoreclr.dylib"; +#else +constexpr char coreClrDll[] = "libcoreclr.so"; +#endif + +bool GetAbsolutePath(const char* path, std::string& absolutePath); +bool GetDirectory(const char* absolutePath, std::string& directory); +bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); +void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); + +} // namespace CoreCLRUtil + diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp new file mode 100644 index 0000000000..29fbfb938c --- /dev/null +++ b/host/cmdline/main.cpp @@ -0,0 +1,194 @@ +#include +#include +#include "coreclrutil.h" +#include +#include + +int main(int argc, char** argv) +{ + // TODO: read from command line args + std::string clrAbsolutePath = "/home/peter/gitwd/monad-linux/scripts/exec_env/app_base"; + + // managed assembly arguments + int managedAssemblyArgc = 0; + const char* managedAssemblyArgv[] = { "" }; + + // there are two assemblies involved in hosting PowerShell: + // - Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll + // + this assembly has to be listed as platform assembly + // - System.Management.Automation.dll + std::string powershellBaseAbsolutePath = "/home/peter/gitwd/monad-linux/scripts/exec_env/app_base"; + std::string assemblyLoadContextAssemblyName = "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext"; + std::string assemblyLoadContextAbsolutePath = powershellBaseAbsolutePath + "/" + assemblyLoadContextAssemblyName + ".dll"; + std::string systemManagementAutomationAssemblyName = "System.Management.Automation"; + std::string systemManagementAutomationAbsolutePath = powershellBaseAbsolutePath + "/" + systemManagementAutomationAssemblyName + ".dll"; + + std::string coreClrDllPath = clrAbsolutePath + "/" + CoreCLRUtil::coreClrDll; + if (coreClrDllPath.size() >= PATH_MAX) + { + std::cerr << "Absolute path to CoreCLR library too long" << std::endl; + return 1; + } + std::cout << "coreClrDllPath: " << coreClrDllPath << std::endl; + + // TPA list + // + // The list of platform assemblies must include all CoreCLR assemblies + // and the Microsoft.PowerShell.CoreCLR.AssemblyLoadContext + // + // TODO: move CLR assemblies to separate path during build&run make steps + // TODO: only add assembly load context to TPA list, not any other PS dll + + std::string tpaList; + CoreCLRUtil::AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); + std::cout << "tpaList: " << tpaList << std::endl; + + // assembly load paths + // + // All PowerShell assemblies are assumed to be in the same path + + std::string appPath; + if (!CoreCLRUtil::GetDirectory(assemblyLoadContextAbsolutePath.c_str(),appPath)) + { + std::cerr << "failed to get assembly search directory from assembly absolute path" << std::endl; + return 1; + } + std::cout << "appPath: " << appPath << std::endl; + + // search paths for native dlls + // + // Add both the CoreCLR directory and the PowerShell directory to this list + std::string nativeDllSearchDirs = appPath + ":" + clrAbsolutePath; + + // get the absolute path of the current executable + std::string currentExeAbsolutePath; + if (!CoreCLRUtil::GetAbsolutePath(argv[0],currentExeAbsolutePath)) + { + std::cerr << "could not get absolute path of current executable" << std::endl; + return 1; + } + + // open the shared library + void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); + if (coreclrLib == nullptr) + { + char* error = dlerror(); + std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; + return 2; + } + + // query the function pointers + CoreCLRUtil::InitializeCoreCLRFunction initializeCoreCLR = (CoreCLRUtil::InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); + CoreCLRUtil::ExecuteAssemblyFunction executeAssembly = (CoreCLRUtil::ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); + CoreCLRUtil::ShutdownCoreCLRFunction shutdownCoreCLR = (CoreCLRUtil::ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); + CoreCLRUtil::CreateDelegateFunction createDelegate = (CoreCLRUtil::CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); + + if (initializeCoreCLR == nullptr) + { + std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; + return 3; + } + if (executeAssembly == nullptr) + { + std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; + return 3; + } + if (shutdownCoreCLR == nullptr) + { + std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; + return 3; + } + if (createDelegate == nullptr) + { + std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; + return 3; + } + + // create list of properties to initialize CoreCLR + const char* propertyKeys[] = { + "TRUSTED_PLATFORM_ASSEMBLIES", + "APP_PATHS", + "APP_NI_PATHS", + "NATIVE_DLL_SEARCH_DIRECTORIES", + "AppDomainCompatSwitch" + }; + + const char* propertyValues[] = { + tpaList.c_str(), + appPath.c_str(), + appPath.c_str(), + nativeDllSearchDirs.c_str(), + "UseLatestBehaviorWhenTFMNotSpecified" + }; + + + // initialize CoreCLR + void* hostHandle; + unsigned int domainId; + int status = initializeCoreCLR( + currentExeAbsolutePath.c_str(), + "ps_cmdline_host", + sizeof(propertyKeys)/sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + &hostHandle, + &domainId); + + if (0 > status) + { + std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; + return 4; + } + + // initialize the PS's custom assembly load context + typedef void (*LoaderRunHelperFp)(const char16_t* appPath); + LoaderRunHelperFp loaderDelegate = nullptr; + status = createDelegate( + hostHandle, + domainId, + "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "System.Management.Automation.PowerShellAssemblyLoadContextInitializer", + "SetPowerShellAssemblyLoadContext", + (void**)&loaderDelegate); + if (0 > status) + { + std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; + return 4; + } + + loaderDelegate(u"/home/peter/gitwd/monad-linux/scripts/exec_env/app_base"); + + + typedef int (*TestDelegate)(); + TestDelegate testDelegate = nullptr; + status = createDelegate( + hostHandle, + domainId, + "System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "System.Management.Automation.Platform", + "IsLinux", + (void**)&testDelegate); + int returnValue = testDelegate(); + std::cout << "returnValue=" << returnValue << std::endl; + + + typedef void (*UnmanagedEntry)(); + UnmanagedEntry unmanagedEntry = nullptr; + status = createDelegate( + hostHandle, + domainId, + "powershell-simple, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "ps_hello_world.Program", + "UnmanagedEntry", + (void**)&unmanagedEntry); + if (0 > status) + { + std::cerr << "could not create delegate for UnmanagedEntry - status: " << std::hex << status << std::endl; + return 4; + } + + unmanagedEntry(); + + return 0; +} + From f7396c956114223403f5d59a201eede3b0194fc0 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Mon, 27 Jul 2015 18:40:33 +0200 Subject: [PATCH 031/298] renamed function pointer type, changed code to call UnmanagedMain --- src/host/cmdline/main.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 29fbfb938c..485ba56e9b 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -172,22 +172,23 @@ int main(int argc, char** argv) std::cout << "returnValue=" << returnValue << std::endl; - typedef void (*UnmanagedEntry)(); - UnmanagedEntry unmanagedEntry = nullptr; + typedef void (*UnmanagedMain)(int argc, const char** argv); + UnmanagedMain unmanagedMain = nullptr; status = createDelegate( hostHandle, domainId, "powershell-simple, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "ps_hello_world.Program", - "UnmanagedEntry", - (void**)&unmanagedEntry); + "UnmanagedMain", + (void**)&unmanagedMain); if (0 > status) { - std::cerr << "could not create delegate for UnmanagedEntry - status: " << std::hex << status << std::endl; + std::cerr << "could not create delegate for UnmanagedMain - status: " << std::hex << status << std::endl; return 4; } - unmanagedEntry(); + const char* testargs[] = { "get-process | out-host", "get-module" }; + unmanagedMain(2,testargs); return 0; } From ba45c8f07600158c9439de2bd93e675bad0588df Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Mon, 27 Jul 2015 18:40:33 +0200 Subject: [PATCH 032/298] renamed function pointer type, changed code to call UnmanagedMain --- host/cmdline/main.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 29fbfb938c..485ba56e9b 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -172,22 +172,23 @@ int main(int argc, char** argv) std::cout << "returnValue=" << returnValue << std::endl; - typedef void (*UnmanagedEntry)(); - UnmanagedEntry unmanagedEntry = nullptr; + typedef void (*UnmanagedMain)(int argc, const char** argv); + UnmanagedMain unmanagedMain = nullptr; status = createDelegate( hostHandle, domainId, "powershell-simple, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "ps_hello_world.Program", - "UnmanagedEntry", - (void**)&unmanagedEntry); + "UnmanagedMain", + (void**)&unmanagedMain); if (0 > status) { - std::cerr << "could not create delegate for UnmanagedEntry - status: " << std::hex << status << std::endl; + std::cerr << "could not create delegate for UnmanagedMain - status: " << std::hex << status << std::endl; return 4; } - unmanagedEntry(); + const char* testargs[] = { "get-process | out-host", "get-module" }; + unmanagedMain(2,testargs); return 0; } From 0a316592717abbcf9e11aeaeac205a8692c1e2f6 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Tue, 28 Jul 2015 18:28:09 +0200 Subject: [PATCH 033/298] cleaned up implementation, added command line parsing and standardized managed interface for cmdline hosts --- src/CMakeLists.txt | 2 +- src/host/cmdline/main.cpp | 339 ++++++++++++++++++++++++++++++-------- 2 files changed, 267 insertions(+), 74 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 98053e3cc7..3a7c35b542 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,7 +21,7 @@ add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) # add pthread and other libs find_package(Threads) target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) -target_link_libraries(host_cmdline dl) +target_link_libraries(host_cmdline dl icuuc) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 485ba56e9b..678d8ccc35 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -3,62 +3,172 @@ #include "coreclrutil.h" #include #include +#include +#include +#include +#include + +namespace Cmdline +{ + +void printHelp() +{ + std::cerr << "PS CoreCLR host" << std::endl; + std::cerr << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl; + std::cerr << " [-b base_path] assembly_name type_name function_name [...]" << std::endl; + std::cerr << std::endl; + std::cerr << "What it does:" << std::endl; + std::cerr << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl; + std::cerr << " as host_cmdline" << std::endl; + std::cerr << " + this behavior can be overridden with the -c command line argument" << std::endl; + std::cerr << "- by default the host assumes that the assembly named" << std::endl; + std::cerr << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl; + std::cerr << " platform assemblies" << std::endl; + std::cerr << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl; + std::cerr << " be provided with the -alc command line argument" << std::endl; + std::cerr << "- all additional parameters at the end of the command line are forwarded" << std::endl; + std::cerr << " to the specified entry function in the assembly" << std::endl; + std::cerr << "- the host will execute the specified entry function in the specified assembly" << std::endl; + std::cerr << " + this assembly has to be located in the search path" << std::endl; + std::cerr << "- by default the host will add the current working directory to the assembly search path" << std::endl; + std::cerr << " + this can be overridden with the -s command line argument" << std::endl; + std::cerr << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl; + std::cerr << " working directory" << std::endl; + std::cerr << " + this can be overridden with the -b command line argument" << std::endl; + std::cerr << "- the function signature of the function that gets executed must be:" << std::endl; + std::cerr << " public static int UnmanagedMain(int argc, [MarshalAs(UnmanagedType.LPArray,ArraySubType=UnmanagedType.LPStr,SizeParamIndex=0)] String[] argv)" << std::endl; + std::cerr << std::endl; + std::cerr << "Options:" << std::endl; + std::cerr << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl; + std::cerr << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl; + std::cerr << "-s a list of assembly search paths, separated by :" << std::endl; + std::cerr << "-b the powershell assembly base path" << std::endl; + std::cerr << "assembly_name the assembly name of the assembly to execute" << std::endl; + std::cerr << " must be available in the search path" << std::endl; + std::cerr << "type_name the type name where the function can be found" << std::endl; + std::cerr << "function_name the function to execute (must have the function signature described above!)" << std::endl; + std::cerr << std::endl; + std::cerr << "Example:" << std::endl; + std::cerr << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'ps_hello_world.Program' 'UnmanagedMain' 'get-process'" << std::endl; +} + +struct Args +{ + Args() : + argc(0), + argv(nullptr) + { + } + + std::string clrPath; + std::string assemblyLoadContextFilePath; + std::string searchPaths; + std::string basePath; + std::string entryAssemblyName; + std::string entryTypeName; + std::string entryFunctionName; + int argc; + char** argv; + + void debugPrint() const + { + std::cerr << "Args:" << std::endl; + std::cerr << "- clrPath " << clrPath << std::endl; + std::cerr << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl; + std::cerr << "- searchPaths " << searchPaths << std::endl; + std::cerr << "- basePath " << basePath << std::endl; + std::cerr << "- entryAssemblyName " << entryAssemblyName << std::endl; + std::cerr << "- entryTypeName " << entryTypeName << std::endl; + std::cerr << "- entryFunctionName " << entryFunctionName << std::endl; + std::cerr << "- argc " << argc << std::endl; + } +}; + +// this is implemented without any 3rd party lib to keep the list +// of dependencies low +bool parseCmdline(const int argc, char** argv, Args& args) +{ + if (argc <= 1) + { + std::cerr << "error: missing arguments" << std::endl; + return false; + } + + for (int i = 1; i < argc; ++i) + { + const std::string arg = argv[i]; + const bool hasNextArg = i+1 < argc; + const std::string nextArg = hasNextArg ? std::string(argv[i+1]) : std::string(""); + + if (hasNextArg && (arg == "-c" || arg == "--clr-path")) + { + args.clrPath = nextArg; + ++i; + } + else if (hasNextArg && arg == "-alc") + { + args.assemblyLoadContextFilePath = nextArg; + ++i; + } + else if (hasNextArg && arg == "-s") + { + args.searchPaths = nextArg; + ++i; + } + else if (hasNextArg && arg == "-b") + { + args.basePath = nextArg; + ++i; + } + else if (args.entryAssemblyName == "") + { + args.entryAssemblyName = arg; + } + else if (args.entryTypeName == "") + { + args.entryTypeName = arg; + } + else if (args.entryFunctionName == "") + { + args.entryFunctionName = arg; + } + else + { + // forward command line parameters + args.argc = argc-i; + args.argv = &argv[i]; + } + } + + // check for mandatory parameters + if (args.entryAssemblyName == "") + { + std::cerr << "error: assembly_name argument missing" << std::endl; + } + if (args.entryTypeName == "") + { + std::cerr << "error: type_name argument missing" << std::endl; + } + if (args.entryFunctionName == "") + { + std::cerr << "error: function_name argument missing" << std::endl; + } + + return true; +} + +} int main(int argc, char** argv) { - // TODO: read from command line args - std::string clrAbsolutePath = "/home/peter/gitwd/monad-linux/scripts/exec_env/app_base"; - - // managed assembly arguments - int managedAssemblyArgc = 0; - const char* managedAssemblyArgv[] = { "" }; - - // there are two assemblies involved in hosting PowerShell: - // - Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll - // + this assembly has to be listed as platform assembly - // - System.Management.Automation.dll - std::string powershellBaseAbsolutePath = "/home/peter/gitwd/monad-linux/scripts/exec_env/app_base"; - std::string assemblyLoadContextAssemblyName = "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext"; - std::string assemblyLoadContextAbsolutePath = powershellBaseAbsolutePath + "/" + assemblyLoadContextAssemblyName + ".dll"; - std::string systemManagementAutomationAssemblyName = "System.Management.Automation"; - std::string systemManagementAutomationAbsolutePath = powershellBaseAbsolutePath + "/" + systemManagementAutomationAssemblyName + ".dll"; - - std::string coreClrDllPath = clrAbsolutePath + "/" + CoreCLRUtil::coreClrDll; - if (coreClrDllPath.size() >= PATH_MAX) + // parse the command line arguments + Cmdline::Args args; + if (!Cmdline::parseCmdline(argc,argv,args)) { - std::cerr << "Absolute path to CoreCLR library too long" << std::endl; + Cmdline::printHelp(); return 1; } - std::cout << "coreClrDllPath: " << coreClrDllPath << std::endl; - - // TPA list - // - // The list of platform assemblies must include all CoreCLR assemblies - // and the Microsoft.PowerShell.CoreCLR.AssemblyLoadContext - // - // TODO: move CLR assemblies to separate path during build&run make steps - // TODO: only add assembly load context to TPA list, not any other PS dll - - std::string tpaList; - CoreCLRUtil::AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); - std::cout << "tpaList: " << tpaList << std::endl; - - // assembly load paths - // - // All PowerShell assemblies are assumed to be in the same path - - std::string appPath; - if (!CoreCLRUtil::GetDirectory(assemblyLoadContextAbsolutePath.c_str(),appPath)) - { - std::cerr << "failed to get assembly search directory from assembly absolute path" << std::endl; - return 1; - } - std::cout << "appPath: " << appPath << std::endl; - - // search paths for native dlls - // - // Add both the CoreCLR directory and the PowerShell directory to this list - std::string nativeDllSearchDirs = appPath + ":" + clrAbsolutePath; + args.debugPrint(); // get the absolute path of the current executable std::string currentExeAbsolutePath; @@ -67,6 +177,91 @@ int main(int argc, char** argv) std::cerr << "could not get absolute path of current executable" << std::endl; return 1; } + std::cerr << "currentExeAbsolutePath=" << currentExeAbsolutePath << std::endl; + + // CLR absolute folder path + // + // This path is created from the location of this executable or a path + // specified with the -c command line argument + std::string clrAbsolutePath; + const char* clrPathArg = args.clrPath == "" ? nullptr : args.clrPath.c_str(); + if (!CoreCLRUtil::GetClrFilesAbsolutePath(currentExeAbsolutePath.c_str(),clrPathArg,clrAbsolutePath)) + { + std::cerr << "could not find absolute CLR path" << std::endl; + return 1; + } + + // the path to the CoreCLR library + // + // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac + + std::string coreClrDllPath = clrAbsolutePath + "/" + CoreCLRUtil::coreClrDll; + if (coreClrDllPath.size() >= PATH_MAX) + { + std::cerr << "Absolute path to CoreCLR library too long" << std::endl; + return 1; + } + std::cerr << "coreClrDllPath: " << coreClrDllPath << std::endl; + + // TPA list + // + // The list of platform assemblies must include all CoreCLR assemblies + // and the Microsoft.PowerShell.CoreCLR.AssemblyLoadContext + // + // if the -alc parameter was specified, add it to the TPA list here + + std::string tpaList; + CoreCLRUtil::AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); + + if (args.assemblyLoadContextFilePath != "") + tpaList += ":" + args.assemblyLoadContextFilePath; + + std::cerr << "tpaList: " << tpaList << std::endl; + + // get the absolute path of the current directory + + std::string currentDirAbsolutePath; + if (!CoreCLRUtil::GetAbsolutePath(".",currentDirAbsolutePath)) + { + std::cerr << "failed to get the absolute path from current working directory" << std::endl; + return 1; + } + + // assembly search paths + // + // add the current directory and anything specified with the -s option + + std::string appPath = currentDirAbsolutePath; + if (args.searchPaths != "") + appPath += ":" + args.searchPaths; + std::cerr << "appPath: " << appPath << std::endl; + + // search paths for native dlls + // + // Add both the CoreCLR directory and the regular search paths to this list + std::string nativeDllSearchDirs = appPath + ":" + clrAbsolutePath; + + // convert the app base to utf-16 + // + // this is needed as a utf-16 LE string by CoreCLR/PS's assembly load context interface + // it is either: + // - the current dir's absolute path + // - the path specified through the -b argument + std::string psBasePath = currentDirAbsolutePath; + if (args.basePath != "") + { + if (!CoreCLRUtil::GetAbsolutePath(args.basePath.c_str(),psBasePath)) + { + std::cerr << "failed to get the absolute path from the base_path argument" << std::endl; + return 1; + } + } + std::basic_string psBasePath16(PATH_MAX,0); + + UnicodeString u8str = UnicodeString(psBasePath.c_str(),"UTF-8"); + int32_t targetSize = u8str.extract(0,u8str.length(),(char*)&psBasePath16[0],psBasePath16.size()*sizeof(char16_t),"UTF-16LE"); + psBasePath16.resize(targetSize/sizeof(char16_t)+1); + std::cerr << "targetSize=" << targetSize << std::endl; // open the shared library void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); @@ -155,31 +350,17 @@ int main(int argc, char** argv) std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; return 4; } + loaderDelegate(psBasePath16.c_str()); - loaderDelegate(u"/home/peter/gitwd/monad-linux/scripts/exec_env/app_base"); - - - typedef int (*TestDelegate)(); - TestDelegate testDelegate = nullptr; - status = createDelegate( - hostHandle, - domainId, - "System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "System.Management.Automation.Platform", - "IsLinux", - (void**)&testDelegate); - int returnValue = testDelegate(); - std::cout << "returnValue=" << returnValue << std::endl; - - - typedef void (*UnmanagedMain)(int argc, const char** argv); + // call the unmanaged entry point for PowerShell + typedef int (*UnmanagedMain)(int argc, char const* const* argv); UnmanagedMain unmanagedMain = nullptr; status = createDelegate( hostHandle, domainId, - "powershell-simple, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "ps_hello_world.Program", - "UnmanagedMain", + args.entryAssemblyName.c_str(), + args.entryTypeName.c_str(), + args.entryFunctionName.c_str(), (void**)&unmanagedMain); if (0 > status) { @@ -187,9 +368,21 @@ int main(int argc, char** argv) return 4; } - const char* testargs[] = { "get-process | out-host", "get-module" }; - unmanagedMain(2,testargs); + int exitCode = unmanagedMain(args.argc,args.argv); - return 0; + // shutdown CoreCLR + status = shutdownCoreCLR(hostHandle,domainId); + if (0 > status) + { + std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; + } + + // close the dynamic library + if (0 != dlclose(coreclrLib)) + { + std::cerr << "failed to close CoreCLR library" << std::endl; + } + + return exitCode; } From c0414f8fc460f2acca28675310ae3ff63f8903c2 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Tue, 28 Jul 2015 18:28:09 +0200 Subject: [PATCH 034/298] cleaned up implementation, added command line parsing and standardized managed interface for cmdline hosts --- CMakeLists.txt | 2 +- host/cmdline/main.cpp | 339 +++++++++++++++++++++++++++++++++--------- 2 files changed, 267 insertions(+), 74 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 98053e3cc7..3a7c35b542 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) # add pthread and other libs find_package(Threads) target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) -target_link_libraries(host_cmdline dl) +target_link_libraries(host_cmdline dl icuuc) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 485ba56e9b..678d8ccc35 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -3,62 +3,172 @@ #include "coreclrutil.h" #include #include +#include +#include +#include +#include + +namespace Cmdline +{ + +void printHelp() +{ + std::cerr << "PS CoreCLR host" << std::endl; + std::cerr << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl; + std::cerr << " [-b base_path] assembly_name type_name function_name [...]" << std::endl; + std::cerr << std::endl; + std::cerr << "What it does:" << std::endl; + std::cerr << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl; + std::cerr << " as host_cmdline" << std::endl; + std::cerr << " + this behavior can be overridden with the -c command line argument" << std::endl; + std::cerr << "- by default the host assumes that the assembly named" << std::endl; + std::cerr << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl; + std::cerr << " platform assemblies" << std::endl; + std::cerr << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl; + std::cerr << " be provided with the -alc command line argument" << std::endl; + std::cerr << "- all additional parameters at the end of the command line are forwarded" << std::endl; + std::cerr << " to the specified entry function in the assembly" << std::endl; + std::cerr << "- the host will execute the specified entry function in the specified assembly" << std::endl; + std::cerr << " + this assembly has to be located in the search path" << std::endl; + std::cerr << "- by default the host will add the current working directory to the assembly search path" << std::endl; + std::cerr << " + this can be overridden with the -s command line argument" << std::endl; + std::cerr << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl; + std::cerr << " working directory" << std::endl; + std::cerr << " + this can be overridden with the -b command line argument" << std::endl; + std::cerr << "- the function signature of the function that gets executed must be:" << std::endl; + std::cerr << " public static int UnmanagedMain(int argc, [MarshalAs(UnmanagedType.LPArray,ArraySubType=UnmanagedType.LPStr,SizeParamIndex=0)] String[] argv)" << std::endl; + std::cerr << std::endl; + std::cerr << "Options:" << std::endl; + std::cerr << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl; + std::cerr << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl; + std::cerr << "-s a list of assembly search paths, separated by :" << std::endl; + std::cerr << "-b the powershell assembly base path" << std::endl; + std::cerr << "assembly_name the assembly name of the assembly to execute" << std::endl; + std::cerr << " must be available in the search path" << std::endl; + std::cerr << "type_name the type name where the function can be found" << std::endl; + std::cerr << "function_name the function to execute (must have the function signature described above!)" << std::endl; + std::cerr << std::endl; + std::cerr << "Example:" << std::endl; + std::cerr << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'ps_hello_world.Program' 'UnmanagedMain' 'get-process'" << std::endl; +} + +struct Args +{ + Args() : + argc(0), + argv(nullptr) + { + } + + std::string clrPath; + std::string assemblyLoadContextFilePath; + std::string searchPaths; + std::string basePath; + std::string entryAssemblyName; + std::string entryTypeName; + std::string entryFunctionName; + int argc; + char** argv; + + void debugPrint() const + { + std::cerr << "Args:" << std::endl; + std::cerr << "- clrPath " << clrPath << std::endl; + std::cerr << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl; + std::cerr << "- searchPaths " << searchPaths << std::endl; + std::cerr << "- basePath " << basePath << std::endl; + std::cerr << "- entryAssemblyName " << entryAssemblyName << std::endl; + std::cerr << "- entryTypeName " << entryTypeName << std::endl; + std::cerr << "- entryFunctionName " << entryFunctionName << std::endl; + std::cerr << "- argc " << argc << std::endl; + } +}; + +// this is implemented without any 3rd party lib to keep the list +// of dependencies low +bool parseCmdline(const int argc, char** argv, Args& args) +{ + if (argc <= 1) + { + std::cerr << "error: missing arguments" << std::endl; + return false; + } + + for (int i = 1; i < argc; ++i) + { + const std::string arg = argv[i]; + const bool hasNextArg = i+1 < argc; + const std::string nextArg = hasNextArg ? std::string(argv[i+1]) : std::string(""); + + if (hasNextArg && (arg == "-c" || arg == "--clr-path")) + { + args.clrPath = nextArg; + ++i; + } + else if (hasNextArg && arg == "-alc") + { + args.assemblyLoadContextFilePath = nextArg; + ++i; + } + else if (hasNextArg && arg == "-s") + { + args.searchPaths = nextArg; + ++i; + } + else if (hasNextArg && arg == "-b") + { + args.basePath = nextArg; + ++i; + } + else if (args.entryAssemblyName == "") + { + args.entryAssemblyName = arg; + } + else if (args.entryTypeName == "") + { + args.entryTypeName = arg; + } + else if (args.entryFunctionName == "") + { + args.entryFunctionName = arg; + } + else + { + // forward command line parameters + args.argc = argc-i; + args.argv = &argv[i]; + } + } + + // check for mandatory parameters + if (args.entryAssemblyName == "") + { + std::cerr << "error: assembly_name argument missing" << std::endl; + } + if (args.entryTypeName == "") + { + std::cerr << "error: type_name argument missing" << std::endl; + } + if (args.entryFunctionName == "") + { + std::cerr << "error: function_name argument missing" << std::endl; + } + + return true; +} + +} int main(int argc, char** argv) { - // TODO: read from command line args - std::string clrAbsolutePath = "/home/peter/gitwd/monad-linux/scripts/exec_env/app_base"; - - // managed assembly arguments - int managedAssemblyArgc = 0; - const char* managedAssemblyArgv[] = { "" }; - - // there are two assemblies involved in hosting PowerShell: - // - Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll - // + this assembly has to be listed as platform assembly - // - System.Management.Automation.dll - std::string powershellBaseAbsolutePath = "/home/peter/gitwd/monad-linux/scripts/exec_env/app_base"; - std::string assemblyLoadContextAssemblyName = "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext"; - std::string assemblyLoadContextAbsolutePath = powershellBaseAbsolutePath + "/" + assemblyLoadContextAssemblyName + ".dll"; - std::string systemManagementAutomationAssemblyName = "System.Management.Automation"; - std::string systemManagementAutomationAbsolutePath = powershellBaseAbsolutePath + "/" + systemManagementAutomationAssemblyName + ".dll"; - - std::string coreClrDllPath = clrAbsolutePath + "/" + CoreCLRUtil::coreClrDll; - if (coreClrDllPath.size() >= PATH_MAX) + // parse the command line arguments + Cmdline::Args args; + if (!Cmdline::parseCmdline(argc,argv,args)) { - std::cerr << "Absolute path to CoreCLR library too long" << std::endl; + Cmdline::printHelp(); return 1; } - std::cout << "coreClrDllPath: " << coreClrDllPath << std::endl; - - // TPA list - // - // The list of platform assemblies must include all CoreCLR assemblies - // and the Microsoft.PowerShell.CoreCLR.AssemblyLoadContext - // - // TODO: move CLR assemblies to separate path during build&run make steps - // TODO: only add assembly load context to TPA list, not any other PS dll - - std::string tpaList; - CoreCLRUtil::AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); - std::cout << "tpaList: " << tpaList << std::endl; - - // assembly load paths - // - // All PowerShell assemblies are assumed to be in the same path - - std::string appPath; - if (!CoreCLRUtil::GetDirectory(assemblyLoadContextAbsolutePath.c_str(),appPath)) - { - std::cerr << "failed to get assembly search directory from assembly absolute path" << std::endl; - return 1; - } - std::cout << "appPath: " << appPath << std::endl; - - // search paths for native dlls - // - // Add both the CoreCLR directory and the PowerShell directory to this list - std::string nativeDllSearchDirs = appPath + ":" + clrAbsolutePath; + args.debugPrint(); // get the absolute path of the current executable std::string currentExeAbsolutePath; @@ -67,6 +177,91 @@ int main(int argc, char** argv) std::cerr << "could not get absolute path of current executable" << std::endl; return 1; } + std::cerr << "currentExeAbsolutePath=" << currentExeAbsolutePath << std::endl; + + // CLR absolute folder path + // + // This path is created from the location of this executable or a path + // specified with the -c command line argument + std::string clrAbsolutePath; + const char* clrPathArg = args.clrPath == "" ? nullptr : args.clrPath.c_str(); + if (!CoreCLRUtil::GetClrFilesAbsolutePath(currentExeAbsolutePath.c_str(),clrPathArg,clrAbsolutePath)) + { + std::cerr << "could not find absolute CLR path" << std::endl; + return 1; + } + + // the path to the CoreCLR library + // + // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac + + std::string coreClrDllPath = clrAbsolutePath + "/" + CoreCLRUtil::coreClrDll; + if (coreClrDllPath.size() >= PATH_MAX) + { + std::cerr << "Absolute path to CoreCLR library too long" << std::endl; + return 1; + } + std::cerr << "coreClrDllPath: " << coreClrDllPath << std::endl; + + // TPA list + // + // The list of platform assemblies must include all CoreCLR assemblies + // and the Microsoft.PowerShell.CoreCLR.AssemblyLoadContext + // + // if the -alc parameter was specified, add it to the TPA list here + + std::string tpaList; + CoreCLRUtil::AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); + + if (args.assemblyLoadContextFilePath != "") + tpaList += ":" + args.assemblyLoadContextFilePath; + + std::cerr << "tpaList: " << tpaList << std::endl; + + // get the absolute path of the current directory + + std::string currentDirAbsolutePath; + if (!CoreCLRUtil::GetAbsolutePath(".",currentDirAbsolutePath)) + { + std::cerr << "failed to get the absolute path from current working directory" << std::endl; + return 1; + } + + // assembly search paths + // + // add the current directory and anything specified with the -s option + + std::string appPath = currentDirAbsolutePath; + if (args.searchPaths != "") + appPath += ":" + args.searchPaths; + std::cerr << "appPath: " << appPath << std::endl; + + // search paths for native dlls + // + // Add both the CoreCLR directory and the regular search paths to this list + std::string nativeDllSearchDirs = appPath + ":" + clrAbsolutePath; + + // convert the app base to utf-16 + // + // this is needed as a utf-16 LE string by CoreCLR/PS's assembly load context interface + // it is either: + // - the current dir's absolute path + // - the path specified through the -b argument + std::string psBasePath = currentDirAbsolutePath; + if (args.basePath != "") + { + if (!CoreCLRUtil::GetAbsolutePath(args.basePath.c_str(),psBasePath)) + { + std::cerr << "failed to get the absolute path from the base_path argument" << std::endl; + return 1; + } + } + std::basic_string psBasePath16(PATH_MAX,0); + + UnicodeString u8str = UnicodeString(psBasePath.c_str(),"UTF-8"); + int32_t targetSize = u8str.extract(0,u8str.length(),(char*)&psBasePath16[0],psBasePath16.size()*sizeof(char16_t),"UTF-16LE"); + psBasePath16.resize(targetSize/sizeof(char16_t)+1); + std::cerr << "targetSize=" << targetSize << std::endl; // open the shared library void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); @@ -155,31 +350,17 @@ int main(int argc, char** argv) std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; return 4; } + loaderDelegate(psBasePath16.c_str()); - loaderDelegate(u"/home/peter/gitwd/monad-linux/scripts/exec_env/app_base"); - - - typedef int (*TestDelegate)(); - TestDelegate testDelegate = nullptr; - status = createDelegate( - hostHandle, - domainId, - "System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "System.Management.Automation.Platform", - "IsLinux", - (void**)&testDelegate); - int returnValue = testDelegate(); - std::cout << "returnValue=" << returnValue << std::endl; - - - typedef void (*UnmanagedMain)(int argc, const char** argv); + // call the unmanaged entry point for PowerShell + typedef int (*UnmanagedMain)(int argc, char const* const* argv); UnmanagedMain unmanagedMain = nullptr; status = createDelegate( hostHandle, domainId, - "powershell-simple, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "ps_hello_world.Program", - "UnmanagedMain", + args.entryAssemblyName.c_str(), + args.entryTypeName.c_str(), + args.entryFunctionName.c_str(), (void**)&unmanagedMain); if (0 > status) { @@ -187,9 +368,21 @@ int main(int argc, char** argv) return 4; } - const char* testargs[] = { "get-process | out-host", "get-module" }; - unmanagedMain(2,testargs); + int exitCode = unmanagedMain(args.argc,args.argv); - return 0; + // shutdown CoreCLR + status = shutdownCoreCLR(hostHandle,domainId); + if (0 > status) + { + std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; + } + + // close the dynamic library + if (0 != dlclose(coreclrLib)) + { + std::cerr << "failed to close CoreCLR library" << std::endl; + } + + return exitCode; } From d09ac28b738a93d686220b432340ae40e66136c5 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Tue, 28 Jul 2015 18:49:32 +0200 Subject: [PATCH 035/298] fixed string termination issue, added verbose mode --- src/host/cmdline/main.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 678d8ccc35..11c9333672 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -43,6 +43,7 @@ void printHelp() std::cerr << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl; std::cerr << "-s a list of assembly search paths, separated by :" << std::endl; std::cerr << "-b the powershell assembly base path" << std::endl; + std::cerr << "-v verbose output, show paths" << std::endl; std::cerr << "assembly_name the assembly name of the assembly to execute" << std::endl; std::cerr << " must be available in the search path" << std::endl; std::cerr << "type_name the type name where the function can be found" << std::endl; @@ -56,7 +57,8 @@ struct Args { Args() : argc(0), - argv(nullptr) + argv(nullptr), + verbose(false) { } @@ -69,6 +71,7 @@ struct Args std::string entryFunctionName; int argc; char** argv; + bool verbose; void debugPrint() const { @@ -81,6 +84,7 @@ struct Args std::cerr << "- entryTypeName " << entryTypeName << std::endl; std::cerr << "- entryFunctionName " << entryFunctionName << std::endl; std::cerr << "- argc " << argc << std::endl; + std::cerr << "- verbose " << (verbose ? "true" : "false") << std::endl; } }; @@ -168,7 +172,8 @@ int main(int argc, char** argv) Cmdline::printHelp(); return 1; } - args.debugPrint(); + if (args.verbose) + args.debugPrint(); // get the absolute path of the current executable std::string currentExeAbsolutePath; @@ -177,7 +182,8 @@ int main(int argc, char** argv) std::cerr << "could not get absolute path of current executable" << std::endl; return 1; } - std::cerr << "currentExeAbsolutePath=" << currentExeAbsolutePath << std::endl; + if (args.verbose) + std::cerr << "currentExeAbsolutePath=" << currentExeAbsolutePath << std::endl; // CLR absolute folder path // @@ -201,7 +207,8 @@ int main(int argc, char** argv) std::cerr << "Absolute path to CoreCLR library too long" << std::endl; return 1; } - std::cerr << "coreClrDllPath: " << coreClrDllPath << std::endl; + if (args.verbose) + std::cerr << "coreClrDllPath: " << coreClrDllPath << std::endl; // TPA list // @@ -216,7 +223,8 @@ int main(int argc, char** argv) if (args.assemblyLoadContextFilePath != "") tpaList += ":" + args.assemblyLoadContextFilePath; - std::cerr << "tpaList: " << tpaList << std::endl; + if (args.verbose) + std::cerr << "tpaList: " << tpaList << std::endl; // get the absolute path of the current directory @@ -234,7 +242,9 @@ int main(int argc, char** argv) std::string appPath = currentDirAbsolutePath; if (args.searchPaths != "") appPath += ":" + args.searchPaths; - std::cerr << "appPath: " << appPath << std::endl; + + if (args.verbose) + std::cerr << "appPath: " << appPath << std::endl; // search paths for native dlls // @@ -256,12 +266,13 @@ int main(int argc, char** argv) return 1; } } - std::basic_string psBasePath16(PATH_MAX,0); + + // make sure to leave 1 byte at the end for null termination + std::basic_string psBasePath16(PATH_MAX+1,0); UnicodeString u8str = UnicodeString(psBasePath.c_str(),"UTF-8"); - int32_t targetSize = u8str.extract(0,u8str.length(),(char*)&psBasePath16[0],psBasePath16.size()*sizeof(char16_t),"UTF-16LE"); + int32_t targetSize = u8str.extract(0,u8str.length(),(char*)&psBasePath16[0],(psBasePath16.size()-1)*sizeof(char16_t),"UTF-16LE"); psBasePath16.resize(targetSize/sizeof(char16_t)+1); - std::cerr << "targetSize=" << targetSize << std::endl; // open the shared library void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); From ea76b7e8fdc269ffd8f571efa88930010b57d75c Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Tue, 28 Jul 2015 18:49:32 +0200 Subject: [PATCH 036/298] fixed string termination issue, added verbose mode --- host/cmdline/main.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 678d8ccc35..11c9333672 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -43,6 +43,7 @@ void printHelp() std::cerr << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl; std::cerr << "-s a list of assembly search paths, separated by :" << std::endl; std::cerr << "-b the powershell assembly base path" << std::endl; + std::cerr << "-v verbose output, show paths" << std::endl; std::cerr << "assembly_name the assembly name of the assembly to execute" << std::endl; std::cerr << " must be available in the search path" << std::endl; std::cerr << "type_name the type name where the function can be found" << std::endl; @@ -56,7 +57,8 @@ struct Args { Args() : argc(0), - argv(nullptr) + argv(nullptr), + verbose(false) { } @@ -69,6 +71,7 @@ struct Args std::string entryFunctionName; int argc; char** argv; + bool verbose; void debugPrint() const { @@ -81,6 +84,7 @@ struct Args std::cerr << "- entryTypeName " << entryTypeName << std::endl; std::cerr << "- entryFunctionName " << entryFunctionName << std::endl; std::cerr << "- argc " << argc << std::endl; + std::cerr << "- verbose " << (verbose ? "true" : "false") << std::endl; } }; @@ -168,7 +172,8 @@ int main(int argc, char** argv) Cmdline::printHelp(); return 1; } - args.debugPrint(); + if (args.verbose) + args.debugPrint(); // get the absolute path of the current executable std::string currentExeAbsolutePath; @@ -177,7 +182,8 @@ int main(int argc, char** argv) std::cerr << "could not get absolute path of current executable" << std::endl; return 1; } - std::cerr << "currentExeAbsolutePath=" << currentExeAbsolutePath << std::endl; + if (args.verbose) + std::cerr << "currentExeAbsolutePath=" << currentExeAbsolutePath << std::endl; // CLR absolute folder path // @@ -201,7 +207,8 @@ int main(int argc, char** argv) std::cerr << "Absolute path to CoreCLR library too long" << std::endl; return 1; } - std::cerr << "coreClrDllPath: " << coreClrDllPath << std::endl; + if (args.verbose) + std::cerr << "coreClrDllPath: " << coreClrDllPath << std::endl; // TPA list // @@ -216,7 +223,8 @@ int main(int argc, char** argv) if (args.assemblyLoadContextFilePath != "") tpaList += ":" + args.assemblyLoadContextFilePath; - std::cerr << "tpaList: " << tpaList << std::endl; + if (args.verbose) + std::cerr << "tpaList: " << tpaList << std::endl; // get the absolute path of the current directory @@ -234,7 +242,9 @@ int main(int argc, char** argv) std::string appPath = currentDirAbsolutePath; if (args.searchPaths != "") appPath += ":" + args.searchPaths; - std::cerr << "appPath: " << appPath << std::endl; + + if (args.verbose) + std::cerr << "appPath: " << appPath << std::endl; // search paths for native dlls // @@ -256,12 +266,13 @@ int main(int argc, char** argv) return 1; } } - std::basic_string psBasePath16(PATH_MAX,0); + + // make sure to leave 1 byte at the end for null termination + std::basic_string psBasePath16(PATH_MAX+1,0); UnicodeString u8str = UnicodeString(psBasePath.c_str(),"UTF-8"); - int32_t targetSize = u8str.extract(0,u8str.length(),(char*)&psBasePath16[0],psBasePath16.size()*sizeof(char16_t),"UTF-16LE"); + int32_t targetSize = u8str.extract(0,u8str.length(),(char*)&psBasePath16[0],(psBasePath16.size()-1)*sizeof(char16_t),"UTF-16LE"); psBasePath16.resize(targetSize/sizeof(char16_t)+1); - std::cerr << "targetSize=" << targetSize << std::endl; // open the shared library void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); From 8e18abaf3103fe5c061334403066fdb79fcd3c6a Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Wed, 29 Jul 2015 18:12:31 +0200 Subject: [PATCH 037/298] added interpreting the verbose option --- src/host/cmdline/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 11c9333672..7793bf1439 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -124,6 +124,10 @@ bool parseCmdline(const int argc, char** argv, Args& args) args.basePath = nextArg; ++i; } + else if (arg == "-v") + { + args.verbose = true; + } else if (args.entryAssemblyName == "") { args.entryAssemblyName = arg; From ff2ceeceb758cba907a18ab3bd7132cf36bc15e8 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Wed, 29 Jul 2015 18:12:31 +0200 Subject: [PATCH 038/298] added interpreting the verbose option --- host/cmdline/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 11c9333672..7793bf1439 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -124,6 +124,10 @@ bool parseCmdline(const int argc, char** argv, Args& args) args.basePath = nextArg; ++i; } + else if (arg == "-v") + { + args.verbose = true; + } else if (args.entryAssemblyName == "") { args.entryAssemblyName = arg; From c1c9a992699229cf69ef22a346b95137ab9f7a15 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Thu, 30 Jul 2015 16:53:35 +0200 Subject: [PATCH 039/298] added hostutil.h, added tests for hostutil, added more cmdline options to PS host --- src/CMakeLists.txt | 9 +++- src/host/cmdline/main.cpp | 53 ++++++++++++++++++-- src/host/{cmdline => common}/coreclrutil.cpp | 4 ++ src/host/{cmdline => common}/coreclrutil.h | 0 src/host/common/hostutil.h | 48 ++++++++++++++++++ src/tests/host/test-hostutil.cpp | 35 +++++++++++++ 6 files changed, 142 insertions(+), 7 deletions(-) rename src/host/{cmdline => common}/coreclrutil.cpp (96%) rename src/host/{cmdline => common}/coreclrutil.h (100%) create mode 100644 src/host/common/hostutil.h create mode 100644 src/tests/host/test-hostutil.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3a7c35b542..a5d27e7bfc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,9 +9,11 @@ link_directories(${monad_native_BINARY_DIR}) # source file definitions set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp) +set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) +set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) -SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp host/cmdline/coreclrutil.cpp) +SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) @@ -23,5 +25,8 @@ find_package(Threads) target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) target_link_libraries(host_cmdline dl icuuc) +# target specific include directories +target_include_directories(monad_native PRIVATE host) +target_include_directories(host_cmdline PRIVATE host) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 7793bf1439..740d99185c 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -1,6 +1,7 @@ #include #include -#include "coreclrutil.h" +#include "common/coreclrutil.h" +#include "common/hostutil.h" #include #include #include @@ -32,6 +33,7 @@ void printHelp() std::cerr << " + this assembly has to be located in the search path" << std::endl; std::cerr << "- by default the host will add the current working directory to the assembly search path" << std::endl; std::cerr << " + this can be overridden with the -s command line argument" << std::endl; + std::cerr << " + if -c is specified, it will be added to the search path instead of the current directory" << std::endl; std::cerr << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl; std::cerr << " working directory" << std::endl; std::cerr << " + this can be overridden with the -b command line argument" << std::endl; @@ -44,13 +46,17 @@ void printHelp() std::cerr << "-s a list of assembly search paths, separated by :" << std::endl; std::cerr << "-b the powershell assembly base path" << std::endl; std::cerr << "-v verbose output, show paths" << std::endl; + std::cerr << "-tpa additional list of trusted platform assemblies, this references dll and exe files" << std::endl; + std::cerr << " separated by :" << std::endl; + std::cerr << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl; + std::cerr << " argument, must always be added to the TPA list with this parameter" << std::endl; std::cerr << "assembly_name the assembly name of the assembly to execute" << std::endl; std::cerr << " must be available in the search path" << std::endl; std::cerr << "type_name the type name where the function can be found" << std::endl; std::cerr << "function_name the function to execute (must have the function signature described above!)" << std::endl; std::cerr << std::endl; std::cerr << "Example:" << std::endl; - std::cerr << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'ps_hello_world.Program' 'UnmanagedMain' 'get-process'" << std::endl; + std::cerr << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'ps_hello_world.Program' 'UnmanagedMain' 'get-process'" << std::endl; } struct Args @@ -66,6 +72,7 @@ struct Args std::string assemblyLoadContextFilePath; std::string searchPaths; std::string basePath; + std::string tpaList; std::string entryAssemblyName; std::string entryTypeName; std::string entryFunctionName; @@ -80,6 +87,7 @@ struct Args std::cerr << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl; std::cerr << "- searchPaths " << searchPaths << std::endl; std::cerr << "- basePath " << basePath << std::endl; + std::cerr << "- tpaList " << tpaList << std::endl; std::cerr << "- entryAssemblyName " << entryAssemblyName << std::endl; std::cerr << "- entryTypeName " << entryTypeName << std::endl; std::cerr << "- entryFunctionName " << entryFunctionName << std::endl; @@ -124,6 +132,11 @@ bool parseCmdline(const int argc, char** argv, Args& args) args.basePath = nextArg; ++i; } + else if (hasNextArg && arg == "-tpa") + { + args.tpaList = nextArg; + ++i; + } else if (arg == "-v") { args.verbose = true; @@ -145,6 +158,9 @@ bool parseCmdline(const int argc, char** argv, Args& args) // forward command line parameters args.argc = argc-i; args.argv = &argv[i]; + + // explicitly break here because the lines above consume all remaining arguments + break; } } @@ -200,6 +216,8 @@ int main(int argc, char** argv) std::cerr << "could not find absolute CLR path" << std::endl; return 1; } + if (args.verbose) + std::cerr << "clrAbsolutePath=" << clrAbsolutePath << std::endl; // the path to the CoreCLR library // @@ -225,7 +243,23 @@ int main(int argc, char** argv) CoreCLRUtil::AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); if (args.assemblyLoadContextFilePath != "") - tpaList += ":" + args.assemblyLoadContextFilePath; + { + std::string assemblyLoadContextAbsoluteFilePath; + if (!CoreCLRUtil::GetAbsolutePath(args.assemblyLoadContextFilePath.c_str(),assemblyLoadContextAbsoluteFilePath)) + { + std::cerr << "Failed to get absolute file path for assembly load context" << std::endl; + return 1; + } + tpaList += ":" + assemblyLoadContextAbsoluteFilePath; + } + + // add the -tpa command line argument + if (args.tpaList != "") + { + std::string tpaAbsolutePathList = HostUtil::getAbsolutePathList(args.tpaList); + if (tpaAbsolutePathList != "") + tpaList += ":" + tpaAbsolutePathList; + } if (args.verbose) std::cerr << "tpaList: " << tpaList << std::endl; @@ -241,11 +275,18 @@ int main(int argc, char** argv) // assembly search paths // - // add the current directory and anything specified with the -s option + // add the current directory, and optionally the CoreCLR directory if -c was specified + // and anything specified with the -s option std::string appPath = currentDirAbsolutePath; + if (args.clrPath != "") + appPath += ":" + clrAbsolutePath; if (args.searchPaths != "") - appPath += ":" + args.searchPaths; + { + std::string searchAbsolutePathList = HostUtil::getAbsolutePathList(args.searchPaths); + if (searchAbsolutePathList != "") + appPath += ":" + searchAbsolutePathList; + } if (args.verbose) std::cerr << "appPath: " << appPath << std::endl; @@ -270,6 +311,8 @@ int main(int argc, char** argv) return 1; } } + if (args.verbose) + std::cerr << "psBasePath=" << psBasePath << std::endl; // make sure to leave 1 byte at the end for null termination std::basic_string psBasePath16(PATH_MAX+1,0); diff --git a/src/host/cmdline/coreclrutil.cpp b/src/host/common/coreclrutil.cpp similarity index 96% rename from src/host/cmdline/coreclrutil.cpp rename to src/host/common/coreclrutil.cpp index d67a1057f8..6aa8b9896a 100644 --- a/src/host/cmdline/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -157,6 +157,10 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) } closedir(dir); + + // strip any trailing : from the tpaList + if (tpaList.size() > 0 && tpaList[tpaList.size()-1] == ':') + tpaList.resize(tpaList.size()-1); } } // namespace CoreCLRUtil diff --git a/src/host/cmdline/coreclrutil.h b/src/host/common/coreclrutil.h similarity index 100% rename from src/host/cmdline/coreclrutil.h rename to src/host/common/coreclrutil.h diff --git a/src/host/common/hostutil.h b/src/host/common/hostutil.h new file mode 100644 index 0000000000..a8c9a208d3 --- /dev/null +++ b/src/host/common/hostutil.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include "common/coreclrutil.h" + +namespace HostUtil +{ + +//!\brief get a list of absolute paths separated by : from a list of relative/absolute paths separated by : +std::string getAbsolutePathList(const std::string& paths) +{ + //std::cerr << "getAbsolutePathList: paths=" << paths << std::endl; + std::string result; + + // split by : + size_t lastPos = 0; + size_t curPos = paths.find(':',lastPos); + do + { + const std::string token = paths.substr(lastPos,curPos-lastPos); + //std::cerr << "curPos=" << curPos << " lastPos=" << lastPos << " token=" << token << std::endl; + + // skip empty tokens + if (token != "") + { + std::string absolutePath; + if (CoreCLRUtil::GetAbsolutePath(token.c_str(),absolutePath)) + { + // add colons correctly + if (result.size() == 0) + result += absolutePath; + else + result += ":" + absolutePath; + } + } + + // increment lastPos to skip the : + lastPos += token.size() + 1; + curPos = paths.find(':',lastPos); + } + while (lastPos < paths.size()); + + return result; +} + +} + + diff --git a/src/tests/host/test-hostutil.cpp b/src/tests/host/test-hostutil.cpp new file mode 100644 index 0000000000..7a8b6b473b --- /dev/null +++ b/src/tests/host/test-hostutil.cpp @@ -0,0 +1,35 @@ +#include +#include "common/hostutil.h" + +TEST(HostUtilTest,simple) +{ + // syntactical corner cases + ASSERT_EQ("",HostUtil::getAbsolutePathList("")); + ASSERT_EQ("",HostUtil::getAbsolutePathList(":")); + ASSERT_EQ("",HostUtil::getAbsolutePathList("::")); + ASSERT_EQ("",HostUtil::getAbsolutePathList(":::::")); + + // current directory + char* cwd = get_current_dir_name(); + ASSERT_EQ(std::string(cwd),HostUtil::getAbsolutePathList(".")); + + // relative and absolute paths that don't exist + ASSERT_EQ("",HostUtil::getAbsolutePathList("/something/that/does/not/exist")); + ASSERT_EQ("",HostUtil::getAbsolutePathList(":/something/that/does/not/exist:")); + ASSERT_EQ("",HostUtil::getAbsolutePathList("something/relative/that/does/not/exist")); + ASSERT_EQ("",HostUtil::getAbsolutePathList(":something/relative/that/does/not/exist:")); + + // absolute existing paths + ASSERT_EQ("/tmp",HostUtil::getAbsolutePathList("/tmp")); + ASSERT_EQ("/tmp:/tmp",HostUtil::getAbsolutePathList("/tmp:/tmp")); + + // relative paths + chdir("/"); + ASSERT_EQ("/tmp",HostUtil::getAbsolutePathList("tmp")); + ASSERT_EQ("/tmp:/tmp",HostUtil::getAbsolutePathList("/tmp:tmp:")); + chdir(cwd); + + // cleanup + free(cwd); +} + From 8eeb24ece919d11fcfc41144d27743a97c0b0791 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Thu, 30 Jul 2015 16:53:35 +0200 Subject: [PATCH 040/298] added hostutil.h, added tests for hostutil, added more cmdline options to PS host --- CMakeLists.txt | 9 +++- host/cmdline/main.cpp | 53 +++++++++++++++++++++--- host/{cmdline => common}/coreclrutil.cpp | 4 ++ host/{cmdline => common}/coreclrutil.h | 0 host/common/hostutil.h | 48 +++++++++++++++++++++ tests/host/test-hostutil.cpp | 35 ++++++++++++++++ 6 files changed, 142 insertions(+), 7 deletions(-) rename host/{cmdline => common}/coreclrutil.cpp (96%) rename host/{cmdline => common}/coreclrutil.h (100%) create mode 100644 host/common/hostutil.h create mode 100644 tests/host/test-hostutil.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a7c35b542..a5d27e7bfc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,9 +9,11 @@ link_directories(${monad_native_BINARY_DIR}) # source file definitions set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp) +set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) +set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) -SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp host/cmdline/coreclrutil.cpp) +SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) @@ -23,5 +25,8 @@ find_package(Threads) target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) target_link_libraries(host_cmdline dl icuuc) +# target specific include directories +target_include_directories(monad_native PRIVATE host) +target_include_directories(host_cmdline PRIVATE host) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 7793bf1439..740d99185c 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -1,6 +1,7 @@ #include #include -#include "coreclrutil.h" +#include "common/coreclrutil.h" +#include "common/hostutil.h" #include #include #include @@ -32,6 +33,7 @@ void printHelp() std::cerr << " + this assembly has to be located in the search path" << std::endl; std::cerr << "- by default the host will add the current working directory to the assembly search path" << std::endl; std::cerr << " + this can be overridden with the -s command line argument" << std::endl; + std::cerr << " + if -c is specified, it will be added to the search path instead of the current directory" << std::endl; std::cerr << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl; std::cerr << " working directory" << std::endl; std::cerr << " + this can be overridden with the -b command line argument" << std::endl; @@ -44,13 +46,17 @@ void printHelp() std::cerr << "-s a list of assembly search paths, separated by :" << std::endl; std::cerr << "-b the powershell assembly base path" << std::endl; std::cerr << "-v verbose output, show paths" << std::endl; + std::cerr << "-tpa additional list of trusted platform assemblies, this references dll and exe files" << std::endl; + std::cerr << " separated by :" << std::endl; + std::cerr << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl; + std::cerr << " argument, must always be added to the TPA list with this parameter" << std::endl; std::cerr << "assembly_name the assembly name of the assembly to execute" << std::endl; std::cerr << " must be available in the search path" << std::endl; std::cerr << "type_name the type name where the function can be found" << std::endl; std::cerr << "function_name the function to execute (must have the function signature described above!)" << std::endl; std::cerr << std::endl; std::cerr << "Example:" << std::endl; - std::cerr << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'ps_hello_world.Program' 'UnmanagedMain' 'get-process'" << std::endl; + std::cerr << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'ps_hello_world.Program' 'UnmanagedMain' 'get-process'" << std::endl; } struct Args @@ -66,6 +72,7 @@ struct Args std::string assemblyLoadContextFilePath; std::string searchPaths; std::string basePath; + std::string tpaList; std::string entryAssemblyName; std::string entryTypeName; std::string entryFunctionName; @@ -80,6 +87,7 @@ struct Args std::cerr << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl; std::cerr << "- searchPaths " << searchPaths << std::endl; std::cerr << "- basePath " << basePath << std::endl; + std::cerr << "- tpaList " << tpaList << std::endl; std::cerr << "- entryAssemblyName " << entryAssemblyName << std::endl; std::cerr << "- entryTypeName " << entryTypeName << std::endl; std::cerr << "- entryFunctionName " << entryFunctionName << std::endl; @@ -124,6 +132,11 @@ bool parseCmdline(const int argc, char** argv, Args& args) args.basePath = nextArg; ++i; } + else if (hasNextArg && arg == "-tpa") + { + args.tpaList = nextArg; + ++i; + } else if (arg == "-v") { args.verbose = true; @@ -145,6 +158,9 @@ bool parseCmdline(const int argc, char** argv, Args& args) // forward command line parameters args.argc = argc-i; args.argv = &argv[i]; + + // explicitly break here because the lines above consume all remaining arguments + break; } } @@ -200,6 +216,8 @@ int main(int argc, char** argv) std::cerr << "could not find absolute CLR path" << std::endl; return 1; } + if (args.verbose) + std::cerr << "clrAbsolutePath=" << clrAbsolutePath << std::endl; // the path to the CoreCLR library // @@ -225,7 +243,23 @@ int main(int argc, char** argv) CoreCLRUtil::AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); if (args.assemblyLoadContextFilePath != "") - tpaList += ":" + args.assemblyLoadContextFilePath; + { + std::string assemblyLoadContextAbsoluteFilePath; + if (!CoreCLRUtil::GetAbsolutePath(args.assemblyLoadContextFilePath.c_str(),assemblyLoadContextAbsoluteFilePath)) + { + std::cerr << "Failed to get absolute file path for assembly load context" << std::endl; + return 1; + } + tpaList += ":" + assemblyLoadContextAbsoluteFilePath; + } + + // add the -tpa command line argument + if (args.tpaList != "") + { + std::string tpaAbsolutePathList = HostUtil::getAbsolutePathList(args.tpaList); + if (tpaAbsolutePathList != "") + tpaList += ":" + tpaAbsolutePathList; + } if (args.verbose) std::cerr << "tpaList: " << tpaList << std::endl; @@ -241,11 +275,18 @@ int main(int argc, char** argv) // assembly search paths // - // add the current directory and anything specified with the -s option + // add the current directory, and optionally the CoreCLR directory if -c was specified + // and anything specified with the -s option std::string appPath = currentDirAbsolutePath; + if (args.clrPath != "") + appPath += ":" + clrAbsolutePath; if (args.searchPaths != "") - appPath += ":" + args.searchPaths; + { + std::string searchAbsolutePathList = HostUtil::getAbsolutePathList(args.searchPaths); + if (searchAbsolutePathList != "") + appPath += ":" + searchAbsolutePathList; + } if (args.verbose) std::cerr << "appPath: " << appPath << std::endl; @@ -270,6 +311,8 @@ int main(int argc, char** argv) return 1; } } + if (args.verbose) + std::cerr << "psBasePath=" << psBasePath << std::endl; // make sure to leave 1 byte at the end for null termination std::basic_string psBasePath16(PATH_MAX+1,0); diff --git a/host/cmdline/coreclrutil.cpp b/host/common/coreclrutil.cpp similarity index 96% rename from host/cmdline/coreclrutil.cpp rename to host/common/coreclrutil.cpp index d67a1057f8..6aa8b9896a 100644 --- a/host/cmdline/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -157,6 +157,10 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) } closedir(dir); + + // strip any trailing : from the tpaList + if (tpaList.size() > 0 && tpaList[tpaList.size()-1] == ':') + tpaList.resize(tpaList.size()-1); } } // namespace CoreCLRUtil diff --git a/host/cmdline/coreclrutil.h b/host/common/coreclrutil.h similarity index 100% rename from host/cmdline/coreclrutil.h rename to host/common/coreclrutil.h diff --git a/host/common/hostutil.h b/host/common/hostutil.h new file mode 100644 index 0000000000..a8c9a208d3 --- /dev/null +++ b/host/common/hostutil.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include "common/coreclrutil.h" + +namespace HostUtil +{ + +//!\brief get a list of absolute paths separated by : from a list of relative/absolute paths separated by : +std::string getAbsolutePathList(const std::string& paths) +{ + //std::cerr << "getAbsolutePathList: paths=" << paths << std::endl; + std::string result; + + // split by : + size_t lastPos = 0; + size_t curPos = paths.find(':',lastPos); + do + { + const std::string token = paths.substr(lastPos,curPos-lastPos); + //std::cerr << "curPos=" << curPos << " lastPos=" << lastPos << " token=" << token << std::endl; + + // skip empty tokens + if (token != "") + { + std::string absolutePath; + if (CoreCLRUtil::GetAbsolutePath(token.c_str(),absolutePath)) + { + // add colons correctly + if (result.size() == 0) + result += absolutePath; + else + result += ":" + absolutePath; + } + } + + // increment lastPos to skip the : + lastPos += token.size() + 1; + curPos = paths.find(':',lastPos); + } + while (lastPos < paths.size()); + + return result; +} + +} + + diff --git a/tests/host/test-hostutil.cpp b/tests/host/test-hostutil.cpp new file mode 100644 index 0000000000..7a8b6b473b --- /dev/null +++ b/tests/host/test-hostutil.cpp @@ -0,0 +1,35 @@ +#include +#include "common/hostutil.h" + +TEST(HostUtilTest,simple) +{ + // syntactical corner cases + ASSERT_EQ("",HostUtil::getAbsolutePathList("")); + ASSERT_EQ("",HostUtil::getAbsolutePathList(":")); + ASSERT_EQ("",HostUtil::getAbsolutePathList("::")); + ASSERT_EQ("",HostUtil::getAbsolutePathList(":::::")); + + // current directory + char* cwd = get_current_dir_name(); + ASSERT_EQ(std::string(cwd),HostUtil::getAbsolutePathList(".")); + + // relative and absolute paths that don't exist + ASSERT_EQ("",HostUtil::getAbsolutePathList("/something/that/does/not/exist")); + ASSERT_EQ("",HostUtil::getAbsolutePathList(":/something/that/does/not/exist:")); + ASSERT_EQ("",HostUtil::getAbsolutePathList("something/relative/that/does/not/exist")); + ASSERT_EQ("",HostUtil::getAbsolutePathList(":something/relative/that/does/not/exist:")); + + // absolute existing paths + ASSERT_EQ("/tmp",HostUtil::getAbsolutePathList("/tmp")); + ASSERT_EQ("/tmp:/tmp",HostUtil::getAbsolutePathList("/tmp:/tmp")); + + // relative paths + chdir("/"); + ASSERT_EQ("/tmp",HostUtil::getAbsolutePathList("tmp")); + ASSERT_EQ("/tmp:/tmp",HostUtil::getAbsolutePathList("/tmp:tmp:")); + chdir(cwd); + + // cleanup + free(cwd); +} + From 84f5b079ec6fefcf0c8c14310b42d80053c68e46 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 30 Jul 2015 12:44:48 -0700 Subject: [PATCH 041/298] Added ERROR_BUFFER_OVERFLOW --- impl/pal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/impl/pal.h b/impl/pal.h index defde3b1fb..d693f778cb 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -71,6 +71,7 @@ #define FALSE 0 #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 + #define ERROR_BUFFER_OVERFLOW 111 #define MAX_PATH 0x00000104 typedef unsigned long long uint64; #endif From 920322c8095d59897626982d1b3c72d21b5ee092 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 30 Jul 2015 12:44:48 -0700 Subject: [PATCH 042/298] Added ERROR_BUFFER_OVERFLOW --- src/impl/pal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/impl/pal.h b/src/impl/pal.h index defde3b1fb..d693f778cb 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -71,6 +71,7 @@ #define FALSE 0 #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 + #define ERROR_BUFFER_OVERFLOW 111 #define MAX_PATH 0x00000104 typedef unsigned long long uint64; #endif From 8797ebb127f42163df06786d40842f46a7edcdd0 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 30 Jul 2015 12:46:28 -0700 Subject: [PATCH 043/298] Added case for failure --- impl/getcomputername.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/impl/getcomputername.cpp b/impl/getcomputername.cpp index 1ec69110c2..6b3d348ae5 100644 --- a/impl/getcomputername.cpp +++ b/impl/getcomputername.cpp @@ -1,12 +1,19 @@ #include "getcomputername.h" #include +#include BOOL GetComputerName(LPTSTR name, LPDWORD len) { + errno = 0; + int host = gethostname(name, HOST_NAME_MAX); if(host == 0) { return TRUE; - } - return FALSE; + } + else + { + errno = ERROR_BUFFER_OVERFLOW; + return FALSE; + } } From bf92f710e87bd5663fd7375dd4ac0d63ff0fd3c1 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 30 Jul 2015 12:46:28 -0700 Subject: [PATCH 044/298] Added case for failure --- src/impl/getcomputername.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/impl/getcomputername.cpp b/src/impl/getcomputername.cpp index 1ec69110c2..6b3d348ae5 100644 --- a/src/impl/getcomputername.cpp +++ b/src/impl/getcomputername.cpp @@ -1,12 +1,19 @@ #include "getcomputername.h" #include +#include BOOL GetComputerName(LPTSTR name, LPDWORD len) { + errno = 0; + int host = gethostname(name, HOST_NAME_MAX); if(host == 0) { return TRUE; - } - return FALSE; + } + else + { + errno = ERROR_BUFFER_OVERFLOW; + return FALSE; + } } From b8ae6d13a9eff0c7ff6acdf1e9a2d99292ae07c7 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 30 Jul 2015 12:47:10 -0700 Subject: [PATCH 045/298] Added failure casex --- tests/test-getcomputername.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index 8b0f19f5d7..207f964212 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -24,4 +24,13 @@ TEST(GetComputerName,simple) ASSERT_TRUE(getComputerName == TRUE); ASSERT_EQ(host,TRUE); ASSERT_EQ(hostnameString,hostnameStringTest); +} + +TEST(GetComputerName,buffertosmall) +{ + char hostname[HOST_NAME_MAX]; + std::string hostnameFunctionTest; + DWORD hostSize = 0; + BOOL getComputerName = GetComputerName(&hostnameFunctionTest[0], &hostSize); + ASSERT_TRUE(getComputerName != 0); } \ No newline at end of file From 385fb20cdf4275a2675e7702d02c015a5d33d032 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 30 Jul 2015 12:47:10 -0700 Subject: [PATCH 046/298] Added failure casex --- src/tests/test-getcomputername.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/tests/test-getcomputername.cpp b/src/tests/test-getcomputername.cpp index 8b0f19f5d7..207f964212 100644 --- a/src/tests/test-getcomputername.cpp +++ b/src/tests/test-getcomputername.cpp @@ -24,4 +24,13 @@ TEST(GetComputerName,simple) ASSERT_TRUE(getComputerName == TRUE); ASSERT_EQ(host,TRUE); ASSERT_EQ(hostnameString,hostnameStringTest); +} + +TEST(GetComputerName,buffertosmall) +{ + char hostname[HOST_NAME_MAX]; + std::string hostnameFunctionTest; + DWORD hostSize = 0; + BOOL getComputerName = GetComputerName(&hostnameFunctionTest[0], &hostSize); + ASSERT_TRUE(getComputerName != 0); } \ No newline at end of file From 4661081c7dc1c0d7849bb5cbe869ee8d96e9935b Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 30 Jul 2015 13:47:31 -0700 Subject: [PATCH 047/298] Added test for buffer not having enough space to write computer name --- impl/getcomputername.cpp | 4 ++-- tests/test-getcomputername.cpp | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/impl/getcomputername.cpp b/impl/getcomputername.cpp index 6b3d348ae5..c8a7c9719d 100644 --- a/impl/getcomputername.cpp +++ b/impl/getcomputername.cpp @@ -5,8 +5,8 @@ BOOL GetComputerName(LPTSTR name, LPDWORD len) { errno = 0; - - int host = gethostname(name, HOST_NAME_MAX); + size_t len2 = *len; + int host = gethostname(name, len2); if(host == 0) { return TRUE; diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index 207f964212..ffce53881b 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -1,5 +1,6 @@ #include #include "getcomputername.h" +#include TEST(GetComputerName,simple) { @@ -26,11 +27,13 @@ TEST(GetComputerName,simple) ASSERT_EQ(hostnameString,hostnameStringTest); } -TEST(GetComputerName,buffertosmall) +TEST(GetComputerName,bufferttoosmall) { char hostname[HOST_NAME_MAX]; std::string hostnameFunctionTest; DWORD hostSize = 0; BOOL getComputerName = GetComputerName(&hostnameFunctionTest[0], &hostSize); - ASSERT_TRUE(getComputerName != 0); + ASSERT_TRUE(getComputerName == 0); + char buffer[ 256 ]; + EXPECT_EQ(errno, ERROR_BUFFER_OVERFLOW); } \ No newline at end of file From da4d4d7a21cc4c29b67a61d13dff4417ff6ecc11 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 30 Jul 2015 13:47:31 -0700 Subject: [PATCH 048/298] Added test for buffer not having enough space to write computer name --- src/impl/getcomputername.cpp | 4 ++-- src/tests/test-getcomputername.cpp | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/impl/getcomputername.cpp b/src/impl/getcomputername.cpp index 6b3d348ae5..c8a7c9719d 100644 --- a/src/impl/getcomputername.cpp +++ b/src/impl/getcomputername.cpp @@ -5,8 +5,8 @@ BOOL GetComputerName(LPTSTR name, LPDWORD len) { errno = 0; - - int host = gethostname(name, HOST_NAME_MAX); + size_t len2 = *len; + int host = gethostname(name, len2); if(host == 0) { return TRUE; diff --git a/src/tests/test-getcomputername.cpp b/src/tests/test-getcomputername.cpp index 207f964212..ffce53881b 100644 --- a/src/tests/test-getcomputername.cpp +++ b/src/tests/test-getcomputername.cpp @@ -1,5 +1,6 @@ #include #include "getcomputername.h" +#include TEST(GetComputerName,simple) { @@ -26,11 +27,13 @@ TEST(GetComputerName,simple) ASSERT_EQ(hostnameString,hostnameStringTest); } -TEST(GetComputerName,buffertosmall) +TEST(GetComputerName,bufferttoosmall) { char hostname[HOST_NAME_MAX]; std::string hostnameFunctionTest; DWORD hostSize = 0; BOOL getComputerName = GetComputerName(&hostnameFunctionTest[0], &hostSize); - ASSERT_TRUE(getComputerName != 0); + ASSERT_TRUE(getComputerName == 0); + char buffer[ 256 ]; + EXPECT_EQ(errno, ERROR_BUFFER_OVERFLOW); } \ No newline at end of file From 7a85d035c071f09882275499aa17ed0bce9f1ab4 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 3 Aug 2015 10:48:46 -0700 Subject: [PATCH 049/298] Add error handing for bad enivronment and bad parameter --- CMakeLists.txt | 4 ++-- impl/getcomputername.cpp | 21 ++++++++++++++++++++- impl/getcomputername.h | 2 +- impl/pal.h | 4 ++-- tests/test-getcomputername.cpp | 21 +++++---------------- 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 05be91e26d..97b14a942a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,10 +8,10 @@ include_directories(../ext-src/gtest/fused-src impl) link_directories(${monad_native_BINARY_DIR}) # source file definitions -set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp) +set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp impl/getcomputername.cpp) set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getcomputername ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) diff --git a/impl/getcomputername.cpp b/impl/getcomputername.cpp index c8a7c9719d..5946851b23 100644 --- a/impl/getcomputername.cpp +++ b/impl/getcomputername.cpp @@ -1,10 +1,28 @@ #include "getcomputername.h" #include #include +#include +#include -BOOL GetComputerName(LPTSTR name, LPDWORD len) +BOOL GetComputerNameW(LPTSTR name, LPDWORD len) { + const std::string utf8 = "UTF-8"; errno = 0; + + // Check parameters + if (!name || !len) { + errno = ERROR_INVALID_PARAMETER; + return 0; + } + + // Select locale from environment + setlocale(LC_ALL, ""); + // Check that locale is UTF-8 + if (nl_langinfo(CODESET) != utf8) { + errno = ERROR_BAD_ENVIRONMENT; + return 0; + } + size_t len2 = *len; int host = gethostname(name, len2); if(host == 0) @@ -17,3 +35,4 @@ BOOL GetComputerName(LPTSTR name, LPDWORD len) return FALSE; } } + diff --git a/impl/getcomputername.h b/impl/getcomputername.h index 7f8dd8eb5a..3c83030dfc 100644 --- a/impl/getcomputername.h +++ b/impl/getcomputername.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetComputerName(LPTSTR name, LPDWORD len); +BOOL GetComputerNameW(LPTSTR name, LPDWORD len); PAL_END_EXTERNC \ No newline at end of file diff --git a/impl/pal.h b/impl/pal.h index 645974e33e..196e0314af 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -63,8 +63,7 @@ typedef void *PVOID; typedef PVOID HANDLE; typedef char TCHAR; - typedef TCHAR *LPTSTR; - typedef DWORD *LPDWORD; + typedef char *LPTSTR; #define NO_ERROR 0 #define INFINITE 0xFFFFFFFF #define WINAPI @@ -74,6 +73,7 @@ #define FALSE 0 #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 + #define ERROR_BAD_ENVIRONMENT 10; #define ERROR_BUFFER_OVERFLOW 111 #define MAX_PATH 0x00000104 typedef unsigned long long uint64; diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index ffce53881b..e76e88df45 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -3,37 +3,26 @@ #include TEST(GetComputerName,simple) -{ +{ char hostname[HOST_NAME_MAX]; - std::string hostnameFunctionTest; + std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0');; DWORD hostSize = HOST_NAME_MAX; - BOOL getComputerName = GetComputerName(&hostnameFunctionTest[0], &hostSize); + BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize); BOOL host = gethostname(hostname, sizeof hostname); - if(host == 0) - { - host = TRUE; - } - else - { - host = FALSE; - } - std::string hostnameString(hostname); std::string hostnameStringTest(&hostnameFunctionTest[0]); ASSERT_TRUE(getComputerName == TRUE); - ASSERT_EQ(host,TRUE); + ASSERT_EQ(host,0); ASSERT_EQ(hostnameString,hostnameStringTest); } TEST(GetComputerName,bufferttoosmall) { - char hostname[HOST_NAME_MAX]; std::string hostnameFunctionTest; DWORD hostSize = 0; - BOOL getComputerName = GetComputerName(&hostnameFunctionTest[0], &hostSize); + BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize); ASSERT_TRUE(getComputerName == 0); - char buffer[ 256 ]; EXPECT_EQ(errno, ERROR_BUFFER_OVERFLOW); } \ No newline at end of file From 530c6883f86f6b3dedf73e1b8c3f9aa795d3fd60 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 3 Aug 2015 10:48:46 -0700 Subject: [PATCH 050/298] Add error handing for bad enivronment and bad parameter --- src/CMakeLists.txt | 4 ++-- src/impl/getcomputername.cpp | 21 ++++++++++++++++++++- src/impl/getcomputername.h | 2 +- src/impl/pal.h | 4 ++-- src/tests/test-getcomputername.cpp | 21 +++++---------------- 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 05be91e26d..97b14a942a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,10 +8,10 @@ include_directories(../ext-src/gtest/fused-src impl) link_directories(${monad_native_BINARY_DIR}) # source file definitions -set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp) +set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp impl/getcomputername.cpp) set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getcomputername ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) diff --git a/src/impl/getcomputername.cpp b/src/impl/getcomputername.cpp index c8a7c9719d..5946851b23 100644 --- a/src/impl/getcomputername.cpp +++ b/src/impl/getcomputername.cpp @@ -1,10 +1,28 @@ #include "getcomputername.h" #include #include +#include +#include -BOOL GetComputerName(LPTSTR name, LPDWORD len) +BOOL GetComputerNameW(LPTSTR name, LPDWORD len) { + const std::string utf8 = "UTF-8"; errno = 0; + + // Check parameters + if (!name || !len) { + errno = ERROR_INVALID_PARAMETER; + return 0; + } + + // Select locale from environment + setlocale(LC_ALL, ""); + // Check that locale is UTF-8 + if (nl_langinfo(CODESET) != utf8) { + errno = ERROR_BAD_ENVIRONMENT; + return 0; + } + size_t len2 = *len; int host = gethostname(name, len2); if(host == 0) @@ -17,3 +35,4 @@ BOOL GetComputerName(LPTSTR name, LPDWORD len) return FALSE; } } + diff --git a/src/impl/getcomputername.h b/src/impl/getcomputername.h index 7f8dd8eb5a..3c83030dfc 100644 --- a/src/impl/getcomputername.h +++ b/src/impl/getcomputername.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetComputerName(LPTSTR name, LPDWORD len); +BOOL GetComputerNameW(LPTSTR name, LPDWORD len); PAL_END_EXTERNC \ No newline at end of file diff --git a/src/impl/pal.h b/src/impl/pal.h index 645974e33e..196e0314af 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -63,8 +63,7 @@ typedef void *PVOID; typedef PVOID HANDLE; typedef char TCHAR; - typedef TCHAR *LPTSTR; - typedef DWORD *LPDWORD; + typedef char *LPTSTR; #define NO_ERROR 0 #define INFINITE 0xFFFFFFFF #define WINAPI @@ -74,6 +73,7 @@ #define FALSE 0 #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 + #define ERROR_BAD_ENVIRONMENT 10; #define ERROR_BUFFER_OVERFLOW 111 #define MAX_PATH 0x00000104 typedef unsigned long long uint64; diff --git a/src/tests/test-getcomputername.cpp b/src/tests/test-getcomputername.cpp index ffce53881b..e76e88df45 100644 --- a/src/tests/test-getcomputername.cpp +++ b/src/tests/test-getcomputername.cpp @@ -3,37 +3,26 @@ #include TEST(GetComputerName,simple) -{ +{ char hostname[HOST_NAME_MAX]; - std::string hostnameFunctionTest; + std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0');; DWORD hostSize = HOST_NAME_MAX; - BOOL getComputerName = GetComputerName(&hostnameFunctionTest[0], &hostSize); + BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize); BOOL host = gethostname(hostname, sizeof hostname); - if(host == 0) - { - host = TRUE; - } - else - { - host = FALSE; - } - std::string hostnameString(hostname); std::string hostnameStringTest(&hostnameFunctionTest[0]); ASSERT_TRUE(getComputerName == TRUE); - ASSERT_EQ(host,TRUE); + ASSERT_EQ(host,0); ASSERT_EQ(hostnameString,hostnameStringTest); } TEST(GetComputerName,bufferttoosmall) { - char hostname[HOST_NAME_MAX]; std::string hostnameFunctionTest; DWORD hostSize = 0; - BOOL getComputerName = GetComputerName(&hostnameFunctionTest[0], &hostSize); + BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize); ASSERT_TRUE(getComputerName == 0); - char buffer[ 256 ]; EXPECT_EQ(errno, ERROR_BUFFER_OVERFLOW); } \ No newline at end of file From 61b4e5513a433cd8b2d884006b5d195384601ca6 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 1 Jul 2015 16:21:52 -0700 Subject: [PATCH 051/298] Update GetUserName signature --- src/impl/getusername.cpp | 2 +- src/impl/getusername.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index b37b1cffc6..e911da41b1 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -1,7 +1,7 @@ #include "getusername.h" #include -BOOL GetUserName(WCHAR_T* userName, UINT32* maxLength) +BOOL GetUserName(WCHAR_T* lpBuffer, LPDWORD lpnSize) { return 0; } diff --git a/src/impl/getusername.h b/src/impl/getusername.h index 922a4e96ad..7650b94cc8 100644 --- a/src/impl/getusername.h +++ b/src/impl/getusername.h @@ -4,7 +4,7 @@ PAL_BEGIN_EXTERNC -BOOL GetUserName(WCHAR_T* userName, UINT32* maxLength); +BOOL GetUserName(WCHAR_T* lpBuffer, LPDWORD lpnSize); PAL_END_EXTERNC From 4404e0361368b6d4fc9c2585ec0086799912c3fc Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 1 Jul 2015 16:21:52 -0700 Subject: [PATCH 052/298] Update GetUserName signature --- impl/getusername.cpp | 2 +- impl/getusername.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index b37b1cffc6..e911da41b1 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -1,7 +1,7 @@ #include "getusername.h" #include -BOOL GetUserName(WCHAR_T* userName, UINT32* maxLength) +BOOL GetUserName(WCHAR_T* lpBuffer, LPDWORD lpnSize) { return 0; } diff --git a/impl/getusername.h b/impl/getusername.h index 922a4e96ad..7650b94cc8 100644 --- a/impl/getusername.h +++ b/impl/getusername.h @@ -4,7 +4,7 @@ PAL_BEGIN_EXTERNC -BOOL GetUserName(WCHAR_T* userName, UINT32* maxLength); +BOOL GetUserName(WCHAR_T* lpBuffer, LPDWORD lpnSize); PAL_END_EXTERNC From 197938c6a64475cd4bb153de9cc151d47472342f Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 1 Jul 2015 16:24:36 -0700 Subject: [PATCH 053/298] Check locale in GetUserName --- src/impl/getusername.cpp | 27 ++++++++++++++++++++++++++- src/impl/pal.h | 1 + 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index e911da41b1..839e85c470 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -1,8 +1,33 @@ #include "getusername.h" +#include +#include +#include #include +#include +using namespace std; + +const string utf8 = "UTF-8"; + +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx +// Sets errno to: +// ERROR_BAD_ENVIRONMENT - locale is not UTF-8 +// +// Returns: +// 1 - succeeded +// 0 - failed BOOL GetUserName(WCHAR_T* lpBuffer, LPDWORD lpnSize) { - return 0; + errno = 0; + + // Select locale from environment + setlocale(LC_ALL, ""); + // Check that locale is UTF-8 + if (nl_langinfo(CODESET) != utf8) { + errno = ERROR_BAD_ENVIRONMENT; + return 0; + } + + return 1; } diff --git a/src/impl/pal.h b/src/impl/pal.h index f981088843..06ff5602c6 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -71,6 +71,7 @@ #define FALSE 0 #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 + #define ERROR_BAD_ENVIRONMENT 0x0000000A #define MAX_PATH 0x00000104 typedef unsigned long long uint64; #endif From f676c77a8e94ff8ba02d1aad18716598ae28587e Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 1 Jul 2015 16:24:36 -0700 Subject: [PATCH 054/298] Check locale in GetUserName --- impl/getusername.cpp | 27 ++++++++++++++++++++++++++- impl/pal.h | 1 + 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index e911da41b1..839e85c470 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -1,8 +1,33 @@ #include "getusername.h" +#include +#include +#include #include +#include +using namespace std; + +const string utf8 = "UTF-8"; + +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx +// Sets errno to: +// ERROR_BAD_ENVIRONMENT - locale is not UTF-8 +// +// Returns: +// 1 - succeeded +// 0 - failed BOOL GetUserName(WCHAR_T* lpBuffer, LPDWORD lpnSize) { - return 0; + errno = 0; + + // Select locale from environment + setlocale(LC_ALL, ""); + // Check that locale is UTF-8 + if (nl_langinfo(CODESET) != utf8) { + errno = ERROR_BAD_ENVIRONMENT; + return 0; + } + + return 1; } diff --git a/impl/pal.h b/impl/pal.h index f981088843..06ff5602c6 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -71,6 +71,7 @@ #define FALSE 0 #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 + #define ERROR_BAD_ENVIRONMENT 0x0000000A #define MAX_PATH 0x00000104 typedef unsigned long long uint64; #endif From 83d2162dc16a525145d3e3c6ebc7ff9bde6eb9e5 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 1 Jul 2015 16:24:58 -0700 Subject: [PATCH 055/298] Use getlogin_r() in GetUserName and map errno --- src/impl/getusername.cpp | 47 ++++++++++++++++++++++++++++++++++++++++ src/impl/pal.h | 5 +++++ 2 files changed, 52 insertions(+) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 839e85c470..55ca9c93ce 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -12,6 +12,13 @@ const string utf8 = "UTF-8"; // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx // Sets errno to: // ERROR_BAD_ENVIRONMENT - locale is not UTF-8 +// ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files +// ERROR_NO_ASSOCIATION - calling process has no controlling terminal +// ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string +// ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file +// ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure +// ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal +// ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code // // Returns: // 1 - succeeded @@ -28,6 +35,46 @@ BOOL GetUserName(WCHAR_T* lpBuffer, LPDWORD lpnSize) return 0; } + // Get username from system in a thread-safe manner + char userName[*lpnSize]; + int err = getlogin_r(userName, *lpnSize); + // Map errno to Win32 Error Codes + if (err != 0) { + switch (errno) { + case EMFILE: + case ENFILE: + errno = ERROR_TOO_MANY_OPEN_FILES; + break; + case ENXIO: + errno = ERROR_NO_ASSOCIATION; + break; + case ERANGE: + errno = ERROR_INSUFFICIENT_BUFFER; + break; + case ENOENT: + errno = ERROR_NO_SUCH_USER; + break; + case ENOMEM: + errno = ERROR_OUTOFMEMORY; + break; + case ENOTTY: + errno = ERROR_NO_ASSOCIATION; + break; + default: + errno = ERROR_INVALID_FUNCTION; + } + return 0; + } + + // TODO: Convert to char* to wchar* (UTF-8 to UTF-16 LE w/o BOM) + + // Unfortunately codecvt is not yet supported by G++, othwerise: + // wstring_convert,char16_t> conversion; + + // TODO: Use PAL's Unicode converters + + // TODO: set the lpnSize to the userName length (see msdn) + return 1; } diff --git a/src/impl/pal.h b/src/impl/pal.h index 06ff5602c6..f30903a2f4 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -72,6 +72,11 @@ #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 #define ERROR_BAD_ENVIRONMENT 0x0000000A + #define ERROR_TOO_MANY_OPEN_FILES 0x00000004 + #define ERROR_INSUFFICIENT_BUFFER 0x0000007A + #define ERROR_NO_ASSOCIATION 0x00000483 + #define ERROR_NO_SUCH_USER 0x00000525 + #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 typedef unsigned long long uint64; #endif From b80da9ab4d8d98a28ea97f75eaafa393bec67a06 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 1 Jul 2015 16:24:58 -0700 Subject: [PATCH 056/298] Use getlogin_r() in GetUserName and map errno --- impl/getusername.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++ impl/pal.h | 5 +++++ 2 files changed, 52 insertions(+) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 839e85c470..55ca9c93ce 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -12,6 +12,13 @@ const string utf8 = "UTF-8"; // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx // Sets errno to: // ERROR_BAD_ENVIRONMENT - locale is not UTF-8 +// ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files +// ERROR_NO_ASSOCIATION - calling process has no controlling terminal +// ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string +// ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file +// ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure +// ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal +// ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code // // Returns: // 1 - succeeded @@ -28,6 +35,46 @@ BOOL GetUserName(WCHAR_T* lpBuffer, LPDWORD lpnSize) return 0; } + // Get username from system in a thread-safe manner + char userName[*lpnSize]; + int err = getlogin_r(userName, *lpnSize); + // Map errno to Win32 Error Codes + if (err != 0) { + switch (errno) { + case EMFILE: + case ENFILE: + errno = ERROR_TOO_MANY_OPEN_FILES; + break; + case ENXIO: + errno = ERROR_NO_ASSOCIATION; + break; + case ERANGE: + errno = ERROR_INSUFFICIENT_BUFFER; + break; + case ENOENT: + errno = ERROR_NO_SUCH_USER; + break; + case ENOMEM: + errno = ERROR_OUTOFMEMORY; + break; + case ENOTTY: + errno = ERROR_NO_ASSOCIATION; + break; + default: + errno = ERROR_INVALID_FUNCTION; + } + return 0; + } + + // TODO: Convert to char* to wchar* (UTF-8 to UTF-16 LE w/o BOM) + + // Unfortunately codecvt is not yet supported by G++, othwerise: + // wstring_convert,char16_t> conversion; + + // TODO: Use PAL's Unicode converters + + // TODO: set the lpnSize to the userName length (see msdn) + return 1; } diff --git a/impl/pal.h b/impl/pal.h index 06ff5602c6..f30903a2f4 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -72,6 +72,11 @@ #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 #define ERROR_BAD_ENVIRONMENT 0x0000000A + #define ERROR_TOO_MANY_OPEN_FILES 0x00000004 + #define ERROR_INSUFFICIENT_BUFFER 0x0000007A + #define ERROR_NO_ASSOCIATION 0x00000483 + #define ERROR_NO_SUCH_USER 0x00000525 + #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 typedef unsigned long long uint64; #endif From 95c6658178bda60883342084d973d16fd9eeec27 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Mon, 20 Jul 2015 11:24:31 -0700 Subject: [PATCH 057/298] Add unit test for GetUserName --- src/CMakeLists.txt | 2 +- src/tests/test-getusername.cpp | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/tests/test-getusername.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a5d27e7bfc..c350c6db02 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,7 @@ link_directories(${monad_native_BINARY_DIR}) set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp) set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp new file mode 100644 index 0000000000..1b15cc2d65 --- /dev/null +++ b/src/tests/test-getusername.cpp @@ -0,0 +1,23 @@ +#include +#include +#include "getusername.h" + +TEST(GetUserName,simple) +{ + // allocate a WCHAR_T buffer to receive username + DWORD lpnSize = 64; + WCHAR_T lpBuffer[lpnSize]; + + BOOL result = GetUserName(lpBuffer, &lpnSize); + + // GetUserName returns 1 on success + ASSERT_EQ(1, result); + + // get expected username + const char *username = getlogin(); + + // GetUserName sets lpnSize to length of username including null + ASSERT_EQ(strlen(username)+1, lpnSize); + + // TODO: ASSERT_STREQ(username, Utf16leToUtf8(lpBuffer)) +} From c8fa2152619286e2dc716c8c137a20061c4e0a2d Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 10:06:31 -0700 Subject: [PATCH 058/298] Add ext-pal dependency Static library and header pulled from a build of the PAL on Ubuntu 14.04. Ugly workaround, but much easier than incorporating that entire project's build system, or even just a part of it. --- .gitmodules | 3 +++ ext-src/pal | 1 + 2 files changed, 4 insertions(+) create mode 160000 ext-src/pal diff --git a/.gitmodules b/.gitmodules index 63ba77f861..d01dc90650 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "ext-src/gtest"] path = ext-src/gtest url = https://msostc.visualstudio.com/DefaultCollection/PS/_git/ext-gtest +[submodule "ext-src/pal"] + path = ext-src/pal + url = https://msostc.visualstudio.com/DefaultCollection/PS/_git/ext-pal diff --git a/ext-src/pal b/ext-src/pal new file mode 160000 index 0000000000..56765ad5b1 --- /dev/null +++ b/ext-src/pal @@ -0,0 +1 @@ +Subproject commit 56765ad5b11e3b061b5af45b74519ce5eda99127 From f8eedc7210df2fec1bc1f7da87b884c56ad5047a Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Mon, 20 Jul 2015 11:24:31 -0700 Subject: [PATCH 059/298] Add unit test for GetUserName --- CMakeLists.txt | 2 +- tests/test-getusername.cpp | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/test-getusername.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a5d27e7bfc..c350c6db02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ link_directories(${monad_native_BINARY_DIR}) set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp) set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp new file mode 100644 index 0000000000..1b15cc2d65 --- /dev/null +++ b/tests/test-getusername.cpp @@ -0,0 +1,23 @@ +#include +#include +#include "getusername.h" + +TEST(GetUserName,simple) +{ + // allocate a WCHAR_T buffer to receive username + DWORD lpnSize = 64; + WCHAR_T lpBuffer[lpnSize]; + + BOOL result = GetUserName(lpBuffer, &lpnSize); + + // GetUserName returns 1 on success + ASSERT_EQ(1, result); + + // get expected username + const char *username = getlogin(); + + // GetUserName sets lpnSize to length of username including null + ASSERT_EQ(strlen(username)+1, lpnSize); + + // TODO: ASSERT_STREQ(username, Utf16leToUtf8(lpBuffer)) +} From 0d9d31d5bdf4c3bcc63dba3baca41361a1078152 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 10:08:26 -0700 Subject: [PATCH 060/298] Link scxcore to ps and include headers --- src/CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c350c6db02..382bf39702 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,7 @@ project(monad_native) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest -include_directories(../ext-src/gtest/fused-src impl) +include_directories(../ext-src/gtest/fused-src ../ext-src/pal/include impl) link_directories(${monad_native_BINARY_DIR}) # source file definitions @@ -17,6 +17,10 @@ SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) +add_library(scxcore STATIC IMPORTED GLOBAL) +set_property(TARGET scxcore PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../ext-src/pal/lib/libscxcore.a) +target_link_libraries(ps scxcore) + add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) @@ -28,5 +32,3 @@ target_link_libraries(host_cmdline dl icuuc) # target specific include directories target_include_directories(monad_native PRIVATE host) target_include_directories(host_cmdline PRIVATE host) - - From 8dbe788284fa94c603ce08cc4c36b96a00bbd655 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 10:08:26 -0700 Subject: [PATCH 061/298] Link scxcore to ps and include headers --- CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c350c6db02..382bf39702 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(monad_native) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest -include_directories(../ext-src/gtest/fused-src impl) +include_directories(../ext-src/gtest/fused-src ../ext-src/pal/include impl) link_directories(${monad_native_BINARY_DIR}) # source file definitions @@ -17,6 +17,10 @@ SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) +add_library(scxcore STATIC IMPORTED GLOBAL) +set_property(TARGET scxcore PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../ext-src/pal/lib/libscxcore.a) +target_link_libraries(ps scxcore) + add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) @@ -28,5 +32,3 @@ target_link_libraries(host_cmdline dl icuuc) # target specific include directories target_include_directories(monad_native PRIVATE host) target_include_directories(host_cmdline PRIVATE host) - - From 5f54d0c7484a504e8bed70e5930d10275c120606 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 10:15:34 -0700 Subject: [PATCH 062/298] Test UTF-16 output of GetUserName --- src/tests/test-getusername.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index 1b15cc2d65..c2c9d1c2db 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -1,7 +1,14 @@ +#include +#include #include #include +#include #include "getusername.h" +using std::string; +using std::vector; +using SCXCoreLib::Utf16leToUtf8; + TEST(GetUserName,simple) { // allocate a WCHAR_T buffer to receive username @@ -14,10 +21,17 @@ TEST(GetUserName,simple) ASSERT_EQ(1, result); // get expected username - const char *username = getlogin(); + string username = string(getlogin()); // GetUserName sets lpnSize to length of username including null - ASSERT_EQ(strlen(username)+1, lpnSize); + ASSERT_EQ(username.size()+1, lpnSize); - // TODO: ASSERT_STREQ(username, Utf16leToUtf8(lpBuffer)) + // copy UTF-16 bytes from lpBuffer to vector for conversion + vector input(reinterpret_cast(&lpBuffer[0]), + reinterpret_cast(&lpBuffer[lpnSize-1])); + // convert to UTF-8 for assertion + string output; + Utf16leToUtf8(input, output); + + EXPECT_EQ(username, output); } From ff0b43015bd0067d9f1bcdd55d2baa99abfba646 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 10:15:34 -0700 Subject: [PATCH 063/298] Test UTF-16 output of GetUserName --- tests/test-getusername.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index 1b15cc2d65..c2c9d1c2db 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -1,7 +1,14 @@ +#include +#include #include #include +#include #include "getusername.h" +using std::string; +using std::vector; +using SCXCoreLib::Utf16leToUtf8; + TEST(GetUserName,simple) { // allocate a WCHAR_T buffer to receive username @@ -14,10 +21,17 @@ TEST(GetUserName,simple) ASSERT_EQ(1, result); // get expected username - const char *username = getlogin(); + string username = string(getlogin()); // GetUserName sets lpnSize to length of username including null - ASSERT_EQ(strlen(username)+1, lpnSize); + ASSERT_EQ(username.size()+1, lpnSize); - // TODO: ASSERT_STREQ(username, Utf16leToUtf8(lpBuffer)) + // copy UTF-16 bytes from lpBuffer to vector for conversion + vector input(reinterpret_cast(&lpBuffer[0]), + reinterpret_cast(&lpBuffer[lpnSize-1])); + // convert to UTF-8 for assertion + string output; + Utf16leToUtf8(input, output); + + EXPECT_EQ(username, output); } From 69bfc8906ba5cfcbe8eb4de58bbc1b39a0c81bdb Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 10:15:45 -0700 Subject: [PATCH 064/298] Explain GetUserName signature --- src/impl/getusername.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/impl/getusername.h b/src/impl/getusername.h index 7650b94cc8..50c6b1d5c9 100644 --- a/src/impl/getusername.h +++ b/src/impl/getusername.h @@ -4,7 +4,8 @@ PAL_BEGIN_EXTERNC -BOOL GetUserName(WCHAR_T* lpBuffer, LPDWORD lpnSize); +// WCHAR_T * is a Unicode LPTSTR +// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR +BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize); PAL_END_EXTERNC - From a18a5912ab92c78abb17909baf4003c75d73427a Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 10:15:45 -0700 Subject: [PATCH 065/298] Explain GetUserName signature --- impl/getusername.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/impl/getusername.h b/impl/getusername.h index 7650b94cc8..50c6b1d5c9 100644 --- a/impl/getusername.h +++ b/impl/getusername.h @@ -4,7 +4,8 @@ PAL_BEGIN_EXTERNC -BOOL GetUserName(WCHAR_T* lpBuffer, LPDWORD lpnSize); +// WCHAR_T * is a Unicode LPTSTR +// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR +BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize); PAL_END_EXTERNC - From e14934d06d9c02ba060fdf367b06476ae29cd359 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 10:17:47 -0700 Subject: [PATCH 066/298] Check for invalid parameters in GetUserName --- src/impl/getusername.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 55ca9c93ce..5e3aeb1c5f 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -11,6 +11,7 @@ const string utf8 = "UTF-8"; // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx // Sets errno to: +// ERROR_INVALID_PARAMETER - parameter is not valid // ERROR_BAD_ENVIRONMENT - locale is not UTF-8 // ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files // ERROR_NO_ASSOCIATION - calling process has no controlling terminal @@ -23,10 +24,16 @@ const string utf8 = "UTF-8"; // Returns: // 1 - succeeded // 0 - failed -BOOL GetUserName(WCHAR_T* lpBuffer, LPDWORD lpnSize) +BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) { errno = 0; + // Check parameters + if (!lpBuffer || !lpnSize) { + errno = ERROR_INVALID_PARAMETER; + return 0; + } + // Select locale from environment setlocale(LC_ALL, ""); // Check that locale is UTF-8 From 6481f0336d7411ca81cb182a7664dcba5374e3bb Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 10:17:47 -0700 Subject: [PATCH 067/298] Check for invalid parameters in GetUserName --- impl/getusername.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 55ca9c93ce..5e3aeb1c5f 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -11,6 +11,7 @@ const string utf8 = "UTF-8"; // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx // Sets errno to: +// ERROR_INVALID_PARAMETER - parameter is not valid // ERROR_BAD_ENVIRONMENT - locale is not UTF-8 // ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files // ERROR_NO_ASSOCIATION - calling process has no controlling terminal @@ -23,10 +24,16 @@ const string utf8 = "UTF-8"; // Returns: // 1 - succeeded // 0 - failed -BOOL GetUserName(WCHAR_T* lpBuffer, LPDWORD lpnSize) +BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) { errno = 0; + // Check parameters + if (!lpBuffer || !lpnSize) { + errno = ERROR_INVALID_PARAMETER; + return 0; + } + // Select locale from environment setlocale(LC_ALL, ""); // Check that locale is UTF-8 From 00390847e6dacfde17cfa38634ce7895592089c6 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 10:20:50 -0700 Subject: [PATCH 068/298] Convert get_login_r to UTF-16 and return --- src/impl/getusername.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 5e3aeb1c5f..ba58182502 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -4,8 +4,13 @@ #include #include #include +#include +#include -using namespace std; +using std::string; +using std::vector; + +using SCXCoreLib::Utf8ToUtf16le; const string utf8 = "UTF-8"; @@ -73,15 +78,22 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) return 0; } - // TODO: Convert to char* to wchar* (UTF-8 to UTF-16 LE w/o BOM) + // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) + string input = string(userName); + vector output; + Utf8ToUtf16le(input, output); - // Unfortunately codecvt is not yet supported by G++, othwerise: - // wstring_convert,char16_t> conversion; + if (output.size()/2 + 1 > *lpnSize) { + errno = ERROR_INSUFFICIENT_BUFFER; + return 0; + } - // TODO: Use PAL's Unicode converters + // Add two null bytes (because it's UTF-16) + output.push_back('\0'); + output.push_back('\0'); - // TODO: set the lpnSize to the userName length (see msdn) + memcpy(lpBuffer, &output[0], output.size()); + *lpnSize = output.size()/2; return 1; } - From 3ac74ab849aa2fa441b6ae4d8d7ada0b743ca9fa Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 10:20:50 -0700 Subject: [PATCH 069/298] Convert get_login_r to UTF-16 and return --- impl/getusername.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 5e3aeb1c5f..ba58182502 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -4,8 +4,13 @@ #include #include #include +#include +#include -using namespace std; +using std::string; +using std::vector; + +using SCXCoreLib::Utf8ToUtf16le; const string utf8 = "UTF-8"; @@ -73,15 +78,22 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) return 0; } - // TODO: Convert to char* to wchar* (UTF-8 to UTF-16 LE w/o BOM) + // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) + string input = string(userName); + vector output; + Utf8ToUtf16le(input, output); - // Unfortunately codecvt is not yet supported by G++, othwerise: - // wstring_convert,char16_t> conversion; + if (output.size()/2 + 1 > *lpnSize) { + errno = ERROR_INSUFFICIENT_BUFFER; + return 0; + } - // TODO: Use PAL's Unicode converters + // Add two null bytes (because it's UTF-16) + output.push_back('\0'); + output.push_back('\0'); - // TODO: set the lpnSize to the userName length (see msdn) + memcpy(lpBuffer, &output[0], output.size()); + *lpnSize = output.size()/2; return 1; } - From 80f8fff6f294e7764f8d2489f2d7d7f5b7a8aee5 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 11:24:57 -0700 Subject: [PATCH 070/298] Clarify lpBuffer layout in GetUserName unit test --- src/tests/test-getusername.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index c2c9d1c2db..825e949608 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -26,9 +26,11 @@ TEST(GetUserName,simple) // GetUserName sets lpnSize to length of username including null ASSERT_EQ(username.size()+1, lpnSize); - // copy UTF-16 bytes from lpBuffer to vector for conversion - vector input(reinterpret_cast(&lpBuffer[0]), - reinterpret_cast(&lpBuffer[lpnSize-1])); + // copy UTF-16 bytes (excluding null) from lpBuffer to vector for conversion + unsigned char *begin = reinterpret_cast(&lpBuffer[0]); + // -1 to skip null; *2 because UTF-16 encodes two bytes per character + unsigned char *end = begin + (lpnSize-1)*2; + vector input(begin, end); // convert to UTF-8 for assertion string output; Utf16leToUtf8(input, output); From 41a00d9279529ca7c5b98958eb39f53fbbd981ed Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 11:24:57 -0700 Subject: [PATCH 071/298] Clarify lpBuffer layout in GetUserName unit test --- tests/test-getusername.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index c2c9d1c2db..825e949608 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -26,9 +26,11 @@ TEST(GetUserName,simple) // GetUserName sets lpnSize to length of username including null ASSERT_EQ(username.size()+1, lpnSize); - // copy UTF-16 bytes from lpBuffer to vector for conversion - vector input(reinterpret_cast(&lpBuffer[0]), - reinterpret_cast(&lpBuffer[lpnSize-1])); + // copy UTF-16 bytes (excluding null) from lpBuffer to vector for conversion + unsigned char *begin = reinterpret_cast(&lpBuffer[0]); + // -1 to skip null; *2 because UTF-16 encodes two bytes per character + unsigned char *end = begin + (lpnSize-1)*2; + vector input(begin, end); // convert to UTF-8 for assertion string output; Utf16leToUtf8(input, output); From 14cec68d087c42f7dcba87ca0b1b33b7e2c6416e Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 13:43:09 -0700 Subject: [PATCH 072/298] Change global to local static const To avoid polluting the global namespace without using a namespace. --- src/impl/getusername.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index ba58182502..6f11b516ae 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -12,8 +12,6 @@ using std::vector; using SCXCoreLib::Utf8ToUtf16le; -const string utf8 = "UTF-8"; - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx // Sets errno to: // ERROR_INVALID_PARAMETER - parameter is not valid @@ -31,6 +29,8 @@ const string utf8 = "UTF-8"; // 0 - failed BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) { + static const std::string utf8 = "UTF-8"; + errno = 0; // Check parameters From 6699091f7b92c1b24f438f355de222d28d245558 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 13:43:09 -0700 Subject: [PATCH 073/298] Change global to local static const To avoid polluting the global namespace without using a namespace. --- impl/getusername.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index ba58182502..6f11b516ae 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -12,8 +12,6 @@ using std::vector; using SCXCoreLib::Utf8ToUtf16le; -const string utf8 = "UTF-8"; - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx // Sets errno to: // ERROR_INVALID_PARAMETER - parameter is not valid @@ -31,6 +29,8 @@ const string utf8 = "UTF-8"; // 0 - failed BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) { + static const std::string utf8 = "UTF-8"; + errno = 0; // Check parameters From 097d2e3821fcd246b274a86957d0f85e4e871342 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 13:45:25 -0700 Subject: [PATCH 074/298] Factor out using directives --- src/impl/getusername.cpp | 11 +++-------- src/tests/test-getusername.cpp | 12 ++++-------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 6f11b516ae..35c034fb9d 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -7,11 +7,6 @@ #include #include -using std::string; -using std::vector; - -using SCXCoreLib::Utf8ToUtf16le; - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx // Sets errno to: // ERROR_INVALID_PARAMETER - parameter is not valid @@ -79,9 +74,9 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) } // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) - string input = string(userName); - vector output; - Utf8ToUtf16le(input, output); + std::string input(userName); + std::vector output; + SCXCoreLib::Utf8ToUtf16le(input, output); if (output.size()/2 + 1 > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index 825e949608..c7bbc14b47 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -5,10 +5,6 @@ #include #include "getusername.h" -using std::string; -using std::vector; -using SCXCoreLib::Utf16leToUtf8; - TEST(GetUserName,simple) { // allocate a WCHAR_T buffer to receive username @@ -21,7 +17,7 @@ TEST(GetUserName,simple) ASSERT_EQ(1, result); // get expected username - string username = string(getlogin()); + std::string username(getlogin()); // GetUserName sets lpnSize to length of username including null ASSERT_EQ(username.size()+1, lpnSize); @@ -30,10 +26,10 @@ TEST(GetUserName,simple) unsigned char *begin = reinterpret_cast(&lpBuffer[0]); // -1 to skip null; *2 because UTF-16 encodes two bytes per character unsigned char *end = begin + (lpnSize-1)*2; - vector input(begin, end); + std::vector input(begin, end); // convert to UTF-8 for assertion - string output; - Utf16leToUtf8(input, output); + std::string output; + SCXCoreLib::Utf16leToUtf8(input, output); EXPECT_EQ(username, output); } From 3ab34083783922867f11ea0900d01d5a7d8eb1c5 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 13:45:25 -0700 Subject: [PATCH 075/298] Factor out using directives --- impl/getusername.cpp | 11 +++-------- tests/test-getusername.cpp | 12 ++++-------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 6f11b516ae..35c034fb9d 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -7,11 +7,6 @@ #include #include -using std::string; -using std::vector; - -using SCXCoreLib::Utf8ToUtf16le; - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx // Sets errno to: // ERROR_INVALID_PARAMETER - parameter is not valid @@ -79,9 +74,9 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) } // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) - string input = string(userName); - vector output; - Utf8ToUtf16le(input, output); + std::string input(userName); + std::vector output; + SCXCoreLib::Utf8ToUtf16le(input, output); if (output.size()/2 + 1 > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index 825e949608..c7bbc14b47 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -5,10 +5,6 @@ #include #include "getusername.h" -using std::string; -using std::vector; -using SCXCoreLib::Utf16leToUtf8; - TEST(GetUserName,simple) { // allocate a WCHAR_T buffer to receive username @@ -21,7 +17,7 @@ TEST(GetUserName,simple) ASSERT_EQ(1, result); // get expected username - string username = string(getlogin()); + std::string username(getlogin()); // GetUserName sets lpnSize to length of username including null ASSERT_EQ(username.size()+1, lpnSize); @@ -30,10 +26,10 @@ TEST(GetUserName,simple) unsigned char *begin = reinterpret_cast(&lpBuffer[0]); // -1 to skip null; *2 because UTF-16 encodes two bytes per character unsigned char *end = begin + (lpnSize-1)*2; - vector input(begin, end); + std::vector input(begin, end); // convert to UTF-8 for assertion - string output; - Utf16leToUtf8(input, output); + std::string output; + SCXCoreLib::Utf16leToUtf8(input, output); EXPECT_EQ(username, output); } From 59eb8a5799c2a676d8e9d74fa3c1f5f07d96b9b1 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 13:48:03 -0700 Subject: [PATCH 076/298] Use L_cuserid instead of 64 and given lpnSize --- src/impl/getusername.cpp | 4 ++-- src/tests/test-getusername.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 35c034fb9d..f9c73280a4 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -43,8 +43,8 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) } // Get username from system in a thread-safe manner - char userName[*lpnSize]; - int err = getlogin_r(userName, *lpnSize); + char userName[L_cuserid]; + int err = getlogin_r(userName, L_cuserid); // Map errno to Win32 Error Codes if (err != 0) { switch (errno) { diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index c7bbc14b47..7e1badee0d 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -8,7 +8,7 @@ TEST(GetUserName,simple) { // allocate a WCHAR_T buffer to receive username - DWORD lpnSize = 64; + DWORD lpnSize = L_cuserid; WCHAR_T lpBuffer[lpnSize]; BOOL result = GetUserName(lpBuffer, &lpnSize); From e8cb7e24fed8da27eac5956c2fc8b3c8630cf4e5 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 13:48:03 -0700 Subject: [PATCH 077/298] Use L_cuserid instead of 64 and given lpnSize --- impl/getusername.cpp | 4 ++-- tests/test-getusername.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 35c034fb9d..f9c73280a4 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -43,8 +43,8 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) } // Get username from system in a thread-safe manner - char userName[*lpnSize]; - int err = getlogin_r(userName, *lpnSize); + char userName[L_cuserid]; + int err = getlogin_r(userName, L_cuserid); // Map errno to Win32 Error Codes if (err != 0) { switch (errno) { diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index c7bbc14b47..7e1badee0d 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -8,7 +8,7 @@ TEST(GetUserName,simple) { // allocate a WCHAR_T buffer to receive username - DWORD lpnSize = 64; + DWORD lpnSize = L_cuserid; WCHAR_T lpBuffer[lpnSize]; BOOL result = GetUserName(lpBuffer, &lpnSize); From edcb8b04023177ec916eac600731b805be4c3479 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 14:21:48 -0700 Subject: [PATCH 078/298] Use test fixture in GetUserName unit tests --- src/tests/test-getusername.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index 7e1badee0d..a565aa31eb 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -5,22 +5,31 @@ #include #include "getusername.h" -TEST(GetUserName,simple) -{ - // allocate a WCHAR_T buffer to receive username - DWORD lpnSize = L_cuserid; - WCHAR_T lpBuffer[lpnSize]; +class GetUserNameTest : public ::testing::Test { +protected: + DWORD lpnSize; + std::vector lpBuffer; + BOOL result; + std::string userName; - BOOL result = GetUserName(lpBuffer, &lpnSize); + GetUserNameTest(): userName(std::string(getlogin())) {} + + void GetUserNameWithSize(DWORD size) { + lpnSize = size; + // allocate a WCHAR_T buffer to receive username + lpBuffer.assign(lpnSize, '\0'); + result = GetUserName(&lpBuffer[0], &lpnSize); + } +}; + +TEST_F(GetUserNameTest, NormalUse) { + GetUserNameWithSize(L_cuserid); // GetUserName returns 1 on success ASSERT_EQ(1, result); - // get expected username - std::string username(getlogin()); - // GetUserName sets lpnSize to length of username including null - ASSERT_EQ(username.size()+1, lpnSize); + ASSERT_EQ(userName.size()+1, lpnSize); // copy UTF-16 bytes (excluding null) from lpBuffer to vector for conversion unsigned char *begin = reinterpret_cast(&lpBuffer[0]); @@ -31,5 +40,5 @@ TEST(GetUserName,simple) std::string output; SCXCoreLib::Utf16leToUtf8(input, output); - EXPECT_EQ(username, output); + EXPECT_EQ(userName, output); } From 0f07a65f501e5860fa5164af826281cb05633723 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 14:21:48 -0700 Subject: [PATCH 079/298] Use test fixture in GetUserName unit tests --- tests/test-getusername.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index 7e1badee0d..a565aa31eb 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -5,22 +5,31 @@ #include #include "getusername.h" -TEST(GetUserName,simple) -{ - // allocate a WCHAR_T buffer to receive username - DWORD lpnSize = L_cuserid; - WCHAR_T lpBuffer[lpnSize]; +class GetUserNameTest : public ::testing::Test { +protected: + DWORD lpnSize; + std::vector lpBuffer; + BOOL result; + std::string userName; - BOOL result = GetUserName(lpBuffer, &lpnSize); + GetUserNameTest(): userName(std::string(getlogin())) {} + + void GetUserNameWithSize(DWORD size) { + lpnSize = size; + // allocate a WCHAR_T buffer to receive username + lpBuffer.assign(lpnSize, '\0'); + result = GetUserName(&lpBuffer[0], &lpnSize); + } +}; + +TEST_F(GetUserNameTest, NormalUse) { + GetUserNameWithSize(L_cuserid); // GetUserName returns 1 on success ASSERT_EQ(1, result); - // get expected username - std::string username(getlogin()); - // GetUserName sets lpnSize to length of username including null - ASSERT_EQ(username.size()+1, lpnSize); + ASSERT_EQ(userName.size()+1, lpnSize); // copy UTF-16 bytes (excluding null) from lpBuffer to vector for conversion unsigned char *begin = reinterpret_cast(&lpBuffer[0]); @@ -31,5 +40,5 @@ TEST(GetUserName,simple) std::string output; SCXCoreLib::Utf16leToUtf8(input, output); - EXPECT_EQ(username, output); + EXPECT_EQ(userName, output); } From 876a88c7d8c8be6da43624ed70c955cdb7a049d4 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 15:10:44 -0700 Subject: [PATCH 080/298] Set lpnSize when insufficient --- src/impl/getusername.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index f9c73280a4..203ed5e7e2 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -80,6 +80,7 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) if (output.size()/2 + 1 > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; + *lpnSize = output.size()/2 + 1; return 0; } From 4a2c1c5a95ebd1bb2de4380167422a1d30c72ec2 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 15:10:44 -0700 Subject: [PATCH 081/298] Set lpnSize when insufficient --- impl/getusername.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index f9c73280a4..203ed5e7e2 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -80,6 +80,7 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) if (output.size()/2 + 1 > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; + *lpnSize = output.size()/2 + 1; return 0; } From e2d4ce0ab1e5563b8482adf4085bfe30b010549b Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 15:21:55 -0700 Subject: [PATCH 082/298] Add more unit test coverage for GetUserName --- src/tests/test-getusername.cpp | 115 +++++++++++++++++++++++++++------ 1 file changed, 96 insertions(+), 19 deletions(-) diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index a565aa31eb..b58387b267 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -14,31 +14,108 @@ protected: GetUserNameTest(): userName(std::string(getlogin())) {} - void GetUserNameWithSize(DWORD size) { + void TestWithSize(DWORD size) { lpnSize = size; // allocate a WCHAR_T buffer to receive username lpBuffer.assign(lpnSize, '\0'); result = GetUserName(&lpBuffer[0], &lpnSize); } + + void TestSuccess() { + SCOPED_TRACE(""); + // returns 1 on success + EXPECT_EQ(1, result); + + // sets lpnSize to length of username + null + ASSERT_EQ(userName.size()+1, lpnSize); + + // copy UTF-16 bytes (excluding null) from lpBuffer to vector for conversion + unsigned char *begin = reinterpret_cast(&lpBuffer[0]); + // -1 to skip null; *2 because UTF-16 encodes two bytes per character + unsigned char *end = begin + (lpnSize-1)*2; + std::vector input(begin, end); + // convert to UTF-8 for comparison + std::string output; + SCXCoreLib::Utf16leToUtf8(input, output); + + EXPECT_EQ(userName, output); + } + + void TestInvalidParameter() { + SCOPED_TRACE(""); + + // returns 0 on failure + EXPECT_EQ(0, result); + + // sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null + // (which is the case for an empty vector) + EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); + } + + void TestInsufficientBuffer() { + SCOPED_TRACE(""); + + // returns 0 on failure + EXPECT_EQ(0, result); + + // sets errno to ERROR_INSUFFICIENT_BUFFER + EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); + + // sets lpnSize to length of username + null + EXPECT_EQ(userName.size()+1, lpnSize); + } }; -TEST_F(GetUserNameTest, NormalUse) { - GetUserNameWithSize(L_cuserid); +TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) { + lpnSize = 1; + result = GetUserName(NULL, &lpnSize); - // GetUserName returns 1 on success - ASSERT_EQ(1, result); - - // GetUserName sets lpnSize to length of username including null - ASSERT_EQ(userName.size()+1, lpnSize); - - // copy UTF-16 bytes (excluding null) from lpBuffer to vector for conversion - unsigned char *begin = reinterpret_cast(&lpBuffer[0]); - // -1 to skip null; *2 because UTF-16 encodes two bytes per character - unsigned char *end = begin + (lpnSize-1)*2; - std::vector input(begin, end); - // convert to UTF-8 for assertion - std::string output; - SCXCoreLib::Utf16leToUtf8(input, output); - - EXPECT_EQ(userName, output); + TestInvalidParameter(); + // does not reset lpnSize + EXPECT_EQ(1, lpnSize); +} + +TEST_F(GetUserNameTest, BufferSizeAsNullButNotBuffer) { + lpBuffer.push_back('\0'); + result = GetUserName(&lpBuffer[0], NULL); + + TestInvalidParameter(); +} + +TEST_F(GetUserNameTest, BufferSizeAsZero) { + TestWithSize(0); + TestInvalidParameter(); + // does not reset lpnSize + EXPECT_EQ(0, lpnSize); +} + +TEST_F(GetUserNameTest, BufferSizeAsOne) { + // theoretically this should never fail because any non-empty + // username length will be >1 with trailing null + TestWithSize(1); + TestInsufficientBuffer(); +} + +TEST_F(GetUserNameTest, BufferSizeAsUserName) { + // the buffer is too small because this does not include null + TestWithSize(userName.size()); + TestInsufficientBuffer(); +} + +TEST_F(GetUserNameTest, BufferSizeAsUserNameMinusOne) { + // the buffer is also too small + TestWithSize(userName.size()-1); + TestInsufficientBuffer(); +} + +TEST_F(GetUserNameTest, BufferSizeAsUserNamePlusOne) { + // the buffer is exactly big enough will null + TestWithSize(userName.size()+1); + TestSuccess(); +} + +TEST_F(GetUserNameTest, L_cuseridSize) { + // L_cuserid is big enough to hold any username + TestWithSize(L_cuserid); + TestSuccess(); } From cbee353d0d0c4b759d7b94c4674dc8fedae2ef6a Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 15:21:55 -0700 Subject: [PATCH 083/298] Add more unit test coverage for GetUserName --- tests/test-getusername.cpp | 115 +++++++++++++++++++++++++++++++------ 1 file changed, 96 insertions(+), 19 deletions(-) diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index a565aa31eb..b58387b267 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -14,31 +14,108 @@ protected: GetUserNameTest(): userName(std::string(getlogin())) {} - void GetUserNameWithSize(DWORD size) { + void TestWithSize(DWORD size) { lpnSize = size; // allocate a WCHAR_T buffer to receive username lpBuffer.assign(lpnSize, '\0'); result = GetUserName(&lpBuffer[0], &lpnSize); } + + void TestSuccess() { + SCOPED_TRACE(""); + // returns 1 on success + EXPECT_EQ(1, result); + + // sets lpnSize to length of username + null + ASSERT_EQ(userName.size()+1, lpnSize); + + // copy UTF-16 bytes (excluding null) from lpBuffer to vector for conversion + unsigned char *begin = reinterpret_cast(&lpBuffer[0]); + // -1 to skip null; *2 because UTF-16 encodes two bytes per character + unsigned char *end = begin + (lpnSize-1)*2; + std::vector input(begin, end); + // convert to UTF-8 for comparison + std::string output; + SCXCoreLib::Utf16leToUtf8(input, output); + + EXPECT_EQ(userName, output); + } + + void TestInvalidParameter() { + SCOPED_TRACE(""); + + // returns 0 on failure + EXPECT_EQ(0, result); + + // sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null + // (which is the case for an empty vector) + EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); + } + + void TestInsufficientBuffer() { + SCOPED_TRACE(""); + + // returns 0 on failure + EXPECT_EQ(0, result); + + // sets errno to ERROR_INSUFFICIENT_BUFFER + EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); + + // sets lpnSize to length of username + null + EXPECT_EQ(userName.size()+1, lpnSize); + } }; -TEST_F(GetUserNameTest, NormalUse) { - GetUserNameWithSize(L_cuserid); +TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) { + lpnSize = 1; + result = GetUserName(NULL, &lpnSize); - // GetUserName returns 1 on success - ASSERT_EQ(1, result); - - // GetUserName sets lpnSize to length of username including null - ASSERT_EQ(userName.size()+1, lpnSize); - - // copy UTF-16 bytes (excluding null) from lpBuffer to vector for conversion - unsigned char *begin = reinterpret_cast(&lpBuffer[0]); - // -1 to skip null; *2 because UTF-16 encodes two bytes per character - unsigned char *end = begin + (lpnSize-1)*2; - std::vector input(begin, end); - // convert to UTF-8 for assertion - std::string output; - SCXCoreLib::Utf16leToUtf8(input, output); - - EXPECT_EQ(userName, output); + TestInvalidParameter(); + // does not reset lpnSize + EXPECT_EQ(1, lpnSize); +} + +TEST_F(GetUserNameTest, BufferSizeAsNullButNotBuffer) { + lpBuffer.push_back('\0'); + result = GetUserName(&lpBuffer[0], NULL); + + TestInvalidParameter(); +} + +TEST_F(GetUserNameTest, BufferSizeAsZero) { + TestWithSize(0); + TestInvalidParameter(); + // does not reset lpnSize + EXPECT_EQ(0, lpnSize); +} + +TEST_F(GetUserNameTest, BufferSizeAsOne) { + // theoretically this should never fail because any non-empty + // username length will be >1 with trailing null + TestWithSize(1); + TestInsufficientBuffer(); +} + +TEST_F(GetUserNameTest, BufferSizeAsUserName) { + // the buffer is too small because this does not include null + TestWithSize(userName.size()); + TestInsufficientBuffer(); +} + +TEST_F(GetUserNameTest, BufferSizeAsUserNameMinusOne) { + // the buffer is also too small + TestWithSize(userName.size()-1); + TestInsufficientBuffer(); +} + +TEST_F(GetUserNameTest, BufferSizeAsUserNamePlusOne) { + // the buffer is exactly big enough will null + TestWithSize(userName.size()+1); + TestSuccess(); +} + +TEST_F(GetUserNameTest, L_cuseridSize) { + // L_cuserid is big enough to hold any username + TestWithSize(L_cuserid); + TestSuccess(); } From bb8d0b793e9e7c5060f42ae093024662f48c14ca Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 16:04:11 -0700 Subject: [PATCH 084/298] Use LOGIN_NAME_MAX instead of L_cuserid Since L_cuserid is only for cuserid, not getlogin_r Unit test for L_cuserid removed because the macro may not be available on all platforms. --- src/impl/getusername.cpp | 4 ++-- src/tests/test-getusername.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 203ed5e7e2..d369a4a3d5 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -43,8 +43,8 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) } // Get username from system in a thread-safe manner - char userName[L_cuserid]; - int err = getlogin_r(userName, L_cuserid); + char userName[LOGIN_NAME_MAX]; + int err = getlogin_r(userName, LOGIN_NAME_MAX); // Map errno to Win32 Error Codes if (err != 0) { switch (errno) { diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index b58387b267..8e025a2de6 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -114,8 +114,8 @@ TEST_F(GetUserNameTest, BufferSizeAsUserNamePlusOne) { TestSuccess(); } -TEST_F(GetUserNameTest, L_cuseridSize) { - // L_cuserid is big enough to hold any username - TestWithSize(L_cuserid); +TEST_F(GetUserNameTest, BufferSizeAsLoginNameMax) { + // LoginNameMax is big enough to hold any username + TestWithSize(LOGIN_NAME_MAX); TestSuccess(); } From 9426e9c4551493db768620e9d08185eae85a1df3 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 16:04:11 -0700 Subject: [PATCH 085/298] Use LOGIN_NAME_MAX instead of L_cuserid Since L_cuserid is only for cuserid, not getlogin_r Unit test for L_cuserid removed because the macro may not be available on all platforms. --- impl/getusername.cpp | 4 ++-- tests/test-getusername.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 203ed5e7e2..d369a4a3d5 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -43,8 +43,8 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) } // Get username from system in a thread-safe manner - char userName[L_cuserid]; - int err = getlogin_r(userName, L_cuserid); + char userName[LOGIN_NAME_MAX]; + int err = getlogin_r(userName, LOGIN_NAME_MAX); // Map errno to Win32 Error Codes if (err != 0) { switch (errno) { diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index b58387b267..8e025a2de6 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -114,8 +114,8 @@ TEST_F(GetUserNameTest, BufferSizeAsUserNamePlusOne) { TestSuccess(); } -TEST_F(GetUserNameTest, L_cuseridSize) { - // L_cuserid is big enough to hold any username - TestWithSize(L_cuserid); +TEST_F(GetUserNameTest, BufferSizeAsLoginNameMax) { + // LoginNameMax is big enough to hold any username + TestWithSize(LOGIN_NAME_MAX); TestSuccess(); } From b36cdcdc1241a83a6176802a79d1b059bfb1f1c6 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 16:29:17 -0700 Subject: [PATCH 086/298] Use std::string instead of C99 dynamic array --- src/impl/getusername.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index d369a4a3d5..baff324c3f 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -43,8 +43,8 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) } // Get username from system in a thread-safe manner - char userName[LOGIN_NAME_MAX]; - int err = getlogin_r(userName, LOGIN_NAME_MAX); + std::string username(LOGIN_NAME_MAX, '\0'); + int err = getlogin_r(&username[0], username.size()); // Map errno to Win32 Error Codes if (err != 0) { switch (errno) { @@ -73,10 +73,17 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) return 0; } + // "Trim" the username to the first trailing null because + // otherwise the std::string with repeated null characters is + // valid, and the conversion will still include all the null + // characters. Creating a std::string from the C string of the + // original effectively trims it to the first null, without + // the need to manually trim whitespace (nor using Boost). + username = std::string(username.c_str()); + // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) - std::string input(userName); std::vector output; - SCXCoreLib::Utf8ToUtf16le(input, output); + SCXCoreLib::Utf8ToUtf16le(username, output); if (output.size()/2 + 1 > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; From 0592a37395188e204241a668612e027fd5d7a80e Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 16:29:17 -0700 Subject: [PATCH 087/298] Use std::string instead of C99 dynamic array --- impl/getusername.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index d369a4a3d5..baff324c3f 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -43,8 +43,8 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) } // Get username from system in a thread-safe manner - char userName[LOGIN_NAME_MAX]; - int err = getlogin_r(userName, LOGIN_NAME_MAX); + std::string username(LOGIN_NAME_MAX, '\0'); + int err = getlogin_r(&username[0], username.size()); // Map errno to Win32 Error Codes if (err != 0) { switch (errno) { @@ -73,10 +73,17 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) return 0; } + // "Trim" the username to the first trailing null because + // otherwise the std::string with repeated null characters is + // valid, and the conversion will still include all the null + // characters. Creating a std::string from the C string of the + // original effectively trims it to the first null, without + // the need to manually trim whitespace (nor using Boost). + username = std::string(username.c_str()); + // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) - std::string input(userName); std::vector output; - SCXCoreLib::Utf8ToUtf16le(input, output); + SCXCoreLib::Utf8ToUtf16le(username, output); if (output.size()/2 + 1 > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; From 865fd0a56be0fde4c559e72b8c7d4fdb63fc9187 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 16:36:06 -0700 Subject: [PATCH 088/298] Remove unnecessary static qualifier from const string --- src/impl/getusername.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index baff324c3f..282cd930da 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -24,7 +24,7 @@ // 0 - failed BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) { - static const std::string utf8 = "UTF-8"; + const std::string utf8 = "UTF-8"; errno = 0; From 2a2c1d92364126fe5bfe793cfd5f890a45114541 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 16:36:06 -0700 Subject: [PATCH 089/298] Remove unnecessary static qualifier from const string --- impl/getusername.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index baff324c3f..282cd930da 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -24,7 +24,7 @@ // 0 - failed BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) { - static const std::string utf8 = "UTF-8"; + const std::string utf8 = "UTF-8"; errno = 0; From d589ac1cbfa4e0f2225ab37c9f9c5fd3b5ea1b0e Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 16:36:19 -0700 Subject: [PATCH 090/298] Refactor setting of lpnSize when buffer size is insufficient --- src/impl/getusername.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 282cd930da..2e1e1dd125 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -85,9 +85,15 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) std::vector output; SCXCoreLib::Utf8ToUtf16le(username, output); - if (output.size()/2 + 1 > *lpnSize) { + // The length is the number of characters in the string, which + // is half the string size because UTF-16 encodes two bytes + // per character, plus one for the trailing null. + const DWORD length = output.size()/2 + 1; + if (length > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; - *lpnSize = output.size()/2 + 1; + // Set lpnSize if buffer is too small to inform user + // of necessary size + *lpnSize = length; return 0; } From b076850012ce66e770436d8b0b4eebdd11517bfb Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 22 Jul 2015 16:36:19 -0700 Subject: [PATCH 091/298] Refactor setting of lpnSize when buffer size is insufficient --- impl/getusername.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 282cd930da..2e1e1dd125 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -85,9 +85,15 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) std::vector output; SCXCoreLib::Utf8ToUtf16le(username, output); - if (output.size()/2 + 1 > *lpnSize) { + // The length is the number of characters in the string, which + // is half the string size because UTF-16 encodes two bytes + // per character, plus one for the trailing null. + const DWORD length = output.size()/2 + 1; + if (length > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; - *lpnSize = output.size()/2 + 1; + // Set lpnSize if buffer is too small to inform user + // of necessary size + *lpnSize = length; return 0; } From 011d8f41ea4a7b51d7f260d7d48d5e5d63da04b9 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 23 Jul 2015 09:28:34 -0700 Subject: [PATCH 092/298] Rename userName in test to expectedUsername To clarify that it is for comparison; not the result of GetUserName. --- src/tests/test-getusername.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index 8e025a2de6..4f249e1187 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -10,9 +10,9 @@ protected: DWORD lpnSize; std::vector lpBuffer; BOOL result; - std::string userName; + std::string expectedUsername; - GetUserNameTest(): userName(std::string(getlogin())) {} + GetUserNameTest(): expectedUsername(std::string(getlogin())) {} void TestWithSize(DWORD size) { lpnSize = size; @@ -27,7 +27,7 @@ protected: EXPECT_EQ(1, result); // sets lpnSize to length of username + null - ASSERT_EQ(userName.size()+1, lpnSize); + ASSERT_EQ(expectedUsername.size()+1, lpnSize); // copy UTF-16 bytes (excluding null) from lpBuffer to vector for conversion unsigned char *begin = reinterpret_cast(&lpBuffer[0]); @@ -38,7 +38,7 @@ protected: std::string output; SCXCoreLib::Utf16leToUtf8(input, output); - EXPECT_EQ(userName, output); + EXPECT_EQ(expectedUsername, output); } void TestInvalidParameter() { @@ -62,7 +62,7 @@ protected: EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); // sets lpnSize to length of username + null - EXPECT_EQ(userName.size()+1, lpnSize); + EXPECT_EQ(expectedUsername.size()+1, lpnSize); } }; @@ -98,19 +98,19 @@ TEST_F(GetUserNameTest, BufferSizeAsOne) { TEST_F(GetUserNameTest, BufferSizeAsUserName) { // the buffer is too small because this does not include null - TestWithSize(userName.size()); + TestWithSize(expectedUsername.size()); TestInsufficientBuffer(); } TEST_F(GetUserNameTest, BufferSizeAsUserNameMinusOne) { // the buffer is also too small - TestWithSize(userName.size()-1); + TestWithSize(expectedUsername.size()-1); TestInsufficientBuffer(); } TEST_F(GetUserNameTest, BufferSizeAsUserNamePlusOne) { // the buffer is exactly big enough will null - TestWithSize(userName.size()+1); + TestWithSize(expectedUsername.size()+1); TestSuccess(); } From 0c9fb0d01b23b5ef68eea4cd93eb01d06a9b4ab6 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 23 Jul 2015 09:28:34 -0700 Subject: [PATCH 093/298] Rename userName in test to expectedUsername To clarify that it is for comparison; not the result of GetUserName. --- tests/test-getusername.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index 8e025a2de6..4f249e1187 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -10,9 +10,9 @@ protected: DWORD lpnSize; std::vector lpBuffer; BOOL result; - std::string userName; + std::string expectedUsername; - GetUserNameTest(): userName(std::string(getlogin())) {} + GetUserNameTest(): expectedUsername(std::string(getlogin())) {} void TestWithSize(DWORD size) { lpnSize = size; @@ -27,7 +27,7 @@ protected: EXPECT_EQ(1, result); // sets lpnSize to length of username + null - ASSERT_EQ(userName.size()+1, lpnSize); + ASSERT_EQ(expectedUsername.size()+1, lpnSize); // copy UTF-16 bytes (excluding null) from lpBuffer to vector for conversion unsigned char *begin = reinterpret_cast(&lpBuffer[0]); @@ -38,7 +38,7 @@ protected: std::string output; SCXCoreLib::Utf16leToUtf8(input, output); - EXPECT_EQ(userName, output); + EXPECT_EQ(expectedUsername, output); } void TestInvalidParameter() { @@ -62,7 +62,7 @@ protected: EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); // sets lpnSize to length of username + null - EXPECT_EQ(userName.size()+1, lpnSize); + EXPECT_EQ(expectedUsername.size()+1, lpnSize); } }; @@ -98,19 +98,19 @@ TEST_F(GetUserNameTest, BufferSizeAsOne) { TEST_F(GetUserNameTest, BufferSizeAsUserName) { // the buffer is too small because this does not include null - TestWithSize(userName.size()); + TestWithSize(expectedUsername.size()); TestInsufficientBuffer(); } TEST_F(GetUserNameTest, BufferSizeAsUserNameMinusOne) { // the buffer is also too small - TestWithSize(userName.size()-1); + TestWithSize(expectedUsername.size()-1); TestInsufficientBuffer(); } TEST_F(GetUserNameTest, BufferSizeAsUserNamePlusOne) { // the buffer is exactly big enough will null - TestWithSize(userName.size()+1); + TestWithSize(expectedUsername.size()+1); TestSuccess(); } From c97988180434ec0fc59d12b188fe96f19b6149f3 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 3 Aug 2015 13:54:07 -0700 Subject: [PATCH 094/298] added more error handling --- CMakeLists.txt | 5 +- impl/getcomputername.cpp | 89 +++++++++++++++++++++++++++++++++- impl/pal.h | 8 ++- tests/test-getcomputername.cpp | 8 +-- 4 files changed, 101 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 97b14a942a..e25d43a83b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(monad_native) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest -include_directories(../ext-src/gtest/fused-src impl) +include_directories(../ext-src/gtest/fused-src ../ext-src/pal/include impl) link_directories(${monad_native_BINARY_DIR}) # source file definitions @@ -18,6 +18,9 @@ SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) +add_library(scxcore STATIC IMPORTED GLOBAL) +set_property(TARGET scxcore PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../ext-src/pal/lib/libscxcore.a) +target_link_libraries(ps scxcore) add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) diff --git a/impl/getcomputername.cpp b/impl/getcomputername.cpp index 5946851b23..1d98940146 100644 --- a/impl/getcomputername.cpp +++ b/impl/getcomputername.cpp @@ -1,9 +1,28 @@ #include "getcomputername.h" -#include #include -#include #include +#include +#include +#include +#include +#include + +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx +// Sets errno to: +// ERROR_INVALID_PARAMETER - parameter is not valid +// ERROR_BAD_ENVIRONMENT - locale is not UTF-8 +// ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files +// ERROR_NO_ASSOCIATION - calling process has no controlling terminal +// ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string +// ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file +// ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure +// ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal +// ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code +// +// Returns: +// 1 - succeeded +// 0 - failed BOOL GetComputerNameW(LPTSTR name, LPDWORD len) { const std::string utf8 = "UTF-8"; @@ -23,6 +42,71 @@ BOOL GetComputerNameW(LPTSTR name, LPDWORD len) return 0; } + // Get username from system in a thread-safe manner + std::string username(LOGIN_NAME_MAX, '\0'); + int err = gethostname(&username[0], username.size()); + // Map errno to Win32 Error Codes + if (err != 0) { + switch (errno) { + case EMFILE: + case ENFILE: + errno = ERROR_TOO_MANY_OPEN_FILES; + break; + case ENXIO: + errno = ERROR_NO_ASSOCIATION; + break; + case ERANGE: + errno = ERROR_INSUFFICIENT_BUFFER; + break; + case ENOENT: + errno = ERROR_NO_SUCH_USER; + break; + case ENOMEM: + errno = ERROR_OUTOFMEMORY; + break; + case ENOTTY: + errno = ERROR_NO_ASSOCIATION; + break; + default: + errno = ERROR_INVALID_FUNCTION; + } + return 0; + } + + // "Trim" the username to the first trailing null because + // otherwise the std::string with repeated null characters is + // valid, and the conversion will still include all the null + // characters. Creating a std::string from the C string of the + // original effectively trims it to the first null, without + // the need to manually trim whitespace (nor using Boost). + username = std::string(username.c_str()); + + // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) + std::vector output; + SCXCoreLib::Utf8ToUtf16le(username, output); + + // The length is the number of characters in the string, which + // is half the string size because UTF-16 encodes two bytes + // per character, plus one for the trailing null. + const DWORD length = output.size()/2 + 1; + if (length > *len) { + errno = ERROR_INSUFFICIENT_BUFFER; + // Set lpnSize if buffer is too small to inform user + // of necessary size + *len= length; + return 0; + } + + // Add two null bytes (because it's UTF-16) + output.push_back('\0'); + output.push_back('\0'); + + memcpy(name, &output[0], output.size()); + *len = output.size()/2; + + return 1; + + /* size_t len2 = *len; int host = gethostname(name, len2); if(host == 0) @@ -34,5 +118,6 @@ BOOL GetComputerNameW(LPTSTR name, LPDWORD len) errno = ERROR_BUFFER_OVERFLOW; return FALSE; } + */ } diff --git a/impl/pal.h b/impl/pal.h index 196e0314af..38ff359340 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -73,8 +73,12 @@ #define FALSE 0 #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 - #define ERROR_BAD_ENVIRONMENT 10; - #define ERROR_BUFFER_OVERFLOW 111 + #define ERROR_BAD_ENVIRONMENT 0x0000000A + #define ERROR_TOO_MANY_OPEN_FILES 0x00000004 + #define ERROR_INSUFFICIENT_BUFFER 0x0000007A + #define ERROR_NO_ASSOCIATION 0x00000483 + #define ERROR_NO_SUCH_USER 0x00000525 + #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 typedef unsigned long long uint64; #endif diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index e76e88df45..0ca76c2c12 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -5,13 +5,13 @@ TEST(GetComputerName,simple) { char hostname[HOST_NAME_MAX]; - std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0');; + std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0'); DWORD hostSize = HOST_NAME_MAX; BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize); BOOL host = gethostname(hostname, sizeof hostname); std::string hostnameString(hostname); - std::string hostnameStringTest(&hostnameFunctionTest[0]); + std::string hostnameStringTest(hostnameFunctionTest); ASSERT_TRUE(getComputerName == TRUE); ASSERT_EQ(host,0); @@ -20,9 +20,9 @@ TEST(GetComputerName,simple) TEST(GetComputerName,bufferttoosmall) { - std::string hostnameFunctionTest; + std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0'); DWORD hostSize = 0; BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize); ASSERT_TRUE(getComputerName == 0); - EXPECT_EQ(errno, ERROR_BUFFER_OVERFLOW); +// EXPECT_EQ(errno, ERROR_BUFFER_OVERFLOW); } \ No newline at end of file From 245b2874435caa83a6b331cac5f17b1d05dc5c7e Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 3 Aug 2015 13:54:07 -0700 Subject: [PATCH 095/298] added more error handling --- src/CMakeLists.txt | 5 +- src/impl/getcomputername.cpp | 89 +++++++++++++++++++++++++++++- src/impl/pal.h | 8 ++- src/tests/test-getcomputername.cpp | 8 +-- 4 files changed, 101 insertions(+), 9 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 97b14a942a..e25d43a83b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,7 @@ project(monad_native) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest -include_directories(../ext-src/gtest/fused-src impl) +include_directories(../ext-src/gtest/fused-src ../ext-src/pal/include impl) link_directories(${monad_native_BINARY_DIR}) # source file definitions @@ -18,6 +18,9 @@ SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) +add_library(scxcore STATIC IMPORTED GLOBAL) +set_property(TARGET scxcore PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../ext-src/pal/lib/libscxcore.a) +target_link_libraries(ps scxcore) add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) diff --git a/src/impl/getcomputername.cpp b/src/impl/getcomputername.cpp index 5946851b23..1d98940146 100644 --- a/src/impl/getcomputername.cpp +++ b/src/impl/getcomputername.cpp @@ -1,9 +1,28 @@ #include "getcomputername.h" -#include #include -#include #include +#include +#include +#include +#include +#include + +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx +// Sets errno to: +// ERROR_INVALID_PARAMETER - parameter is not valid +// ERROR_BAD_ENVIRONMENT - locale is not UTF-8 +// ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files +// ERROR_NO_ASSOCIATION - calling process has no controlling terminal +// ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string +// ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file +// ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure +// ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal +// ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code +// +// Returns: +// 1 - succeeded +// 0 - failed BOOL GetComputerNameW(LPTSTR name, LPDWORD len) { const std::string utf8 = "UTF-8"; @@ -23,6 +42,71 @@ BOOL GetComputerNameW(LPTSTR name, LPDWORD len) return 0; } + // Get username from system in a thread-safe manner + std::string username(LOGIN_NAME_MAX, '\0'); + int err = gethostname(&username[0], username.size()); + // Map errno to Win32 Error Codes + if (err != 0) { + switch (errno) { + case EMFILE: + case ENFILE: + errno = ERROR_TOO_MANY_OPEN_FILES; + break; + case ENXIO: + errno = ERROR_NO_ASSOCIATION; + break; + case ERANGE: + errno = ERROR_INSUFFICIENT_BUFFER; + break; + case ENOENT: + errno = ERROR_NO_SUCH_USER; + break; + case ENOMEM: + errno = ERROR_OUTOFMEMORY; + break; + case ENOTTY: + errno = ERROR_NO_ASSOCIATION; + break; + default: + errno = ERROR_INVALID_FUNCTION; + } + return 0; + } + + // "Trim" the username to the first trailing null because + // otherwise the std::string with repeated null characters is + // valid, and the conversion will still include all the null + // characters. Creating a std::string from the C string of the + // original effectively trims it to the first null, without + // the need to manually trim whitespace (nor using Boost). + username = std::string(username.c_str()); + + // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) + std::vector output; + SCXCoreLib::Utf8ToUtf16le(username, output); + + // The length is the number of characters in the string, which + // is half the string size because UTF-16 encodes two bytes + // per character, plus one for the trailing null. + const DWORD length = output.size()/2 + 1; + if (length > *len) { + errno = ERROR_INSUFFICIENT_BUFFER; + // Set lpnSize if buffer is too small to inform user + // of necessary size + *len= length; + return 0; + } + + // Add two null bytes (because it's UTF-16) + output.push_back('\0'); + output.push_back('\0'); + + memcpy(name, &output[0], output.size()); + *len = output.size()/2; + + return 1; + + /* size_t len2 = *len; int host = gethostname(name, len2); if(host == 0) @@ -34,5 +118,6 @@ BOOL GetComputerNameW(LPTSTR name, LPDWORD len) errno = ERROR_BUFFER_OVERFLOW; return FALSE; } + */ } diff --git a/src/impl/pal.h b/src/impl/pal.h index 196e0314af..38ff359340 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -73,8 +73,12 @@ #define FALSE 0 #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 - #define ERROR_BAD_ENVIRONMENT 10; - #define ERROR_BUFFER_OVERFLOW 111 + #define ERROR_BAD_ENVIRONMENT 0x0000000A + #define ERROR_TOO_MANY_OPEN_FILES 0x00000004 + #define ERROR_INSUFFICIENT_BUFFER 0x0000007A + #define ERROR_NO_ASSOCIATION 0x00000483 + #define ERROR_NO_SUCH_USER 0x00000525 + #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 typedef unsigned long long uint64; #endif diff --git a/src/tests/test-getcomputername.cpp b/src/tests/test-getcomputername.cpp index e76e88df45..0ca76c2c12 100644 --- a/src/tests/test-getcomputername.cpp +++ b/src/tests/test-getcomputername.cpp @@ -5,13 +5,13 @@ TEST(GetComputerName,simple) { char hostname[HOST_NAME_MAX]; - std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0');; + std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0'); DWORD hostSize = HOST_NAME_MAX; BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize); BOOL host = gethostname(hostname, sizeof hostname); std::string hostnameString(hostname); - std::string hostnameStringTest(&hostnameFunctionTest[0]); + std::string hostnameStringTest(hostnameFunctionTest); ASSERT_TRUE(getComputerName == TRUE); ASSERT_EQ(host,0); @@ -20,9 +20,9 @@ TEST(GetComputerName,simple) TEST(GetComputerName,bufferttoosmall) { - std::string hostnameFunctionTest; + std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0'); DWORD hostSize = 0; BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize); ASSERT_TRUE(getComputerName == 0); - EXPECT_EQ(errno, ERROR_BUFFER_OVERFLOW); +// EXPECT_EQ(errno, ERROR_BUFFER_OVERFLOW); } \ No newline at end of file From 84d24589befa85bb12685678dba477444e3b6669 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 4 Aug 2015 13:53:44 -0700 Subject: [PATCH 096/298] Link ps against icu instead of scxcore Remove scxcore library from CMake --- src/CMakeLists.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 382bf39702..439546e2a1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,7 @@ project(monad_native) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest -include_directories(../ext-src/gtest/fused-src ../ext-src/pal/include impl) +include_directories(../ext-src/gtest/fused-src impl) link_directories(${monad_native_BINARY_DIR}) # source file definitions @@ -17,9 +17,7 @@ SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) -add_library(scxcore STATIC IMPORTED GLOBAL) -set_property(TARGET scxcore PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../ext-src/pal/lib/libscxcore.a) -target_link_libraries(ps scxcore) +target_link_libraries(ps icuuc) add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) From 6ddb39e33760e633aafabf8c7fa671ef53a54195 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 4 Aug 2015 13:53:44 -0700 Subject: [PATCH 097/298] Link ps against icu instead of scxcore Remove scxcore library from CMake --- CMakeLists.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 382bf39702..439546e2a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(monad_native) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest -include_directories(../ext-src/gtest/fused-src ../ext-src/pal/include impl) +include_directories(../ext-src/gtest/fused-src impl) link_directories(${monad_native_BINARY_DIR}) # source file definitions @@ -17,9 +17,7 @@ SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) -add_library(scxcore STATIC IMPORTED GLOBAL) -set_property(TARGET scxcore PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../ext-src/pal/lib/libscxcore.a) -target_link_libraries(ps scxcore) +target_link_libraries(ps icuuc) add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) From 052ecc801d1360722d02eee4f6022b7c016baa2d Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 4 Aug 2015 13:58:44 -0700 Subject: [PATCH 098/298] Use icu for Unicode conversion and fix lpnSize A careful reading of the GetUserName documentation and Windows Data Types says that lpnSize is "the number of TCHARs copied to the buffer...including the terminating null character," and a TCHAR in this environment is a CHAR because we assume UNICODE is always defined for CoreCLR. A CHAR is a byte. So lpSize is number of bytes, not number of UTF-16 characters as we previously believed. --- src/impl/getusername.cpp | 112 +++++++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 39 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 2e1e1dd125..0314b0abed 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -4,24 +4,65 @@ #include #include #include -#include -#include +#include +#include +#include +#include -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx -// Sets errno to: -// ERROR_INVALID_PARAMETER - parameter is not valid -// ERROR_BAD_ENVIRONMENT - locale is not UTF-8 -// ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files -// ERROR_NO_ASSOCIATION - calling process has no controlling terminal -// ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string -// ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file -// ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure -// ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal -// ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code -// -// Returns: -// 1 - succeeded -// 0 - failed +/* + GetUserName function + + https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx + + Retrieves the name of the user associated with the current thread. + + Parameters + + lpBuffer [out] + + A pointer to the buffer to receive the user's logon name. If this + buffer is not large enough to contain the entire user name, the + function fails. A buffer size of (UNLEN + 1) characters will hold + the maximum length user name including the terminating null + character. UNLEN is defined in Lmcons.h. + + lpnSize [in, out] + + On input, this variable specifies the size of the lpBuffer buffer, + in TCHARs. On output, the variable receives the number of TCHARs + copied to the buffer, including the terminating null character. + + Note that TCHAR is CHAR here because UNICODE is defined, and so a + TCHAR is a byte. + + https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#CHAR + + If lpBuffer is too small, the function fails and GetLastError + returns ERROR_INSUFFICIENT_BUFFER. This parameter receives the + required buffer size, including the terminating null character. + + + Sets errno to: + ERROR_INVALID_PARAMETER - parameter is not valid + ERROR_BAD_ENVIRONMENT - locale is not UTF-8 + ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files + ERROR_NO_ASSOCIATION - calling process has no controlling terminal + ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string + ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file + ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure + ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal + ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code + + Return value + + If the function succeeds, the return value is a nonzero value, and + the variable pointed to by lpnSize contains the number of TCHARs + copied to the buffer specified by lpBuffer, including the + terminating null character. + + If the function fails, the return value is zero. To get extended + error information, call GetLastError. +*/ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) { const std::string utf8 = "UTF-8"; @@ -73,36 +114,29 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) return 0; } - // "Trim" the username to the first trailing null because - // otherwise the std::string with repeated null characters is - // valid, and the conversion will still include all the null - // characters. Creating a std::string from the C string of the - // original effectively trims it to the first null, without - // the need to manually trim whitespace (nor using Boost). - username = std::string(username.c_str()); - // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) - std::vector output; - SCXCoreLib::Utf8ToUtf16le(username, output); + std::basic_string username16(LOGIN_NAME_MAX+1, 0); + icu::UnicodeString username8(username.c_str(), "UTF-8"); + int32_t targetSize = username8.extract(0, username8.length(), + reinterpret_cast(&username16[0]), + (username16.size()-1)*sizeof(char16_t), + "UTF-16LE"); + // number of characters including null + username16.resize(targetSize/sizeof(char16_t)+1); - // The length is the number of characters in the string, which - // is half the string size because UTF-16 encodes two bytes - // per character, plus one for the trailing null. - const DWORD length = output.size()/2 + 1; - if (length > *lpnSize) { + // Size in bytes including null + const DWORD size = username16.length()*sizeof(char16_t); + if (size > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; // Set lpnSize if buffer is too small to inform user // of necessary size - *lpnSize = length; + *lpnSize = size; return 0; } - // Add two null bytes (because it's UTF-16) - output.push_back('\0'); - output.push_back('\0'); - - memcpy(lpBuffer, &output[0], output.size()); - *lpnSize = output.size()/2; + // Copy bytes from string to buffer + memcpy(lpBuffer, &username16[0], size); + *lpnSize = size; return 1; } From d60bfe03764102b5a3c8fbe81d374f00758eb406 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 4 Aug 2015 13:58:44 -0700 Subject: [PATCH 099/298] Use icu for Unicode conversion and fix lpnSize A careful reading of the GetUserName documentation and Windows Data Types says that lpnSize is "the number of TCHARs copied to the buffer...including the terminating null character," and a TCHAR in this environment is a CHAR because we assume UNICODE is always defined for CoreCLR. A CHAR is a byte. So lpSize is number of bytes, not number of UTF-16 characters as we previously believed. --- impl/getusername.cpp | 112 ++++++++++++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 39 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 2e1e1dd125..0314b0abed 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -4,24 +4,65 @@ #include #include #include -#include -#include +#include +#include +#include +#include -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx -// Sets errno to: -// ERROR_INVALID_PARAMETER - parameter is not valid -// ERROR_BAD_ENVIRONMENT - locale is not UTF-8 -// ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files -// ERROR_NO_ASSOCIATION - calling process has no controlling terminal -// ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string -// ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file -// ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure -// ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal -// ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code -// -// Returns: -// 1 - succeeded -// 0 - failed +/* + GetUserName function + + https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx + + Retrieves the name of the user associated with the current thread. + + Parameters + + lpBuffer [out] + + A pointer to the buffer to receive the user's logon name. If this + buffer is not large enough to contain the entire user name, the + function fails. A buffer size of (UNLEN + 1) characters will hold + the maximum length user name including the terminating null + character. UNLEN is defined in Lmcons.h. + + lpnSize [in, out] + + On input, this variable specifies the size of the lpBuffer buffer, + in TCHARs. On output, the variable receives the number of TCHARs + copied to the buffer, including the terminating null character. + + Note that TCHAR is CHAR here because UNICODE is defined, and so a + TCHAR is a byte. + + https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#CHAR + + If lpBuffer is too small, the function fails and GetLastError + returns ERROR_INSUFFICIENT_BUFFER. This parameter receives the + required buffer size, including the terminating null character. + + + Sets errno to: + ERROR_INVALID_PARAMETER - parameter is not valid + ERROR_BAD_ENVIRONMENT - locale is not UTF-8 + ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files + ERROR_NO_ASSOCIATION - calling process has no controlling terminal + ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string + ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file + ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure + ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal + ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code + + Return value + + If the function succeeds, the return value is a nonzero value, and + the variable pointed to by lpnSize contains the number of TCHARs + copied to the buffer specified by lpBuffer, including the + terminating null character. + + If the function fails, the return value is zero. To get extended + error information, call GetLastError. +*/ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) { const std::string utf8 = "UTF-8"; @@ -73,36 +114,29 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) return 0; } - // "Trim" the username to the first trailing null because - // otherwise the std::string with repeated null characters is - // valid, and the conversion will still include all the null - // characters. Creating a std::string from the C string of the - // original effectively trims it to the first null, without - // the need to manually trim whitespace (nor using Boost). - username = std::string(username.c_str()); - // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) - std::vector output; - SCXCoreLib::Utf8ToUtf16le(username, output); + std::basic_string username16(LOGIN_NAME_MAX+1, 0); + icu::UnicodeString username8(username.c_str(), "UTF-8"); + int32_t targetSize = username8.extract(0, username8.length(), + reinterpret_cast(&username16[0]), + (username16.size()-1)*sizeof(char16_t), + "UTF-16LE"); + // number of characters including null + username16.resize(targetSize/sizeof(char16_t)+1); - // The length is the number of characters in the string, which - // is half the string size because UTF-16 encodes two bytes - // per character, plus one for the trailing null. - const DWORD length = output.size()/2 + 1; - if (length > *lpnSize) { + // Size in bytes including null + const DWORD size = username16.length()*sizeof(char16_t); + if (size > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; // Set lpnSize if buffer is too small to inform user // of necessary size - *lpnSize = length; + *lpnSize = size; return 0; } - // Add two null bytes (because it's UTF-16) - output.push_back('\0'); - output.push_back('\0'); - - memcpy(lpBuffer, &output[0], output.size()); - *lpnSize = output.size()/2; + // Copy bytes from string to buffer + memcpy(lpBuffer, &username16[0], size); + *lpnSize = size; return 1; } From b77b0a7e6c56c4e0af239f0f572469c4f5b62247 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 4 Aug 2015 14:02:34 -0700 Subject: [PATCH 100/298] Update GetUserName tests Note that these fail when run in a Docker container because a) the current container's locale is not completely set, and b) getlogin() returns null with ENOENT since /var/run/utmp is being mapped to the host, and thus denied access from within the container. The container needs the locale set and its own /run/utmp, see https://lists.linuxcontainers.org/pipermail/lxc-users/2011-July/002374.html --- src/tests/test-getusername.cpp | 69 ++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index 4f249e1187..575aa85452 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -1,8 +1,10 @@ #include -#include #include #include -#include +#include +#include +#include +#include #include "getusername.h" class GetUserNameTest : public ::testing::Test { @@ -11,8 +13,11 @@ protected: std::vector lpBuffer; BOOL result; std::string expectedUsername; + DWORD expectedSize; - GetUserNameTest(): expectedUsername(std::string(getlogin())) {} + GetUserNameTest(): expectedUsername(std::string(getlogin())), + expectedSize((expectedUsername.length()+1)*sizeof(char16_t)) + {} void TestWithSize(DWORD size) { lpnSize = size; @@ -23,22 +28,28 @@ protected: void TestSuccess() { SCOPED_TRACE(""); + // returns 1 on success EXPECT_EQ(1, result); - // sets lpnSize to length of username + null - ASSERT_EQ(expectedUsername.size()+1, lpnSize); + // sets lpnSize to number of bytes including null, + // note that this is (length+1)*sizeof(char16_t) + ASSERT_EQ(expectedSize, lpnSize); - // copy UTF-16 bytes (excluding null) from lpBuffer to vector for conversion - unsigned char *begin = reinterpret_cast(&lpBuffer[0]); - // -1 to skip null; *2 because UTF-16 encodes two bytes per character - unsigned char *end = begin + (lpnSize-1)*2; - std::vector input(begin, end); - // convert to UTF-8 for comparison - std::string output; - SCXCoreLib::Utf16leToUtf8(input, output); + // setup for conversion from UTF-16LE + const char *begin = reinterpret_cast(&lpBuffer[0]); + icu::UnicodeString username16(begin, lpnSize, "UTF-16LE"); + // username16 length includes null and is number of characters + ASSERT_EQ(expectedUsername.length()+1, username16.length()); - EXPECT_EQ(expectedUsername, output); + // convert (minus null) to UTF-8 for comparison + std::string username(lpnSize/sizeof(char16_t)-1, 0); + ASSERT_EQ(expectedUsername.length(), username.length()); + int32_t targetSize = username16.extract(0, username.length(), + reinterpret_cast(&username[0]), + "UTF-8"); + + EXPECT_EQ(expectedUsername, username); } void TestInvalidParameter() { @@ -62,7 +73,7 @@ protected: EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); // sets lpnSize to length of username + null - EXPECT_EQ(expectedUsername.size()+1, lpnSize); + EXPECT_EQ(expectedSize, lpnSize); } }; @@ -96,21 +107,33 @@ TEST_F(GetUserNameTest, BufferSizeAsOne) { TestInsufficientBuffer(); } -TEST_F(GetUserNameTest, BufferSizeAsUserName) { - // the buffer is too small because this does not include null +TEST_F(GetUserNameTest, BufferSizeAsUsername) { + // the buffer is too small because this is a UTF-8 size TestWithSize(expectedUsername.size()); TestInsufficientBuffer(); } -TEST_F(GetUserNameTest, BufferSizeAsUserNameMinusOne) { - // the buffer is also too small - TestWithSize(expectedUsername.size()-1); +TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOne) { + // the buffer is still too small even with null + TestWithSize(expectedUsername.size()+1); TestInsufficientBuffer(); } -TEST_F(GetUserNameTest, BufferSizeAsUserNamePlusOne) { - // the buffer is exactly big enough will null - TestWithSize(expectedUsername.size()+1); +TEST_F(GetUserNameTest, BufferSizeAsUsernameInUTF16) { + // the buffer is still too small because it is missing null + TestWithSize(expectedUsername.size()*sizeof(char16_t)); + TestInsufficientBuffer(); +} + +TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOneInUTF16) { + // the buffer is exactly big enough + TestWithSize((expectedUsername.size()+1)*sizeof(char16_t)); + TestSuccess(); +} + +TEST_F(GetUserNameTest, BufferSizeAsExpectedSize) { + // expectedSize is the same as username.size()+1 in UTF16 + TestWithSize(expectedSize); TestSuccess(); } From e64c8961c935a4ffdd13dc82c97d3f074b6a219f Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 4 Aug 2015 14:02:34 -0700 Subject: [PATCH 101/298] Update GetUserName tests Note that these fail when run in a Docker container because a) the current container's locale is not completely set, and b) getlogin() returns null with ENOENT since /var/run/utmp is being mapped to the host, and thus denied access from within the container. The container needs the locale set and its own /run/utmp, see https://lists.linuxcontainers.org/pipermail/lxc-users/2011-July/002374.html --- tests/test-getusername.cpp | 69 +++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index 4f249e1187..575aa85452 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -1,8 +1,10 @@ #include -#include #include #include -#include +#include +#include +#include +#include #include "getusername.h" class GetUserNameTest : public ::testing::Test { @@ -11,8 +13,11 @@ protected: std::vector lpBuffer; BOOL result; std::string expectedUsername; + DWORD expectedSize; - GetUserNameTest(): expectedUsername(std::string(getlogin())) {} + GetUserNameTest(): expectedUsername(std::string(getlogin())), + expectedSize((expectedUsername.length()+1)*sizeof(char16_t)) + {} void TestWithSize(DWORD size) { lpnSize = size; @@ -23,22 +28,28 @@ protected: void TestSuccess() { SCOPED_TRACE(""); + // returns 1 on success EXPECT_EQ(1, result); - // sets lpnSize to length of username + null - ASSERT_EQ(expectedUsername.size()+1, lpnSize); + // sets lpnSize to number of bytes including null, + // note that this is (length+1)*sizeof(char16_t) + ASSERT_EQ(expectedSize, lpnSize); - // copy UTF-16 bytes (excluding null) from lpBuffer to vector for conversion - unsigned char *begin = reinterpret_cast(&lpBuffer[0]); - // -1 to skip null; *2 because UTF-16 encodes two bytes per character - unsigned char *end = begin + (lpnSize-1)*2; - std::vector input(begin, end); - // convert to UTF-8 for comparison - std::string output; - SCXCoreLib::Utf16leToUtf8(input, output); + // setup for conversion from UTF-16LE + const char *begin = reinterpret_cast(&lpBuffer[0]); + icu::UnicodeString username16(begin, lpnSize, "UTF-16LE"); + // username16 length includes null and is number of characters + ASSERT_EQ(expectedUsername.length()+1, username16.length()); - EXPECT_EQ(expectedUsername, output); + // convert (minus null) to UTF-8 for comparison + std::string username(lpnSize/sizeof(char16_t)-1, 0); + ASSERT_EQ(expectedUsername.length(), username.length()); + int32_t targetSize = username16.extract(0, username.length(), + reinterpret_cast(&username[0]), + "UTF-8"); + + EXPECT_EQ(expectedUsername, username); } void TestInvalidParameter() { @@ -62,7 +73,7 @@ protected: EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); // sets lpnSize to length of username + null - EXPECT_EQ(expectedUsername.size()+1, lpnSize); + EXPECT_EQ(expectedSize, lpnSize); } }; @@ -96,21 +107,33 @@ TEST_F(GetUserNameTest, BufferSizeAsOne) { TestInsufficientBuffer(); } -TEST_F(GetUserNameTest, BufferSizeAsUserName) { - // the buffer is too small because this does not include null +TEST_F(GetUserNameTest, BufferSizeAsUsername) { + // the buffer is too small because this is a UTF-8 size TestWithSize(expectedUsername.size()); TestInsufficientBuffer(); } -TEST_F(GetUserNameTest, BufferSizeAsUserNameMinusOne) { - // the buffer is also too small - TestWithSize(expectedUsername.size()-1); +TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOne) { + // the buffer is still too small even with null + TestWithSize(expectedUsername.size()+1); TestInsufficientBuffer(); } -TEST_F(GetUserNameTest, BufferSizeAsUserNamePlusOne) { - // the buffer is exactly big enough will null - TestWithSize(expectedUsername.size()+1); +TEST_F(GetUserNameTest, BufferSizeAsUsernameInUTF16) { + // the buffer is still too small because it is missing null + TestWithSize(expectedUsername.size()*sizeof(char16_t)); + TestInsufficientBuffer(); +} + +TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOneInUTF16) { + // the buffer is exactly big enough + TestWithSize((expectedUsername.size()+1)*sizeof(char16_t)); + TestSuccess(); +} + +TEST_F(GetUserNameTest, BufferSizeAsExpectedSize) { + // expectedSize is the same as username.size()+1 in UTF16 + TestWithSize(expectedSize); TestSuccess(); } From 7d007d67084ef9a4bce364af05d36a31619066b0 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 4 Aug 2015 14:08:27 -0700 Subject: [PATCH 102/298] Remove PAL submodule --- .gitmodules | 3 --- ext-src/pal | 1 - 2 files changed, 4 deletions(-) delete mode 160000 ext-src/pal diff --git a/.gitmodules b/.gitmodules index d01dc90650..63ba77f861 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "ext-src/gtest"] path = ext-src/gtest url = https://msostc.visualstudio.com/DefaultCollection/PS/_git/ext-gtest -[submodule "ext-src/pal"] - path = ext-src/pal - url = https://msostc.visualstudio.com/DefaultCollection/PS/_git/ext-pal diff --git a/ext-src/pal b/ext-src/pal deleted file mode 160000 index 56765ad5b1..0000000000 --- a/ext-src/pal +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 56765ad5b11e3b061b5af45b74519ce5eda99127 From 54618f1750a4567b5c66a23cfedaf76070b51dd4 Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 4 Aug 2015 14:38:53 -0700 Subject: [PATCH 103/298] Made changes based off feedback from Peter. Also added more unit tests --- CMakeLists.txt | 2 +- impl/getcomputername.cpp | 56 ++++------------- impl/getcomputername.h | 2 +- impl/pal.h | 1 + tests/test-getcomputername.cpp | 107 +++++++++++++++++++++++++++------ 5 files changed, 103 insertions(+), 65 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e25d43a83b..755b5c1db7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(monad_native) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest -include_directories(../ext-src/gtest/fused-src ../ext-src/pal/include impl) +include_directories(../ext-src/gtest/fused-src impl) link_directories(${monad_native_BINARY_DIR}) # source file definitions diff --git a/impl/getcomputername.cpp b/impl/getcomputername.cpp index 1d98940146..c403cfe6d0 100644 --- a/impl/getcomputername.cpp +++ b/impl/getcomputername.cpp @@ -1,11 +1,9 @@ #include "getcomputername.h" #include #include -#include #include #include -#include -#include +#include // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx @@ -23,13 +21,13 @@ // Returns: // 1 - succeeded // 0 - failed -BOOL GetComputerNameW(LPTSTR name, LPDWORD len) +BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len) { const std::string utf8 = "UTF-8"; errno = 0; // Check parameters - if (!name || !len) { + if (!nameOfComputer || !len) { errno = ERROR_INVALID_PARAMETER; return 0; } @@ -42,9 +40,9 @@ BOOL GetComputerNameW(LPTSTR name, LPDWORD len) return 0; } - // Get username from system in a thread-safe manner - std::string username(LOGIN_NAME_MAX, '\0'); - int err = gethostname(&username[0], username.size()); + // Get computername from system in a thread-safe manner + std::string computerName(HOST_MAX_NAME, '\0'); + int err = gethostname(&computerName[0], computerName.size()); // Map errno to Win32 Error Codes if (err != 0) { switch (errno) { @@ -67,28 +65,18 @@ BOOL GetComputerNameW(LPTSTR name, LPDWORD len) case ENOTTY: errno = ERROR_NO_ASSOCIATION; break; + errno = ERROR_NO_ASSOCIATION; default: errno = ERROR_INVALID_FUNCTION; } return 0; } - // "Trim" the username to the first trailing null because - // otherwise the std::string with repeated null characters is - // valid, and the conversion will still include all the null - // characters. Creating a std::string from the C string of the - // original effectively trims it to the first null, without - // the need to manually trim whitespace (nor using Boost). - username = std::string(username.c_str()); + //Resize the string to not inlcude extra buffer space + const DWORD length = computerName.find_first_of('\0') + 1; + computerName.resize(length); - // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) - std::vector output; - SCXCoreLib::Utf8ToUtf16le(username, output); - - // The length is the number of characters in the string, which - // is half the string size because UTF-16 encodes two bytes - // per character, plus one for the trailing null. - const DWORD length = output.size()/2 + 1; + //Check if parameters passed enough buffer space if (length > *len) { errno = ERROR_INSUFFICIENT_BUFFER; // Set lpnSize if buffer is too small to inform user @@ -97,27 +85,9 @@ BOOL GetComputerNameW(LPTSTR name, LPDWORD len) return 0; } - // Add two null bytes (because it's UTF-16) - output.push_back('\0'); - output.push_back('\0'); - - memcpy(name, &output[0], output.size()); - *len = output.size()/2; - + memcpy(nameOfComputer, &computerName[0], length); + *len = length; return 1; - /* - size_t len2 = *len; - int host = gethostname(name, len2); - if(host == 0) - { - return TRUE; - } - else - { - errno = ERROR_BUFFER_OVERFLOW; - return FALSE; - } - */ } diff --git a/impl/getcomputername.h b/impl/getcomputername.h index 3c83030dfc..5e0d5be2ba 100644 --- a/impl/getcomputername.h +++ b/impl/getcomputername.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetComputerNameW(LPTSTR name, LPDWORD len); +BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len); PAL_END_EXTERNC \ No newline at end of file diff --git a/impl/pal.h b/impl/pal.h index 38ff359340..1692f15df4 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -80,6 +80,7 @@ #define ERROR_NO_SUCH_USER 0x00000525 #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 + #define HOST_MAX_NAME 256 typedef unsigned long long uint64; #endif diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index 0ca76c2c12..b917305535 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -2,27 +2,94 @@ #include "getcomputername.h" #include -TEST(GetComputerName,simple) -{ - char hostname[HOST_NAME_MAX]; - std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0'); - DWORD hostSize = HOST_NAME_MAX; - BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize); - BOOL host = gethostname(hostname, sizeof hostname); +class GetComputerNameTest : public ::testing::Test { +protected: + DWORD lpnSize; + BOOL result; + std::string expectedComputerName; + std::string computerName; + + //Get expected result from using linux call + GetComputerNameTest(){ + char hostname[HOST_MAX_NAME]; + BOOL host = gethostname(hostname, sizeof hostname); + expectedComputerName = hostname; + } + + void TestWithSize(DWORD size) { + lpnSize = size; + // allocate a DWORD buffer to receive computername + computerName.assign(lpnSize, '\0'); + result = GetComputerNameW(&computerName[0], &lpnSize); + } + + void TestSuccess() { + SCOPED_TRACE(""); + // returns 1 on success + EXPECT_EQ(1, result); + //Resize to cut off '\0' + computerName.resize(expectedComputerName.length()); + ASSERT_EQ(expectedComputerName.size()+1, lpnSize); + EXPECT_EQ(computerName, expectedComputerName); + } + + void TestInvalidParameter() { + SCOPED_TRACE(""); + + // returns 0 on failure + EXPECT_EQ(0, result); + + // sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null + EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); + } + + void TestInsufficientBuffer() { + SCOPED_TRACE(""); + + // returns 0 on failure + EXPECT_EQ(0, result); + + // sets errno to ERROR_INSUFFICIENT_BUFFER + EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); + + // sets lpnSize to length of username + null + ASSERT_EQ(expectedComputerName.size()+1, lpnSize); + } +}; - std::string hostnameString(hostname); - std::string hostnameStringTest(hostnameFunctionTest); - - ASSERT_TRUE(getComputerName == TRUE); - ASSERT_EQ(host,0); - ASSERT_EQ(hostnameString,hostnameStringTest); +TEST_F(GetComputerNameTest, BufferAsNullButNotBufferSize) { + lpnSize = 1; + result = GetComputerNameW(NULL, &lpnSize); + TestInvalidParameter(); + // does not reset lpnSize + EXPECT_EQ(1, lpnSize); } -TEST(GetComputerName,bufferttoosmall) -{ - std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0'); - DWORD hostSize = 0; - BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize); - ASSERT_TRUE(getComputerName == 0); -// EXPECT_EQ(errno, ERROR_BUFFER_OVERFLOW); +TEST_F(GetComputerNameTest, BufferSizeAsNullButNotBuffer) { + computerName.push_back('\0'); + result = GetComputerNameW(&computerName[0], NULL); + TestInvalidParameter(); +} + +TEST_F(GetComputerNameTest, BufferSizeAsZero) { + TestWithSize(0); + EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); +} + +TEST_F(GetComputerNameTest, BufferSizeAsUserNameMinusOne) { + // the buffer is also too small + TestWithSize(expectedComputerName.size()-1); + TestInsufficientBuffer(); +} + +TEST_F(GetComputerNameTest, BufferSizeAsUserNamePlusOne) { + // the buffer is exactly big enough + TestWithSize(expectedComputerName.size()+1); + TestSuccess(); +} + +TEST_F(GetComputerNameTest, BufferSizeAsLoginNameMax) { + // the buffer larger than needed + TestWithSize(HOST_MAX_NAME); + TestSuccess(); } \ No newline at end of file From 9ff9a882796ac63249dd27b71491db0ff5075404 Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 4 Aug 2015 14:38:53 -0700 Subject: [PATCH 104/298] Made changes based off feedback from Peter. Also added more unit tests --- src/CMakeLists.txt | 2 +- src/impl/getcomputername.cpp | 56 ++++----------- src/impl/getcomputername.h | 2 +- src/impl/pal.h | 1 + src/tests/test-getcomputername.cpp | 107 +++++++++++++++++++++++------ 5 files changed, 103 insertions(+), 65 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e25d43a83b..755b5c1db7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,7 @@ project(monad_native) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #include gtest -include_directories(../ext-src/gtest/fused-src ../ext-src/pal/include impl) +include_directories(../ext-src/gtest/fused-src impl) link_directories(${monad_native_BINARY_DIR}) # source file definitions diff --git a/src/impl/getcomputername.cpp b/src/impl/getcomputername.cpp index 1d98940146..c403cfe6d0 100644 --- a/src/impl/getcomputername.cpp +++ b/src/impl/getcomputername.cpp @@ -1,11 +1,9 @@ #include "getcomputername.h" #include #include -#include #include #include -#include -#include +#include // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx @@ -23,13 +21,13 @@ // Returns: // 1 - succeeded // 0 - failed -BOOL GetComputerNameW(LPTSTR name, LPDWORD len) +BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len) { const std::string utf8 = "UTF-8"; errno = 0; // Check parameters - if (!name || !len) { + if (!nameOfComputer || !len) { errno = ERROR_INVALID_PARAMETER; return 0; } @@ -42,9 +40,9 @@ BOOL GetComputerNameW(LPTSTR name, LPDWORD len) return 0; } - // Get username from system in a thread-safe manner - std::string username(LOGIN_NAME_MAX, '\0'); - int err = gethostname(&username[0], username.size()); + // Get computername from system in a thread-safe manner + std::string computerName(HOST_MAX_NAME, '\0'); + int err = gethostname(&computerName[0], computerName.size()); // Map errno to Win32 Error Codes if (err != 0) { switch (errno) { @@ -67,28 +65,18 @@ BOOL GetComputerNameW(LPTSTR name, LPDWORD len) case ENOTTY: errno = ERROR_NO_ASSOCIATION; break; + errno = ERROR_NO_ASSOCIATION; default: errno = ERROR_INVALID_FUNCTION; } return 0; } - // "Trim" the username to the first trailing null because - // otherwise the std::string with repeated null characters is - // valid, and the conversion will still include all the null - // characters. Creating a std::string from the C string of the - // original effectively trims it to the first null, without - // the need to manually trim whitespace (nor using Boost). - username = std::string(username.c_str()); + //Resize the string to not inlcude extra buffer space + const DWORD length = computerName.find_first_of('\0') + 1; + computerName.resize(length); - // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) - std::vector output; - SCXCoreLib::Utf8ToUtf16le(username, output); - - // The length is the number of characters in the string, which - // is half the string size because UTF-16 encodes two bytes - // per character, plus one for the trailing null. - const DWORD length = output.size()/2 + 1; + //Check if parameters passed enough buffer space if (length > *len) { errno = ERROR_INSUFFICIENT_BUFFER; // Set lpnSize if buffer is too small to inform user @@ -97,27 +85,9 @@ BOOL GetComputerNameW(LPTSTR name, LPDWORD len) return 0; } - // Add two null bytes (because it's UTF-16) - output.push_back('\0'); - output.push_back('\0'); - - memcpy(name, &output[0], output.size()); - *len = output.size()/2; - + memcpy(nameOfComputer, &computerName[0], length); + *len = length; return 1; - /* - size_t len2 = *len; - int host = gethostname(name, len2); - if(host == 0) - { - return TRUE; - } - else - { - errno = ERROR_BUFFER_OVERFLOW; - return FALSE; - } - */ } diff --git a/src/impl/getcomputername.h b/src/impl/getcomputername.h index 3c83030dfc..5e0d5be2ba 100644 --- a/src/impl/getcomputername.h +++ b/src/impl/getcomputername.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetComputerNameW(LPTSTR name, LPDWORD len); +BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len); PAL_END_EXTERNC \ No newline at end of file diff --git a/src/impl/pal.h b/src/impl/pal.h index 38ff359340..1692f15df4 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -80,6 +80,7 @@ #define ERROR_NO_SUCH_USER 0x00000525 #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 + #define HOST_MAX_NAME 256 typedef unsigned long long uint64; #endif diff --git a/src/tests/test-getcomputername.cpp b/src/tests/test-getcomputername.cpp index 0ca76c2c12..b917305535 100644 --- a/src/tests/test-getcomputername.cpp +++ b/src/tests/test-getcomputername.cpp @@ -2,27 +2,94 @@ #include "getcomputername.h" #include -TEST(GetComputerName,simple) -{ - char hostname[HOST_NAME_MAX]; - std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0'); - DWORD hostSize = HOST_NAME_MAX; - BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize); - BOOL host = gethostname(hostname, sizeof hostname); +class GetComputerNameTest : public ::testing::Test { +protected: + DWORD lpnSize; + BOOL result; + std::string expectedComputerName; + std::string computerName; + + //Get expected result from using linux call + GetComputerNameTest(){ + char hostname[HOST_MAX_NAME]; + BOOL host = gethostname(hostname, sizeof hostname); + expectedComputerName = hostname; + } + + void TestWithSize(DWORD size) { + lpnSize = size; + // allocate a DWORD buffer to receive computername + computerName.assign(lpnSize, '\0'); + result = GetComputerNameW(&computerName[0], &lpnSize); + } + + void TestSuccess() { + SCOPED_TRACE(""); + // returns 1 on success + EXPECT_EQ(1, result); + //Resize to cut off '\0' + computerName.resize(expectedComputerName.length()); + ASSERT_EQ(expectedComputerName.size()+1, lpnSize); + EXPECT_EQ(computerName, expectedComputerName); + } + + void TestInvalidParameter() { + SCOPED_TRACE(""); + + // returns 0 on failure + EXPECT_EQ(0, result); + + // sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null + EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); + } + + void TestInsufficientBuffer() { + SCOPED_TRACE(""); + + // returns 0 on failure + EXPECT_EQ(0, result); + + // sets errno to ERROR_INSUFFICIENT_BUFFER + EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); + + // sets lpnSize to length of username + null + ASSERT_EQ(expectedComputerName.size()+1, lpnSize); + } +}; - std::string hostnameString(hostname); - std::string hostnameStringTest(hostnameFunctionTest); - - ASSERT_TRUE(getComputerName == TRUE); - ASSERT_EQ(host,0); - ASSERT_EQ(hostnameString,hostnameStringTest); +TEST_F(GetComputerNameTest, BufferAsNullButNotBufferSize) { + lpnSize = 1; + result = GetComputerNameW(NULL, &lpnSize); + TestInvalidParameter(); + // does not reset lpnSize + EXPECT_EQ(1, lpnSize); } -TEST(GetComputerName,bufferttoosmall) -{ - std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0'); - DWORD hostSize = 0; - BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize); - ASSERT_TRUE(getComputerName == 0); -// EXPECT_EQ(errno, ERROR_BUFFER_OVERFLOW); +TEST_F(GetComputerNameTest, BufferSizeAsNullButNotBuffer) { + computerName.push_back('\0'); + result = GetComputerNameW(&computerName[0], NULL); + TestInvalidParameter(); +} + +TEST_F(GetComputerNameTest, BufferSizeAsZero) { + TestWithSize(0); + EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); +} + +TEST_F(GetComputerNameTest, BufferSizeAsUserNameMinusOne) { + // the buffer is also too small + TestWithSize(expectedComputerName.size()-1); + TestInsufficientBuffer(); +} + +TEST_F(GetComputerNameTest, BufferSizeAsUserNamePlusOne) { + // the buffer is exactly big enough + TestWithSize(expectedComputerName.size()+1); + TestSuccess(); +} + +TEST_F(GetComputerNameTest, BufferSizeAsLoginNameMax) { + // the buffer larger than needed + TestWithSize(HOST_MAX_NAME); + TestSuccess(); } \ No newline at end of file From 447896aede3dbea54ff3a3078565c149d6466de7 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 4 Aug 2015 18:27:29 -0700 Subject: [PATCH 105/298] Use WCHAR sizes instead of CHAR sizes Such that lpnSize is the length (number of UTF-16 characters, including null) of the username. Must be multiplied by sizeof(char16_t) for bytes. --- impl/getusername.cpp | 10 +++++----- tests/test-getusername.cpp | 36 ++++++++++++------------------------ 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 0314b0abed..e2bd4e8377 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -32,7 +32,7 @@ in TCHARs. On output, the variable receives the number of TCHARs copied to the buffer, including the terminating null character. - Note that TCHAR is CHAR here because UNICODE is defined, and so a + Note that TCHAR is WCHAR here because UNICODE is defined, and so a TCHAR is a byte. https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#CHAR @@ -121,11 +121,11 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) reinterpret_cast(&username16[0]), (username16.size()-1)*sizeof(char16_t), "UTF-16LE"); - // number of characters including null + // Number of characters including null username16.resize(targetSize/sizeof(char16_t)+1); - // Size in bytes including null - const DWORD size = username16.length()*sizeof(char16_t); + // Size in WCHARs including null + const DWORD size = username16.length(); if (size > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; // Set lpnSize if buffer is too small to inform user @@ -135,7 +135,7 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) } // Copy bytes from string to buffer - memcpy(lpBuffer, &username16[0], size); + memcpy(lpBuffer, &username16[0], size*sizeof(char16_t)); *lpnSize = size; return 1; diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index 575aa85452..1aab90721e 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -16,7 +17,7 @@ protected: DWORD expectedSize; GetUserNameTest(): expectedUsername(std::string(getlogin())), - expectedSize((expectedUsername.length()+1)*sizeof(char16_t)) + expectedSize(expectedUsername.length()+1) {} void TestWithSize(DWORD size) { @@ -32,22 +33,21 @@ protected: // returns 1 on success EXPECT_EQ(1, result); - // sets lpnSize to number of bytes including null, - // note that this is (length+1)*sizeof(char16_t) + // sets lpnSize to number of WCHARs including null ASSERT_EQ(expectedSize, lpnSize); // setup for conversion from UTF-16LE const char *begin = reinterpret_cast(&lpBuffer[0]); - icu::UnicodeString username16(begin, lpnSize, "UTF-16LE"); + // multiply to get number of bytes + icu::UnicodeString username16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); // username16 length includes null and is number of characters - ASSERT_EQ(expectedUsername.length()+1, username16.length()); + ASSERT_EQ(expectedSize, username16.length()); // convert (minus null) to UTF-8 for comparison - std::string username(lpnSize/sizeof(char16_t)-1, 0); + std::string username(lpnSize-1, 0); ASSERT_EQ(expectedUsername.length(), username.length()); int32_t targetSize = username16.extract(0, username.length(), - reinterpret_cast(&username[0]), - "UTF-8"); + reinterpret_cast(&username[0]), "UTF-8"); EXPECT_EQ(expectedUsername, username); } @@ -109,30 +109,18 @@ TEST_F(GetUserNameTest, BufferSizeAsOne) { TEST_F(GetUserNameTest, BufferSizeAsUsername) { // the buffer is too small because this is a UTF-8 size - TestWithSize(expectedUsername.size()); + TestWithSize(expectedUsername.length()); TestInsufficientBuffer(); } TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOne) { - // the buffer is still too small even with null - TestWithSize(expectedUsername.size()+1); - TestInsufficientBuffer(); -} - -TEST_F(GetUserNameTest, BufferSizeAsUsernameInUTF16) { - // the buffer is still too small because it is missing null - TestWithSize(expectedUsername.size()*sizeof(char16_t)); - TestInsufficientBuffer(); -} - -TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOneInUTF16) { - // the buffer is exactly big enough - TestWithSize((expectedUsername.size()+1)*sizeof(char16_t)); + // includes null and so should be sufficient + TestWithSize(expectedUsername.length()+1); TestSuccess(); } TEST_F(GetUserNameTest, BufferSizeAsExpectedSize) { - // expectedSize is the same as username.size()+1 in UTF16 + // expectedSize is the same as username.size()+1 TestWithSize(expectedSize); TestSuccess(); } From 2ec0c2996f8048d5feb84e660af674bd5528ec2b Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 4 Aug 2015 18:27:29 -0700 Subject: [PATCH 106/298] Use WCHAR sizes instead of CHAR sizes Such that lpnSize is the length (number of UTF-16 characters, including null) of the username. Must be multiplied by sizeof(char16_t) for bytes. --- src/impl/getusername.cpp | 10 +++++----- src/tests/test-getusername.cpp | 36 ++++++++++++---------------------- 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 0314b0abed..e2bd4e8377 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -32,7 +32,7 @@ in TCHARs. On output, the variable receives the number of TCHARs copied to the buffer, including the terminating null character. - Note that TCHAR is CHAR here because UNICODE is defined, and so a + Note that TCHAR is WCHAR here because UNICODE is defined, and so a TCHAR is a byte. https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#CHAR @@ -121,11 +121,11 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) reinterpret_cast(&username16[0]), (username16.size()-1)*sizeof(char16_t), "UTF-16LE"); - // number of characters including null + // Number of characters including null username16.resize(targetSize/sizeof(char16_t)+1); - // Size in bytes including null - const DWORD size = username16.length()*sizeof(char16_t); + // Size in WCHARs including null + const DWORD size = username16.length(); if (size > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; // Set lpnSize if buffer is too small to inform user @@ -135,7 +135,7 @@ BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) } // Copy bytes from string to buffer - memcpy(lpBuffer, &username16[0], size); + memcpy(lpBuffer, &username16[0], size*sizeof(char16_t)); *lpnSize = size; return 1; diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index 575aa85452..1aab90721e 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -16,7 +17,7 @@ protected: DWORD expectedSize; GetUserNameTest(): expectedUsername(std::string(getlogin())), - expectedSize((expectedUsername.length()+1)*sizeof(char16_t)) + expectedSize(expectedUsername.length()+1) {} void TestWithSize(DWORD size) { @@ -32,22 +33,21 @@ protected: // returns 1 on success EXPECT_EQ(1, result); - // sets lpnSize to number of bytes including null, - // note that this is (length+1)*sizeof(char16_t) + // sets lpnSize to number of WCHARs including null ASSERT_EQ(expectedSize, lpnSize); // setup for conversion from UTF-16LE const char *begin = reinterpret_cast(&lpBuffer[0]); - icu::UnicodeString username16(begin, lpnSize, "UTF-16LE"); + // multiply to get number of bytes + icu::UnicodeString username16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); // username16 length includes null and is number of characters - ASSERT_EQ(expectedUsername.length()+1, username16.length()); + ASSERT_EQ(expectedSize, username16.length()); // convert (minus null) to UTF-8 for comparison - std::string username(lpnSize/sizeof(char16_t)-1, 0); + std::string username(lpnSize-1, 0); ASSERT_EQ(expectedUsername.length(), username.length()); int32_t targetSize = username16.extract(0, username.length(), - reinterpret_cast(&username[0]), - "UTF-8"); + reinterpret_cast(&username[0]), "UTF-8"); EXPECT_EQ(expectedUsername, username); } @@ -109,30 +109,18 @@ TEST_F(GetUserNameTest, BufferSizeAsOne) { TEST_F(GetUserNameTest, BufferSizeAsUsername) { // the buffer is too small because this is a UTF-8 size - TestWithSize(expectedUsername.size()); + TestWithSize(expectedUsername.length()); TestInsufficientBuffer(); } TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOne) { - // the buffer is still too small even with null - TestWithSize(expectedUsername.size()+1); - TestInsufficientBuffer(); -} - -TEST_F(GetUserNameTest, BufferSizeAsUsernameInUTF16) { - // the buffer is still too small because it is missing null - TestWithSize(expectedUsername.size()*sizeof(char16_t)); - TestInsufficientBuffer(); -} - -TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOneInUTF16) { - // the buffer is exactly big enough - TestWithSize((expectedUsername.size()+1)*sizeof(char16_t)); + // includes null and so should be sufficient + TestWithSize(expectedUsername.length()+1); TestSuccess(); } TEST_F(GetUserNameTest, BufferSizeAsExpectedSize) { - // expectedSize is the same as username.size()+1 in UTF16 + // expectedSize is the same as username.size()+1 TestWithSize(expectedSize); TestSuccess(); } From 3aba128b6d9a0ce572a0dcd85b5cb0da3fdeb944 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 6 Aug 2015 10:16:13 -0700 Subject: [PATCH 107/298] Got rid of tests for UTF7, added error checking, adding test to check for null paramater for codepage --- src/CMakeLists.txt | 4 +-- src/impl/getcpinfo.cpp | 52 +++++++++++++++++++++++++----------- src/impl/getcpinfo.h | 2 +- src/impl/pal.h | 2 ++ src/tests/test-getcpinfo.cpp | 34 +++++++++++++---------- 5 files changed, 62 insertions(+), 32 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a5d27e7bfc..9fce473e17 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,10 +8,10 @@ include_directories(../ext-src/gtest/fused-src impl) link_directories(${monad_native_BINARY_DIR}) # source file definitions -set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp) +set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp impl/getcpinfo.cpp) set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getcpinfo.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) diff --git a/src/impl/getcpinfo.cpp b/src/impl/getcpinfo.cpp index 857b00de71..419c4c5f6e 100644 --- a/src/impl/getcpinfo.cpp +++ b/src/impl/getcpinfo.cpp @@ -1,28 +1,50 @@ #include "getcpinfo.h" -#include +#include #include +#include -BOOL GetCPInfo(UINT codepage, CPINFO &cpinfo) + +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx +// Sets errno to: +// ERROR_INVALID_PARAMETER - parameter is not valid +// ERROR_BAD_ENVIRONMENT - locale is not UTF-8 +// +// Returns: +// TRUE - succeeded +// FALSE - failed + +BOOL GetCPInfoW(UINT codepage, CPINFO &cpinfo) { - std::string test; - switch(codepage) - { - case 65000: - cpinfo.DefaultChar[0] = '?'; - cpinfo.DefaultChar[1] = '0'; - cpinfo.LeadByte[0] = '0'; - cpinfo.LeadByte[1] = '0'; - cpinfo.MaxCharSize = 5; - return TRUE; - case 65001: + + const std::string utf8 = "UTF-8"; + errno = 0; + + //Check that codepage is not null + if(!codepage) { + errno = ERROR_INVALID_PARAMETER; + return FALSE; + } + + // Select locale from environment + setlocale(LC_ALL, ""); + // Check that locale is UTF-8 + if (nl_langinfo(CODESET) != utf8) { + errno = ERROR_BAD_ENVIRONMENT; + return 0; + } + + //if codepage is utf8 + if(codepage == 65001) { cpinfo.DefaultChar[0] = '?'; cpinfo.DefaultChar[1] = '0'; cpinfo.LeadByte[0] = '0'; cpinfo.LeadByte[1] = '0'; cpinfo.MaxCharSize = 4; return TRUE; - default: + } + else{ + errno = ERROR_INVALID_PARAMETER; return FALSE; - } + } } diff --git a/src/impl/getcpinfo.h b/src/impl/getcpinfo.h index 0e5d574628..e1b203bc1c 100644 --- a/src/impl/getcpinfo.h +++ b/src/impl/getcpinfo.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetCPInfo(UINT codepage, CPINFO &cpinfo); +BOOL GetCPInfoW(UINT codepage, CPINFO &cpinfo); PAL_END_EXTERNC diff --git a/src/impl/pal.h b/src/impl/pal.h index 46ae8feb5f..5d398c8b80 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -75,6 +75,8 @@ #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 #define MAX_PATH 0x00000104 + #define UTF8 65001 + #define ERROR_BAD_ENVIRONMENT 0x0000000A typedef unsigned long long uint64; #endif diff --git a/src/tests/test-getcpinfo.cpp b/src/tests/test-getcpinfo.cpp index 0a8d110e9b..341c5279d0 100644 --- a/src/tests/test-getcpinfo.cpp +++ b/src/tests/test-getcpinfo.cpp @@ -1,14 +1,14 @@ #include #include "getcpinfo.h" -// This is a very simple test case to show how tests can be written -TEST(GetCPInfo,utf8) +// This test is with correct parameters +TEST(GetCPInfo,Utf8) { CPINFO cpinfo; - BOOL utf8 = GetCPInfo(65001, cpinfo); + BOOL result = GetCPInfoW(UTF8, cpinfo); // first make sure that the function worked - ASSERT_TRUE(utf8 == TRUE); + ASSERT_TRUE(result == TRUE); // now compare the actual values ASSERT_EQ(cpinfo.DefaultChar[0],'?'); @@ -18,18 +18,24 @@ TEST(GetCPInfo,utf8) ASSERT_EQ(cpinfo.MaxCharSize,4); } -TEST(GetCPInfo,utf7) +// This test is with codepage being null +TEST(GetCPInfo, NullForCodePageUINTButNotCpinfo) { CPINFO cpinfo; - BOOL utf7 = GetCPInfo(65000, cpinfo); + BOOL result = GetCPInfoW(NULL, cpinfo); - // first make sure that the function worked - ASSERT_TRUE(utf7 == TRUE); + ASSERT_TRUE(result == FALSE); + EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); + +} - // now compare the actual values - ASSERT_EQ(cpinfo.DefaultChar[0],'?'); - ASSERT_EQ(cpinfo.DefaultChar[1],'0'); - ASSERT_EQ(cpinfo.LeadByte[0],'0'); - ASSERT_EQ(cpinfo.LeadByte[1],'0'); - ASSERT_EQ(cpinfo.MaxCharSize,5); +// This test is with codepage not being utf8 +TEST(GetCPInfo, CodePageNotUTF8) +{ + CPINFO cpinfo; + BOOL result = GetCPInfoW(65000, cpinfo); + + ASSERT_TRUE(result == FALSE); + EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); + } \ No newline at end of file From 316cabbdcf367d409eb2ab281be02ced3ea08e65 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 6 Aug 2015 10:16:13 -0700 Subject: [PATCH 108/298] Got rid of tests for UTF7, added error checking, adding test to check for null paramater for codepage --- CMakeLists.txt | 4 ++-- impl/getcpinfo.cpp | 52 ++++++++++++++++++++++++++++------------ impl/getcpinfo.h | 2 +- impl/pal.h | 2 ++ tests/test-getcpinfo.cpp | 34 +++++++++++++++----------- 5 files changed, 62 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a5d27e7bfc..9fce473e17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,10 +8,10 @@ include_directories(../ext-src/gtest/fused-src impl) link_directories(${monad_native_BINARY_DIR}) # source file definitions -set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp) +set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp impl/getcpinfo.cpp) set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getcpinfo.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) diff --git a/impl/getcpinfo.cpp b/impl/getcpinfo.cpp index 857b00de71..419c4c5f6e 100644 --- a/impl/getcpinfo.cpp +++ b/impl/getcpinfo.cpp @@ -1,28 +1,50 @@ #include "getcpinfo.h" -#include +#include #include +#include -BOOL GetCPInfo(UINT codepage, CPINFO &cpinfo) + +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx +// Sets errno to: +// ERROR_INVALID_PARAMETER - parameter is not valid +// ERROR_BAD_ENVIRONMENT - locale is not UTF-8 +// +// Returns: +// TRUE - succeeded +// FALSE - failed + +BOOL GetCPInfoW(UINT codepage, CPINFO &cpinfo) { - std::string test; - switch(codepage) - { - case 65000: - cpinfo.DefaultChar[0] = '?'; - cpinfo.DefaultChar[1] = '0'; - cpinfo.LeadByte[0] = '0'; - cpinfo.LeadByte[1] = '0'; - cpinfo.MaxCharSize = 5; - return TRUE; - case 65001: + + const std::string utf8 = "UTF-8"; + errno = 0; + + //Check that codepage is not null + if(!codepage) { + errno = ERROR_INVALID_PARAMETER; + return FALSE; + } + + // Select locale from environment + setlocale(LC_ALL, ""); + // Check that locale is UTF-8 + if (nl_langinfo(CODESET) != utf8) { + errno = ERROR_BAD_ENVIRONMENT; + return 0; + } + + //if codepage is utf8 + if(codepage == 65001) { cpinfo.DefaultChar[0] = '?'; cpinfo.DefaultChar[1] = '0'; cpinfo.LeadByte[0] = '0'; cpinfo.LeadByte[1] = '0'; cpinfo.MaxCharSize = 4; return TRUE; - default: + } + else{ + errno = ERROR_INVALID_PARAMETER; return FALSE; - } + } } diff --git a/impl/getcpinfo.h b/impl/getcpinfo.h index 0e5d574628..e1b203bc1c 100644 --- a/impl/getcpinfo.h +++ b/impl/getcpinfo.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetCPInfo(UINT codepage, CPINFO &cpinfo); +BOOL GetCPInfoW(UINT codepage, CPINFO &cpinfo); PAL_END_EXTERNC diff --git a/impl/pal.h b/impl/pal.h index 46ae8feb5f..5d398c8b80 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -75,6 +75,8 @@ #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 #define MAX_PATH 0x00000104 + #define UTF8 65001 + #define ERROR_BAD_ENVIRONMENT 0x0000000A typedef unsigned long long uint64; #endif diff --git a/tests/test-getcpinfo.cpp b/tests/test-getcpinfo.cpp index 0a8d110e9b..341c5279d0 100644 --- a/tests/test-getcpinfo.cpp +++ b/tests/test-getcpinfo.cpp @@ -1,14 +1,14 @@ #include #include "getcpinfo.h" -// This is a very simple test case to show how tests can be written -TEST(GetCPInfo,utf8) +// This test is with correct parameters +TEST(GetCPInfo,Utf8) { CPINFO cpinfo; - BOOL utf8 = GetCPInfo(65001, cpinfo); + BOOL result = GetCPInfoW(UTF8, cpinfo); // first make sure that the function worked - ASSERT_TRUE(utf8 == TRUE); + ASSERT_TRUE(result == TRUE); // now compare the actual values ASSERT_EQ(cpinfo.DefaultChar[0],'?'); @@ -18,18 +18,24 @@ TEST(GetCPInfo,utf8) ASSERT_EQ(cpinfo.MaxCharSize,4); } -TEST(GetCPInfo,utf7) +// This test is with codepage being null +TEST(GetCPInfo, NullForCodePageUINTButNotCpinfo) { CPINFO cpinfo; - BOOL utf7 = GetCPInfo(65000, cpinfo); + BOOL result = GetCPInfoW(NULL, cpinfo); - // first make sure that the function worked - ASSERT_TRUE(utf7 == TRUE); + ASSERT_TRUE(result == FALSE); + EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); + +} - // now compare the actual values - ASSERT_EQ(cpinfo.DefaultChar[0],'?'); - ASSERT_EQ(cpinfo.DefaultChar[1],'0'); - ASSERT_EQ(cpinfo.LeadByte[0],'0'); - ASSERT_EQ(cpinfo.LeadByte[1],'0'); - ASSERT_EQ(cpinfo.MaxCharSize,5); +// This test is with codepage not being utf8 +TEST(GetCPInfo, CodePageNotUTF8) +{ + CPINFO cpinfo; + BOOL result = GetCPInfoW(65000, cpinfo); + + ASSERT_TRUE(result == FALSE); + EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); + } \ No newline at end of file From b379fb4a6b8f9d56d4fa0f7fbe4f7673fe3f53d7 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 6 Aug 2015 16:28:29 -0700 Subject: [PATCH 109/298] Rename to GetUserNameW since it is Unicode --- impl/getusername.cpp | 4 ++-- impl/getusername.h | 2 +- tests/test-getusername.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index e2bd4e8377..ba6f64ad86 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -10,7 +10,7 @@ #include /* - GetUserName function + GetUserNameW function https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx @@ -63,7 +63,7 @@ If the function fails, the return value is zero. To get extended error information, call GetLastError. */ -BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) +BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize) { const std::string utf8 = "UTF-8"; diff --git a/impl/getusername.h b/impl/getusername.h index 50c6b1d5c9..ad6099c4b0 100644 --- a/impl/getusername.h +++ b/impl/getusername.h @@ -6,6 +6,6 @@ PAL_BEGIN_EXTERNC // WCHAR_T * is a Unicode LPTSTR // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR -BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize); +BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize); PAL_END_EXTERNC diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index 1aab90721e..5a6a8535cc 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -24,7 +24,7 @@ protected: lpnSize = size; // allocate a WCHAR_T buffer to receive username lpBuffer.assign(lpnSize, '\0'); - result = GetUserName(&lpBuffer[0], &lpnSize); + result = GetUserNameW(&lpBuffer[0], &lpnSize); } void TestSuccess() { @@ -79,7 +79,7 @@ protected: TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) { lpnSize = 1; - result = GetUserName(NULL, &lpnSize); + result = GetUserNameW(NULL, &lpnSize); TestInvalidParameter(); // does not reset lpnSize @@ -88,7 +88,7 @@ TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) { TEST_F(GetUserNameTest, BufferSizeAsNullButNotBuffer) { lpBuffer.push_back('\0'); - result = GetUserName(&lpBuffer[0], NULL); + result = GetUserNameW(&lpBuffer[0], NULL); TestInvalidParameter(); } From afab62205adba68538fdef3dbdef5f57ec3c6c26 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 6 Aug 2015 16:28:29 -0700 Subject: [PATCH 110/298] Rename to GetUserNameW since it is Unicode --- src/impl/getusername.cpp | 4 ++-- src/impl/getusername.h | 2 +- src/tests/test-getusername.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index e2bd4e8377..ba6f64ad86 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -10,7 +10,7 @@ #include /* - GetUserName function + GetUserNameW function https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx @@ -63,7 +63,7 @@ If the function fails, the return value is zero. To get extended error information, call GetLastError. */ -BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize) +BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize) { const std::string utf8 = "UTF-8"; diff --git a/src/impl/getusername.h b/src/impl/getusername.h index 50c6b1d5c9..ad6099c4b0 100644 --- a/src/impl/getusername.h +++ b/src/impl/getusername.h @@ -6,6 +6,6 @@ PAL_BEGIN_EXTERNC // WCHAR_T * is a Unicode LPTSTR // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR -BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize); +BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize); PAL_END_EXTERNC diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index 1aab90721e..5a6a8535cc 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -24,7 +24,7 @@ protected: lpnSize = size; // allocate a WCHAR_T buffer to receive username lpBuffer.assign(lpnSize, '\0'); - result = GetUserName(&lpBuffer[0], &lpnSize); + result = GetUserNameW(&lpBuffer[0], &lpnSize); } void TestSuccess() { @@ -79,7 +79,7 @@ protected: TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) { lpnSize = 1; - result = GetUserName(NULL, &lpnSize); + result = GetUserNameW(NULL, &lpnSize); TestInvalidParameter(); // does not reset lpnSize @@ -88,7 +88,7 @@ TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) { TEST_F(GetUserNameTest, BufferSizeAsNullButNotBuffer) { lpBuffer.push_back('\0'); - result = GetUserName(&lpBuffer[0], NULL); + result = GetUserNameW(&lpBuffer[0], NULL); TestInvalidParameter(); } From c8f977748123ad360b0917262099d8db896e2d98 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 6 Aug 2015 17:03:53 -0700 Subject: [PATCH 111/298] Clean up CMakeLists --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 439546e2a1..1e6cafdbd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,17 +13,17 @@ set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) -SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) +set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) -target_link_libraries(ps icuuc) add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) # add pthread and other libs find_package(Threads) +target_link_libraries(ps icuuc) target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) target_link_libraries(host_cmdline dl icuuc) From 1b18bfd5e13e274a389a7b867a0476c8dbfdda02 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 6 Aug 2015 17:03:53 -0700 Subject: [PATCH 112/298] Clean up CMakeLists --- src/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 439546e2a1..1e6cafdbd6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,17 +13,17 @@ set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) -SET(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) +set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) -target_link_libraries(ps icuuc) add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) # add pthread and other libs find_package(Threads) +target_link_libraries(ps icuuc) target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) target_link_libraries(host_cmdline dl icuuc) From f8e9dfde8cabd1826b664f5ac71b66caf881f374 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 6 Aug 2015 17:06:04 -0700 Subject: [PATCH 113/298] Fix style issues - Use Doxygen style comments (with better comments) - Use `type* ident` instead of `type *ident` - Start { on new lines - Use TRUE/FALSE from PAL.H --- impl/getusername.cpp | 127 ++++++++++++++++++------------------- impl/getusername.h | 4 +- tests/test-getusername.cpp | 84 +++++++++++++++--------- 3 files changed, 119 insertions(+), 96 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index ba6f64ad86..eb35137bde 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -1,4 +1,7 @@ -#include "getusername.h" +//! @file getusername.cpp +//! @author Andrew Schwartzmeyer +//! @brief Implements GetUserName Win32 API + #include #include #include @@ -8,66 +11,62 @@ #include #include #include +#include "getusername.h" -/* - GetUserNameW function - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx - - Retrieves the name of the user associated with the current thread. - - Parameters - - lpBuffer [out] - - A pointer to the buffer to receive the user's logon name. If this - buffer is not large enough to contain the entire user name, the - function fails. A buffer size of (UNLEN + 1) characters will hold - the maximum length user name including the terminating null - character. UNLEN is defined in Lmcons.h. - - lpnSize [in, out] - - On input, this variable specifies the size of the lpBuffer buffer, - in TCHARs. On output, the variable receives the number of TCHARs - copied to the buffer, including the terminating null character. - - Note that TCHAR is WCHAR here because UNICODE is defined, and so a - TCHAR is a byte. - - https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#CHAR - - If lpBuffer is too small, the function fails and GetLastError - returns ERROR_INSUFFICIENT_BUFFER. This parameter receives the - required buffer size, including the terminating null character. - - - Sets errno to: - ERROR_INVALID_PARAMETER - parameter is not valid - ERROR_BAD_ENVIRONMENT - locale is not UTF-8 - ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files - ERROR_NO_ASSOCIATION - calling process has no controlling terminal - ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string - ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file - ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure - ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal - ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code - - Return value - - If the function succeeds, the return value is a nonzero value, and - the variable pointed to by lpnSize contains the number of TCHARs - copied to the buffer specified by lpBuffer, including the - terminating null character. - - If the function fails, the return value is zero. To get extended - error information, call GetLastError. -*/ -BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize) +//! @brief GetUserName retrieves the name of the user associated with +//! the current thread. +//! +//! GetUserNameW is the Unicode variation. See [MSDN documentation]. +//! +//! @param[out] lpBuffer +//! @parblock +//! A pointer to the buffer to receive the user's +//! logon name. If this buffer is not large enough to contain the +//! entire user name, the function fails. +//! +//! WCHAR_T* is a Unicode [LPTSTR]. +//! @endparblock +//! +//! @param[in, out] lpnSize +//! @parblock +//! On input, this variable specifies the size of the lpBuffer buffer, +//! in TCHARs. On output, the variable receives the number of TCHARs +//! copied to the buffer, including the terminating null character. +//! +//! TCHAR is a Unicode 16-bit [WCHAR]. +//! +//! If lpBuffer is too small, the function fails and GetLastError +//! returns ERROR_INSUFFICIENT_BUFFER. This parameter receives the +//! required buffer size, including the terminating null character. +//! @endparblock +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_INVALID_PARAMETER: parameter is not valid +//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 +//! - ERROR_TOO_MANY_OPEN_FILES: already have the maximum allowed number of open files +//! - ERROR_NO_ASSOCIATION: calling process has no controlling terminal +//! - ERROR_INSUFFICIENT_BUFFER: buffer not large enough to hold username string +//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file +//! - ERROR_OUTOFMEMORY: insufficient memory to allocate passwd structure +//! - ERROR_NO_ASSOCIATION: standard input didn't refer to a terminal +//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code +//! +//! @retval 1 If the function succeeds, the return value is a nonzero +//! value, and the variable pointed to by lpnSize contains the number +//! of TCHARs copied to the buffer specified by lpBuffer, including +//! the terminating null character. +//! +//! @retval 0 If the function fails, the return value is zero. To get +//! extended error information, call GetLastError. +//! +//! [MSDN documentation]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx +//! [WCHAR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#WCHAR +//! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR +BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { const std::string utf8 = "UTF-8"; - errno = 0; + errno = FALSE; // Check parameters if (!lpBuffer || !lpnSize) { @@ -80,14 +79,14 @@ BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize) // Check that locale is UTF-8 if (nl_langinfo(CODESET) != utf8) { errno = ERROR_BAD_ENVIRONMENT; - return 0; + return FALSE; } // Get username from system in a thread-safe manner std::string username(LOGIN_NAME_MAX, '\0'); - int err = getlogin_r(&username[0], username.size()); + int ret = getlogin_r(&username[0], username.size()); // Map errno to Win32 Error Codes - if (err != 0) { + if (ret) { switch (errno) { case EMFILE: case ENFILE: @@ -111,14 +110,14 @@ BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize) default: errno = ERROR_INVALID_FUNCTION; } - return 0; + return FALSE; } - // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) + // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) std::basic_string username16(LOGIN_NAME_MAX+1, 0); icu::UnicodeString username8(username.c_str(), "UTF-8"); int32_t targetSize = username8.extract(0, username8.length(), - reinterpret_cast(&username16[0]), + reinterpret_cast(&username16[0]), (username16.size()-1)*sizeof(char16_t), "UTF-16LE"); // Number of characters including null @@ -138,5 +137,5 @@ BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize) memcpy(lpBuffer, &username16[0], size*sizeof(char16_t)); *lpnSize = size; - return 1; + return TRUE; } diff --git a/impl/getusername.h b/impl/getusername.h index ad6099c4b0..6083078bc0 100644 --- a/impl/getusername.h +++ b/impl/getusername.h @@ -4,8 +4,6 @@ PAL_BEGIN_EXTERNC -// WCHAR_T * is a Unicode LPTSTR -// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR -BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize); +BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize); PAL_END_EXTERNC diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index 5a6a8535cc..d00acdf30b 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -1,3 +1,7 @@ +//! @file test-getusername.cpp +//! @author Andrew Schwartzmeyer +//! @brief Unit tests for GetUserName + #include #include #include @@ -8,7 +12,9 @@ #include #include "getusername.h" -class GetUserNameTest : public ::testing::Test { +//! Test fixture for GetUserNameW +class GetUserNameTest : public ::testing::Test +{ protected: DWORD lpnSize; std::vector lpBuffer; @@ -20,24 +26,31 @@ protected: expectedSize(expectedUsername.length()+1) {} - void TestWithSize(DWORD size) { + //! Invokes GetUserNameW with lpnSize and lpBuffer, saves result. + //! + //! @param size Assigns to lpnSize and allocates lpBuffer with + //! size number of null characters. + void TestWithSize(DWORD size) + { lpnSize = size; // allocate a WCHAR_T buffer to receive username lpBuffer.assign(lpnSize, '\0'); result = GetUserNameW(&lpBuffer[0], &lpnSize); } - void TestSuccess() { + //! Checks the effects of GetUserNameW for success. + void TestSuccess() + { SCOPED_TRACE(""); - // returns 1 on success - EXPECT_EQ(1, result); + //! Returns TRUE on success. + EXPECT_EQ(TRUE, result); - // sets lpnSize to number of WCHARs including null + //! Sets lpnSize to number of WCHARs including null. ASSERT_EQ(expectedSize, lpnSize); // setup for conversion from UTF-16LE - const char *begin = reinterpret_cast(&lpBuffer[0]); + const char* begin = reinterpret_cast(&lpBuffer[0]); // multiply to get number of bytes icu::UnicodeString username16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); // username16 length includes null and is number of characters @@ -46,38 +59,44 @@ protected: // convert (minus null) to UTF-8 for comparison std::string username(lpnSize-1, 0); ASSERT_EQ(expectedUsername.length(), username.length()); - int32_t targetSize = username16.extract(0, username.length(), - reinterpret_cast(&username[0]), "UTF-8"); + username16.extract(0, username.length(), + reinterpret_cast(&username[0]), "UTF-8"); + //! Returned username (after conversion) is what was expected. EXPECT_EQ(expectedUsername, username); } - void TestInvalidParameter() { + //! Checks the effects of GetUserNameW on failure with invalid parameters. + void TestInvalidParameter() + { SCOPED_TRACE(""); - // returns 0 on failure - EXPECT_EQ(0, result); + //! Returns FALSE on failure. + EXPECT_EQ(FALSE, result); - // sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null - // (which is the case for an empty vector) + //! Sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null + //! (which is the case for an empty vector). EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); } - void TestInsufficientBuffer() { + //! Checks the effects of GetUserNameW on failure with a buffer that is too small. + void TestInsufficientBuffer() + { SCOPED_TRACE(""); - // returns 0 on failure - EXPECT_EQ(0, result); + //! Returns FALSE on failure. + EXPECT_EQ(FALSE, result); - // sets errno to ERROR_INSUFFICIENT_BUFFER + //! Sets errno to ERROR_INSUFFICIENT_BUFFER. EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); - // sets lpnSize to length of username + null + //! Sets lpnSize to length of username plus null. EXPECT_EQ(expectedSize, lpnSize); } }; -TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) { +TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) +{ lpnSize = 1; result = GetUserNameW(NULL, &lpnSize); @@ -86,47 +105,54 @@ TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) { EXPECT_EQ(1, lpnSize); } -TEST_F(GetUserNameTest, BufferSizeAsNullButNotBuffer) { +TEST_F(GetUserNameTest, BufferSizeAsNullButNotBuffer) +{ lpBuffer.push_back('\0'); result = GetUserNameW(&lpBuffer[0], NULL); TestInvalidParameter(); } -TEST_F(GetUserNameTest, BufferSizeAsZero) { +TEST_F(GetUserNameTest, BufferSizeAsZero) +{ TestWithSize(0); TestInvalidParameter(); // does not reset lpnSize EXPECT_EQ(0, lpnSize); } -TEST_F(GetUserNameTest, BufferSizeAsOne) { +TEST_F(GetUserNameTest, BufferSizeAsOne) +{ // theoretically this should never fail because any non-empty // username length will be >1 with trailing null TestWithSize(1); TestInsufficientBuffer(); } -TEST_F(GetUserNameTest, BufferSizeAsUsername) { - // the buffer is too small because this is a UTF-8 size +TEST_F(GetUserNameTest, BufferSizeAsUsername) +{ + // the buffer is too small because it does not account for null TestWithSize(expectedUsername.length()); TestInsufficientBuffer(); } -TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOne) { +TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOne) +{ // includes null and so should be sufficient TestWithSize(expectedUsername.length()+1); TestSuccess(); } -TEST_F(GetUserNameTest, BufferSizeAsExpectedSize) { +TEST_F(GetUserNameTest, BufferSizeAsExpectedSize) +{ // expectedSize is the same as username.size()+1 TestWithSize(expectedSize); TestSuccess(); } -TEST_F(GetUserNameTest, BufferSizeAsLoginNameMax) { - // LoginNameMax is big enough to hold any username +TEST_F(GetUserNameTest, BufferSizeAsLoginNameMax) +{ + // LoginNameMax is big enough to hold any username, including null TestWithSize(LOGIN_NAME_MAX); TestSuccess(); } From 062eb5a7b4e8be20bbde962239abfc6843d10076 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 6 Aug 2015 17:06:04 -0700 Subject: [PATCH 114/298] Fix style issues - Use Doxygen style comments (with better comments) - Use `type* ident` instead of `type *ident` - Start { on new lines - Use TRUE/FALSE from PAL.H --- src/impl/getusername.cpp | 127 ++++++++++++++++----------------- src/impl/getusername.h | 4 +- src/tests/test-getusername.cpp | 84 ++++++++++++++-------- 3 files changed, 119 insertions(+), 96 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index ba6f64ad86..eb35137bde 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -1,4 +1,7 @@ -#include "getusername.h" +//! @file getusername.cpp +//! @author Andrew Schwartzmeyer +//! @brief Implements GetUserName Win32 API + #include #include #include @@ -8,66 +11,62 @@ #include #include #include +#include "getusername.h" -/* - GetUserNameW function - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx - - Retrieves the name of the user associated with the current thread. - - Parameters - - lpBuffer [out] - - A pointer to the buffer to receive the user's logon name. If this - buffer is not large enough to contain the entire user name, the - function fails. A buffer size of (UNLEN + 1) characters will hold - the maximum length user name including the terminating null - character. UNLEN is defined in Lmcons.h. - - lpnSize [in, out] - - On input, this variable specifies the size of the lpBuffer buffer, - in TCHARs. On output, the variable receives the number of TCHARs - copied to the buffer, including the terminating null character. - - Note that TCHAR is WCHAR here because UNICODE is defined, and so a - TCHAR is a byte. - - https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#CHAR - - If lpBuffer is too small, the function fails and GetLastError - returns ERROR_INSUFFICIENT_BUFFER. This parameter receives the - required buffer size, including the terminating null character. - - - Sets errno to: - ERROR_INVALID_PARAMETER - parameter is not valid - ERROR_BAD_ENVIRONMENT - locale is not UTF-8 - ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files - ERROR_NO_ASSOCIATION - calling process has no controlling terminal - ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string - ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file - ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure - ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal - ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code - - Return value - - If the function succeeds, the return value is a nonzero value, and - the variable pointed to by lpnSize contains the number of TCHARs - copied to the buffer specified by lpBuffer, including the - terminating null character. - - If the function fails, the return value is zero. To get extended - error information, call GetLastError. -*/ -BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize) +//! @brief GetUserName retrieves the name of the user associated with +//! the current thread. +//! +//! GetUserNameW is the Unicode variation. See [MSDN documentation]. +//! +//! @param[out] lpBuffer +//! @parblock +//! A pointer to the buffer to receive the user's +//! logon name. If this buffer is not large enough to contain the +//! entire user name, the function fails. +//! +//! WCHAR_T* is a Unicode [LPTSTR]. +//! @endparblock +//! +//! @param[in, out] lpnSize +//! @parblock +//! On input, this variable specifies the size of the lpBuffer buffer, +//! in TCHARs. On output, the variable receives the number of TCHARs +//! copied to the buffer, including the terminating null character. +//! +//! TCHAR is a Unicode 16-bit [WCHAR]. +//! +//! If lpBuffer is too small, the function fails and GetLastError +//! returns ERROR_INSUFFICIENT_BUFFER. This parameter receives the +//! required buffer size, including the terminating null character. +//! @endparblock +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_INVALID_PARAMETER: parameter is not valid +//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 +//! - ERROR_TOO_MANY_OPEN_FILES: already have the maximum allowed number of open files +//! - ERROR_NO_ASSOCIATION: calling process has no controlling terminal +//! - ERROR_INSUFFICIENT_BUFFER: buffer not large enough to hold username string +//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file +//! - ERROR_OUTOFMEMORY: insufficient memory to allocate passwd structure +//! - ERROR_NO_ASSOCIATION: standard input didn't refer to a terminal +//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code +//! +//! @retval 1 If the function succeeds, the return value is a nonzero +//! value, and the variable pointed to by lpnSize contains the number +//! of TCHARs copied to the buffer specified by lpBuffer, including +//! the terminating null character. +//! +//! @retval 0 If the function fails, the return value is zero. To get +//! extended error information, call GetLastError. +//! +//! [MSDN documentation]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx +//! [WCHAR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#WCHAR +//! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR +BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { const std::string utf8 = "UTF-8"; - errno = 0; + errno = FALSE; // Check parameters if (!lpBuffer || !lpnSize) { @@ -80,14 +79,14 @@ BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize) // Check that locale is UTF-8 if (nl_langinfo(CODESET) != utf8) { errno = ERROR_BAD_ENVIRONMENT; - return 0; + return FALSE; } // Get username from system in a thread-safe manner std::string username(LOGIN_NAME_MAX, '\0'); - int err = getlogin_r(&username[0], username.size()); + int ret = getlogin_r(&username[0], username.size()); // Map errno to Win32 Error Codes - if (err != 0) { + if (ret) { switch (errno) { case EMFILE: case ENFILE: @@ -111,14 +110,14 @@ BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize) default: errno = ERROR_INVALID_FUNCTION; } - return 0; + return FALSE; } - // Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM) + // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) std::basic_string username16(LOGIN_NAME_MAX+1, 0); icu::UnicodeString username8(username.c_str(), "UTF-8"); int32_t targetSize = username8.extract(0, username8.length(), - reinterpret_cast(&username16[0]), + reinterpret_cast(&username16[0]), (username16.size()-1)*sizeof(char16_t), "UTF-16LE"); // Number of characters including null @@ -138,5 +137,5 @@ BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize) memcpy(lpBuffer, &username16[0], size*sizeof(char16_t)); *lpnSize = size; - return 1; + return TRUE; } diff --git a/src/impl/getusername.h b/src/impl/getusername.h index ad6099c4b0..6083078bc0 100644 --- a/src/impl/getusername.h +++ b/src/impl/getusername.h @@ -4,8 +4,6 @@ PAL_BEGIN_EXTERNC -// WCHAR_T * is a Unicode LPTSTR -// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR -BOOL GetUserNameW(WCHAR_T *lpBuffer, LPDWORD lpnSize); +BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize); PAL_END_EXTERNC diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index 5a6a8535cc..d00acdf30b 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -1,3 +1,7 @@ +//! @file test-getusername.cpp +//! @author Andrew Schwartzmeyer +//! @brief Unit tests for GetUserName + #include #include #include @@ -8,7 +12,9 @@ #include #include "getusername.h" -class GetUserNameTest : public ::testing::Test { +//! Test fixture for GetUserNameW +class GetUserNameTest : public ::testing::Test +{ protected: DWORD lpnSize; std::vector lpBuffer; @@ -20,24 +26,31 @@ protected: expectedSize(expectedUsername.length()+1) {} - void TestWithSize(DWORD size) { + //! Invokes GetUserNameW with lpnSize and lpBuffer, saves result. + //! + //! @param size Assigns to lpnSize and allocates lpBuffer with + //! size number of null characters. + void TestWithSize(DWORD size) + { lpnSize = size; // allocate a WCHAR_T buffer to receive username lpBuffer.assign(lpnSize, '\0'); result = GetUserNameW(&lpBuffer[0], &lpnSize); } - void TestSuccess() { + //! Checks the effects of GetUserNameW for success. + void TestSuccess() + { SCOPED_TRACE(""); - // returns 1 on success - EXPECT_EQ(1, result); + //! Returns TRUE on success. + EXPECT_EQ(TRUE, result); - // sets lpnSize to number of WCHARs including null + //! Sets lpnSize to number of WCHARs including null. ASSERT_EQ(expectedSize, lpnSize); // setup for conversion from UTF-16LE - const char *begin = reinterpret_cast(&lpBuffer[0]); + const char* begin = reinterpret_cast(&lpBuffer[0]); // multiply to get number of bytes icu::UnicodeString username16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); // username16 length includes null and is number of characters @@ -46,38 +59,44 @@ protected: // convert (minus null) to UTF-8 for comparison std::string username(lpnSize-1, 0); ASSERT_EQ(expectedUsername.length(), username.length()); - int32_t targetSize = username16.extract(0, username.length(), - reinterpret_cast(&username[0]), "UTF-8"); + username16.extract(0, username.length(), + reinterpret_cast(&username[0]), "UTF-8"); + //! Returned username (after conversion) is what was expected. EXPECT_EQ(expectedUsername, username); } - void TestInvalidParameter() { + //! Checks the effects of GetUserNameW on failure with invalid parameters. + void TestInvalidParameter() + { SCOPED_TRACE(""); - // returns 0 on failure - EXPECT_EQ(0, result); + //! Returns FALSE on failure. + EXPECT_EQ(FALSE, result); - // sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null - // (which is the case for an empty vector) + //! Sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null + //! (which is the case for an empty vector). EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); } - void TestInsufficientBuffer() { + //! Checks the effects of GetUserNameW on failure with a buffer that is too small. + void TestInsufficientBuffer() + { SCOPED_TRACE(""); - // returns 0 on failure - EXPECT_EQ(0, result); + //! Returns FALSE on failure. + EXPECT_EQ(FALSE, result); - // sets errno to ERROR_INSUFFICIENT_BUFFER + //! Sets errno to ERROR_INSUFFICIENT_BUFFER. EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); - // sets lpnSize to length of username + null + //! Sets lpnSize to length of username plus null. EXPECT_EQ(expectedSize, lpnSize); } }; -TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) { +TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) +{ lpnSize = 1; result = GetUserNameW(NULL, &lpnSize); @@ -86,47 +105,54 @@ TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) { EXPECT_EQ(1, lpnSize); } -TEST_F(GetUserNameTest, BufferSizeAsNullButNotBuffer) { +TEST_F(GetUserNameTest, BufferSizeAsNullButNotBuffer) +{ lpBuffer.push_back('\0'); result = GetUserNameW(&lpBuffer[0], NULL); TestInvalidParameter(); } -TEST_F(GetUserNameTest, BufferSizeAsZero) { +TEST_F(GetUserNameTest, BufferSizeAsZero) +{ TestWithSize(0); TestInvalidParameter(); // does not reset lpnSize EXPECT_EQ(0, lpnSize); } -TEST_F(GetUserNameTest, BufferSizeAsOne) { +TEST_F(GetUserNameTest, BufferSizeAsOne) +{ // theoretically this should never fail because any non-empty // username length will be >1 with trailing null TestWithSize(1); TestInsufficientBuffer(); } -TEST_F(GetUserNameTest, BufferSizeAsUsername) { - // the buffer is too small because this is a UTF-8 size +TEST_F(GetUserNameTest, BufferSizeAsUsername) +{ + // the buffer is too small because it does not account for null TestWithSize(expectedUsername.length()); TestInsufficientBuffer(); } -TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOne) { +TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOne) +{ // includes null and so should be sufficient TestWithSize(expectedUsername.length()+1); TestSuccess(); } -TEST_F(GetUserNameTest, BufferSizeAsExpectedSize) { +TEST_F(GetUserNameTest, BufferSizeAsExpectedSize) +{ // expectedSize is the same as username.size()+1 TestWithSize(expectedSize); TestSuccess(); } -TEST_F(GetUserNameTest, BufferSizeAsLoginNameMax) { - // LoginNameMax is big enough to hold any username +TEST_F(GetUserNameTest, BufferSizeAsLoginNameMax) +{ + // LoginNameMax is big enough to hold any username, including null TestWithSize(LOGIN_NAME_MAX); TestSuccess(); } From 665f8f1e87439d8045f1ca8b5f325b3d990acd05 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 7 Aug 2015 12:05:07 -0700 Subject: [PATCH 115/298] Map getlogin_r()'s ERANGE to ERROR_GEN_FAILURE ERROR_INSUFFICIENT_BUFFER should never occur here and would be a misleading error for the user. --- impl/getusername.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index eb35137bde..0ca96e5a92 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -96,7 +96,7 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) errno = ERROR_NO_ASSOCIATION; break; case ERANGE: - errno = ERROR_INSUFFICIENT_BUFFER; + errno = ERROR_GEN_FAILURE; break; case ENOENT: errno = ERROR_NO_SUCH_USER; From 467fdeeb0ce1ceb5ca46f956ea0c673c5ec3d026 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 7 Aug 2015 12:05:07 -0700 Subject: [PATCH 116/298] Map getlogin_r()'s ERANGE to ERROR_GEN_FAILURE ERROR_INSUFFICIENT_BUFFER should never occur here and would be a misleading error for the user. --- src/impl/getusername.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index eb35137bde..0ca96e5a92 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -96,7 +96,7 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) errno = ERROR_NO_ASSOCIATION; break; case ERANGE: - errno = ERROR_INSUFFICIENT_BUFFER; + errno = ERROR_GEN_FAILURE; break; case ENOENT: errno = ERROR_NO_SUCH_USER; From da1e65cfaff8f709f9470c5ee646b0b99af2d9fd Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 7 Aug 2015 12:07:19 -0700 Subject: [PATCH 117/298] Add -Wall to CMAKE_CXX_FLAGS --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e6cafdbd6..ae57dc376a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8.4) project(monad_native) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall") #include gtest include_directories(../ext-src/gtest/fused-src impl) From f35efda7e782f7904d5ce4c0439058ac2b283d3c Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 7 Aug 2015 12:07:19 -0700 Subject: [PATCH 118/298] Add -Wall to CMAKE_CXX_FLAGS --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1e6cafdbd6..ae57dc376a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8.4) project(monad_native) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall") #include gtest include_directories(../ext-src/gtest/fused-src impl) From 9a42b894f286cb0a77d5ae3478ed63cdba13fa09 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 7 Aug 2015 18:43:58 -0700 Subject: [PATCH 119/298] Convert to Allman style with 4-space indentation --- impl/getusername.cpp | 137 ++++++++++++++-------------- tests/test-getusername.cpp | 181 +++++++++++++++++++------------------ 2 files changed, 162 insertions(+), 156 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 0ca96e5a92..5d0bec0361 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -64,78 +64,83 @@ //! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { - const std::string utf8 = "UTF-8"; + const std::string utf8 = "UTF-8"; - errno = FALSE; + errno = FALSE; - // Check parameters - if (!lpBuffer || !lpnSize) { - errno = ERROR_INVALID_PARAMETER; - return 0; - } + // Check parameters + if (!lpBuffer || !lpnSize) + { + errno = ERROR_INVALID_PARAMETER; + return 0; + } - // Select locale from environment - setlocale(LC_ALL, ""); - // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != utf8) { - errno = ERROR_BAD_ENVIRONMENT; - return FALSE; - } + // Select locale from environment + setlocale(LC_ALL, ""); + // Check that locale is UTF-8 + if (nl_langinfo(CODESET) != utf8) + { + errno = ERROR_BAD_ENVIRONMENT; + return FALSE; + } - // Get username from system in a thread-safe manner - std::string username(LOGIN_NAME_MAX, '\0'); - int ret = getlogin_r(&username[0], username.size()); - // Map errno to Win32 Error Codes - if (ret) { - switch (errno) { - case EMFILE: - case ENFILE: - errno = ERROR_TOO_MANY_OPEN_FILES; - break; - case ENXIO: - errno = ERROR_NO_ASSOCIATION; - break; - case ERANGE: - errno = ERROR_GEN_FAILURE; - break; - case ENOENT: - errno = ERROR_NO_SUCH_USER; - break; - case ENOMEM: - errno = ERROR_OUTOFMEMORY; - break; - case ENOTTY: - errno = ERROR_NO_ASSOCIATION; - break; - default: - errno = ERROR_INVALID_FUNCTION; - } - return FALSE; - } + // Get username from system in a thread-safe manner + std::string username(LOGIN_NAME_MAX, '\0'); + int ret = getlogin_r(&username[0], username.size()); + // Map errno to Win32 Error Codes + if (ret) + { + switch (errno) + { + case EMFILE: + case ENFILE: + errno = ERROR_TOO_MANY_OPEN_FILES; + break; + case ENXIO: + errno = ERROR_NO_ASSOCIATION; + break; + case ERANGE: + errno = ERROR_GEN_FAILURE; + break; + case ENOENT: + errno = ERROR_NO_SUCH_USER; + break; + case ENOMEM: + errno = ERROR_OUTOFMEMORY; + break; + case ENOTTY: + errno = ERROR_NO_ASSOCIATION; + break; + default: + errno = ERROR_INVALID_FUNCTION; + } + return FALSE; + } - // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) - std::basic_string username16(LOGIN_NAME_MAX+1, 0); - icu::UnicodeString username8(username.c_str(), "UTF-8"); - int32_t targetSize = username8.extract(0, username8.length(), - reinterpret_cast(&username16[0]), - (username16.size()-1)*sizeof(char16_t), - "UTF-16LE"); - // Number of characters including null - username16.resize(targetSize/sizeof(char16_t)+1); + // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) + std::basic_string username16(LOGIN_NAME_MAX+1, 0); + icu::UnicodeString username8(username.c_str(), "UTF-8"); + int32_t targetSize = username8.extract(0, username8.length(), + reinterpret_cast(&username16[0]), + (username16.size()-1)*sizeof(char16_t), + "UTF-16LE"); + // Number of characters including null + username16.resize(targetSize/sizeof(char16_t)+1); - // Size in WCHARs including null - const DWORD size = username16.length(); - if (size > *lpnSize) { - errno = ERROR_INSUFFICIENT_BUFFER; - // Set lpnSize if buffer is too small to inform user - // of necessary size - *lpnSize = size; - return 0; - } + // Size in WCHARs including null + const DWORD size = username16.length(); + if (size > *lpnSize) + { + errno = ERROR_INSUFFICIENT_BUFFER; + // Set lpnSize if buffer is too small to inform user + // of necessary size + *lpnSize = size; + return 0; + } - // Copy bytes from string to buffer - memcpy(lpBuffer, &username16[0], size*sizeof(char16_t)); - *lpnSize = size; + // Copy bytes from string to buffer + memcpy(lpBuffer, &username16[0], size*sizeof(char16_t)); + *lpnSize = size; - return TRUE; + return TRUE; } diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index d00acdf30b..e27aeef28b 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -16,143 +16,144 @@ class GetUserNameTest : public ::testing::Test { protected: - DWORD lpnSize; - std::vector lpBuffer; - BOOL result; - std::string expectedUsername; - DWORD expectedSize; + DWORD lpnSize; + std::vector lpBuffer; + BOOL result; + std::string expectedUsername; + DWORD expectedSize; - GetUserNameTest(): expectedUsername(std::string(getlogin())), - expectedSize(expectedUsername.length()+1) - {} + GetUserNameTest(): expectedUsername(std::string(getlogin())), + expectedSize(expectedUsername.length()+1) + { + } - //! Invokes GetUserNameW with lpnSize and lpBuffer, saves result. - //! - //! @param size Assigns to lpnSize and allocates lpBuffer with - //! size number of null characters. - void TestWithSize(DWORD size) - { - lpnSize = size; - // allocate a WCHAR_T buffer to receive username - lpBuffer.assign(lpnSize, '\0'); - result = GetUserNameW(&lpBuffer[0], &lpnSize); - } + //! Invokes GetUserNameW with lpnSize and lpBuffer, saves result. + //! + //! @param size Assigns to lpnSize and allocates lpBuffer with + //! size number of null characters. + void TestWithSize(DWORD size) + { + lpnSize = size; + // allocate a WCHAR_T buffer to receive username + lpBuffer.assign(lpnSize, '\0'); + result = GetUserNameW(&lpBuffer[0], &lpnSize); + } - //! Checks the effects of GetUserNameW for success. - void TestSuccess() - { - SCOPED_TRACE(""); + //! Checks the effects of GetUserNameW for success. + void TestSuccess() + { + SCOPED_TRACE(""); - //! Returns TRUE on success. - EXPECT_EQ(TRUE, result); + //! Returns TRUE on success. + EXPECT_EQ(TRUE, result); - //! Sets lpnSize to number of WCHARs including null. - ASSERT_EQ(expectedSize, lpnSize); + //! Sets lpnSize to number of WCHARs including null. + ASSERT_EQ(expectedSize, lpnSize); - // setup for conversion from UTF-16LE - const char* begin = reinterpret_cast(&lpBuffer[0]); - // multiply to get number of bytes - icu::UnicodeString username16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); - // username16 length includes null and is number of characters - ASSERT_EQ(expectedSize, username16.length()); + // setup for conversion from UTF-16LE + const char* begin = reinterpret_cast(&lpBuffer[0]); + // multiply to get number of bytes + icu::UnicodeString username16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); + // username16 length includes null and is number of characters + ASSERT_EQ(expectedSize, username16.length()); - // convert (minus null) to UTF-8 for comparison - std::string username(lpnSize-1, 0); - ASSERT_EQ(expectedUsername.length(), username.length()); - username16.extract(0, username.length(), - reinterpret_cast(&username[0]), "UTF-8"); + // convert (minus null) to UTF-8 for comparison + std::string username(lpnSize-1, 0); + ASSERT_EQ(expectedUsername.length(), username.length()); + username16.extract(0, username.length(), + reinterpret_cast(&username[0]), "UTF-8"); - //! Returned username (after conversion) is what was expected. - EXPECT_EQ(expectedUsername, username); - } + //! Returned username (after conversion) is what was expected. + EXPECT_EQ(expectedUsername, username); + } - //! Checks the effects of GetUserNameW on failure with invalid parameters. - void TestInvalidParameter() - { - SCOPED_TRACE(""); + //! Checks the effects of GetUserNameW on failure with invalid parameters. + void TestInvalidParameter() + { + SCOPED_TRACE(""); - //! Returns FALSE on failure. - EXPECT_EQ(FALSE, result); + //! Returns FALSE on failure. + EXPECT_EQ(FALSE, result); - //! Sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null - //! (which is the case for an empty vector). - EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); - } + //! Sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null + //! (which is the case for an empty vector). + EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); + } - //! Checks the effects of GetUserNameW on failure with a buffer that is too small. - void TestInsufficientBuffer() - { - SCOPED_TRACE(""); + //! Checks the effects of GetUserNameW on failure with a buffer that is too small. + void TestInsufficientBuffer() + { + SCOPED_TRACE(""); - //! Returns FALSE on failure. - EXPECT_EQ(FALSE, result); + //! Returns FALSE on failure. + EXPECT_EQ(FALSE, result); - //! Sets errno to ERROR_INSUFFICIENT_BUFFER. - EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); + //! Sets errno to ERROR_INSUFFICIENT_BUFFER. + EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); - //! Sets lpnSize to length of username plus null. - EXPECT_EQ(expectedSize, lpnSize); - } + //! Sets lpnSize to length of username plus null. + EXPECT_EQ(expectedSize, lpnSize); + } }; TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) { - lpnSize = 1; - result = GetUserNameW(NULL, &lpnSize); + lpnSize = 1; + result = GetUserNameW(NULL, &lpnSize); - TestInvalidParameter(); - // does not reset lpnSize - EXPECT_EQ(1, lpnSize); + TestInvalidParameter(); + // does not reset lpnSize + EXPECT_EQ(1, lpnSize); } TEST_F(GetUserNameTest, BufferSizeAsNullButNotBuffer) { - lpBuffer.push_back('\0'); - result = GetUserNameW(&lpBuffer[0], NULL); + lpBuffer.push_back('\0'); + result = GetUserNameW(&lpBuffer[0], NULL); - TestInvalidParameter(); + TestInvalidParameter(); } TEST_F(GetUserNameTest, BufferSizeAsZero) { - TestWithSize(0); - TestInvalidParameter(); - // does not reset lpnSize - EXPECT_EQ(0, lpnSize); + TestWithSize(0); + TestInvalidParameter(); + // does not reset lpnSize + EXPECT_EQ(0, lpnSize); } TEST_F(GetUserNameTest, BufferSizeAsOne) { - // theoretically this should never fail because any non-empty - // username length will be >1 with trailing null - TestWithSize(1); - TestInsufficientBuffer(); + // theoretically this should never fail because any non-empty + // username length will be >1 with trailing null + TestWithSize(1); + TestInsufficientBuffer(); } TEST_F(GetUserNameTest, BufferSizeAsUsername) { - // the buffer is too small because it does not account for null - TestWithSize(expectedUsername.length()); - TestInsufficientBuffer(); + // the buffer is too small because it does not account for null + TestWithSize(expectedUsername.length()); + TestInsufficientBuffer(); } TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOne) { - // includes null and so should be sufficient - TestWithSize(expectedUsername.length()+1); - TestSuccess(); + // includes null and so should be sufficient + TestWithSize(expectedUsername.length()+1); + TestSuccess(); } TEST_F(GetUserNameTest, BufferSizeAsExpectedSize) { - // expectedSize is the same as username.size()+1 - TestWithSize(expectedSize); - TestSuccess(); + // expectedSize is the same as username.size()+1 + TestWithSize(expectedSize); + TestSuccess(); } TEST_F(GetUserNameTest, BufferSizeAsLoginNameMax) { - // LoginNameMax is big enough to hold any username, including null - TestWithSize(LOGIN_NAME_MAX); - TestSuccess(); + // LoginNameMax is big enough to hold any username, including null + TestWithSize(LOGIN_NAME_MAX); + TestSuccess(); } From a99c56eea3264b8c492bc0edf5e3a65102397af9 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 7 Aug 2015 18:43:58 -0700 Subject: [PATCH 120/298] Convert to Allman style with 4-space indentation --- src/impl/getusername.cpp | 137 +++++++++++++------------ src/tests/test-getusername.cpp | 181 +++++++++++++++++---------------- 2 files changed, 162 insertions(+), 156 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 0ca96e5a92..5d0bec0361 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -64,78 +64,83 @@ //! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { - const std::string utf8 = "UTF-8"; + const std::string utf8 = "UTF-8"; - errno = FALSE; + errno = FALSE; - // Check parameters - if (!lpBuffer || !lpnSize) { - errno = ERROR_INVALID_PARAMETER; - return 0; - } + // Check parameters + if (!lpBuffer || !lpnSize) + { + errno = ERROR_INVALID_PARAMETER; + return 0; + } - // Select locale from environment - setlocale(LC_ALL, ""); - // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != utf8) { - errno = ERROR_BAD_ENVIRONMENT; - return FALSE; - } + // Select locale from environment + setlocale(LC_ALL, ""); + // Check that locale is UTF-8 + if (nl_langinfo(CODESET) != utf8) + { + errno = ERROR_BAD_ENVIRONMENT; + return FALSE; + } - // Get username from system in a thread-safe manner - std::string username(LOGIN_NAME_MAX, '\0'); - int ret = getlogin_r(&username[0], username.size()); - // Map errno to Win32 Error Codes - if (ret) { - switch (errno) { - case EMFILE: - case ENFILE: - errno = ERROR_TOO_MANY_OPEN_FILES; - break; - case ENXIO: - errno = ERROR_NO_ASSOCIATION; - break; - case ERANGE: - errno = ERROR_GEN_FAILURE; - break; - case ENOENT: - errno = ERROR_NO_SUCH_USER; - break; - case ENOMEM: - errno = ERROR_OUTOFMEMORY; - break; - case ENOTTY: - errno = ERROR_NO_ASSOCIATION; - break; - default: - errno = ERROR_INVALID_FUNCTION; - } - return FALSE; - } + // Get username from system in a thread-safe manner + std::string username(LOGIN_NAME_MAX, '\0'); + int ret = getlogin_r(&username[0], username.size()); + // Map errno to Win32 Error Codes + if (ret) + { + switch (errno) + { + case EMFILE: + case ENFILE: + errno = ERROR_TOO_MANY_OPEN_FILES; + break; + case ENXIO: + errno = ERROR_NO_ASSOCIATION; + break; + case ERANGE: + errno = ERROR_GEN_FAILURE; + break; + case ENOENT: + errno = ERROR_NO_SUCH_USER; + break; + case ENOMEM: + errno = ERROR_OUTOFMEMORY; + break; + case ENOTTY: + errno = ERROR_NO_ASSOCIATION; + break; + default: + errno = ERROR_INVALID_FUNCTION; + } + return FALSE; + } - // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) - std::basic_string username16(LOGIN_NAME_MAX+1, 0); - icu::UnicodeString username8(username.c_str(), "UTF-8"); - int32_t targetSize = username8.extract(0, username8.length(), - reinterpret_cast(&username16[0]), - (username16.size()-1)*sizeof(char16_t), - "UTF-16LE"); - // Number of characters including null - username16.resize(targetSize/sizeof(char16_t)+1); + // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) + std::basic_string username16(LOGIN_NAME_MAX+1, 0); + icu::UnicodeString username8(username.c_str(), "UTF-8"); + int32_t targetSize = username8.extract(0, username8.length(), + reinterpret_cast(&username16[0]), + (username16.size()-1)*sizeof(char16_t), + "UTF-16LE"); + // Number of characters including null + username16.resize(targetSize/sizeof(char16_t)+1); - // Size in WCHARs including null - const DWORD size = username16.length(); - if (size > *lpnSize) { - errno = ERROR_INSUFFICIENT_BUFFER; - // Set lpnSize if buffer is too small to inform user - // of necessary size - *lpnSize = size; - return 0; - } + // Size in WCHARs including null + const DWORD size = username16.length(); + if (size > *lpnSize) + { + errno = ERROR_INSUFFICIENT_BUFFER; + // Set lpnSize if buffer is too small to inform user + // of necessary size + *lpnSize = size; + return 0; + } - // Copy bytes from string to buffer - memcpy(lpBuffer, &username16[0], size*sizeof(char16_t)); - *lpnSize = size; + // Copy bytes from string to buffer + memcpy(lpBuffer, &username16[0], size*sizeof(char16_t)); + *lpnSize = size; - return TRUE; + return TRUE; } diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index d00acdf30b..e27aeef28b 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -16,143 +16,144 @@ class GetUserNameTest : public ::testing::Test { protected: - DWORD lpnSize; - std::vector lpBuffer; - BOOL result; - std::string expectedUsername; - DWORD expectedSize; + DWORD lpnSize; + std::vector lpBuffer; + BOOL result; + std::string expectedUsername; + DWORD expectedSize; - GetUserNameTest(): expectedUsername(std::string(getlogin())), - expectedSize(expectedUsername.length()+1) - {} + GetUserNameTest(): expectedUsername(std::string(getlogin())), + expectedSize(expectedUsername.length()+1) + { + } - //! Invokes GetUserNameW with lpnSize and lpBuffer, saves result. - //! - //! @param size Assigns to lpnSize and allocates lpBuffer with - //! size number of null characters. - void TestWithSize(DWORD size) - { - lpnSize = size; - // allocate a WCHAR_T buffer to receive username - lpBuffer.assign(lpnSize, '\0'); - result = GetUserNameW(&lpBuffer[0], &lpnSize); - } + //! Invokes GetUserNameW with lpnSize and lpBuffer, saves result. + //! + //! @param size Assigns to lpnSize and allocates lpBuffer with + //! size number of null characters. + void TestWithSize(DWORD size) + { + lpnSize = size; + // allocate a WCHAR_T buffer to receive username + lpBuffer.assign(lpnSize, '\0'); + result = GetUserNameW(&lpBuffer[0], &lpnSize); + } - //! Checks the effects of GetUserNameW for success. - void TestSuccess() - { - SCOPED_TRACE(""); + //! Checks the effects of GetUserNameW for success. + void TestSuccess() + { + SCOPED_TRACE(""); - //! Returns TRUE on success. - EXPECT_EQ(TRUE, result); + //! Returns TRUE on success. + EXPECT_EQ(TRUE, result); - //! Sets lpnSize to number of WCHARs including null. - ASSERT_EQ(expectedSize, lpnSize); + //! Sets lpnSize to number of WCHARs including null. + ASSERT_EQ(expectedSize, lpnSize); - // setup for conversion from UTF-16LE - const char* begin = reinterpret_cast(&lpBuffer[0]); - // multiply to get number of bytes - icu::UnicodeString username16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); - // username16 length includes null and is number of characters - ASSERT_EQ(expectedSize, username16.length()); + // setup for conversion from UTF-16LE + const char* begin = reinterpret_cast(&lpBuffer[0]); + // multiply to get number of bytes + icu::UnicodeString username16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); + // username16 length includes null and is number of characters + ASSERT_EQ(expectedSize, username16.length()); - // convert (minus null) to UTF-8 for comparison - std::string username(lpnSize-1, 0); - ASSERT_EQ(expectedUsername.length(), username.length()); - username16.extract(0, username.length(), - reinterpret_cast(&username[0]), "UTF-8"); + // convert (minus null) to UTF-8 for comparison + std::string username(lpnSize-1, 0); + ASSERT_EQ(expectedUsername.length(), username.length()); + username16.extract(0, username.length(), + reinterpret_cast(&username[0]), "UTF-8"); - //! Returned username (after conversion) is what was expected. - EXPECT_EQ(expectedUsername, username); - } + //! Returned username (after conversion) is what was expected. + EXPECT_EQ(expectedUsername, username); + } - //! Checks the effects of GetUserNameW on failure with invalid parameters. - void TestInvalidParameter() - { - SCOPED_TRACE(""); + //! Checks the effects of GetUserNameW on failure with invalid parameters. + void TestInvalidParameter() + { + SCOPED_TRACE(""); - //! Returns FALSE on failure. - EXPECT_EQ(FALSE, result); + //! Returns FALSE on failure. + EXPECT_EQ(FALSE, result); - //! Sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null - //! (which is the case for an empty vector). - EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); - } + //! Sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null + //! (which is the case for an empty vector). + EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); + } - //! Checks the effects of GetUserNameW on failure with a buffer that is too small. - void TestInsufficientBuffer() - { - SCOPED_TRACE(""); + //! Checks the effects of GetUserNameW on failure with a buffer that is too small. + void TestInsufficientBuffer() + { + SCOPED_TRACE(""); - //! Returns FALSE on failure. - EXPECT_EQ(FALSE, result); + //! Returns FALSE on failure. + EXPECT_EQ(FALSE, result); - //! Sets errno to ERROR_INSUFFICIENT_BUFFER. - EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); + //! Sets errno to ERROR_INSUFFICIENT_BUFFER. + EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); - //! Sets lpnSize to length of username plus null. - EXPECT_EQ(expectedSize, lpnSize); - } + //! Sets lpnSize to length of username plus null. + EXPECT_EQ(expectedSize, lpnSize); + } }; TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) { - lpnSize = 1; - result = GetUserNameW(NULL, &lpnSize); + lpnSize = 1; + result = GetUserNameW(NULL, &lpnSize); - TestInvalidParameter(); - // does not reset lpnSize - EXPECT_EQ(1, lpnSize); + TestInvalidParameter(); + // does not reset lpnSize + EXPECT_EQ(1, lpnSize); } TEST_F(GetUserNameTest, BufferSizeAsNullButNotBuffer) { - lpBuffer.push_back('\0'); - result = GetUserNameW(&lpBuffer[0], NULL); + lpBuffer.push_back('\0'); + result = GetUserNameW(&lpBuffer[0], NULL); - TestInvalidParameter(); + TestInvalidParameter(); } TEST_F(GetUserNameTest, BufferSizeAsZero) { - TestWithSize(0); - TestInvalidParameter(); - // does not reset lpnSize - EXPECT_EQ(0, lpnSize); + TestWithSize(0); + TestInvalidParameter(); + // does not reset lpnSize + EXPECT_EQ(0, lpnSize); } TEST_F(GetUserNameTest, BufferSizeAsOne) { - // theoretically this should never fail because any non-empty - // username length will be >1 with trailing null - TestWithSize(1); - TestInsufficientBuffer(); + // theoretically this should never fail because any non-empty + // username length will be >1 with trailing null + TestWithSize(1); + TestInsufficientBuffer(); } TEST_F(GetUserNameTest, BufferSizeAsUsername) { - // the buffer is too small because it does not account for null - TestWithSize(expectedUsername.length()); - TestInsufficientBuffer(); + // the buffer is too small because it does not account for null + TestWithSize(expectedUsername.length()); + TestInsufficientBuffer(); } TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOne) { - // includes null and so should be sufficient - TestWithSize(expectedUsername.length()+1); - TestSuccess(); + // includes null and so should be sufficient + TestWithSize(expectedUsername.length()+1); + TestSuccess(); } TEST_F(GetUserNameTest, BufferSizeAsExpectedSize) { - // expectedSize is the same as username.size()+1 - TestWithSize(expectedSize); - TestSuccess(); + // expectedSize is the same as username.size()+1 + TestWithSize(expectedSize); + TestSuccess(); } TEST_F(GetUserNameTest, BufferSizeAsLoginNameMax) { - // LoginNameMax is big enough to hold any username, including null - TestWithSize(LOGIN_NAME_MAX); - TestSuccess(); + // LoginNameMax is big enough to hold any username, including null + TestWithSize(LOGIN_NAME_MAX); + TestSuccess(); } From f2ce0d713d8fd529d0e18b04c69cc97ec087c347 Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 12 Aug 2015 13:56:55 -0700 Subject: [PATCH 121/298] changes to pal.h --- impl/pal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impl/pal.h b/impl/pal.h index 1692f15df4..a6034f0ebd 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -63,7 +63,7 @@ typedef void *PVOID; typedef PVOID HANDLE; typedef char TCHAR; - typedef char *LPTSTR; + typedef char* LPTSTR; #define NO_ERROR 0 #define INFINITE 0xFFFFFFFF #define WINAPI From 6fc54d4e4236b05136ab7d97e76964812941b59d Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 12 Aug 2015 13:56:55 -0700 Subject: [PATCH 122/298] changes to pal.h --- src/impl/pal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/impl/pal.h b/src/impl/pal.h index 1692f15df4..a6034f0ebd 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -63,7 +63,7 @@ typedef void *PVOID; typedef PVOID HANDLE; typedef char TCHAR; - typedef char *LPTSTR; + typedef char* LPTSTR; #define NO_ERROR 0 #define INFINITE 0xFFFFFFFF #define WINAPI From f496f91af09c421926163a682e20834906f7ddf7 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 13 Aug 2015 09:47:10 -0700 Subject: [PATCH 123/298] Added changes to code based on additional documention and using a 16 bit string --- impl/getcomputername.cpp | 109 ++++++++++++++++++++++++--------- impl/getcomputername.h | 2 +- impl/pal.h | 1 - tests/test-getcomputername.cpp | 63 ++++++++++++++----- 4 files changed, 127 insertions(+), 48 deletions(-) diff --git a/impl/getcomputername.cpp b/impl/getcomputername.cpp index c403cfe6d0..801c4000ba 100644 --- a/impl/getcomputername.cpp +++ b/impl/getcomputername.cpp @@ -1,33 +1,74 @@ -#include "getcomputername.h" +//! @file getcomputername.cpp +//! @author Aaron Katz +//! @brief Implements GetComputerName Win32 API + #include #include +#include #include #include -#include +#include +#include +#include +#include +#include "getcomputername.h" - -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx -// Sets errno to: -// ERROR_INVALID_PARAMETER - parameter is not valid -// ERROR_BAD_ENVIRONMENT - locale is not UTF-8 -// ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files -// ERROR_NO_ASSOCIATION - calling process has no controlling terminal -// ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string -// ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file -// ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure -// ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal -// ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code -// -// Returns: -// 1 - succeeded -// 0 - failed -BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len) +//! @brief GetComputerName retrieves the name of the host associated with +//! the current thread. +//! +//! GetComputerNameW is the Unicode variation. See [MSDN documentation]. +//! +//! @param[out] lpBuffer +//! @parblock +//! A pointer to the buffer to receive the hosts's +//! name. If this buffer is not large enough to contain the +//! entire user hosts name, the function fails. +//! +//! WCHAR_T* is a Unicode [LPTSTR]. +//! @endparblock +//! +//! @param[in, out] lpnSize +//! @parblock +//! On input, this variable specifies the size of the lpBuffer buffer, +//! in TCHARs. On output, the variable receives the number of TCHARs +//! copied to the buffer, including the terminating null character. +//! +//! TCHAR is a Unicode 16-bit [WCHAR]. +//! +//! If lpBuffer is too small, the function fails and GetLastError +//! returns ERROR_INSUFFICIENT_BUFFER. This parameter receives the +//! required buffer size, including the terminating null character. +//! @endparblock +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_INVALID_PARAMETER: parameter is not valid +//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 +//! - ERROR_TOO_MANY_OPEN_FILES: already have the maximum allowed number of open files +//! - ERROR_NO_ASSOCIATION: calling process has no controlling terminal +//! - ERROR_INSUFFICIENT_BUFFER: buffer not large enough to hold username string +//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file +//! - ERROR_OUTOFMEMORY: insufficient memory to allocate passwd structure +//! - ERROR_NO_ASSOCIATION: standard input didn't refer to a terminal +//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code +//! +//! @retval 1 If the function succeeds, the return value is a nonzero +//! value, and the variable pointed to by lpnSize contains the number +//! of TCHARs copied to the buffer specified by lpBuffer, including +//! the terminating null character. +//! +//! @retval 0 If the function fails, the return value is zero. To get +//! extended error information, call GetLastError. +//! +//! [MSDN documentation]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724295%28v=vs.85%29.aspx +//! [WCHAR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#WCHAR +//! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR +BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { const std::string utf8 = "UTF-8"; errno = 0; // Check parameters - if (!nameOfComputer || !len) { + if (!lpBuffer || !lpnSize) { errno = ERROR_INVALID_PARAMETER; return 0; } @@ -41,8 +82,8 @@ BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len) } // Get computername from system in a thread-safe manner - std::string computerName(HOST_MAX_NAME, '\0'); - int err = gethostname(&computerName[0], computerName.size()); + std::string computername(HOST_NAME_MAX, '\0'); + int err = gethostname(&computername[0], computername.size()); // Map errno to Win32 Error Codes if (err != 0) { switch (errno) { @@ -72,21 +113,31 @@ BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len) return 0; } - //Resize the string to not inlcude extra buffer space - const DWORD length = computerName.find_first_of('\0') + 1; - computerName.resize(length); + // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) + std::basic_string computername16(HOST_NAME_MAX + 1, 0); + icu::UnicodeString computername8(computername.c_str(), "UTF-8"); + int32_t targetSize = computername8.extract(0, computername8.length(), + reinterpret_cast(&computername16[0]), + (computername16.size()-1)*sizeof(char16_t), + "UTF-16LE"); + // Number of characters including null + computername16.resize(targetSize/sizeof(char16_t)+1); + + // Size in WCHARs including null + const DWORD size = computername16.length(); //Check if parameters passed enough buffer space - if (length > *len) { + if (size > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; // Set lpnSize if buffer is too small to inform user // of necessary size - *len= length; + *lpnSize= size; return 0; } - memcpy(nameOfComputer, &computerName[0], length); - *len = length; + // Copy bytes from string to buffer + memcpy(lpBuffer, &computername16[0], size*sizeof(char16_t)); + *lpnSize = size; return 1; } diff --git a/impl/getcomputername.h b/impl/getcomputername.h index 5e0d5be2ba..8d39d3f9fa 100644 --- a/impl/getcomputername.h +++ b/impl/getcomputername.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len); +BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize); PAL_END_EXTERNC \ No newline at end of file diff --git a/impl/pal.h b/impl/pal.h index a6034f0ebd..17e58d409f 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -80,7 +80,6 @@ #define ERROR_NO_SUCH_USER 0x00000525 #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 - #define HOST_MAX_NAME 256 typedef unsigned long long uint64; #endif diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index b917305535..93cbfe71d5 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -1,36 +1,65 @@ -#include -#include "getcomputername.h" -#include +//! @file test-getcomputername.cpp +//! @author Aaron Katz +//! @brief Unit tests for GetComputerNameW +#include +#include +#include +#include +#include +#include +#include +#include +#include "getcomputername.h" + +//! Test fixture for GetComputerNameTest class GetComputerNameTest : public ::testing::Test { protected: DWORD lpnSize; + std::vector lpBuffer; BOOL result; std::string expectedComputerName; - std::string computerName; + DWORD expectedSize; //Get expected result from using linux call GetComputerNameTest(){ - char hostname[HOST_MAX_NAME]; + char hostname[HOST_NAME_MAX]; BOOL host = gethostname(hostname, sizeof hostname); expectedComputerName = hostname; + expectedSize = expectedComputerName.length() + 1; } void TestWithSize(DWORD size) { lpnSize = size; // allocate a DWORD buffer to receive computername - computerName.assign(lpnSize, '\0'); - result = GetComputerNameW(&computerName[0], &lpnSize); + lpBuffer.assign(lpnSize, '\0'); + result = GetComputerNameW(&lpBuffer[0], &lpnSize); } void TestSuccess() { SCOPED_TRACE(""); - // returns 1 on success - EXPECT_EQ(1, result); - //Resize to cut off '\0' - computerName.resize(expectedComputerName.length()); - ASSERT_EQ(expectedComputerName.size()+1, lpnSize); - EXPECT_EQ(computerName, expectedComputerName); + + //! Returns TRUE on success. + EXPECT_EQ(TRUE, result); + + //! Sets lpnSize to number of WCHARs including null. + ASSERT_EQ(expectedSize, lpnSize); + + // setup for conversion from UTF-16LE + const char* begin = reinterpret_cast(&lpBuffer[0]); + // multiply to get number of bytes + icu::UnicodeString usercomputer16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); + // username16 length includes null and is number of characters + ASSERT_EQ(expectedSize, usercomputer16.length()); + + // convert (minus null) to UTF-8 for comparison + std::string computername(lpnSize-1, 0); + ASSERT_EQ(expectedComputerName.length(), computername.length()); + usercomputer16.extract(0, computername.length(), + reinterpret_cast(&computername[0]), "UTF-8"); + + //! Returned computername(after conversion) is what was expected. + EXPECT_EQ(expectedComputerName, computername); } void TestInvalidParameter() { @@ -66,14 +95,14 @@ TEST_F(GetComputerNameTest, BufferAsNullButNotBufferSize) { } TEST_F(GetComputerNameTest, BufferSizeAsNullButNotBuffer) { - computerName.push_back('\0'); - result = GetComputerNameW(&computerName[0], NULL); + lpBuffer.push_back('\0'); + result = GetComputerNameW(&lpBuffer[0], NULL); TestInvalidParameter(); } TEST_F(GetComputerNameTest, BufferSizeAsZero) { TestWithSize(0); - EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); + EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); } TEST_F(GetComputerNameTest, BufferSizeAsUserNameMinusOne) { @@ -90,6 +119,6 @@ TEST_F(GetComputerNameTest, BufferSizeAsUserNamePlusOne) { TEST_F(GetComputerNameTest, BufferSizeAsLoginNameMax) { // the buffer larger than needed - TestWithSize(HOST_MAX_NAME); + TestWithSize(HOST_NAME_MAX); TestSuccess(); } \ No newline at end of file From dfb7a49c21120c0b0e5181e247727b42d4fbc4e7 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 13 Aug 2015 09:47:10 -0700 Subject: [PATCH 124/298] Added changes to code based on additional documention and using a 16 bit string --- src/impl/getcomputername.cpp | 109 +++++++++++++++++++++-------- src/impl/getcomputername.h | 2 +- src/impl/pal.h | 1 - src/tests/test-getcomputername.cpp | 63 ++++++++++++----- 4 files changed, 127 insertions(+), 48 deletions(-) diff --git a/src/impl/getcomputername.cpp b/src/impl/getcomputername.cpp index c403cfe6d0..801c4000ba 100644 --- a/src/impl/getcomputername.cpp +++ b/src/impl/getcomputername.cpp @@ -1,33 +1,74 @@ -#include "getcomputername.h" +//! @file getcomputername.cpp +//! @author Aaron Katz +//! @brief Implements GetComputerName Win32 API + #include #include +#include #include #include -#include +#include +#include +#include +#include +#include "getcomputername.h" - -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx -// Sets errno to: -// ERROR_INVALID_PARAMETER - parameter is not valid -// ERROR_BAD_ENVIRONMENT - locale is not UTF-8 -// ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files -// ERROR_NO_ASSOCIATION - calling process has no controlling terminal -// ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string -// ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file -// ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure -// ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal -// ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code -// -// Returns: -// 1 - succeeded -// 0 - failed -BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len) +//! @brief GetComputerName retrieves the name of the host associated with +//! the current thread. +//! +//! GetComputerNameW is the Unicode variation. See [MSDN documentation]. +//! +//! @param[out] lpBuffer +//! @parblock +//! A pointer to the buffer to receive the hosts's +//! name. If this buffer is not large enough to contain the +//! entire user hosts name, the function fails. +//! +//! WCHAR_T* is a Unicode [LPTSTR]. +//! @endparblock +//! +//! @param[in, out] lpnSize +//! @parblock +//! On input, this variable specifies the size of the lpBuffer buffer, +//! in TCHARs. On output, the variable receives the number of TCHARs +//! copied to the buffer, including the terminating null character. +//! +//! TCHAR is a Unicode 16-bit [WCHAR]. +//! +//! If lpBuffer is too small, the function fails and GetLastError +//! returns ERROR_INSUFFICIENT_BUFFER. This parameter receives the +//! required buffer size, including the terminating null character. +//! @endparblock +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_INVALID_PARAMETER: parameter is not valid +//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 +//! - ERROR_TOO_MANY_OPEN_FILES: already have the maximum allowed number of open files +//! - ERROR_NO_ASSOCIATION: calling process has no controlling terminal +//! - ERROR_INSUFFICIENT_BUFFER: buffer not large enough to hold username string +//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file +//! - ERROR_OUTOFMEMORY: insufficient memory to allocate passwd structure +//! - ERROR_NO_ASSOCIATION: standard input didn't refer to a terminal +//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code +//! +//! @retval 1 If the function succeeds, the return value is a nonzero +//! value, and the variable pointed to by lpnSize contains the number +//! of TCHARs copied to the buffer specified by lpBuffer, including +//! the terminating null character. +//! +//! @retval 0 If the function fails, the return value is zero. To get +//! extended error information, call GetLastError. +//! +//! [MSDN documentation]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724295%28v=vs.85%29.aspx +//! [WCHAR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#WCHAR +//! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR +BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { const std::string utf8 = "UTF-8"; errno = 0; // Check parameters - if (!nameOfComputer || !len) { + if (!lpBuffer || !lpnSize) { errno = ERROR_INVALID_PARAMETER; return 0; } @@ -41,8 +82,8 @@ BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len) } // Get computername from system in a thread-safe manner - std::string computerName(HOST_MAX_NAME, '\0'); - int err = gethostname(&computerName[0], computerName.size()); + std::string computername(HOST_NAME_MAX, '\0'); + int err = gethostname(&computername[0], computername.size()); // Map errno to Win32 Error Codes if (err != 0) { switch (errno) { @@ -72,21 +113,31 @@ BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len) return 0; } - //Resize the string to not inlcude extra buffer space - const DWORD length = computerName.find_first_of('\0') + 1; - computerName.resize(length); + // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) + std::basic_string computername16(HOST_NAME_MAX + 1, 0); + icu::UnicodeString computername8(computername.c_str(), "UTF-8"); + int32_t targetSize = computername8.extract(0, computername8.length(), + reinterpret_cast(&computername16[0]), + (computername16.size()-1)*sizeof(char16_t), + "UTF-16LE"); + // Number of characters including null + computername16.resize(targetSize/sizeof(char16_t)+1); + + // Size in WCHARs including null + const DWORD size = computername16.length(); //Check if parameters passed enough buffer space - if (length > *len) { + if (size > *lpnSize) { errno = ERROR_INSUFFICIENT_BUFFER; // Set lpnSize if buffer is too small to inform user // of necessary size - *len= length; + *lpnSize= size; return 0; } - memcpy(nameOfComputer, &computerName[0], length); - *len = length; + // Copy bytes from string to buffer + memcpy(lpBuffer, &computername16[0], size*sizeof(char16_t)); + *lpnSize = size; return 1; } diff --git a/src/impl/getcomputername.h b/src/impl/getcomputername.h index 5e0d5be2ba..8d39d3f9fa 100644 --- a/src/impl/getcomputername.h +++ b/src/impl/getcomputername.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len); +BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize); PAL_END_EXTERNC \ No newline at end of file diff --git a/src/impl/pal.h b/src/impl/pal.h index a6034f0ebd..17e58d409f 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -80,7 +80,6 @@ #define ERROR_NO_SUCH_USER 0x00000525 #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 - #define HOST_MAX_NAME 256 typedef unsigned long long uint64; #endif diff --git a/src/tests/test-getcomputername.cpp b/src/tests/test-getcomputername.cpp index b917305535..93cbfe71d5 100644 --- a/src/tests/test-getcomputername.cpp +++ b/src/tests/test-getcomputername.cpp @@ -1,36 +1,65 @@ -#include -#include "getcomputername.h" -#include +//! @file test-getcomputername.cpp +//! @author Aaron Katz +//! @brief Unit tests for GetComputerNameW +#include +#include +#include +#include +#include +#include +#include +#include +#include "getcomputername.h" + +//! Test fixture for GetComputerNameTest class GetComputerNameTest : public ::testing::Test { protected: DWORD lpnSize; + std::vector lpBuffer; BOOL result; std::string expectedComputerName; - std::string computerName; + DWORD expectedSize; //Get expected result from using linux call GetComputerNameTest(){ - char hostname[HOST_MAX_NAME]; + char hostname[HOST_NAME_MAX]; BOOL host = gethostname(hostname, sizeof hostname); expectedComputerName = hostname; + expectedSize = expectedComputerName.length() + 1; } void TestWithSize(DWORD size) { lpnSize = size; // allocate a DWORD buffer to receive computername - computerName.assign(lpnSize, '\0'); - result = GetComputerNameW(&computerName[0], &lpnSize); + lpBuffer.assign(lpnSize, '\0'); + result = GetComputerNameW(&lpBuffer[0], &lpnSize); } void TestSuccess() { SCOPED_TRACE(""); - // returns 1 on success - EXPECT_EQ(1, result); - //Resize to cut off '\0' - computerName.resize(expectedComputerName.length()); - ASSERT_EQ(expectedComputerName.size()+1, lpnSize); - EXPECT_EQ(computerName, expectedComputerName); + + //! Returns TRUE on success. + EXPECT_EQ(TRUE, result); + + //! Sets lpnSize to number of WCHARs including null. + ASSERT_EQ(expectedSize, lpnSize); + + // setup for conversion from UTF-16LE + const char* begin = reinterpret_cast(&lpBuffer[0]); + // multiply to get number of bytes + icu::UnicodeString usercomputer16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); + // username16 length includes null and is number of characters + ASSERT_EQ(expectedSize, usercomputer16.length()); + + // convert (minus null) to UTF-8 for comparison + std::string computername(lpnSize-1, 0); + ASSERT_EQ(expectedComputerName.length(), computername.length()); + usercomputer16.extract(0, computername.length(), + reinterpret_cast(&computername[0]), "UTF-8"); + + //! Returned computername(after conversion) is what was expected. + EXPECT_EQ(expectedComputerName, computername); } void TestInvalidParameter() { @@ -66,14 +95,14 @@ TEST_F(GetComputerNameTest, BufferAsNullButNotBufferSize) { } TEST_F(GetComputerNameTest, BufferSizeAsNullButNotBuffer) { - computerName.push_back('\0'); - result = GetComputerNameW(&computerName[0], NULL); + lpBuffer.push_back('\0'); + result = GetComputerNameW(&lpBuffer[0], NULL); TestInvalidParameter(); } TEST_F(GetComputerNameTest, BufferSizeAsZero) { TestWithSize(0); - EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); + EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); } TEST_F(GetComputerNameTest, BufferSizeAsUserNameMinusOne) { @@ -90,6 +119,6 @@ TEST_F(GetComputerNameTest, BufferSizeAsUserNamePlusOne) { TEST_F(GetComputerNameTest, BufferSizeAsLoginNameMax) { // the buffer larger than needed - TestWithSize(HOST_MAX_NAME); + TestWithSize(HOST_NAME_MAX); TestSuccess(); } \ No newline at end of file From 72ea5abd0b724d0ed8743de190e29823d8bffd03 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 13 Aug 2015 10:53:09 -0700 Subject: [PATCH 125/298] New line for { --- impl/getcomputername.cpp | 15 +++++++++----- tests/test-getcomputername.cpp | 36 ++++++++++++++++++++++------------ 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/impl/getcomputername.cpp b/impl/getcomputername.cpp index 801c4000ba..f930dc890d 100644 --- a/impl/getcomputername.cpp +++ b/impl/getcomputername.cpp @@ -68,7 +68,8 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) errno = 0; // Check parameters - if (!lpBuffer || !lpnSize) { + if (!lpBuffer || !lpnSize) + { errno = ERROR_INVALID_PARAMETER; return 0; } @@ -76,7 +77,8 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) // Select locale from environment setlocale(LC_ALL, ""); // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != utf8) { + if (nl_langinfo(CODESET) != utf8) + { errno = ERROR_BAD_ENVIRONMENT; return 0; } @@ -85,8 +87,10 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) std::string computername(HOST_NAME_MAX, '\0'); int err = gethostname(&computername[0], computername.size()); // Map errno to Win32 Error Codes - if (err != 0) { - switch (errno) { + if (err != 0) + { + switch (errno) + { case EMFILE: case ENFILE: errno = ERROR_TOO_MANY_OPEN_FILES; @@ -127,7 +131,8 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) const DWORD size = computername16.length(); //Check if parameters passed enough buffer space - if (size > *lpnSize) { + if (size > *lpnSize) + { errno = ERROR_INSUFFICIENT_BUFFER; // Set lpnSize if buffer is too small to inform user // of necessary size diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index 93cbfe71d5..a566d83ccb 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -13,7 +13,8 @@ #include "getcomputername.h" //! Test fixture for GetComputerNameTest -class GetComputerNameTest : public ::testing::Test { +class GetComputerNameTest : public ::testing::Test +{ protected: DWORD lpnSize; std::vector lpBuffer; @@ -22,21 +23,24 @@ protected: DWORD expectedSize; //Get expected result from using linux call - GetComputerNameTest(){ + GetComputerNameTest() + { char hostname[HOST_NAME_MAX]; BOOL host = gethostname(hostname, sizeof hostname); expectedComputerName = hostname; expectedSize = expectedComputerName.length() + 1; } - void TestWithSize(DWORD size) { + void TestWithSize(DWORD size) + { lpnSize = size; // allocate a DWORD buffer to receive computername lpBuffer.assign(lpnSize, '\0'); result = GetComputerNameW(&lpBuffer[0], &lpnSize); } - void TestSuccess() { + void TestSuccess() + { SCOPED_TRACE(""); //! Returns TRUE on success. @@ -62,7 +66,8 @@ protected: EXPECT_EQ(expectedComputerName, computername); } - void TestInvalidParameter() { + void TestInvalidParameter() + { SCOPED_TRACE(""); // returns 0 on failure @@ -72,7 +77,8 @@ protected: EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); } - void TestInsufficientBuffer() { + void TestInsufficientBuffer() + { SCOPED_TRACE(""); // returns 0 on failure @@ -86,7 +92,8 @@ protected: } }; -TEST_F(GetComputerNameTest, BufferAsNullButNotBufferSize) { +TEST_F(GetComputerNameTest, BufferAsNullButNotBufferSize) +{ lpnSize = 1; result = GetComputerNameW(NULL, &lpnSize); TestInvalidParameter(); @@ -94,30 +101,35 @@ TEST_F(GetComputerNameTest, BufferAsNullButNotBufferSize) { EXPECT_EQ(1, lpnSize); } -TEST_F(GetComputerNameTest, BufferSizeAsNullButNotBuffer) { +TEST_F(GetComputerNameTest, BufferSizeAsNullButNotBuffer) +{ lpBuffer.push_back('\0'); result = GetComputerNameW(&lpBuffer[0], NULL); TestInvalidParameter(); } -TEST_F(GetComputerNameTest, BufferSizeAsZero) { +TEST_F(GetComputerNameTest, BufferSizeAsZero) +{ TestWithSize(0); EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); } -TEST_F(GetComputerNameTest, BufferSizeAsUserNameMinusOne) { +TEST_F(GetComputerNameTest, BufferSizeAsUserNameMinusOne) +{ // the buffer is also too small TestWithSize(expectedComputerName.size()-1); TestInsufficientBuffer(); } -TEST_F(GetComputerNameTest, BufferSizeAsUserNamePlusOne) { +TEST_F(GetComputerNameTest, BufferSizeAsUserNamePlusOne) +{ // the buffer is exactly big enough TestWithSize(expectedComputerName.size()+1); TestSuccess(); } -TEST_F(GetComputerNameTest, BufferSizeAsLoginNameMax) { +TEST_F(GetComputerNameTest, BufferSizeAsLoginNameMax) +{ // the buffer larger than needed TestWithSize(HOST_NAME_MAX); TestSuccess(); From 6bb2c697825f65adbbbe96819dc64843c7a8026f Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 13 Aug 2015 10:53:09 -0700 Subject: [PATCH 126/298] New line for { --- src/impl/getcomputername.cpp | 15 ++++++++----- src/tests/test-getcomputername.cpp | 36 ++++++++++++++++++++---------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/impl/getcomputername.cpp b/src/impl/getcomputername.cpp index 801c4000ba..f930dc890d 100644 --- a/src/impl/getcomputername.cpp +++ b/src/impl/getcomputername.cpp @@ -68,7 +68,8 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) errno = 0; // Check parameters - if (!lpBuffer || !lpnSize) { + if (!lpBuffer || !lpnSize) + { errno = ERROR_INVALID_PARAMETER; return 0; } @@ -76,7 +77,8 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) // Select locale from environment setlocale(LC_ALL, ""); // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != utf8) { + if (nl_langinfo(CODESET) != utf8) + { errno = ERROR_BAD_ENVIRONMENT; return 0; } @@ -85,8 +87,10 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) std::string computername(HOST_NAME_MAX, '\0'); int err = gethostname(&computername[0], computername.size()); // Map errno to Win32 Error Codes - if (err != 0) { - switch (errno) { + if (err != 0) + { + switch (errno) + { case EMFILE: case ENFILE: errno = ERROR_TOO_MANY_OPEN_FILES; @@ -127,7 +131,8 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) const DWORD size = computername16.length(); //Check if parameters passed enough buffer space - if (size > *lpnSize) { + if (size > *lpnSize) + { errno = ERROR_INSUFFICIENT_BUFFER; // Set lpnSize if buffer is too small to inform user // of necessary size diff --git a/src/tests/test-getcomputername.cpp b/src/tests/test-getcomputername.cpp index 93cbfe71d5..a566d83ccb 100644 --- a/src/tests/test-getcomputername.cpp +++ b/src/tests/test-getcomputername.cpp @@ -13,7 +13,8 @@ #include "getcomputername.h" //! Test fixture for GetComputerNameTest -class GetComputerNameTest : public ::testing::Test { +class GetComputerNameTest : public ::testing::Test +{ protected: DWORD lpnSize; std::vector lpBuffer; @@ -22,21 +23,24 @@ protected: DWORD expectedSize; //Get expected result from using linux call - GetComputerNameTest(){ + GetComputerNameTest() + { char hostname[HOST_NAME_MAX]; BOOL host = gethostname(hostname, sizeof hostname); expectedComputerName = hostname; expectedSize = expectedComputerName.length() + 1; } - void TestWithSize(DWORD size) { + void TestWithSize(DWORD size) + { lpnSize = size; // allocate a DWORD buffer to receive computername lpBuffer.assign(lpnSize, '\0'); result = GetComputerNameW(&lpBuffer[0], &lpnSize); } - void TestSuccess() { + void TestSuccess() + { SCOPED_TRACE(""); //! Returns TRUE on success. @@ -62,7 +66,8 @@ protected: EXPECT_EQ(expectedComputerName, computername); } - void TestInvalidParameter() { + void TestInvalidParameter() + { SCOPED_TRACE(""); // returns 0 on failure @@ -72,7 +77,8 @@ protected: EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); } - void TestInsufficientBuffer() { + void TestInsufficientBuffer() + { SCOPED_TRACE(""); // returns 0 on failure @@ -86,7 +92,8 @@ protected: } }; -TEST_F(GetComputerNameTest, BufferAsNullButNotBufferSize) { +TEST_F(GetComputerNameTest, BufferAsNullButNotBufferSize) +{ lpnSize = 1; result = GetComputerNameW(NULL, &lpnSize); TestInvalidParameter(); @@ -94,30 +101,35 @@ TEST_F(GetComputerNameTest, BufferAsNullButNotBufferSize) { EXPECT_EQ(1, lpnSize); } -TEST_F(GetComputerNameTest, BufferSizeAsNullButNotBuffer) { +TEST_F(GetComputerNameTest, BufferSizeAsNullButNotBuffer) +{ lpBuffer.push_back('\0'); result = GetComputerNameW(&lpBuffer[0], NULL); TestInvalidParameter(); } -TEST_F(GetComputerNameTest, BufferSizeAsZero) { +TEST_F(GetComputerNameTest, BufferSizeAsZero) +{ TestWithSize(0); EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); } -TEST_F(GetComputerNameTest, BufferSizeAsUserNameMinusOne) { +TEST_F(GetComputerNameTest, BufferSizeAsUserNameMinusOne) +{ // the buffer is also too small TestWithSize(expectedComputerName.size()-1); TestInsufficientBuffer(); } -TEST_F(GetComputerNameTest, BufferSizeAsUserNamePlusOne) { +TEST_F(GetComputerNameTest, BufferSizeAsUserNamePlusOne) +{ // the buffer is exactly big enough TestWithSize(expectedComputerName.size()+1); TestSuccess(); } -TEST_F(GetComputerNameTest, BufferSizeAsLoginNameMax) { +TEST_F(GetComputerNameTest, BufferSizeAsLoginNameMax) +{ // the buffer larger than needed TestWithSize(HOST_NAME_MAX); TestSuccess(); From 46677d776b6a634d6f216bf5d86abb970165c5d7 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 17:43:32 -0700 Subject: [PATCH 127/298] Return FALSE instead of 0 --- impl/getusername.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 5d0bec0361..82a6be1806 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -51,12 +51,12 @@ //! - ERROR_NO_ASSOCIATION: standard input didn't refer to a terminal //! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code //! -//! @retval 1 If the function succeeds, the return value is a nonzero +//! @retval TRUE If the function succeeds, the return value is a nonzero //! value, and the variable pointed to by lpnSize contains the number //! of TCHARs copied to the buffer specified by lpBuffer, including //! the terminating null character. //! -//! @retval 0 If the function fails, the return value is zero. To get +//! @retval FALSE If the function fails, the return value is zero. To get //! extended error information, call GetLastError. //! //! [MSDN documentation]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx @@ -72,7 +72,7 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) if (!lpBuffer || !lpnSize) { errno = ERROR_INVALID_PARAMETER; - return 0; + return FALSE; } // Select locale from environment @@ -135,7 +135,7 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) // Set lpnSize if buffer is too small to inform user // of necessary size *lpnSize = size; - return 0; + return FALSE; } // Copy bytes from string to buffer From 454d1f276a711322a4bd0bc76fe46ce054c860e8 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 17:43:32 -0700 Subject: [PATCH 128/298] Return FALSE instead of 0 --- src/impl/getusername.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 5d0bec0361..82a6be1806 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -51,12 +51,12 @@ //! - ERROR_NO_ASSOCIATION: standard input didn't refer to a terminal //! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code //! -//! @retval 1 If the function succeeds, the return value is a nonzero +//! @retval TRUE If the function succeeds, the return value is a nonzero //! value, and the variable pointed to by lpnSize contains the number //! of TCHARs copied to the buffer specified by lpBuffer, including //! the terminating null character. //! -//! @retval 0 If the function fails, the return value is zero. To get +//! @retval FALSE If the function fails, the return value is zero. To get //! extended error information, call GetLastError. //! //! [MSDN documentation]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx @@ -72,7 +72,7 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) if (!lpBuffer || !lpnSize) { errno = ERROR_INVALID_PARAMETER; - return 0; + return FALSE; } // Select locale from environment @@ -135,7 +135,7 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) // Set lpnSize if buffer is too small to inform user // of necessary size *lpnSize = size; - return 0; + return FALSE; } // Copy bytes from string to buffer From bb67bfaae7c3227875ae5e99b232776f00f7fd6e Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 17:53:28 -0700 Subject: [PATCH 129/298] Remove std::string utf8 Not used consistently. Use in-place for comparison. --- impl/getusername.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 82a6be1806..849f4896ad 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -64,8 +64,6 @@ //! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { - const std::string utf8 = "UTF-8"; - errno = FALSE; // Check parameters @@ -78,7 +76,7 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) // Select locale from environment setlocale(LC_ALL, ""); // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != utf8) + if (nl_langinfo(CODESET) != std::string("UTF-8")) { errno = ERROR_BAD_ENVIRONMENT; return FALSE; From bef9deeb84bfd7c4d5f62e98a777cb4bfbc831dd Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 17:53:28 -0700 Subject: [PATCH 130/298] Remove std::string utf8 Not used consistently. Use in-place for comparison. --- src/impl/getusername.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 82a6be1806..849f4896ad 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -64,8 +64,6 @@ //! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { - const std::string utf8 = "UTF-8"; - errno = FALSE; // Check parameters @@ -78,7 +76,7 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) // Select locale from environment setlocale(LC_ALL, ""); // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != utf8) + if (nl_langinfo(CODESET) != std::string("UTF-8")) { errno = ERROR_BAD_ENVIRONMENT; return FALSE; From fc8f5d18c4972dbaa14d230d0d52c443a443dacb Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 17:54:13 -0700 Subject: [PATCH 131/298] Use 0 instead of '\0' To be consistent with tests --- impl/getusername.cpp | 2 +- tests/test-getusername.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 849f4896ad..9ae1e665f8 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -83,8 +83,8 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) } // Get username from system in a thread-safe manner - std::string username(LOGIN_NAME_MAX, '\0'); int ret = getlogin_r(&username[0], username.size()); + std::string username(LOGIN_NAME_MAX, 0); // Map errno to Win32 Error Codes if (ret) { diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index e27aeef28b..87ee5367c4 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -35,7 +35,7 @@ protected: { lpnSize = size; // allocate a WCHAR_T buffer to receive username - lpBuffer.assign(lpnSize, '\0'); + lpBuffer.assign(lpnSize, 0); result = GetUserNameW(&lpBuffer[0], &lpnSize); } From 91345a149eb8873b305cd53e4e8b4f2339527129 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 17:54:13 -0700 Subject: [PATCH 132/298] Use 0 instead of '\0' To be consistent with tests --- src/impl/getusername.cpp | 2 +- src/tests/test-getusername.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 849f4896ad..9ae1e665f8 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -83,8 +83,8 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) } // Get username from system in a thread-safe manner - std::string username(LOGIN_NAME_MAX, '\0'); int ret = getlogin_r(&username[0], username.size()); + std::string username(LOGIN_NAME_MAX, 0); // Map errno to Win32 Error Codes if (ret) { diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index e27aeef28b..87ee5367c4 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -35,7 +35,7 @@ protected: { lpnSize = size; // allocate a WCHAR_T buffer to receive username - lpBuffer.assign(lpnSize, '\0'); + lpBuffer.assign(lpnSize, 0); result = GetUserNameW(&lpBuffer[0], &lpnSize); } From db7117bd47424a531251fbe4f042e0180b443f57 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 17:54:29 -0700 Subject: [PATCH 133/298] Use length() instead of size() To be consistent with everything else. --- impl/getusername.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 9ae1e665f8..0990269c76 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -83,8 +83,8 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) } // Get username from system in a thread-safe manner - int ret = getlogin_r(&username[0], username.size()); std::string username(LOGIN_NAME_MAX, 0); + int ret = getlogin_r(&username[0], username.length()); // Map errno to Win32 Error Codes if (ret) { From c6aa25acd515c3c46c681dec53a16f840fc59715 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 17:54:29 -0700 Subject: [PATCH 134/298] Use length() instead of size() To be consistent with everything else. --- src/impl/getusername.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 9ae1e665f8..0990269c76 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -83,8 +83,8 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) } // Get username from system in a thread-safe manner - int ret = getlogin_r(&username[0], username.size()); std::string username(LOGIN_NAME_MAX, 0); + int ret = getlogin_r(&username[0], username.length()); // Map errno to Win32 Error Codes if (ret) { From 674ca43046e0f569d3077b1cfe5aa4806c009c5a Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 17:54:45 -0700 Subject: [PATCH 135/298] Use just LOGIN_NAME_MAX The +1 is unnecessary since LOGIN_NAME_MAX includes null. --- impl/getusername.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 0990269c76..583485e411 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -116,7 +116,7 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) } // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) - std::basic_string username16(LOGIN_NAME_MAX+1, 0); + std::basic_string username16(LOGIN_NAME_MAX, 0); icu::UnicodeString username8(username.c_str(), "UTF-8"); int32_t targetSize = username8.extract(0, username8.length(), reinterpret_cast(&username16[0]), From fd8352c4690fe1d87fbf723386eeeeeeee916910 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 17:54:45 -0700 Subject: [PATCH 136/298] Use just LOGIN_NAME_MAX The +1 is unnecessary since LOGIN_NAME_MAX includes null. --- src/impl/getusername.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 0990269c76..583485e411 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -116,7 +116,7 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) } // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) - std::basic_string username16(LOGIN_NAME_MAX+1, 0); + std::basic_string username16(LOGIN_NAME_MAX, 0); icu::UnicodeString username8(username.c_str(), "UTF-8"); int32_t targetSize = username8.extract(0, username8.length(), reinterpret_cast(&username16[0]), From 70a163e0612ad1b7487cb56af09c06b4a1c337be Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 17:55:29 -0700 Subject: [PATCH 137/298] Use known size instead of calculation --- impl/getusername.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 583485e411..6bd458a70e 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -120,8 +120,7 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) icu::UnicodeString username8(username.c_str(), "UTF-8"); int32_t targetSize = username8.extract(0, username8.length(), reinterpret_cast(&username16[0]), - (username16.size()-1)*sizeof(char16_t), - "UTF-16LE"); + LOGIN_NAME_MAX, "UTF-16LE"); // Number of characters including null username16.resize(targetSize/sizeof(char16_t)+1); From 77f9757a0512904f8b04839f108e6feaba8e86fb Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 17:55:29 -0700 Subject: [PATCH 138/298] Use known size instead of calculation --- src/impl/getusername.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 583485e411..6bd458a70e 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -120,8 +120,7 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) icu::UnicodeString username8(username.c_str(), "UTF-8"); int32_t targetSize = username8.extract(0, username8.length(), reinterpret_cast(&username16[0]), - (username16.size()-1)*sizeof(char16_t), - "UTF-16LE"); + LOGIN_NAME_MAX, "UTF-16LE"); // Number of characters including null username16.resize(targetSize/sizeof(char16_t)+1); From 60a9a360a177889b2c10311ffbc722f25add7477 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 20:30:48 -0700 Subject: [PATCH 139/298] Use libicu properly for UTF-16 conversion - No more messy calculations - Only one include, not four - No resizing - No memcpy - Faster because of fromUTF8() --- impl/getusername.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 6bd458a70e..88e5955d64 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -7,10 +7,7 @@ #include #include #include -#include -#include -#include -#include +#include #include "getusername.h" //! @brief GetUserName retrieves the name of the user associated with @@ -115,14 +112,10 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) return FALSE; } - // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) - std::basic_string username16(LOGIN_NAME_MAX, 0); - icu::UnicodeString username8(username.c_str(), "UTF-8"); - int32_t targetSize = username8.extract(0, username8.length(), - reinterpret_cast(&username16[0]), - LOGIN_NAME_MAX, "UTF-16LE"); - // Number of characters including null - username16.resize(targetSize/sizeof(char16_t)+1); + // Convert to UnicodeString + auto username16 = icu::UnicodeString::fromUTF8(username.c_str()); + // Terminate string with null + username16.append('\0'); // Size in WCHARs including null const DWORD size = username16.length(); @@ -135,8 +128,9 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) return FALSE; } - // Copy bytes from string to buffer - memcpy(lpBuffer, &username16[0], size*sizeof(char16_t)); + // Extract string as UTF-16LE to buffer + username16.extract(0, size, reinterpret_cast(lpBuffer), "UTF-16LE"); + *lpnSize = size; return TRUE; From 8fdfeb250d08da2311198f5919771b1db31f682c Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 20:30:48 -0700 Subject: [PATCH 140/298] Use libicu properly for UTF-16 conversion - No more messy calculations - Only one include, not four - No resizing - No memcpy - Faster because of fromUTF8() --- src/impl/getusername.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 6bd458a70e..88e5955d64 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -7,10 +7,7 @@ #include #include #include -#include -#include -#include -#include +#include #include "getusername.h" //! @brief GetUserName retrieves the name of the user associated with @@ -115,14 +112,10 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) return FALSE; } - // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) - std::basic_string username16(LOGIN_NAME_MAX, 0); - icu::UnicodeString username8(username.c_str(), "UTF-8"); - int32_t targetSize = username8.extract(0, username8.length(), - reinterpret_cast(&username16[0]), - LOGIN_NAME_MAX, "UTF-16LE"); - // Number of characters including null - username16.resize(targetSize/sizeof(char16_t)+1); + // Convert to UnicodeString + auto username16 = icu::UnicodeString::fromUTF8(username.c_str()); + // Terminate string with null + username16.append('\0'); // Size in WCHARs including null const DWORD size = username16.length(); @@ -135,8 +128,9 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) return FALSE; } - // Copy bytes from string to buffer - memcpy(lpBuffer, &username16[0], size*sizeof(char16_t)); + // Extract string as UTF-16LE to buffer + username16.extract(0, size, reinterpret_cast(lpBuffer), "UTF-16LE"); + *lpnSize = size; return TRUE; From d298302e8cf5edc6dc39a325bdf4256095107e0f Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 20:42:01 -0700 Subject: [PATCH 141/298] Use libicu properly in tests --- tests/test-getusername.cpp | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index 87ee5367c4..b6c0b5e776 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -6,10 +6,7 @@ #include #include #include -#include -#include -#include -#include +#include #include "getusername.h" //! Test fixture for GetUserNameW @@ -50,18 +47,14 @@ protected: //! Sets lpnSize to number of WCHARs including null. ASSERT_EQ(expectedSize, lpnSize); - // setup for conversion from UTF-16LE + // Read lpBuffer into UnicodeString (without null) const char* begin = reinterpret_cast(&lpBuffer[0]); - // multiply to get number of bytes - icu::UnicodeString username16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); - // username16 length includes null and is number of characters - ASSERT_EQ(expectedSize, username16.length()); - - // convert (minus null) to UTF-8 for comparison - std::string username(lpnSize-1, 0); + icu::UnicodeString username16(begin, (lpnSize-1)*sizeof(UChar), "UTF-16LE"); + ASSERT_EQ(expectedUsername.length(), username16.length()); + // Convert to UTF-8 for comparison + std::string username; + username16.toUTF8String(username); ASSERT_EQ(expectedUsername.length(), username.length()); - username16.extract(0, username.length(), - reinterpret_cast(&username[0]), "UTF-8"); //! Returned username (after conversion) is what was expected. EXPECT_EQ(expectedUsername, username); From 9164baa9c452f89c71811a90b5ff519f0baf46b1 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 13 Aug 2015 20:42:01 -0700 Subject: [PATCH 142/298] Use libicu properly in tests --- src/tests/test-getusername.cpp | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index 87ee5367c4..b6c0b5e776 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -6,10 +6,7 @@ #include #include #include -#include -#include -#include -#include +#include #include "getusername.h" //! Test fixture for GetUserNameW @@ -50,18 +47,14 @@ protected: //! Sets lpnSize to number of WCHARs including null. ASSERT_EQ(expectedSize, lpnSize); - // setup for conversion from UTF-16LE + // Read lpBuffer into UnicodeString (without null) const char* begin = reinterpret_cast(&lpBuffer[0]); - // multiply to get number of bytes - icu::UnicodeString username16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); - // username16 length includes null and is number of characters - ASSERT_EQ(expectedSize, username16.length()); - - // convert (minus null) to UTF-8 for comparison - std::string username(lpnSize-1, 0); + icu::UnicodeString username16(begin, (lpnSize-1)*sizeof(UChar), "UTF-16LE"); + ASSERT_EQ(expectedUsername.length(), username16.length()); + // Convert to UTF-8 for comparison + std::string username; + username16.toUTF8String(username); ASSERT_EQ(expectedUsername.length(), username.length()); - username16.extract(0, username.length(), - reinterpret_cast(&username[0]), "UTF-8"); //! Returned username (after conversion) is what was expected. EXPECT_EQ(expectedUsername, username); From 427cce83f0a8d2784f7e8cc5bf19ab481a5c7ad3 Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 14 Aug 2015 09:26:45 -0700 Subject: [PATCH 143/298] Added changes based of feedback from Peter --- src/CMakeCache.txt | 324 +++++++++++++++++++++++++++++++++++ src/impl/getcpinfo.cpp | 60 +++++-- src/impl/getcpinfo.h | 2 +- src/impl/pal.h | 5 +- src/tests/test-getcpinfo.cpp | 35 ++-- 5 files changed, 386 insertions(+), 40 deletions(-) create mode 100644 src/CMakeCache.txt diff --git a/src/CMakeCache.txt b/src/CMakeCache.txt new file mode 100644 index 0000000000..2f6e2fc4b0 --- /dev/null +++ b/src/CMakeCache.txt @@ -0,0 +1,324 @@ +# This is the CMakeCache file. +# For build in directory: /home/aakatz/gitwd/monad-native/src +# It was generated by CMake: /usr/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a program. +CMAKE_AR:FILEPATH=/usr/bin/ar + +//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or +// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel. +CMAKE_BUILD_TYPE:STRING= + +//Enable/Disable color output during build. +CMAKE_COLOR_MAKEFILE:BOOL=ON + +//CXX compiler. +CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ + +//Flags used by the compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=-g + +//Flags used by the compiler during release minsize builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds (/MD /Ob1 /Oi +// /Ot /Oy /Gs will produce slightly less optimized but smaller +// files). +CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the compiler during Release with Debug Info builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//C compiler. +CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc + +//Flags used by the compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_C_FLAGS_DEBUG:STRING=-g + +//Flags used by the compiler during release minsize builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds (/MD /Ob1 /Oi +// /Ot /Oy /Gs will produce slightly less optimized but smaller +// files). +CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the compiler during Release with Debug Info builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Flags used by the linker. +CMAKE_EXE_LINKER_FLAGS:STRING=' ' + +//Flags used by the linker during debug builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Path to a program. +CMAKE_LINKER:FILEPATH=/usr/bin/ld + +//Path to a program. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make + +//Flags used by the linker during the creation of modules. +CMAKE_MODULE_LINKER_FLAGS:STRING=' ' + +//Flags used by the linker during debug builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/usr/bin/nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=monad_native + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib + +//Flags used by the linker during the creation of dll's. +CMAKE_SHARED_LINKER_FLAGS:STRING=' ' + +//Flags used by the linker during debug builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during debug builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/usr/bin/strip + +//If true, cmake will use relative paths in makefiles and projects. +CMAKE_USE_RELATIVE_PATHS:BOOL=OFF + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Value Computed by CMake +monad_native_BINARY_DIR:STATIC=/home/aakatz/gitwd/monad-native/src + +//Value Computed by CMake +monad_native_SOURCE_DIR:STATIC=/home/aakatz/gitwd/monad-native/src + +//Dependencies for the target +ps_LIB_DEPENDS:STATIC=general;icuuc; + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_BUILD_TOOL +CMAKE_BUILD_TOOL-ADVANCED:INTERNAL=1 +//What is the target build tool cmake is generating for. +CMAKE_BUILD_TOOL:INTERNAL=/usr/bin/make +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/aakatz/gitwd/monad-native/src +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=2 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=8 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=12 +//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE +CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/usr/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER +CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Unix Makefiles +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Have symbol pthread_create +CMAKE_HAVE_LIBC_CREATE:INTERNAL= +//Have library pthreads +CMAKE_HAVE_PTHREADS_CREATE:INTERNAL= +//Have library pthread +CMAKE_HAVE_PTHREAD_CREATE:INTERNAL=1 +//Have include pthread.h +CMAKE_HAVE_PTHREAD_H:INTERNAL=1 +//Start directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/aakatz/gitwd/monad-native/src +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_LOCAL_GENERATORS:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/usr/share/cmake-2.8 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/bin/uname +//ADVANCED property for variable: CMAKE_USE_RELATIVE_PATHS +CMAKE_USE_RELATIVE_PATHS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//Details about finding Threads +FIND_PACKAGE_MESSAGE_DETAILS_Threads:INTERNAL=[TRUE][v()] + diff --git a/src/impl/getcpinfo.cpp b/src/impl/getcpinfo.cpp index c9ea60f3e2..4786327729 100644 --- a/src/impl/getcpinfo.cpp +++ b/src/impl/getcpinfo.cpp @@ -1,19 +1,46 @@ -#include "getcpinfo.h" +//! @file getcpinfo.cpp +//! @author Aaron Ktaz +//! @brief Implements GetCpInfoW Win32 API + #include #include #include +#include "getcpinfo.h" +//! @brief GetCPInfoW retrieves the name of the code page associated with +//! the current thread. +//! +//! GetCpInfoW the Unicode variation. See [MSDN documentation]. +//! +//! @param[in] codepage +//! @parblock +//! An UINT Identifier for the code page for which to retrieve information. +//! See Code Page Identifiers for details +//! +//! @endparblock +//! +//! @param[out] cpinfo +//! @parblock +//! Pointer to a CPINFO structure that receives information about the code page +//! +//! LPCPINFO is a pointer to the structure _cpinfo used to contain the information +//! about a code page +//! +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_INVALID_PARAMETER: parameter is not valid +//! +//! @retval 1 If the function succeeds, the return value is a nonzero +//! value, and cpinfo is population with information about the code page +//! +//! @retval 0 If the function fails, the return value is zero. To get +//! extended error information, call GetLastError. +//! +//! [MSDN documentation]:https://msdn.microsoft.com/en-us/library/windows/desktop/dd318078%28v=vs.85%29.aspx +//! [_cpinfo]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317780%28v=vs.85%29.aspx +//! [CodePageIdentifiers] https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx -// Sets errno to: -// ERROR_INVALID_PARAMETER - parameter is not valid -// ERROR_BAD_ENVIRONMENT - locale is not UTF-8 -// -// Returns: -// TRUE - succeeded -// FALSE - failed - -BOOL GetCPInfoW(UINT codepage, CPINFO &cpinfo) +BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) { const std::string utf8 = "UTF-8"; @@ -31,11 +58,12 @@ BOOL GetCPInfoW(UINT codepage, CPINFO &cpinfo) //if codepage is utf8 if(codepage == 65001) { - cpinfo.DefaultChar[0] = '?'; - cpinfo.DefaultChar[1] = '0'; - cpinfo.LeadByte[0] = '0'; - cpinfo.LeadByte[1] = '0'; - cpinfo.MaxCharSize = 4; + cpinfo->DefaultChar[0] = '?'; + cpinfo->DefaultChar[1] = '0'; + cpinfo->MaxCharSize = 4; + for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ){ + cpinfo->LeadByte[i] = '0'; + } return TRUE; } else diff --git a/src/impl/getcpinfo.h b/src/impl/getcpinfo.h index e1b203bc1c..54a2ebbcdf 100644 --- a/src/impl/getcpinfo.h +++ b/src/impl/getcpinfo.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetCPInfoW(UINT codepage, CPINFO &cpinfo); +BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo); PAL_END_EXTERNC diff --git a/src/impl/pal.h b/src/impl/pal.h index c94422007a..0999c7882c 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -81,7 +81,6 @@ #define ERROR_NO_SUCH_USER 0x00000525 #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 - #define UTF8 65001 #define ERROR_BAD_ENVIRONMENT 0x0000000A typedef unsigned long long uint64; #endif @@ -608,8 +607,8 @@ typedef unsigned char PAL_Boolean; */ namespace const_cpinfo{ - constexpr int MAX_DEFAULTCHAR = 2; - constexpr int MAX_LEADBYTES = 12; + constexpr int MAX_DEFAULTCHAR = 2; + constexpr int MAX_LEADBYTES = 12; } /* diff --git a/src/tests/test-getcpinfo.cpp b/src/tests/test-getcpinfo.cpp index 341c5279d0..90f64deff0 100644 --- a/src/tests/test-getcpinfo.cpp +++ b/src/tests/test-getcpinfo.cpp @@ -1,38 +1,33 @@ +//! @file test-getcpinfo.cpp +//! @author Aaron Ktaz +//! @brief Implements Unit test for GetCPInfoW + #include #include "getcpinfo.h" // This test is with correct parameters TEST(GetCPInfo,Utf8) { - CPINFO cpinfo; - BOOL result = GetCPInfoW(UTF8, cpinfo); + CPINFO* cpinfo; + int UTF8CodePageNumber = 65001; + BOOL result = GetCPInfoW(UTF8CodePageNumber, cpinfo); // first make sure that the function worked - ASSERT_TRUE(result == TRUE); + ASSERT_EQ(result, TRUE); // now compare the actual values - ASSERT_EQ(cpinfo.DefaultChar[0],'?'); - ASSERT_EQ(cpinfo.DefaultChar[1],'0'); - ASSERT_EQ(cpinfo.LeadByte[0],'0'); - ASSERT_EQ(cpinfo.LeadByte[1],'0'); - ASSERT_EQ(cpinfo.MaxCharSize,4); -} - -// This test is with codepage being null -TEST(GetCPInfo, NullForCodePageUINTButNotCpinfo) -{ - CPINFO cpinfo; - BOOL result = GetCPInfoW(NULL, cpinfo); - - ASSERT_TRUE(result == FALSE); - EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); - + ASSERT_EQ(cpinfo->DefaultChar[0],'?'); + ASSERT_EQ(cpinfo->DefaultChar[1],'0'); + ASSERT_EQ(cpinfo->MaxCharSize,4); + for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ){ + ASSERT_EQ(cpinfo->LeadByte[i],'0'); + } } // This test is with codepage not being utf8 TEST(GetCPInfo, CodePageNotUTF8) { - CPINFO cpinfo; + CPINFO* cpinfo; BOOL result = GetCPInfoW(65000, cpinfo); ASSERT_TRUE(result == FALSE); From 53e7c11e6948b0b9b9f9d9fa9d42970c6e9aae1e Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 14 Aug 2015 09:26:45 -0700 Subject: [PATCH 144/298] Added changes based of feedback from Peter --- CMakeCache.txt | 324 +++++++++++++++++++++++++++++++++++++++ impl/getcpinfo.cpp | 60 ++++++-- impl/getcpinfo.h | 2 +- impl/pal.h | 5 +- tests/test-getcpinfo.cpp | 35 ++--- 5 files changed, 386 insertions(+), 40 deletions(-) create mode 100644 CMakeCache.txt diff --git a/CMakeCache.txt b/CMakeCache.txt new file mode 100644 index 0000000000..2f6e2fc4b0 --- /dev/null +++ b/CMakeCache.txt @@ -0,0 +1,324 @@ +# This is the CMakeCache file. +# For build in directory: /home/aakatz/gitwd/monad-native/src +# It was generated by CMake: /usr/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a program. +CMAKE_AR:FILEPATH=/usr/bin/ar + +//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or +// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel. +CMAKE_BUILD_TYPE:STRING= + +//Enable/Disable color output during build. +CMAKE_COLOR_MAKEFILE:BOOL=ON + +//CXX compiler. +CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ + +//Flags used by the compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=-g + +//Flags used by the compiler during release minsize builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds (/MD /Ob1 /Oi +// /Ot /Oy /Gs will produce slightly less optimized but smaller +// files). +CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the compiler during Release with Debug Info builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//C compiler. +CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc + +//Flags used by the compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_C_FLAGS_DEBUG:STRING=-g + +//Flags used by the compiler during release minsize builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds (/MD /Ob1 /Oi +// /Ot /Oy /Gs will produce slightly less optimized but smaller +// files). +CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the compiler during Release with Debug Info builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Flags used by the linker. +CMAKE_EXE_LINKER_FLAGS:STRING=' ' + +//Flags used by the linker during debug builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Path to a program. +CMAKE_LINKER:FILEPATH=/usr/bin/ld + +//Path to a program. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make + +//Flags used by the linker during the creation of modules. +CMAKE_MODULE_LINKER_FLAGS:STRING=' ' + +//Flags used by the linker during debug builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/usr/bin/nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=monad_native + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib + +//Flags used by the linker during the creation of dll's. +CMAKE_SHARED_LINKER_FLAGS:STRING=' ' + +//Flags used by the linker during debug builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during debug builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/usr/bin/strip + +//If true, cmake will use relative paths in makefiles and projects. +CMAKE_USE_RELATIVE_PATHS:BOOL=OFF + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Value Computed by CMake +monad_native_BINARY_DIR:STATIC=/home/aakatz/gitwd/monad-native/src + +//Value Computed by CMake +monad_native_SOURCE_DIR:STATIC=/home/aakatz/gitwd/monad-native/src + +//Dependencies for the target +ps_LIB_DEPENDS:STATIC=general;icuuc; + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_BUILD_TOOL +CMAKE_BUILD_TOOL-ADVANCED:INTERNAL=1 +//What is the target build tool cmake is generating for. +CMAKE_BUILD_TOOL:INTERNAL=/usr/bin/make +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/aakatz/gitwd/monad-native/src +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=2 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=8 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=12 +//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE +CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/usr/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER +CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Unix Makefiles +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Have symbol pthread_create +CMAKE_HAVE_LIBC_CREATE:INTERNAL= +//Have library pthreads +CMAKE_HAVE_PTHREADS_CREATE:INTERNAL= +//Have library pthread +CMAKE_HAVE_PTHREAD_CREATE:INTERNAL=1 +//Have include pthread.h +CMAKE_HAVE_PTHREAD_H:INTERNAL=1 +//Start directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/aakatz/gitwd/monad-native/src +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_LOCAL_GENERATORS:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/usr/share/cmake-2.8 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/bin/uname +//ADVANCED property for variable: CMAKE_USE_RELATIVE_PATHS +CMAKE_USE_RELATIVE_PATHS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//Details about finding Threads +FIND_PACKAGE_MESSAGE_DETAILS_Threads:INTERNAL=[TRUE][v()] + diff --git a/impl/getcpinfo.cpp b/impl/getcpinfo.cpp index c9ea60f3e2..4786327729 100644 --- a/impl/getcpinfo.cpp +++ b/impl/getcpinfo.cpp @@ -1,19 +1,46 @@ -#include "getcpinfo.h" +//! @file getcpinfo.cpp +//! @author Aaron Ktaz +//! @brief Implements GetCpInfoW Win32 API + #include #include #include +#include "getcpinfo.h" +//! @brief GetCPInfoW retrieves the name of the code page associated with +//! the current thread. +//! +//! GetCpInfoW the Unicode variation. See [MSDN documentation]. +//! +//! @param[in] codepage +//! @parblock +//! An UINT Identifier for the code page for which to retrieve information. +//! See Code Page Identifiers for details +//! +//! @endparblock +//! +//! @param[out] cpinfo +//! @parblock +//! Pointer to a CPINFO structure that receives information about the code page +//! +//! LPCPINFO is a pointer to the structure _cpinfo used to contain the information +//! about a code page +//! +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_INVALID_PARAMETER: parameter is not valid +//! +//! @retval 1 If the function succeeds, the return value is a nonzero +//! value, and cpinfo is population with information about the code page +//! +//! @retval 0 If the function fails, the return value is zero. To get +//! extended error information, call GetLastError. +//! +//! [MSDN documentation]:https://msdn.microsoft.com/en-us/library/windows/desktop/dd318078%28v=vs.85%29.aspx +//! [_cpinfo]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317780%28v=vs.85%29.aspx +//! [CodePageIdentifiers] https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx -// Sets errno to: -// ERROR_INVALID_PARAMETER - parameter is not valid -// ERROR_BAD_ENVIRONMENT - locale is not UTF-8 -// -// Returns: -// TRUE - succeeded -// FALSE - failed - -BOOL GetCPInfoW(UINT codepage, CPINFO &cpinfo) +BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) { const std::string utf8 = "UTF-8"; @@ -31,11 +58,12 @@ BOOL GetCPInfoW(UINT codepage, CPINFO &cpinfo) //if codepage is utf8 if(codepage == 65001) { - cpinfo.DefaultChar[0] = '?'; - cpinfo.DefaultChar[1] = '0'; - cpinfo.LeadByte[0] = '0'; - cpinfo.LeadByte[1] = '0'; - cpinfo.MaxCharSize = 4; + cpinfo->DefaultChar[0] = '?'; + cpinfo->DefaultChar[1] = '0'; + cpinfo->MaxCharSize = 4; + for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ){ + cpinfo->LeadByte[i] = '0'; + } return TRUE; } else diff --git a/impl/getcpinfo.h b/impl/getcpinfo.h index e1b203bc1c..54a2ebbcdf 100644 --- a/impl/getcpinfo.h +++ b/impl/getcpinfo.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetCPInfoW(UINT codepage, CPINFO &cpinfo); +BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo); PAL_END_EXTERNC diff --git a/impl/pal.h b/impl/pal.h index c94422007a..0999c7882c 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -81,7 +81,6 @@ #define ERROR_NO_SUCH_USER 0x00000525 #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 - #define UTF8 65001 #define ERROR_BAD_ENVIRONMENT 0x0000000A typedef unsigned long long uint64; #endif @@ -608,8 +607,8 @@ typedef unsigned char PAL_Boolean; */ namespace const_cpinfo{ - constexpr int MAX_DEFAULTCHAR = 2; - constexpr int MAX_LEADBYTES = 12; + constexpr int MAX_DEFAULTCHAR = 2; + constexpr int MAX_LEADBYTES = 12; } /* diff --git a/tests/test-getcpinfo.cpp b/tests/test-getcpinfo.cpp index 341c5279d0..90f64deff0 100644 --- a/tests/test-getcpinfo.cpp +++ b/tests/test-getcpinfo.cpp @@ -1,38 +1,33 @@ +//! @file test-getcpinfo.cpp +//! @author Aaron Ktaz +//! @brief Implements Unit test for GetCPInfoW + #include #include "getcpinfo.h" // This test is with correct parameters TEST(GetCPInfo,Utf8) { - CPINFO cpinfo; - BOOL result = GetCPInfoW(UTF8, cpinfo); + CPINFO* cpinfo; + int UTF8CodePageNumber = 65001; + BOOL result = GetCPInfoW(UTF8CodePageNumber, cpinfo); // first make sure that the function worked - ASSERT_TRUE(result == TRUE); + ASSERT_EQ(result, TRUE); // now compare the actual values - ASSERT_EQ(cpinfo.DefaultChar[0],'?'); - ASSERT_EQ(cpinfo.DefaultChar[1],'0'); - ASSERT_EQ(cpinfo.LeadByte[0],'0'); - ASSERT_EQ(cpinfo.LeadByte[1],'0'); - ASSERT_EQ(cpinfo.MaxCharSize,4); -} - -// This test is with codepage being null -TEST(GetCPInfo, NullForCodePageUINTButNotCpinfo) -{ - CPINFO cpinfo; - BOOL result = GetCPInfoW(NULL, cpinfo); - - ASSERT_TRUE(result == FALSE); - EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); - + ASSERT_EQ(cpinfo->DefaultChar[0],'?'); + ASSERT_EQ(cpinfo->DefaultChar[1],'0'); + ASSERT_EQ(cpinfo->MaxCharSize,4); + for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ){ + ASSERT_EQ(cpinfo->LeadByte[i],'0'); + } } // This test is with codepage not being utf8 TEST(GetCPInfo, CodePageNotUTF8) { - CPINFO cpinfo; + CPINFO* cpinfo; BOOL result = GetCPInfoW(65000, cpinfo); ASSERT_TRUE(result == FALSE); From 1a796b59244b2681965ad5e22586ac3ec3f136bf Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 14 Aug 2015 10:51:25 -0700 Subject: [PATCH 145/298] Changes to make converting beteween UTF8 and UTF16 --- impl/getcomputername.cpp | 44 ++++++++++++++-------------------- tests/test-getcomputername.cpp | 22 +++++++---------- 2 files changed, 26 insertions(+), 40 deletions(-) diff --git a/impl/getcomputername.cpp b/impl/getcomputername.cpp index f930dc890d..03a8cda0e3 100644 --- a/impl/getcomputername.cpp +++ b/impl/getcomputername.cpp @@ -7,10 +7,7 @@ #include #include #include -#include -#include -#include -#include +#include #include "getcomputername.h" //! @brief GetComputerName retrieves the name of the host associated with @@ -51,12 +48,12 @@ //! - ERROR_NO_ASSOCIATION: standard input didn't refer to a terminal //! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code //! -//! @retval 1 If the function succeeds, the return value is a nonzero +//! @retval TRUE If the function succeeds, the return value is a nonzero //! value, and the variable pointed to by lpnSize contains the number //! of TCHARs copied to the buffer specified by lpBuffer, including //! the terminating null character. //! -//! @retval 0 If the function fails, the return value is zero. To get +//! @retval FALSE If the function fails, the return value is zero. To get //! extended error information, call GetLastError. //! //! [MSDN documentation]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724295%28v=vs.85%29.aspx @@ -64,28 +61,27 @@ //! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { - const std::string utf8 = "UTF-8"; errno = 0; // Check parameters if (!lpBuffer || !lpnSize) { errno = ERROR_INVALID_PARAMETER; - return 0; + return FALSE; } // Select locale from environment setlocale(LC_ALL, ""); // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != utf8) + if (nl_langinfo(CODESET) != std::string("UTF-8")) { errno = ERROR_BAD_ENVIRONMENT; - return 0; + return FALSE; } // Get computername from system in a thread-safe manner - std::string computername(HOST_NAME_MAX, '\0'); - int err = gethostname(&computername[0], computername.size()); + std::string computername(HOST_NAME_MAX, 0); + int err = gethostname(&computername[0], computername.length()); // Map errno to Win32 Error Codes if (err != 0) { @@ -114,18 +110,13 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) default: errno = ERROR_INVALID_FUNCTION; } - return 0; + return FALSE; } - // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) - std::basic_string computername16(HOST_NAME_MAX + 1, 0); - icu::UnicodeString computername8(computername.c_str(), "UTF-8"); - int32_t targetSize = computername8.extract(0, computername8.length(), - reinterpret_cast(&computername16[0]), - (computername16.size()-1)*sizeof(char16_t), - "UTF-16LE"); - // Number of characters including null - computername16.resize(targetSize/sizeof(char16_t)+1); + // Convert to UnicodeString + auto computername16 = icu::UnicodeString::fromUTF8(computername.c_str()); + // Terminate string with null + computername16.append('\0'); // Size in WCHARs including null const DWORD size = computername16.length(); @@ -137,13 +128,14 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) // Set lpnSize if buffer is too small to inform user // of necessary size *lpnSize= size; - return 0; + return FALSE; } - // Copy bytes from string to buffer - memcpy(lpBuffer, &computername16[0], size*sizeof(char16_t)); + // Extract string as UTF-16LE to buffer + computername16.extract(0, size, reinterpret_cast(lpBuffer), "UTF-16LE"); + *lpnSize = size; - return 1; + return TRUE; } diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index a566d83ccb..612655c229 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -6,10 +6,7 @@ #include #include #include -#include -#include -#include -#include +#include #include "getcomputername.h" //! Test fixture for GetComputerNameTest @@ -35,7 +32,7 @@ protected: { lpnSize = size; // allocate a DWORD buffer to receive computername - lpBuffer.assign(lpnSize, '\0'); + lpBuffer.assign(lpnSize, 0); result = GetComputerNameW(&lpBuffer[0], &lpnSize); } @@ -49,18 +46,15 @@ protected: //! Sets lpnSize to number of WCHARs including null. ASSERT_EQ(expectedSize, lpnSize); - // setup for conversion from UTF-16LE + // Read lpBuffer into UnicodeString (without null) const char* begin = reinterpret_cast(&lpBuffer[0]); - // multiply to get number of bytes - icu::UnicodeString usercomputer16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); - // username16 length includes null and is number of characters - ASSERT_EQ(expectedSize, usercomputer16.length()); + icu::UnicodeString computername16(begin, (lpnSize-1)*sizeof(UChar), "UTF-16LE"); + ASSERT_EQ(expectedComputerName.length(), computername16.length()); + // Convert to UTF-8 for comparison + std::string computername; + computername16.toUTF8String(computername); - // convert (minus null) to UTF-8 for comparison - std::string computername(lpnSize-1, 0); ASSERT_EQ(expectedComputerName.length(), computername.length()); - usercomputer16.extract(0, computername.length(), - reinterpret_cast(&computername[0]), "UTF-8"); //! Returned computername(after conversion) is what was expected. EXPECT_EQ(expectedComputerName, computername); From df8ab7f662657be1006da90ace47a7eacea3cb3b Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 14 Aug 2015 10:51:25 -0700 Subject: [PATCH 146/298] Changes to make converting beteween UTF8 and UTF16 --- src/impl/getcomputername.cpp | 44 ++++++++++++------------------ src/tests/test-getcomputername.cpp | 22 ++++++--------- 2 files changed, 26 insertions(+), 40 deletions(-) diff --git a/src/impl/getcomputername.cpp b/src/impl/getcomputername.cpp index f930dc890d..03a8cda0e3 100644 --- a/src/impl/getcomputername.cpp +++ b/src/impl/getcomputername.cpp @@ -7,10 +7,7 @@ #include #include #include -#include -#include -#include -#include +#include #include "getcomputername.h" //! @brief GetComputerName retrieves the name of the host associated with @@ -51,12 +48,12 @@ //! - ERROR_NO_ASSOCIATION: standard input didn't refer to a terminal //! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code //! -//! @retval 1 If the function succeeds, the return value is a nonzero +//! @retval TRUE If the function succeeds, the return value is a nonzero //! value, and the variable pointed to by lpnSize contains the number //! of TCHARs copied to the buffer specified by lpBuffer, including //! the terminating null character. //! -//! @retval 0 If the function fails, the return value is zero. To get +//! @retval FALSE If the function fails, the return value is zero. To get //! extended error information, call GetLastError. //! //! [MSDN documentation]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724295%28v=vs.85%29.aspx @@ -64,28 +61,27 @@ //! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { - const std::string utf8 = "UTF-8"; errno = 0; // Check parameters if (!lpBuffer || !lpnSize) { errno = ERROR_INVALID_PARAMETER; - return 0; + return FALSE; } // Select locale from environment setlocale(LC_ALL, ""); // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != utf8) + if (nl_langinfo(CODESET) != std::string("UTF-8")) { errno = ERROR_BAD_ENVIRONMENT; - return 0; + return FALSE; } // Get computername from system in a thread-safe manner - std::string computername(HOST_NAME_MAX, '\0'); - int err = gethostname(&computername[0], computername.size()); + std::string computername(HOST_NAME_MAX, 0); + int err = gethostname(&computername[0], computername.length()); // Map errno to Win32 Error Codes if (err != 0) { @@ -114,18 +110,13 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) default: errno = ERROR_INVALID_FUNCTION; } - return 0; + return FALSE; } - // Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM) - std::basic_string computername16(HOST_NAME_MAX + 1, 0); - icu::UnicodeString computername8(computername.c_str(), "UTF-8"); - int32_t targetSize = computername8.extract(0, computername8.length(), - reinterpret_cast(&computername16[0]), - (computername16.size()-1)*sizeof(char16_t), - "UTF-16LE"); - // Number of characters including null - computername16.resize(targetSize/sizeof(char16_t)+1); + // Convert to UnicodeString + auto computername16 = icu::UnicodeString::fromUTF8(computername.c_str()); + // Terminate string with null + computername16.append('\0'); // Size in WCHARs including null const DWORD size = computername16.length(); @@ -137,13 +128,14 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) // Set lpnSize if buffer is too small to inform user // of necessary size *lpnSize= size; - return 0; + return FALSE; } - // Copy bytes from string to buffer - memcpy(lpBuffer, &computername16[0], size*sizeof(char16_t)); + // Extract string as UTF-16LE to buffer + computername16.extract(0, size, reinterpret_cast(lpBuffer), "UTF-16LE"); + *lpnSize = size; - return 1; + return TRUE; } diff --git a/src/tests/test-getcomputername.cpp b/src/tests/test-getcomputername.cpp index a566d83ccb..612655c229 100644 --- a/src/tests/test-getcomputername.cpp +++ b/src/tests/test-getcomputername.cpp @@ -6,10 +6,7 @@ #include #include #include -#include -#include -#include -#include +#include #include "getcomputername.h" //! Test fixture for GetComputerNameTest @@ -35,7 +32,7 @@ protected: { lpnSize = size; // allocate a DWORD buffer to receive computername - lpBuffer.assign(lpnSize, '\0'); + lpBuffer.assign(lpnSize, 0); result = GetComputerNameW(&lpBuffer[0], &lpnSize); } @@ -49,18 +46,15 @@ protected: //! Sets lpnSize to number of WCHARs including null. ASSERT_EQ(expectedSize, lpnSize); - // setup for conversion from UTF-16LE + // Read lpBuffer into UnicodeString (without null) const char* begin = reinterpret_cast(&lpBuffer[0]); - // multiply to get number of bytes - icu::UnicodeString usercomputer16(begin, lpnSize*sizeof(char16_t), "UTF-16LE"); - // username16 length includes null and is number of characters - ASSERT_EQ(expectedSize, usercomputer16.length()); + icu::UnicodeString computername16(begin, (lpnSize-1)*sizeof(UChar), "UTF-16LE"); + ASSERT_EQ(expectedComputerName.length(), computername16.length()); + // Convert to UTF-8 for comparison + std::string computername; + computername16.toUTF8String(computername); - // convert (minus null) to UTF-8 for comparison - std::string computername(lpnSize-1, 0); ASSERT_EQ(expectedComputerName.length(), computername.length()); - usercomputer16.extract(0, computername.length(), - reinterpret_cast(&computername[0]), "UTF-8"); //! Returned computername(after conversion) is what was expected. EXPECT_EQ(expectedComputerName, computername); From 2241d63a28e7813e210bab4884f05a14b66c3b6a Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 14 Aug 2015 11:27:22 -0700 Subject: [PATCH 147/298] No longer defining LPSTR --- impl/pal.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/impl/pal.h b/impl/pal.h index 17e58d409f..f30903a2f4 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -62,8 +62,6 @@ typedef char *PSTR; typedef void *PVOID; typedef PVOID HANDLE; - typedef char TCHAR; - typedef char* LPTSTR; #define NO_ERROR 0 #define INFINITE 0xFFFFFFFF #define WINAPI From 18e8bb1dfa0d19614fe5db095884b54be70c80ab Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 14 Aug 2015 11:27:22 -0700 Subject: [PATCH 148/298] No longer defining LPSTR --- src/impl/pal.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/impl/pal.h b/src/impl/pal.h index 17e58d409f..f30903a2f4 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -62,8 +62,6 @@ typedef char *PSTR; typedef void *PVOID; typedef PVOID HANDLE; - typedef char TCHAR; - typedef char* LPTSTR; #define NO_ERROR 0 #define INFINITE 0xFFFFFFFF #define WINAPI From d2f7ba1cb48e25f1c877cf0ebb95f737b34599f5 Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 14 Aug 2015 12:26:15 -0700 Subject: [PATCH 149/298] implemented suggested changes based off of feedback --- src/impl/getcpinfo.cpp | 2 +- src/impl/pal.h | 16 ++-------------- src/tests/test-getcpinfo.cpp | 2 +- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/impl/getcpinfo.cpp b/src/impl/getcpinfo.cpp index 4786327729..49e2ce8011 100644 --- a/src/impl/getcpinfo.cpp +++ b/src/impl/getcpinfo.cpp @@ -55,7 +55,7 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) return 0; } - //if codepage is utf8 + // if codepage is utf8 if(codepage == 65001) { cpinfo->DefaultChar[0] = '?'; diff --git a/src/impl/pal.h b/src/impl/pal.h index 0999c7882c..26095179e3 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -598,26 +598,14 @@ typedef unsigned char PAL_Boolean; # define PAL_COUNT(ARR) (sizeof(ARR) / sizeof(ARR[0])) #endif -/* -**============================================================================== -** -** NameSpace -** -**============================================================================== -*/ +//!* NameSpace namespace const_cpinfo{ constexpr int MAX_DEFAULTCHAR = 2; constexpr int MAX_LEADBYTES = 12; } -/* -**============================================================================== -** -** Structs -** -**============================================================================== -*/ +//!* Structs typedef struct _cpinfo { UINT MaxCharSize; diff --git a/src/tests/test-getcpinfo.cpp b/src/tests/test-getcpinfo.cpp index 90f64deff0..582620cdf5 100644 --- a/src/tests/test-getcpinfo.cpp +++ b/src/tests/test-getcpinfo.cpp @@ -30,7 +30,7 @@ TEST(GetCPInfo, CodePageNotUTF8) CPINFO* cpinfo; BOOL result = GetCPInfoW(65000, cpinfo); - ASSERT_TRUE(result == FALSE); + ASSERT_EQ(result, FALSE); EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); } \ No newline at end of file From d7355a0572f86cae3bd2374b1e0e997cafe9b645 Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 14 Aug 2015 12:26:15 -0700 Subject: [PATCH 150/298] implemented suggested changes based off of feedback --- impl/getcpinfo.cpp | 2 +- impl/pal.h | 16 ++-------------- tests/test-getcpinfo.cpp | 2 +- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/impl/getcpinfo.cpp b/impl/getcpinfo.cpp index 4786327729..49e2ce8011 100644 --- a/impl/getcpinfo.cpp +++ b/impl/getcpinfo.cpp @@ -55,7 +55,7 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) return 0; } - //if codepage is utf8 + // if codepage is utf8 if(codepage == 65001) { cpinfo->DefaultChar[0] = '?'; diff --git a/impl/pal.h b/impl/pal.h index 0999c7882c..26095179e3 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -598,26 +598,14 @@ typedef unsigned char PAL_Boolean; # define PAL_COUNT(ARR) (sizeof(ARR) / sizeof(ARR[0])) #endif -/* -**============================================================================== -** -** NameSpace -** -**============================================================================== -*/ +//!* NameSpace namespace const_cpinfo{ constexpr int MAX_DEFAULTCHAR = 2; constexpr int MAX_LEADBYTES = 12; } -/* -**============================================================================== -** -** Structs -** -**============================================================================== -*/ +//!* Structs typedef struct _cpinfo { UINT MaxCharSize; diff --git a/tests/test-getcpinfo.cpp b/tests/test-getcpinfo.cpp index 90f64deff0..582620cdf5 100644 --- a/tests/test-getcpinfo.cpp +++ b/tests/test-getcpinfo.cpp @@ -30,7 +30,7 @@ TEST(GetCPInfo, CodePageNotUTF8) CPINFO* cpinfo; BOOL result = GetCPInfoW(65000, cpinfo); - ASSERT_TRUE(result == FALSE); + ASSERT_EQ(result, FALSE); EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); } \ No newline at end of file From e4fd76b7398ec4657ea014ac7f28a19dbb0077c7 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 17 Aug 2015 17:02:40 -0700 Subject: [PATCH 151/298] Added changed from feedback from Andy --- CMakeLists.txt | 2 +- impl/getcomputername.cpp | 24 +++++------------------ impl/pal.h | 2 ++ tests/test-getcomputername.cpp | 36 +++++++++++++++++++--------------- 4 files changed, 28 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ee935bc3b..d799e590bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ link_directories(${monad_native_BINARY_DIR}) set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp impl/getcomputername.cpp) set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) diff --git a/impl/getcomputername.cpp b/impl/getcomputername.cpp index 03a8cda0e3..364179aa13 100644 --- a/impl/getcomputername.cpp +++ b/impl/getcomputername.cpp @@ -87,26 +87,12 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { switch (errno) { - case EMFILE: - case ENFILE: - errno = ERROR_TOO_MANY_OPEN_FILES; + case EFAULT: + errno = ERROR_INVALID_ADDRESS; break; - case ENXIO: - errno = ERROR_NO_ASSOCIATION; - break; - case ERANGE: - errno = ERROR_INSUFFICIENT_BUFFER; - break; - case ENOENT: - errno = ERROR_NO_SUCH_USER; - break; - case ENOMEM: - errno = ERROR_OUTOFMEMORY; - break; - case ENOTTY: - errno = ERROR_NO_ASSOCIATION; - break; - errno = ERROR_NO_ASSOCIATION; + case ENAMETOOLONG: + errno = ERROR_BUFFER_OVERFLOW; + break; default: errno = ERROR_INVALID_FUNCTION; } diff --git a/impl/pal.h b/impl/pal.h index f30903a2f4..3ef233fd69 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -78,6 +78,8 @@ #define ERROR_NO_SUCH_USER 0x00000525 #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 + #define ERROR_INVALID_ADDRESS 0x1e7 + #define ERROR_BUFFER_OVERFLOW 0x6F typedef unsigned long long uint64; #endif diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index 612655c229..21e8c5382b 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -3,6 +3,7 @@ //! @brief Unit tests for GetComputerNameW #include +#include #include #include #include @@ -21,17 +22,21 @@ protected: //Get expected result from using linux call GetComputerNameTest() - { - char hostname[HOST_NAME_MAX]; - BOOL host = gethostname(hostname, sizeof hostname); - expectedComputerName = hostname; - expectedSize = expectedComputerName.length() + 1; + { + expectedComputerName.resize(HOST_NAME_MAX); + BOOL ret = gethostname(&expectedComputerName[0], expectedComputerName.length()); + EXPECT_EQ(ret, 0); + expectedSize = std::strlen(expectedComputerName.c_str()) + 1; + expectedComputerName.resize(expectedSize - 1); } - + + //! Invokes GetComputerNameW with lpnSize and lpBuffer, saves result. + //! + //! @param size Assigns to lpnSize and allocates lpBuffer with + //! size number of null characters. void TestWithSize(DWORD size) { lpnSize = size; - // allocate a DWORD buffer to receive computername lpBuffer.assign(lpnSize, 0); result = GetComputerNameW(&lpBuffer[0], &lpnSize); } @@ -49,12 +54,11 @@ protected: // Read lpBuffer into UnicodeString (without null) const char* begin = reinterpret_cast(&lpBuffer[0]); icu::UnicodeString computername16(begin, (lpnSize-1)*sizeof(UChar), "UTF-16LE"); - ASSERT_EQ(expectedComputerName.length(), computername16.length()); // Convert to UTF-8 for comparison std::string computername; computername16.toUTF8String(computername); - ASSERT_EQ(expectedComputerName.length(), computername.length()); + ASSERT_EQ(expectedSize, computername.length() + 1); //! Returned computername(after conversion) is what was expected. EXPECT_EQ(expectedComputerName, computername); @@ -64,8 +68,8 @@ protected: { SCOPED_TRACE(""); - // returns 0 on failure - EXPECT_EQ(0, result); + // returns FALSE on failure + EXPECT_EQ(FALSE, result); // sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); @@ -75,14 +79,14 @@ protected: { SCOPED_TRACE(""); - // returns 0 on failure - EXPECT_EQ(0, result); + // returns FALSE on failure + EXPECT_EQ(FALSE, result); // sets errno to ERROR_INSUFFICIENT_BUFFER EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); // sets lpnSize to length of username + null - ASSERT_EQ(expectedComputerName.size()+1, lpnSize); + ASSERT_EQ(expectedSize, lpnSize); } }; @@ -111,14 +115,14 @@ TEST_F(GetComputerNameTest, BufferSizeAsZero) TEST_F(GetComputerNameTest, BufferSizeAsUserNameMinusOne) { // the buffer is also too small - TestWithSize(expectedComputerName.size()-1); + TestWithSize(expectedSize-1); TestInsufficientBuffer(); } TEST_F(GetComputerNameTest, BufferSizeAsUserNamePlusOne) { // the buffer is exactly big enough - TestWithSize(expectedComputerName.size()+1); + TestWithSize(expectedSize+1); TestSuccess(); } From f62c92432b3f86f9f239c78b518cddb811573735 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 17 Aug 2015 17:02:40 -0700 Subject: [PATCH 152/298] Added changed from feedback from Andy --- src/CMakeLists.txt | 2 +- src/impl/getcomputername.cpp | 24 +++++--------------- src/impl/pal.h | 2 ++ src/tests/test-getcomputername.cpp | 36 +++++++++++++++++------------- 4 files changed, 28 insertions(+), 36 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5ee935bc3b..d799e590bc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,7 @@ link_directories(${monad_native_BINARY_DIR}) set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp impl/getcomputername.cpp) set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) diff --git a/src/impl/getcomputername.cpp b/src/impl/getcomputername.cpp index 03a8cda0e3..364179aa13 100644 --- a/src/impl/getcomputername.cpp +++ b/src/impl/getcomputername.cpp @@ -87,26 +87,12 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { switch (errno) { - case EMFILE: - case ENFILE: - errno = ERROR_TOO_MANY_OPEN_FILES; + case EFAULT: + errno = ERROR_INVALID_ADDRESS; break; - case ENXIO: - errno = ERROR_NO_ASSOCIATION; - break; - case ERANGE: - errno = ERROR_INSUFFICIENT_BUFFER; - break; - case ENOENT: - errno = ERROR_NO_SUCH_USER; - break; - case ENOMEM: - errno = ERROR_OUTOFMEMORY; - break; - case ENOTTY: - errno = ERROR_NO_ASSOCIATION; - break; - errno = ERROR_NO_ASSOCIATION; + case ENAMETOOLONG: + errno = ERROR_BUFFER_OVERFLOW; + break; default: errno = ERROR_INVALID_FUNCTION; } diff --git a/src/impl/pal.h b/src/impl/pal.h index f30903a2f4..3ef233fd69 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -78,6 +78,8 @@ #define ERROR_NO_SUCH_USER 0x00000525 #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 + #define ERROR_INVALID_ADDRESS 0x1e7 + #define ERROR_BUFFER_OVERFLOW 0x6F typedef unsigned long long uint64; #endif diff --git a/src/tests/test-getcomputername.cpp b/src/tests/test-getcomputername.cpp index 612655c229..21e8c5382b 100644 --- a/src/tests/test-getcomputername.cpp +++ b/src/tests/test-getcomputername.cpp @@ -3,6 +3,7 @@ //! @brief Unit tests for GetComputerNameW #include +#include #include #include #include @@ -21,17 +22,21 @@ protected: //Get expected result from using linux call GetComputerNameTest() - { - char hostname[HOST_NAME_MAX]; - BOOL host = gethostname(hostname, sizeof hostname); - expectedComputerName = hostname; - expectedSize = expectedComputerName.length() + 1; + { + expectedComputerName.resize(HOST_NAME_MAX); + BOOL ret = gethostname(&expectedComputerName[0], expectedComputerName.length()); + EXPECT_EQ(ret, 0); + expectedSize = std::strlen(expectedComputerName.c_str()) + 1; + expectedComputerName.resize(expectedSize - 1); } - + + //! Invokes GetComputerNameW with lpnSize and lpBuffer, saves result. + //! + //! @param size Assigns to lpnSize and allocates lpBuffer with + //! size number of null characters. void TestWithSize(DWORD size) { lpnSize = size; - // allocate a DWORD buffer to receive computername lpBuffer.assign(lpnSize, 0); result = GetComputerNameW(&lpBuffer[0], &lpnSize); } @@ -49,12 +54,11 @@ protected: // Read lpBuffer into UnicodeString (without null) const char* begin = reinterpret_cast(&lpBuffer[0]); icu::UnicodeString computername16(begin, (lpnSize-1)*sizeof(UChar), "UTF-16LE"); - ASSERT_EQ(expectedComputerName.length(), computername16.length()); // Convert to UTF-8 for comparison std::string computername; computername16.toUTF8String(computername); - ASSERT_EQ(expectedComputerName.length(), computername.length()); + ASSERT_EQ(expectedSize, computername.length() + 1); //! Returned computername(after conversion) is what was expected. EXPECT_EQ(expectedComputerName, computername); @@ -64,8 +68,8 @@ protected: { SCOPED_TRACE(""); - // returns 0 on failure - EXPECT_EQ(0, result); + // returns FALSE on failure + EXPECT_EQ(FALSE, result); // sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); @@ -75,14 +79,14 @@ protected: { SCOPED_TRACE(""); - // returns 0 on failure - EXPECT_EQ(0, result); + // returns FALSE on failure + EXPECT_EQ(FALSE, result); // sets errno to ERROR_INSUFFICIENT_BUFFER EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); // sets lpnSize to length of username + null - ASSERT_EQ(expectedComputerName.size()+1, lpnSize); + ASSERT_EQ(expectedSize, lpnSize); } }; @@ -111,14 +115,14 @@ TEST_F(GetComputerNameTest, BufferSizeAsZero) TEST_F(GetComputerNameTest, BufferSizeAsUserNameMinusOne) { // the buffer is also too small - TestWithSize(expectedComputerName.size()-1); + TestWithSize(expectedSize-1); TestInsufficientBuffer(); } TEST_F(GetComputerNameTest, BufferSizeAsUserNamePlusOne) { // the buffer is exactly big enough - TestWithSize(expectedComputerName.size()+1); + TestWithSize(expectedSize+1); TestSuccess(); } From ca4504ec0a61d474e23c047006b0742e4f238a75 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 20 Aug 2015 14:40:02 -0700 Subject: [PATCH 153/298] changes back on feedback from pull request --- src/impl/getcpinfo.cpp | 74 +++++++++++++++++++++++++++--------- src/impl/pal.h | 1 + src/tests/test-getcpinfo.cpp | 19 ++++----- 3 files changed, 66 insertions(+), 28 deletions(-) diff --git a/src/impl/getcpinfo.cpp b/src/impl/getcpinfo.cpp index 49e2ce8011..09ac0183a0 100644 --- a/src/impl/getcpinfo.cpp +++ b/src/impl/getcpinfo.cpp @@ -16,6 +16,8 @@ //! @parblock //! An UINT Identifier for the code page for which to retrieve information. //! See Code Page Identifiers for details +//! 65001 in the number for UTF8. It is the only valid inpur parameter +//!because Linux and Unix only use UTF8 for codepage //! //! @endparblock //! @@ -26,14 +28,45 @@ //! LPCPINFO is a pointer to the structure _cpinfo used to contain the information //! about a code page //! +//! _cpinfo is a struct that comprises +//! +//! UINT MaxCharSize; +//! Maximum length, in bytes, of a character in the code page. +//! The length can be 1 for a single-byte character set (SBCS), +//! 2 for a double-byte character set (DBCS), or a value larger +//! than 2 for other character set types. The function cannot +//! use the size to distinguish an SBCS or a DBCS from other +//! character sets because of other factors, for example, +//! the use of ISCII or ISO-2022-xx code pages. +//! +//! BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; +//! Default character used when translating character +//! strings to the specific code page. This character is used by +//! the WideCharToMultiByte function if an explicit default +//! character is not specified. The default is usually the "?" +//! character for the code page +//! +//! BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; +//! A fixed-length array of lead byte ranges, for which the number +//! of lead byte ranges is variable. If the code page has no lead +//! bytes, every element of the array is set to NULL. If the code +//! page has lead bytes, the array specifies a starting value and +//! an ending value for each range. Ranges are inclusive, and the +//! maximum number of ranges for any code page is five. The array +//! uses two bytes to describe each range, with two null bytes as +//! a terminator after the last range. +//! +//! MAX_DEFAULTCHAR is an int of size 2 +//! MAX_LEADBYTES is an int of size 12 +//! //! //! @exception errno Passes these errors via errno to GetLastError: //! - ERROR_INVALID_PARAMETER: parameter is not valid //! -//! @retval 1 If the function succeeds, the return value is a nonzero +//! @retval TRUE If the function succeeds, the return value is a nonzero //! value, and cpinfo is population with information about the code page //! -//! @retval 0 If the function fails, the return value is zero. To get +//! @retval FALSE If the function fails, the return value is zero. To get //! extended error information, call GetLastError. //! //! [MSDN documentation]:https://msdn.microsoft.com/en-us/library/windows/desktop/dd318078%28v=vs.85%29.aspx @@ -42,34 +75,37 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) { - - const std::string utf8 = "UTF-8"; - errno = 0; + errno = FALSE; // Select locale from environment setlocale(LC_ALL, ""); + // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != utf8) + if (nl_langinfo(CODESET) != std::string("UTF-8")) { errno = ERROR_BAD_ENVIRONMENT; - return 0; + return FALSE; } - // if codepage is utf8 - if(codepage == 65001) - { - cpinfo->DefaultChar[0] = '?'; - cpinfo->DefaultChar[1] = '0'; - cpinfo->MaxCharSize = 4; - for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ){ - cpinfo->LeadByte[i] = '0'; - } - return TRUE; - } - else + // 65001 is the code page for UTF8, Linux and Unix default it UTF8 + if (codepage != const_cpinfo::UTF8) { + //If other value is used return error because Linux and Unix only used UTF-8 for codepage errno = ERROR_INVALID_PARAMETER; return FALSE; } + + // UTF-8 uses the default char for DefaultChar[0] which is '?' + cpinfo->DefaultChar[0] = '?'; + cpinfo->DefaultChar[1] = '0'; + cpinfo->MaxCharSize = 4; + for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ) + { + // UTF-8 uses the default has no LeadByte as result LeadByte is '0' + cpinfo->LeadByte[i] = '0'; + + } + return TRUE; + } diff --git a/src/impl/pal.h b/src/impl/pal.h index 26095179e3..d07e4c0268 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -603,6 +603,7 @@ typedef unsigned char PAL_Boolean; namespace const_cpinfo{ constexpr int MAX_DEFAULTCHAR = 2; constexpr int MAX_LEADBYTES = 12; + constexpr int UTF8 = 65001; } //!* Structs diff --git a/src/tests/test-getcpinfo.cpp b/src/tests/test-getcpinfo.cpp index 582620cdf5..34c061eb62 100644 --- a/src/tests/test-getcpinfo.cpp +++ b/src/tests/test-getcpinfo.cpp @@ -9,18 +9,19 @@ TEST(GetCPInfo,Utf8) { CPINFO* cpinfo; - int UTF8CodePageNumber = 65001; + int UTF8CodePageNumber = const_cpinfo::UTF8; BOOL result = GetCPInfoW(UTF8CodePageNumber, cpinfo); // first make sure that the function worked - ASSERT_EQ(result, TRUE); + ASSERT_EQ(TRUE, result); // now compare the actual values - ASSERT_EQ(cpinfo->DefaultChar[0],'?'); - ASSERT_EQ(cpinfo->DefaultChar[1],'0'); - ASSERT_EQ(cpinfo->MaxCharSize,4); - for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ){ - ASSERT_EQ(cpinfo->LeadByte[i],'0'); + EXPECT_EQ(cpinfo->DefaultChar[0], '?'); + EXPECT_EQ(cpinfo->DefaultChar[1], '0'); + EXPECT_EQ(cpinfo->MaxCharSize,4); + for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ) + { + EXPECT_EQ(cpinfo->LeadByte[i], '0'); } } @@ -30,7 +31,7 @@ TEST(GetCPInfo, CodePageNotUTF8) CPINFO* cpinfo; BOOL result = GetCPInfoW(65000, cpinfo); - ASSERT_EQ(result, FALSE); - EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); + ASSERT_EQ(FALSE, result); + ASSERT_EQ(errno, ERROR_INVALID_PARAMETER); } \ No newline at end of file From 50f9af1bd3057f82d27bfa0407bd3e6e9fcfd311 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 20 Aug 2015 14:40:02 -0700 Subject: [PATCH 154/298] changes back on feedback from pull request --- impl/getcpinfo.cpp | 74 +++++++++++++++++++++++++++++----------- impl/pal.h | 1 + tests/test-getcpinfo.cpp | 19 ++++++----- 3 files changed, 66 insertions(+), 28 deletions(-) diff --git a/impl/getcpinfo.cpp b/impl/getcpinfo.cpp index 49e2ce8011..09ac0183a0 100644 --- a/impl/getcpinfo.cpp +++ b/impl/getcpinfo.cpp @@ -16,6 +16,8 @@ //! @parblock //! An UINT Identifier for the code page for which to retrieve information. //! See Code Page Identifiers for details +//! 65001 in the number for UTF8. It is the only valid inpur parameter +//!because Linux and Unix only use UTF8 for codepage //! //! @endparblock //! @@ -26,14 +28,45 @@ //! LPCPINFO is a pointer to the structure _cpinfo used to contain the information //! about a code page //! +//! _cpinfo is a struct that comprises +//! +//! UINT MaxCharSize; +//! Maximum length, in bytes, of a character in the code page. +//! The length can be 1 for a single-byte character set (SBCS), +//! 2 for a double-byte character set (DBCS), or a value larger +//! than 2 for other character set types. The function cannot +//! use the size to distinguish an SBCS or a DBCS from other +//! character sets because of other factors, for example, +//! the use of ISCII or ISO-2022-xx code pages. +//! +//! BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; +//! Default character used when translating character +//! strings to the specific code page. This character is used by +//! the WideCharToMultiByte function if an explicit default +//! character is not specified. The default is usually the "?" +//! character for the code page +//! +//! BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; +//! A fixed-length array of lead byte ranges, for which the number +//! of lead byte ranges is variable. If the code page has no lead +//! bytes, every element of the array is set to NULL. If the code +//! page has lead bytes, the array specifies a starting value and +//! an ending value for each range. Ranges are inclusive, and the +//! maximum number of ranges for any code page is five. The array +//! uses two bytes to describe each range, with two null bytes as +//! a terminator after the last range. +//! +//! MAX_DEFAULTCHAR is an int of size 2 +//! MAX_LEADBYTES is an int of size 12 +//! //! //! @exception errno Passes these errors via errno to GetLastError: //! - ERROR_INVALID_PARAMETER: parameter is not valid //! -//! @retval 1 If the function succeeds, the return value is a nonzero +//! @retval TRUE If the function succeeds, the return value is a nonzero //! value, and cpinfo is population with information about the code page //! -//! @retval 0 If the function fails, the return value is zero. To get +//! @retval FALSE If the function fails, the return value is zero. To get //! extended error information, call GetLastError. //! //! [MSDN documentation]:https://msdn.microsoft.com/en-us/library/windows/desktop/dd318078%28v=vs.85%29.aspx @@ -42,34 +75,37 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) { - - const std::string utf8 = "UTF-8"; - errno = 0; + errno = FALSE; // Select locale from environment setlocale(LC_ALL, ""); + // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != utf8) + if (nl_langinfo(CODESET) != std::string("UTF-8")) { errno = ERROR_BAD_ENVIRONMENT; - return 0; + return FALSE; } - // if codepage is utf8 - if(codepage == 65001) - { - cpinfo->DefaultChar[0] = '?'; - cpinfo->DefaultChar[1] = '0'; - cpinfo->MaxCharSize = 4; - for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ){ - cpinfo->LeadByte[i] = '0'; - } - return TRUE; - } - else + // 65001 is the code page for UTF8, Linux and Unix default it UTF8 + if (codepage != const_cpinfo::UTF8) { + //If other value is used return error because Linux and Unix only used UTF-8 for codepage errno = ERROR_INVALID_PARAMETER; return FALSE; } + + // UTF-8 uses the default char for DefaultChar[0] which is '?' + cpinfo->DefaultChar[0] = '?'; + cpinfo->DefaultChar[1] = '0'; + cpinfo->MaxCharSize = 4; + for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ) + { + // UTF-8 uses the default has no LeadByte as result LeadByte is '0' + cpinfo->LeadByte[i] = '0'; + + } + return TRUE; + } diff --git a/impl/pal.h b/impl/pal.h index 26095179e3..d07e4c0268 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -603,6 +603,7 @@ typedef unsigned char PAL_Boolean; namespace const_cpinfo{ constexpr int MAX_DEFAULTCHAR = 2; constexpr int MAX_LEADBYTES = 12; + constexpr int UTF8 = 65001; } //!* Structs diff --git a/tests/test-getcpinfo.cpp b/tests/test-getcpinfo.cpp index 582620cdf5..34c061eb62 100644 --- a/tests/test-getcpinfo.cpp +++ b/tests/test-getcpinfo.cpp @@ -9,18 +9,19 @@ TEST(GetCPInfo,Utf8) { CPINFO* cpinfo; - int UTF8CodePageNumber = 65001; + int UTF8CodePageNumber = const_cpinfo::UTF8; BOOL result = GetCPInfoW(UTF8CodePageNumber, cpinfo); // first make sure that the function worked - ASSERT_EQ(result, TRUE); + ASSERT_EQ(TRUE, result); // now compare the actual values - ASSERT_EQ(cpinfo->DefaultChar[0],'?'); - ASSERT_EQ(cpinfo->DefaultChar[1],'0'); - ASSERT_EQ(cpinfo->MaxCharSize,4); - for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ){ - ASSERT_EQ(cpinfo->LeadByte[i],'0'); + EXPECT_EQ(cpinfo->DefaultChar[0], '?'); + EXPECT_EQ(cpinfo->DefaultChar[1], '0'); + EXPECT_EQ(cpinfo->MaxCharSize,4); + for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ) + { + EXPECT_EQ(cpinfo->LeadByte[i], '0'); } } @@ -30,7 +31,7 @@ TEST(GetCPInfo, CodePageNotUTF8) CPINFO* cpinfo; BOOL result = GetCPInfoW(65000, cpinfo); - ASSERT_EQ(result, FALSE); - EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); + ASSERT_EQ(FALSE, result); + ASSERT_EQ(errno, ERROR_INVALID_PARAMETER); } \ No newline at end of file From 23ad440cfc5d6cd6f7bce5b93bed616d16ba1854 Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 21 Aug 2015 09:55:39 -0700 Subject: [PATCH 155/298] made changes based on feedback from pull request --- impl/getcomputername.cpp | 2 +- impl/pal.h | 4 ++-- tests/test-getcomputername.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/impl/getcomputername.cpp b/impl/getcomputername.cpp index 364179aa13..818623ddfe 100644 --- a/impl/getcomputername.cpp +++ b/impl/getcomputername.cpp @@ -91,7 +91,7 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) errno = ERROR_INVALID_ADDRESS; break; case ENAMETOOLONG: - errno = ERROR_BUFFER_OVERFLOW; + errno = ERROR_GEN_FAILURE; break; default: errno = ERROR_INVALID_FUNCTION; diff --git a/impl/pal.h b/impl/pal.h index 3ef233fd69..8bf54dbce8 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -78,8 +78,8 @@ #define ERROR_NO_SUCH_USER 0x00000525 #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 - #define ERROR_INVALID_ADDRESS 0x1e7 - #define ERROR_BUFFER_OVERFLOW 0x6F + #define ERROR_INVALID_ADDRESS 0x000001e7 + #define ERROR_GEN_FAILURE 0x0000001F typedef unsigned long long uint64; #endif diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index 21e8c5382b..51ebd0cccf 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -25,7 +25,7 @@ protected: { expectedComputerName.resize(HOST_NAME_MAX); BOOL ret = gethostname(&expectedComputerName[0], expectedComputerName.length()); - EXPECT_EQ(ret, 0); + EXPECT_EQ(0, ret); expectedSize = std::strlen(expectedComputerName.c_str()) + 1; expectedComputerName.resize(expectedSize - 1); } From e1d4d14028f9f6e0ee846388220883a1ab65b2cc Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 21 Aug 2015 09:55:39 -0700 Subject: [PATCH 156/298] made changes based on feedback from pull request --- src/impl/getcomputername.cpp | 2 +- src/impl/pal.h | 4 ++-- src/tests/test-getcomputername.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/impl/getcomputername.cpp b/src/impl/getcomputername.cpp index 364179aa13..818623ddfe 100644 --- a/src/impl/getcomputername.cpp +++ b/src/impl/getcomputername.cpp @@ -91,7 +91,7 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) errno = ERROR_INVALID_ADDRESS; break; case ENAMETOOLONG: - errno = ERROR_BUFFER_OVERFLOW; + errno = ERROR_GEN_FAILURE; break; default: errno = ERROR_INVALID_FUNCTION; diff --git a/src/impl/pal.h b/src/impl/pal.h index 3ef233fd69..8bf54dbce8 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -78,8 +78,8 @@ #define ERROR_NO_SUCH_USER 0x00000525 #define ERROR_INVALID_FUNCTION 0x00000001 #define MAX_PATH 0x00000104 - #define ERROR_INVALID_ADDRESS 0x1e7 - #define ERROR_BUFFER_OVERFLOW 0x6F + #define ERROR_INVALID_ADDRESS 0x000001e7 + #define ERROR_GEN_FAILURE 0x0000001F typedef unsigned long long uint64; #endif diff --git a/src/tests/test-getcomputername.cpp b/src/tests/test-getcomputername.cpp index 21e8c5382b..51ebd0cccf 100644 --- a/src/tests/test-getcomputername.cpp +++ b/src/tests/test-getcomputername.cpp @@ -25,7 +25,7 @@ protected: { expectedComputerName.resize(HOST_NAME_MAX); BOOL ret = gethostname(&expectedComputerName[0], expectedComputerName.length()); - EXPECT_EQ(ret, 0); + EXPECT_EQ(0, ret); expectedSize = std::strlen(expectedComputerName.c_str()) + 1; expectedComputerName.resize(expectedSize - 1); } From 24f0f853a8319f21d7082cb847d3ec069fedb51d Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Wed, 29 Jul 2015 15:04:34 +0200 Subject: [PATCH 157/298] added testing code to call into Main --- host/cmdline/main.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 740d99185c..7ae1936ffe 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -410,6 +410,13 @@ int main(int argc, char** argv) } loaderDelegate(psBasePath16.c_str()); + // NOTE: + // this code is intended for testing purposes only, it calls into the Main + // function of the powershell-simple.exe assembly, because that's what would + // be nice to have. + unsigned int exitCode2; + executeAssembly(hostHandle,domainId,args.argc,(const char**)args.argv,(currentDirAbsolutePath+"/powershell-simple.exe").c_str(),&exitCode2); + // call the unmanaged entry point for PowerShell typedef int (*UnmanagedMain)(int argc, char const* const* argv); UnmanagedMain unmanagedMain = nullptr; From 4ffb564dbd2e4308ae0d62fecbf96f042c64008e Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Wed, 29 Jul 2015 15:04:34 +0200 Subject: [PATCH 158/298] added testing code to call into Main --- src/host/cmdline/main.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 740d99185c..7ae1936ffe 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -410,6 +410,13 @@ int main(int argc, char** argv) } loaderDelegate(psBasePath16.c_str()); + // NOTE: + // this code is intended for testing purposes only, it calls into the Main + // function of the powershell-simple.exe assembly, because that's what would + // be nice to have. + unsigned int exitCode2; + executeAssembly(hostHandle,domainId,args.argc,(const char**)args.argv,(currentDirAbsolutePath+"/powershell-simple.exe").c_str(),&exitCode2); + // call the unmanaged entry point for PowerShell typedef int (*UnmanagedMain)(int argc, char const* const* argv); UnmanagedMain unmanagedMain = nullptr; From 46d3894c02983774df8948e858606283de5c6d01 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 21 Aug 2015 16:17:16 -0700 Subject: [PATCH 159/298] Call into Main of PowerShell assembly Instead of UnmanagedMain. Requires patch to CoreCLR (submitted upstream but backported until we've integrated their work). --- host/cmdline/main.cpp | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 7ae1936ffe..0c05453771 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -410,30 +410,12 @@ int main(int argc, char** argv) } loaderDelegate(psBasePath16.c_str()); - // NOTE: - // this code is intended for testing purposes only, it calls into the Main - // function of the powershell-simple.exe assembly, because that's what would - // be nice to have. - unsigned int exitCode2; - executeAssembly(hostHandle,domainId,args.argc,(const char**)args.argv,(currentDirAbsolutePath+"/powershell-simple.exe").c_str(),&exitCode2); - - // call the unmanaged entry point for PowerShell - typedef int (*UnmanagedMain)(int argc, char const* const* argv); - UnmanagedMain unmanagedMain = nullptr; - status = createDelegate( - hostHandle, - domainId, - args.entryAssemblyName.c_str(), - args.entryTypeName.c_str(), - args.entryFunctionName.c_str(), - (void**)&unmanagedMain); - if (0 > status) - { - std::cerr << "could not create delegate for UnmanagedMain - status: " << std::hex << status << std::endl; - return 4; - } - - int exitCode = unmanagedMain(args.argc,args.argv); + // call into Main of powershell-simple.exe + unsigned int exitCode; + executeAssembly(hostHandle, domainId, args.argc, + (const char**)args.argv, + (currentDirAbsolutePath+"/powershell-simple.exe").c_str(), + &exitCode); // shutdown CoreCLR status = shutdownCoreCLR(hostHandle,domainId); From 5d117330a8a68349bbfce088653e833ceea877f9 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 21 Aug 2015 16:17:16 -0700 Subject: [PATCH 160/298] Call into Main of PowerShell assembly Instead of UnmanagedMain. Requires patch to CoreCLR (submitted upstream but backported until we've integrated their work). --- src/host/cmdline/main.cpp | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 7ae1936ffe..0c05453771 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -410,30 +410,12 @@ int main(int argc, char** argv) } loaderDelegate(psBasePath16.c_str()); - // NOTE: - // this code is intended for testing purposes only, it calls into the Main - // function of the powershell-simple.exe assembly, because that's what would - // be nice to have. - unsigned int exitCode2; - executeAssembly(hostHandle,domainId,args.argc,(const char**)args.argv,(currentDirAbsolutePath+"/powershell-simple.exe").c_str(),&exitCode2); - - // call the unmanaged entry point for PowerShell - typedef int (*UnmanagedMain)(int argc, char const* const* argv); - UnmanagedMain unmanagedMain = nullptr; - status = createDelegate( - hostHandle, - domainId, - args.entryAssemblyName.c_str(), - args.entryTypeName.c_str(), - args.entryFunctionName.c_str(), - (void**)&unmanagedMain); - if (0 > status) - { - std::cerr << "could not create delegate for UnmanagedMain - status: " << std::hex << status << std::endl; - return 4; - } - - int exitCode = unmanagedMain(args.argc,args.argv); + // call into Main of powershell-simple.exe + unsigned int exitCode; + executeAssembly(hostHandle, domainId, args.argc, + (const char**)args.argv, + (currentDirAbsolutePath+"/powershell-simple.exe").c_str(), + &exitCode); // shutdown CoreCLR status = shutdownCoreCLR(hostHandle,domainId); From 42ce3fa48bb6186876cc563e86c24998a1084657 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 21 Aug 2015 17:39:52 -0700 Subject: [PATCH 161/298] Remove type_name and function_name from host Custom hosting code was refactored to take a path to an assembly instead of an assembly name coupled with a type and function to execute. Instead, the host now directly executes the given assembly, calling its Main function. The path is resolved relative to the current directory, as should be expected. --- host/cmdline/main.cpp | 49 ++++++++++++------------------------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 0c05453771..7cc4637cee 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -16,7 +16,7 @@ void printHelp() { std::cerr << "PS CoreCLR host" << std::endl; std::cerr << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl; - std::cerr << " [-b base_path] assembly_name type_name function_name [...]" << std::endl; + std::cerr << " [-b base_path] assembly [...]" << std::endl; std::cerr << std::endl; std::cerr << "What it does:" << std::endl; std::cerr << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl; @@ -28,8 +28,8 @@ void printHelp() std::cerr << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl; std::cerr << " be provided with the -alc command line argument" << std::endl; std::cerr << "- all additional parameters at the end of the command line are forwarded" << std::endl; - std::cerr << " to the specified entry function in the assembly" << std::endl; - std::cerr << "- the host will execute the specified entry function in the specified assembly" << std::endl; + std::cerr << " to the Main function in the assembly" << std::endl; + std::cerr << "- the host will execute the Main function in the specified assembly" << std::endl; std::cerr << " + this assembly has to be located in the search path" << std::endl; std::cerr << "- by default the host will add the current working directory to the assembly search path" << std::endl; std::cerr << " + this can be overridden with the -s command line argument" << std::endl; @@ -37,8 +37,8 @@ void printHelp() std::cerr << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl; std::cerr << " working directory" << std::endl; std::cerr << " + this can be overridden with the -b command line argument" << std::endl; - std::cerr << "- the function signature of the function that gets executed must be:" << std::endl; - std::cerr << " public static int UnmanagedMain(int argc, [MarshalAs(UnmanagedType.LPArray,ArraySubType=UnmanagedType.LPStr,SizeParamIndex=0)] String[] argv)" << std::endl; + std::cerr << "- the function signature of the Main function that gets executed must be:" << std::endl; + std::cerr << " static void Main(string[] args)" << std::endl; std::cerr << std::endl; std::cerr << "Options:" << std::endl; std::cerr << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl; @@ -50,13 +50,10 @@ void printHelp() std::cerr << " separated by :" << std::endl; std::cerr << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl; std::cerr << " argument, must always be added to the TPA list with this parameter" << std::endl; - std::cerr << "assembly_name the assembly name of the assembly to execute" << std::endl; - std::cerr << " must be available in the search path" << std::endl; - std::cerr << "type_name the type name where the function can be found" << std::endl; - std::cerr << "function_name the function to execute (must have the function signature described above!)" << std::endl; + std::cerr << "assembly the path of the assembly to execute relative to current directory" << std::endl; std::cerr << std::endl; std::cerr << "Example:" << std::endl; - std::cerr << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'ps_hello_world.Program' 'UnmanagedMain' 'get-process'" << std::endl; + std::cerr << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; } struct Args @@ -73,9 +70,7 @@ struct Args std::string searchPaths; std::string basePath; std::string tpaList; - std::string entryAssemblyName; - std::string entryTypeName; - std::string entryFunctionName; + std::string entryAssemblyPath; int argc; char** argv; bool verbose; @@ -88,9 +83,7 @@ struct Args std::cerr << "- searchPaths " << searchPaths << std::endl; std::cerr << "- basePath " << basePath << std::endl; std::cerr << "- tpaList " << tpaList << std::endl; - std::cerr << "- entryAssemblyName " << entryAssemblyName << std::endl; - std::cerr << "- entryTypeName " << entryTypeName << std::endl; - std::cerr << "- entryFunctionName " << entryFunctionName << std::endl; + std::cerr << "- entryAssemblyPath " << entryAssemblyPath << std::endl; std::cerr << "- argc " << argc << std::endl; std::cerr << "- verbose " << (verbose ? "true" : "false") << std::endl; } @@ -141,17 +134,9 @@ bool parseCmdline(const int argc, char** argv, Args& args) { args.verbose = true; } - else if (args.entryAssemblyName == "") + else if (args.entryAssemblyPath == "") { - args.entryAssemblyName = arg; - } - else if (args.entryTypeName == "") - { - args.entryTypeName = arg; - } - else if (args.entryFunctionName == "") - { - args.entryFunctionName = arg; + args.entryAssemblyPath = arg; } else { @@ -165,18 +150,10 @@ bool parseCmdline(const int argc, char** argv, Args& args) } // check for mandatory parameters - if (args.entryAssemblyName == "") + if (args.entryAssemblyPath == "") { std::cerr << "error: assembly_name argument missing" << std::endl; } - if (args.entryTypeName == "") - { - std::cerr << "error: type_name argument missing" << std::endl; - } - if (args.entryFunctionName == "") - { - std::cerr << "error: function_name argument missing" << std::endl; - } return true; } @@ -414,7 +391,7 @@ int main(int argc, char** argv) unsigned int exitCode; executeAssembly(hostHandle, domainId, args.argc, (const char**)args.argv, - (currentDirAbsolutePath+"/powershell-simple.exe").c_str(), + (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), &exitCode); // shutdown CoreCLR From 440cf6a236067eba2d5dcfd5e3707a36295cee97 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 21 Aug 2015 17:39:52 -0700 Subject: [PATCH 162/298] Remove type_name and function_name from host Custom hosting code was refactored to take a path to an assembly instead of an assembly name coupled with a type and function to execute. Instead, the host now directly executes the given assembly, calling its Main function. The path is resolved relative to the current directory, as should be expected. --- src/host/cmdline/main.cpp | 49 +++++++++++---------------------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 0c05453771..7cc4637cee 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -16,7 +16,7 @@ void printHelp() { std::cerr << "PS CoreCLR host" << std::endl; std::cerr << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl; - std::cerr << " [-b base_path] assembly_name type_name function_name [...]" << std::endl; + std::cerr << " [-b base_path] assembly [...]" << std::endl; std::cerr << std::endl; std::cerr << "What it does:" << std::endl; std::cerr << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl; @@ -28,8 +28,8 @@ void printHelp() std::cerr << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl; std::cerr << " be provided with the -alc command line argument" << std::endl; std::cerr << "- all additional parameters at the end of the command line are forwarded" << std::endl; - std::cerr << " to the specified entry function in the assembly" << std::endl; - std::cerr << "- the host will execute the specified entry function in the specified assembly" << std::endl; + std::cerr << " to the Main function in the assembly" << std::endl; + std::cerr << "- the host will execute the Main function in the specified assembly" << std::endl; std::cerr << " + this assembly has to be located in the search path" << std::endl; std::cerr << "- by default the host will add the current working directory to the assembly search path" << std::endl; std::cerr << " + this can be overridden with the -s command line argument" << std::endl; @@ -37,8 +37,8 @@ void printHelp() std::cerr << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl; std::cerr << " working directory" << std::endl; std::cerr << " + this can be overridden with the -b command line argument" << std::endl; - std::cerr << "- the function signature of the function that gets executed must be:" << std::endl; - std::cerr << " public static int UnmanagedMain(int argc, [MarshalAs(UnmanagedType.LPArray,ArraySubType=UnmanagedType.LPStr,SizeParamIndex=0)] String[] argv)" << std::endl; + std::cerr << "- the function signature of the Main function that gets executed must be:" << std::endl; + std::cerr << " static void Main(string[] args)" << std::endl; std::cerr << std::endl; std::cerr << "Options:" << std::endl; std::cerr << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl; @@ -50,13 +50,10 @@ void printHelp() std::cerr << " separated by :" << std::endl; std::cerr << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl; std::cerr << " argument, must always be added to the TPA list with this parameter" << std::endl; - std::cerr << "assembly_name the assembly name of the assembly to execute" << std::endl; - std::cerr << " must be available in the search path" << std::endl; - std::cerr << "type_name the type name where the function can be found" << std::endl; - std::cerr << "function_name the function to execute (must have the function signature described above!)" << std::endl; + std::cerr << "assembly the path of the assembly to execute relative to current directory" << std::endl; std::cerr << std::endl; std::cerr << "Example:" << std::endl; - std::cerr << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'ps_hello_world.Program' 'UnmanagedMain' 'get-process'" << std::endl; + std::cerr << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; } struct Args @@ -73,9 +70,7 @@ struct Args std::string searchPaths; std::string basePath; std::string tpaList; - std::string entryAssemblyName; - std::string entryTypeName; - std::string entryFunctionName; + std::string entryAssemblyPath; int argc; char** argv; bool verbose; @@ -88,9 +83,7 @@ struct Args std::cerr << "- searchPaths " << searchPaths << std::endl; std::cerr << "- basePath " << basePath << std::endl; std::cerr << "- tpaList " << tpaList << std::endl; - std::cerr << "- entryAssemblyName " << entryAssemblyName << std::endl; - std::cerr << "- entryTypeName " << entryTypeName << std::endl; - std::cerr << "- entryFunctionName " << entryFunctionName << std::endl; + std::cerr << "- entryAssemblyPath " << entryAssemblyPath << std::endl; std::cerr << "- argc " << argc << std::endl; std::cerr << "- verbose " << (verbose ? "true" : "false") << std::endl; } @@ -141,17 +134,9 @@ bool parseCmdline(const int argc, char** argv, Args& args) { args.verbose = true; } - else if (args.entryAssemblyName == "") + else if (args.entryAssemblyPath == "") { - args.entryAssemblyName = arg; - } - else if (args.entryTypeName == "") - { - args.entryTypeName = arg; - } - else if (args.entryFunctionName == "") - { - args.entryFunctionName = arg; + args.entryAssemblyPath = arg; } else { @@ -165,18 +150,10 @@ bool parseCmdline(const int argc, char** argv, Args& args) } // check for mandatory parameters - if (args.entryAssemblyName == "") + if (args.entryAssemblyPath == "") { std::cerr << "error: assembly_name argument missing" << std::endl; } - if (args.entryTypeName == "") - { - std::cerr << "error: type_name argument missing" << std::endl; - } - if (args.entryFunctionName == "") - { - std::cerr << "error: function_name argument missing" << std::endl; - } return true; } @@ -414,7 +391,7 @@ int main(int argc, char** argv) unsigned int exitCode; executeAssembly(hostHandle, domainId, args.argc, (const char**)args.argv, - (currentDirAbsolutePath+"/powershell-simple.exe").c_str(), + (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), &exitCode); // shutdown CoreCLR From c9164d5401eb970672fbf40f0b0a02f421803806 Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 25 Aug 2015 13:47:39 -0700 Subject: [PATCH 163/298] made changes based on feedback from pull request --- src/tests/test-getcpinfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/test-getcpinfo.cpp b/src/tests/test-getcpinfo.cpp index 34c061eb62..108819d9bb 100644 --- a/src/tests/test-getcpinfo.cpp +++ b/src/tests/test-getcpinfo.cpp @@ -19,7 +19,7 @@ TEST(GetCPInfo,Utf8) EXPECT_EQ(cpinfo->DefaultChar[0], '?'); EXPECT_EQ(cpinfo->DefaultChar[1], '0'); EXPECT_EQ(cpinfo->MaxCharSize,4); - for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ) + for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++) { EXPECT_EQ(cpinfo->LeadByte[i], '0'); } @@ -32,6 +32,6 @@ TEST(GetCPInfo, CodePageNotUTF8) BOOL result = GetCPInfoW(65000, cpinfo); ASSERT_EQ(FALSE, result); - ASSERT_EQ(errno, ERROR_INVALID_PARAMETER); + ASSERT_EQ(ERROR_INVALID_PARAMETER, errno); } \ No newline at end of file From 8080e537869f4bac317850757ba0d4307e46390b Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 25 Aug 2015 13:47:39 -0700 Subject: [PATCH 164/298] made changes based on feedback from pull request --- tests/test-getcpinfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test-getcpinfo.cpp b/tests/test-getcpinfo.cpp index 34c061eb62..108819d9bb 100644 --- a/tests/test-getcpinfo.cpp +++ b/tests/test-getcpinfo.cpp @@ -19,7 +19,7 @@ TEST(GetCPInfo,Utf8) EXPECT_EQ(cpinfo->DefaultChar[0], '?'); EXPECT_EQ(cpinfo->DefaultChar[1], '0'); EXPECT_EQ(cpinfo->MaxCharSize,4); - for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ) + for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++) { EXPECT_EQ(cpinfo->LeadByte[i], '0'); } @@ -32,6 +32,6 @@ TEST(GetCPInfo, CodePageNotUTF8) BOOL result = GetCPInfoW(65000, cpinfo); ASSERT_EQ(FALSE, result); - ASSERT_EQ(errno, ERROR_INVALID_PARAMETER); + ASSERT_EQ(ERROR_INVALID_PARAMETER, errno); } \ No newline at end of file From 95060b345f4ea58d121029f4dc28606c5aaf8fbb Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 26 Aug 2015 11:55:58 -0700 Subject: [PATCH 165/298] Merge Conflict --- src/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2a4779bfbc..003c9b9854 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,7 +15,6 @@ set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername. set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) - # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) From b6d880eab8941889af4e217ce502f3bada850c3b Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 26 Aug 2015 11:55:58 -0700 Subject: [PATCH 166/298] Merge Conflict --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a4779bfbc..003c9b9854 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,6 @@ set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername. set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) - # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) From 5d59019d01e68a698cf6631a2a85c8b671b7cd3e Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 26 Aug 2015 13:03:51 -0700 Subject: [PATCH 167/298] Get rid of merge conflict --- src/impl/pal.h | 6 +++--- src/tests/test-getcpinfo.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/impl/pal.h b/src/impl/pal.h index 4947c1cac0..0bb04f05aa 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -601,9 +601,9 @@ typedef unsigned char PAL_Boolean; //!* NameSpace namespace const_cpinfo{ - constexpr int MAX_DEFAULTCHAR = 2; - constexpr int MAX_LEADBYTES = 12; - constexpr int UTF8 = 65001; + constexpr int MAX_DEFAULTCHAR = 2; + constexpr int MAX_LEADBYTES = 12; + constexpr int UTF8 = 65001; } //!* Structs diff --git a/src/tests/test-getcpinfo.cpp b/src/tests/test-getcpinfo.cpp index 108819d9bb..3ec7596456 100644 --- a/src/tests/test-getcpinfo.cpp +++ b/src/tests/test-getcpinfo.cpp @@ -19,7 +19,7 @@ TEST(GetCPInfo,Utf8) EXPECT_EQ(cpinfo->DefaultChar[0], '?'); EXPECT_EQ(cpinfo->DefaultChar[1], '0'); EXPECT_EQ(cpinfo->MaxCharSize,4); - for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++) + for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++) { EXPECT_EQ(cpinfo->LeadByte[i], '0'); } From 47628205193de763939de7ac289b0c1b5b96364d Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 26 Aug 2015 13:03:51 -0700 Subject: [PATCH 168/298] Get rid of merge conflict --- impl/pal.h | 6 +++--- tests/test-getcpinfo.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/impl/pal.h b/impl/pal.h index 4947c1cac0..0bb04f05aa 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -601,9 +601,9 @@ typedef unsigned char PAL_Boolean; //!* NameSpace namespace const_cpinfo{ - constexpr int MAX_DEFAULTCHAR = 2; - constexpr int MAX_LEADBYTES = 12; - constexpr int UTF8 = 65001; + constexpr int MAX_DEFAULTCHAR = 2; + constexpr int MAX_LEADBYTES = 12; + constexpr int UTF8 = 65001; } //!* Structs diff --git a/tests/test-getcpinfo.cpp b/tests/test-getcpinfo.cpp index 108819d9bb..3ec7596456 100644 --- a/tests/test-getcpinfo.cpp +++ b/tests/test-getcpinfo.cpp @@ -19,7 +19,7 @@ TEST(GetCPInfo,Utf8) EXPECT_EQ(cpinfo->DefaultChar[0], '?'); EXPECT_EQ(cpinfo->DefaultChar[1], '0'); EXPECT_EQ(cpinfo->MaxCharSize,4); - for(int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++) + for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++) { EXPECT_EQ(cpinfo->LeadByte[i], '0'); } From a7c773ec8ee73f2723dd1bc5e24fbdc439472d75 Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 26 Aug 2015 13:28:51 -0700 Subject: [PATCH 169/298] Merge Conflict --- src/impl/pal.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/impl/pal.h b/src/impl/pal.h index 0bb04f05aa..8a27636008 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -600,7 +600,8 @@ typedef unsigned char PAL_Boolean; //!* NameSpace -namespace const_cpinfo{ +namespace const_cpinfo +{ constexpr int MAX_DEFAULTCHAR = 2; constexpr int MAX_LEADBYTES = 12; constexpr int UTF8 = 65001; @@ -608,7 +609,8 @@ namespace const_cpinfo{ //!* Structs -typedef struct _cpinfo { +typedef struct _cpinfo +{ UINT MaxCharSize; BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; From f32441327dd034567a6aaa6a037bb3b934c28aa3 Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 26 Aug 2015 13:28:51 -0700 Subject: [PATCH 170/298] Merge Conflict --- impl/pal.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/impl/pal.h b/impl/pal.h index 0bb04f05aa..8a27636008 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -600,7 +600,8 @@ typedef unsigned char PAL_Boolean; //!* NameSpace -namespace const_cpinfo{ +namespace const_cpinfo +{ constexpr int MAX_DEFAULTCHAR = 2; constexpr int MAX_LEADBYTES = 12; constexpr int UTF8 = 65001; @@ -608,7 +609,8 @@ namespace const_cpinfo{ //!* Structs -typedef struct _cpinfo { +typedef struct _cpinfo +{ UINT MaxCharSize; BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; From b2d89ceba5d71336ee84560eae7950a366694c5b Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 26 Aug 2015 13:32:21 -0700 Subject: [PATCH 171/298] Deleted CMakeCache.txt --- src/CMakeCache.txt | 324 --------------------------------------------- 1 file changed, 324 deletions(-) delete mode 100644 src/CMakeCache.txt diff --git a/src/CMakeCache.txt b/src/CMakeCache.txt deleted file mode 100644 index 2f6e2fc4b0..0000000000 --- a/src/CMakeCache.txt +++ /dev/null @@ -1,324 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: /home/aakatz/gitwd/monad-native/src -# It was generated by CMake: /usr/bin/cmake -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//Path to a program. -CMAKE_AR:FILEPATH=/usr/bin/ar - -//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or -// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel. -CMAKE_BUILD_TYPE:STRING= - -//Enable/Disable color output during build. -CMAKE_COLOR_MAKEFILE:BOOL=ON - -//CXX compiler. -CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ - -//Flags used by the compiler during all build types. -CMAKE_CXX_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_CXX_FLAGS_DEBUG:STRING=-g - -//Flags used by the compiler during release minsize builds. -CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds (/MD /Ob1 /Oi -// /Ot /Oy /Gs will produce slightly less optimized but smaller -// files). -CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG - -//Flags used by the compiler during Release with Debug Info builds. -CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//C compiler. -CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc - -//Flags used by the compiler during all build types. -CMAKE_C_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_C_FLAGS_DEBUG:STRING=-g - -//Flags used by the compiler during release minsize builds. -CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds (/MD /Ob1 /Oi -// /Ot /Oy /Gs will produce slightly less optimized but smaller -// files). -CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG - -//Flags used by the compiler during Release with Debug Info builds. -CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Flags used by the linker. -CMAKE_EXE_LINKER_FLAGS:STRING=' ' - -//Flags used by the linker during debug builds. -CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Enable/Disable output of compile commands during generation. -CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF - -//Install path prefix, prepended onto install directories. -CMAKE_INSTALL_PREFIX:PATH=/usr/local - -//Path to a program. -CMAKE_LINKER:FILEPATH=/usr/bin/ld - -//Path to a program. -CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make - -//Flags used by the linker during the creation of modules. -CMAKE_MODULE_LINKER_FLAGS:STRING=' ' - -//Flags used by the linker during debug builds. -CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_NM:FILEPATH=/usr/bin/nm - -//Path to a program. -CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy - -//Path to a program. -CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=monad_native - -//Path to a program. -CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib - -//Flags used by the linker during the creation of dll's. -CMAKE_SHARED_LINKER_FLAGS:STRING=' ' - -//Flags used by the linker during debug builds. -CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If set, runtime paths are not added when installing shared libraries, -// but are added when building. -CMAKE_SKIP_INSTALL_RPATH:BOOL=NO - -//If set, runtime paths are not added when using shared libraries. -CMAKE_SKIP_RPATH:BOOL=NO - -//Flags used by the linker during the creation of static libraries. -CMAKE_STATIC_LINKER_FLAGS:STRING= - -//Flags used by the linker during debug builds. -CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_STRIP:FILEPATH=/usr/bin/strip - -//If true, cmake will use relative paths in makefiles and projects. -CMAKE_USE_RELATIVE_PATHS:BOOL=OFF - -//If this value is on, makefiles will be generated without the -// .SILENT directive, and all commands will be echoed to the console -// during the make. This is useful for debugging only. With Visual -// Studio IDE projects all commands are done without /nologo. -CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE - -//Value Computed by CMake -monad_native_BINARY_DIR:STATIC=/home/aakatz/gitwd/monad-native/src - -//Value Computed by CMake -monad_native_SOURCE_DIR:STATIC=/home/aakatz/gitwd/monad-native/src - -//Dependencies for the target -ps_LIB_DEPENDS:STATIC=general;icuuc; - - -######################## -# INTERNAL cache entries -######################## - -//ADVANCED property for variable: CMAKE_AR -CMAKE_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_BUILD_TOOL -CMAKE_BUILD_TOOL-ADVANCED:INTERNAL=1 -//What is the target build tool cmake is generating for. -CMAKE_BUILD_TOOL:INTERNAL=/usr/bin/make -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=/home/aakatz/gitwd/monad-native/src -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=2 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=8 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=12 -//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE -CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=/usr/bin/cmake -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest -//ADVANCED property for variable: CMAKE_CXX_COMPILER -CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS -CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG -CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL -CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE -CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO -CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER -CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS -CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG -CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL -CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE -CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO -CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Executable file format -CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS -CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG -CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE -CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS -CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 -//Name of generator. -CMAKE_GENERATOR:INTERNAL=Unix Makefiles -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Have symbol pthread_create -CMAKE_HAVE_LIBC_CREATE:INTERNAL= -//Have library pthreads -CMAKE_HAVE_PTHREADS_CREATE:INTERNAL= -//Have library pthread -CMAKE_HAVE_PTHREAD_CREATE:INTERNAL=1 -//Have include pthread.h -CMAKE_HAVE_PTHREAD_H:INTERNAL=1 -//Start directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=/home/aakatz/gitwd/monad-native/src -//Install .so files without execute permission. -CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 -//ADVANCED property for variable: CMAKE_LINKER -CMAKE_LINKER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MAKE_PROGRAM -CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS -CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG -CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE -CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_NM -CMAKE_NM-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_LOCAL_GENERATORS:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJCOPY -CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJDUMP -CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RANLIB -CMAKE_RANLIB-ADVANCED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=/usr/share/cmake-2.8 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS -CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG -CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE -CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH -CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_RPATH -CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS -CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG -CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE -CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STRIP -CMAKE_STRIP-ADVANCED:INTERNAL=1 -//uname command -CMAKE_UNAME:INTERNAL=/bin/uname -//ADVANCED property for variable: CMAKE_USE_RELATIVE_PATHS -CMAKE_USE_RELATIVE_PATHS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE -CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 -//Details about finding Threads -FIND_PACKAGE_MESSAGE_DETAILS_Threads:INTERNAL=[TRUE][v()] - From 0acd64bfc7dd5951c9a5fad08422a635cd8321b3 Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 26 Aug 2015 13:32:21 -0700 Subject: [PATCH 172/298] Deleted CMakeCache.txt --- CMakeCache.txt | 324 ------------------------------------------------- 1 file changed, 324 deletions(-) delete mode 100644 CMakeCache.txt diff --git a/CMakeCache.txt b/CMakeCache.txt deleted file mode 100644 index 2f6e2fc4b0..0000000000 --- a/CMakeCache.txt +++ /dev/null @@ -1,324 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: /home/aakatz/gitwd/monad-native/src -# It was generated by CMake: /usr/bin/cmake -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//Path to a program. -CMAKE_AR:FILEPATH=/usr/bin/ar - -//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or -// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel. -CMAKE_BUILD_TYPE:STRING= - -//Enable/Disable color output during build. -CMAKE_COLOR_MAKEFILE:BOOL=ON - -//CXX compiler. -CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ - -//Flags used by the compiler during all build types. -CMAKE_CXX_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_CXX_FLAGS_DEBUG:STRING=-g - -//Flags used by the compiler during release minsize builds. -CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds (/MD /Ob1 /Oi -// /Ot /Oy /Gs will produce slightly less optimized but smaller -// files). -CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG - -//Flags used by the compiler during Release with Debug Info builds. -CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//C compiler. -CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc - -//Flags used by the compiler during all build types. -CMAKE_C_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_C_FLAGS_DEBUG:STRING=-g - -//Flags used by the compiler during release minsize builds. -CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds (/MD /Ob1 /Oi -// /Ot /Oy /Gs will produce slightly less optimized but smaller -// files). -CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG - -//Flags used by the compiler during Release with Debug Info builds. -CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Flags used by the linker. -CMAKE_EXE_LINKER_FLAGS:STRING=' ' - -//Flags used by the linker during debug builds. -CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Enable/Disable output of compile commands during generation. -CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF - -//Install path prefix, prepended onto install directories. -CMAKE_INSTALL_PREFIX:PATH=/usr/local - -//Path to a program. -CMAKE_LINKER:FILEPATH=/usr/bin/ld - -//Path to a program. -CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make - -//Flags used by the linker during the creation of modules. -CMAKE_MODULE_LINKER_FLAGS:STRING=' ' - -//Flags used by the linker during debug builds. -CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_NM:FILEPATH=/usr/bin/nm - -//Path to a program. -CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy - -//Path to a program. -CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=monad_native - -//Path to a program. -CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib - -//Flags used by the linker during the creation of dll's. -CMAKE_SHARED_LINKER_FLAGS:STRING=' ' - -//Flags used by the linker during debug builds. -CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If set, runtime paths are not added when installing shared libraries, -// but are added when building. -CMAKE_SKIP_INSTALL_RPATH:BOOL=NO - -//If set, runtime paths are not added when using shared libraries. -CMAKE_SKIP_RPATH:BOOL=NO - -//Flags used by the linker during the creation of static libraries. -CMAKE_STATIC_LINKER_FLAGS:STRING= - -//Flags used by the linker during debug builds. -CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_STRIP:FILEPATH=/usr/bin/strip - -//If true, cmake will use relative paths in makefiles and projects. -CMAKE_USE_RELATIVE_PATHS:BOOL=OFF - -//If this value is on, makefiles will be generated without the -// .SILENT directive, and all commands will be echoed to the console -// during the make. This is useful for debugging only. With Visual -// Studio IDE projects all commands are done without /nologo. -CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE - -//Value Computed by CMake -monad_native_BINARY_DIR:STATIC=/home/aakatz/gitwd/monad-native/src - -//Value Computed by CMake -monad_native_SOURCE_DIR:STATIC=/home/aakatz/gitwd/monad-native/src - -//Dependencies for the target -ps_LIB_DEPENDS:STATIC=general;icuuc; - - -######################## -# INTERNAL cache entries -######################## - -//ADVANCED property for variable: CMAKE_AR -CMAKE_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_BUILD_TOOL -CMAKE_BUILD_TOOL-ADVANCED:INTERNAL=1 -//What is the target build tool cmake is generating for. -CMAKE_BUILD_TOOL:INTERNAL=/usr/bin/make -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=/home/aakatz/gitwd/monad-native/src -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=2 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=8 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=12 -//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE -CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=/usr/bin/cmake -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest -//ADVANCED property for variable: CMAKE_CXX_COMPILER -CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS -CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG -CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL -CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE -CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO -CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER -CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS -CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG -CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL -CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE -CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO -CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Executable file format -CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS -CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG -CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE -CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS -CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 -//Name of generator. -CMAKE_GENERATOR:INTERNAL=Unix Makefiles -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Have symbol pthread_create -CMAKE_HAVE_LIBC_CREATE:INTERNAL= -//Have library pthreads -CMAKE_HAVE_PTHREADS_CREATE:INTERNAL= -//Have library pthread -CMAKE_HAVE_PTHREAD_CREATE:INTERNAL=1 -//Have include pthread.h -CMAKE_HAVE_PTHREAD_H:INTERNAL=1 -//Start directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=/home/aakatz/gitwd/monad-native/src -//Install .so files without execute permission. -CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 -//ADVANCED property for variable: CMAKE_LINKER -CMAKE_LINKER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MAKE_PROGRAM -CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS -CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG -CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE -CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_NM -CMAKE_NM-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_LOCAL_GENERATORS:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJCOPY -CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJDUMP -CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RANLIB -CMAKE_RANLIB-ADVANCED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=/usr/share/cmake-2.8 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS -CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG -CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE -CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH -CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_RPATH -CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS -CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG -CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE -CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STRIP -CMAKE_STRIP-ADVANCED:INTERNAL=1 -//uname command -CMAKE_UNAME:INTERNAL=/bin/uname -//ADVANCED property for variable: CMAKE_USE_RELATIVE_PATHS -CMAKE_USE_RELATIVE_PATHS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE -CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 -//Details about finding Threads -FIND_PACKAGE_MESSAGE_DETAILS_Threads:INTERNAL=[TRUE][v()] - From 777a30c51ae700d26c1cbf41db9ac0ef3b4e4528 Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 28 Aug 2015 15:17:34 -0700 Subject: [PATCH 173/298] Changes to documentation --- src/impl/getcpinfo.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/impl/getcpinfo.cpp b/src/impl/getcpinfo.cpp index 09ac0183a0..a27c553076 100644 --- a/src/impl/getcpinfo.cpp +++ b/src/impl/getcpinfo.cpp @@ -16,7 +16,7 @@ //! @parblock //! An UINT Identifier for the code page for which to retrieve information. //! See Code Page Identifiers for details -//! 65001 in the number for UTF8. It is the only valid inpur parameter +//! 65001 in the number for UTF8. It is the only valid input parameter //!because Linux and Unix only use UTF8 for codepage //! //! @endparblock @@ -28,6 +28,13 @@ //! LPCPINFO is a pointer to the structure _cpinfo used to contain the information //! about a code page //! +//! +//! typedef struct _cpinfo { +//! UINT MaxCharSize; +//! BYTE DefaultChar[MAX_DEFAULTCHAR]; +//! BYTE LeadByte[MAX_LEADBYTES]; +//! } CPINFO, *LPCPINFO; +//! //! _cpinfo is a struct that comprises //! //! UINT MaxCharSize; @@ -70,8 +77,8 @@ //! extended error information, call GetLastError. //! //! [MSDN documentation]:https://msdn.microsoft.com/en-us/library/windows/desktop/dd318078%28v=vs.85%29.aspx -//! [_cpinfo]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317780%28v=vs.85%29.aspx -//! [CodePageIdentifiers] https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx +//! [_cpinfo]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317780(v=vs.85).aspx +//! [CodePageIdentifiers] https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) { @@ -87,7 +94,6 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) return FALSE; } - // 65001 is the code page for UTF8, Linux and Unix default it UTF8 if (codepage != const_cpinfo::UTF8) { //If other value is used return error because Linux and Unix only used UTF-8 for codepage @@ -99,12 +105,13 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) cpinfo->DefaultChar[0] = '?'; cpinfo->DefaultChar[1] = '0'; cpinfo->MaxCharSize = 4; + for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ) { // UTF-8 uses the default has no LeadByte as result LeadByte is '0' - cpinfo->LeadByte[i] = '0'; - + cpinfo->LeadByte[i] = '0'; } + return TRUE; } From 782d1642475078854eaee6857ccf2accfefdbf88 Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 28 Aug 2015 15:17:34 -0700 Subject: [PATCH 174/298] Changes to documentation --- impl/getcpinfo.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/impl/getcpinfo.cpp b/impl/getcpinfo.cpp index 09ac0183a0..a27c553076 100644 --- a/impl/getcpinfo.cpp +++ b/impl/getcpinfo.cpp @@ -16,7 +16,7 @@ //! @parblock //! An UINT Identifier for the code page for which to retrieve information. //! See Code Page Identifiers for details -//! 65001 in the number for UTF8. It is the only valid inpur parameter +//! 65001 in the number for UTF8. It is the only valid input parameter //!because Linux and Unix only use UTF8 for codepage //! //! @endparblock @@ -28,6 +28,13 @@ //! LPCPINFO is a pointer to the structure _cpinfo used to contain the information //! about a code page //! +//! +//! typedef struct _cpinfo { +//! UINT MaxCharSize; +//! BYTE DefaultChar[MAX_DEFAULTCHAR]; +//! BYTE LeadByte[MAX_LEADBYTES]; +//! } CPINFO, *LPCPINFO; +//! //! _cpinfo is a struct that comprises //! //! UINT MaxCharSize; @@ -70,8 +77,8 @@ //! extended error information, call GetLastError. //! //! [MSDN documentation]:https://msdn.microsoft.com/en-us/library/windows/desktop/dd318078%28v=vs.85%29.aspx -//! [_cpinfo]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317780%28v=vs.85%29.aspx -//! [CodePageIdentifiers] https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx +//! [_cpinfo]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317780(v=vs.85).aspx +//! [CodePageIdentifiers] https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) { @@ -87,7 +94,6 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) return FALSE; } - // 65001 is the code page for UTF8, Linux and Unix default it UTF8 if (codepage != const_cpinfo::UTF8) { //If other value is used return error because Linux and Unix only used UTF-8 for codepage @@ -99,12 +105,13 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) cpinfo->DefaultChar[0] = '?'; cpinfo->DefaultChar[1] = '0'; cpinfo->MaxCharSize = 4; + for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ) { // UTF-8 uses the default has no LeadByte as result LeadByte is '0' - cpinfo->LeadByte[i] = '0'; - + cpinfo->LeadByte[i] = '0'; } + return TRUE; } From 276b5c54810f58669cacfbf0fa888cc654db57cc Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 28 Aug 2015 15:44:04 -0700 Subject: [PATCH 175/298] Got rid of warnings from cpinfo struct --- src/tests/test-getcpinfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/test-getcpinfo.cpp b/src/tests/test-getcpinfo.cpp index 3ec7596456..56d36b46ae 100644 --- a/src/tests/test-getcpinfo.cpp +++ b/src/tests/test-getcpinfo.cpp @@ -8,7 +8,7 @@ // This test is with correct parameters TEST(GetCPInfo,Utf8) { - CPINFO* cpinfo; + CPINFO* cpinfo = new CPINFO(); int UTF8CodePageNumber = const_cpinfo::UTF8; BOOL result = GetCPInfoW(UTF8CodePageNumber, cpinfo); @@ -28,7 +28,7 @@ TEST(GetCPInfo,Utf8) // This test is with codepage not being utf8 TEST(GetCPInfo, CodePageNotUTF8) { - CPINFO* cpinfo; + CPINFO* cpinfo = new CPINFO();; BOOL result = GetCPInfoW(65000, cpinfo); ASSERT_EQ(FALSE, result); From 67531511610373031bb2d338643589e07636e9cd Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 28 Aug 2015 15:44:04 -0700 Subject: [PATCH 176/298] Got rid of warnings from cpinfo struct --- tests/test-getcpinfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test-getcpinfo.cpp b/tests/test-getcpinfo.cpp index 3ec7596456..56d36b46ae 100644 --- a/tests/test-getcpinfo.cpp +++ b/tests/test-getcpinfo.cpp @@ -8,7 +8,7 @@ // This test is with correct parameters TEST(GetCPInfo,Utf8) { - CPINFO* cpinfo; + CPINFO* cpinfo = new CPINFO(); int UTF8CodePageNumber = const_cpinfo::UTF8; BOOL result = GetCPInfoW(UTF8CodePageNumber, cpinfo); @@ -28,7 +28,7 @@ TEST(GetCPInfo,Utf8) // This test is with codepage not being utf8 TEST(GetCPInfo, CodePageNotUTF8) { - CPINFO* cpinfo; + CPINFO* cpinfo = new CPINFO();; BOOL result = GetCPInfoW(65000, cpinfo); ASSERT_EQ(FALSE, result); From a1f94e6c702c0a4bbb4f1dcba7dfac7ed518e9d9 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 28 Aug 2015 15:57:31 -0700 Subject: [PATCH 177/298] Fix GetCpInfo - Move cpinfo related code out of pal.h and into getcpinfo.h - Use static cpinfo struct (not pointer) in test and pass address - Whitespace cleanup --- src/impl/getcpinfo.cpp | 36 ++++++++++++++++++------------------ src/impl/getcpinfo.h | 18 ++++++++++++++++++ src/impl/pal.h | 18 ------------------ src/tests/test-getcpinfo.cpp | 31 ++++++++++++++----------------- 4 files changed, 50 insertions(+), 53 deletions(-) diff --git a/src/impl/getcpinfo.cpp b/src/impl/getcpinfo.cpp index a27c553076..79f39ea25e 100644 --- a/src/impl/getcpinfo.cpp +++ b/src/impl/getcpinfo.cpp @@ -25,7 +25,7 @@ //! @parblock //! Pointer to a CPINFO structure that receives information about the code page //! -//! LPCPINFO is a pointer to the structure _cpinfo used to contain the information +//! LPCPINFO is a pointer to the structure _cpinfo used to contain the information //! about a code page //! //! @@ -34,33 +34,33 @@ //! BYTE DefaultChar[MAX_DEFAULTCHAR]; //! BYTE LeadByte[MAX_LEADBYTES]; //! } CPINFO, *LPCPINFO; -//! +//! //! _cpinfo is a struct that comprises //! //! UINT MaxCharSize; //! Maximum length, in bytes, of a character in the code page. -//! The length can be 1 for a single-byte character set (SBCS), +//! The length can be 1 for a single-byte character set (SBCS), //! 2 for a double-byte character set (DBCS), or a value larger -//! than 2 for other character set types. The function cannot +//! than 2 for other character set types. The function cannot //! use the size to distinguish an SBCS or a DBCS from other -//! character sets because of other factors, for example, +//! character sets because of other factors, for example, //! the use of ISCII or ISO-2022-xx code pages. //! //! BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; -//! Default character used when translating character +//! Default character used when translating character //! strings to the specific code page. This character is used by //! the WideCharToMultiByte function if an explicit default //! character is not specified. The default is usually the "?" //! character for the code page -//! +//! //! BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; -//! A fixed-length array of lead byte ranges, for which the number -//! of lead byte ranges is variable. If the code page has no lead +//! A fixed-length array of lead byte ranges, for which the number +//! of lead byte ranges is variable. If the code page has no lead //! bytes, every element of the array is set to NULL. If the code //! page has lead bytes, the array specifies a starting value and -//! an ending value for each range. Ranges are inclusive, and the +//! an ending value for each range. Ranges are inclusive, and the //! maximum number of ranges for any code page is five. The array -//! uses two bytes to describe each range, with two null bytes as +//! uses two bytes to describe each range, with two null bytes as //! a terminator after the last range. //! //! MAX_DEFAULTCHAR is an int of size 2 @@ -83,7 +83,7 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) { errno = FALSE; - + // Select locale from environment setlocale(LC_ALL, ""); @@ -93,8 +93,8 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) errno = ERROR_BAD_ENVIRONMENT; return FALSE; } - - if (codepage != const_cpinfo::UTF8) + + if (codepage != const_cpinfo::UTF8) { //If other value is used return error because Linux and Unix only used UTF-8 for codepage errno = ERROR_INVALID_PARAMETER; @@ -105,13 +105,13 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) cpinfo->DefaultChar[0] = '?'; cpinfo->DefaultChar[1] = '0'; cpinfo->MaxCharSize = 4; - - for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ) + + for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ) { // UTF-8 uses the default has no LeadByte as result LeadByte is '0' - cpinfo->LeadByte[i] = '0'; + cpinfo->LeadByte[i] = '0'; } - + return TRUE; } diff --git a/src/impl/getcpinfo.h b/src/impl/getcpinfo.h index 54a2ebbcdf..cd0883d7b4 100644 --- a/src/impl/getcpinfo.h +++ b/src/impl/getcpinfo.h @@ -2,6 +2,24 @@ #include "pal.h" +//!* NameSpace + +namespace const_cpinfo +{ + constexpr int MAX_DEFAULTCHAR = 2; + constexpr int MAX_LEADBYTES = 12; + constexpr int UTF8 = 65001; +} + +//!* Structs + +typedef struct _cpinfo +{ + UINT MaxCharSize; + BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; + BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; +} CPINFO; + PAL_BEGIN_EXTERNC BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo); diff --git a/src/impl/pal.h b/src/impl/pal.h index 8a27636008..944336ab0e 100644 --- a/src/impl/pal.h +++ b/src/impl/pal.h @@ -597,21 +597,3 @@ typedef unsigned char PAL_Boolean; #else # define PAL_COUNT(ARR) (sizeof(ARR) / sizeof(ARR[0])) #endif - -//!* NameSpace - -namespace const_cpinfo -{ - constexpr int MAX_DEFAULTCHAR = 2; - constexpr int MAX_LEADBYTES = 12; - constexpr int UTF8 = 65001; -} - -//!* Structs - -typedef struct _cpinfo -{ - UINT MaxCharSize; - BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; - BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; -} CPINFO; diff --git a/src/tests/test-getcpinfo.cpp b/src/tests/test-getcpinfo.cpp index 56d36b46ae..0c8a339604 100644 --- a/src/tests/test-getcpinfo.cpp +++ b/src/tests/test-getcpinfo.cpp @@ -5,33 +5,30 @@ #include #include "getcpinfo.h" -// This test is with correct parameters -TEST(GetCPInfo,Utf8) +TEST(GetCPInfo, CodePageIsUTF8) { - CPINFO* cpinfo = new CPINFO(); - int UTF8CodePageNumber = const_cpinfo::UTF8; - BOOL result = GetCPInfoW(UTF8CodePageNumber, cpinfo); + CPINFO cpinfo; + BOOL result = GetCPInfoW(const_cpinfo::UTF8, &cpinfo); // first make sure that the function worked ASSERT_EQ(TRUE, result); - + // now compare the actual values - EXPECT_EQ(cpinfo->DefaultChar[0], '?'); - EXPECT_EQ(cpinfo->DefaultChar[1], '0'); - EXPECT_EQ(cpinfo->MaxCharSize,4); + EXPECT_EQ(cpinfo.DefaultChar[0], '?'); + EXPECT_EQ(cpinfo.DefaultChar[1], '0'); + EXPECT_EQ(cpinfo.MaxCharSize, 4); + for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++) { - EXPECT_EQ(cpinfo->LeadByte[i], '0'); + EXPECT_EQ(cpinfo.LeadByte[i], '0'); } } -// This test is with codepage not being utf8 -TEST(GetCPInfo, CodePageNotUTF8) +TEST(GetCPInfo, CodePageIsNotUTF8) { - CPINFO* cpinfo = new CPINFO();; - BOOL result = GetCPInfoW(65000, cpinfo); - + CPINFO cpinfo; + BOOL result = GetCPInfoW(const_cpinfo::UTF8+1, &cpinfo); + ASSERT_EQ(FALSE, result); ASSERT_EQ(ERROR_INVALID_PARAMETER, errno); - -} \ No newline at end of file +} From 39174a0afbea722576f65c24db5b2df2b6a01321 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 28 Aug 2015 15:57:31 -0700 Subject: [PATCH 178/298] Fix GetCpInfo - Move cpinfo related code out of pal.h and into getcpinfo.h - Use static cpinfo struct (not pointer) in test and pass address - Whitespace cleanup --- impl/getcpinfo.cpp | 36 ++++++++++++++++++------------------ impl/getcpinfo.h | 18 ++++++++++++++++++ impl/pal.h | 18 ------------------ tests/test-getcpinfo.cpp | 31 ++++++++++++++----------------- 4 files changed, 50 insertions(+), 53 deletions(-) diff --git a/impl/getcpinfo.cpp b/impl/getcpinfo.cpp index a27c553076..79f39ea25e 100644 --- a/impl/getcpinfo.cpp +++ b/impl/getcpinfo.cpp @@ -25,7 +25,7 @@ //! @parblock //! Pointer to a CPINFO structure that receives information about the code page //! -//! LPCPINFO is a pointer to the structure _cpinfo used to contain the information +//! LPCPINFO is a pointer to the structure _cpinfo used to contain the information //! about a code page //! //! @@ -34,33 +34,33 @@ //! BYTE DefaultChar[MAX_DEFAULTCHAR]; //! BYTE LeadByte[MAX_LEADBYTES]; //! } CPINFO, *LPCPINFO; -//! +//! //! _cpinfo is a struct that comprises //! //! UINT MaxCharSize; //! Maximum length, in bytes, of a character in the code page. -//! The length can be 1 for a single-byte character set (SBCS), +//! The length can be 1 for a single-byte character set (SBCS), //! 2 for a double-byte character set (DBCS), or a value larger -//! than 2 for other character set types. The function cannot +//! than 2 for other character set types. The function cannot //! use the size to distinguish an SBCS or a DBCS from other -//! character sets because of other factors, for example, +//! character sets because of other factors, for example, //! the use of ISCII or ISO-2022-xx code pages. //! //! BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; -//! Default character used when translating character +//! Default character used when translating character //! strings to the specific code page. This character is used by //! the WideCharToMultiByte function if an explicit default //! character is not specified. The default is usually the "?" //! character for the code page -//! +//! //! BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; -//! A fixed-length array of lead byte ranges, for which the number -//! of lead byte ranges is variable. If the code page has no lead +//! A fixed-length array of lead byte ranges, for which the number +//! of lead byte ranges is variable. If the code page has no lead //! bytes, every element of the array is set to NULL. If the code //! page has lead bytes, the array specifies a starting value and -//! an ending value for each range. Ranges are inclusive, and the +//! an ending value for each range. Ranges are inclusive, and the //! maximum number of ranges for any code page is five. The array -//! uses two bytes to describe each range, with two null bytes as +//! uses two bytes to describe each range, with two null bytes as //! a terminator after the last range. //! //! MAX_DEFAULTCHAR is an int of size 2 @@ -83,7 +83,7 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) { errno = FALSE; - + // Select locale from environment setlocale(LC_ALL, ""); @@ -93,8 +93,8 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) errno = ERROR_BAD_ENVIRONMENT; return FALSE; } - - if (codepage != const_cpinfo::UTF8) + + if (codepage != const_cpinfo::UTF8) { //If other value is used return error because Linux and Unix only used UTF-8 for codepage errno = ERROR_INVALID_PARAMETER; @@ -105,13 +105,13 @@ BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) cpinfo->DefaultChar[0] = '?'; cpinfo->DefaultChar[1] = '0'; cpinfo->MaxCharSize = 4; - - for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ) + + for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ) { // UTF-8 uses the default has no LeadByte as result LeadByte is '0' - cpinfo->LeadByte[i] = '0'; + cpinfo->LeadByte[i] = '0'; } - + return TRUE; } diff --git a/impl/getcpinfo.h b/impl/getcpinfo.h index 54a2ebbcdf..cd0883d7b4 100644 --- a/impl/getcpinfo.h +++ b/impl/getcpinfo.h @@ -2,6 +2,24 @@ #include "pal.h" +//!* NameSpace + +namespace const_cpinfo +{ + constexpr int MAX_DEFAULTCHAR = 2; + constexpr int MAX_LEADBYTES = 12; + constexpr int UTF8 = 65001; +} + +//!* Structs + +typedef struct _cpinfo +{ + UINT MaxCharSize; + BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; + BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; +} CPINFO; + PAL_BEGIN_EXTERNC BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo); diff --git a/impl/pal.h b/impl/pal.h index 8a27636008..944336ab0e 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -597,21 +597,3 @@ typedef unsigned char PAL_Boolean; #else # define PAL_COUNT(ARR) (sizeof(ARR) / sizeof(ARR[0])) #endif - -//!* NameSpace - -namespace const_cpinfo -{ - constexpr int MAX_DEFAULTCHAR = 2; - constexpr int MAX_LEADBYTES = 12; - constexpr int UTF8 = 65001; -} - -//!* Structs - -typedef struct _cpinfo -{ - UINT MaxCharSize; - BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; - BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; -} CPINFO; diff --git a/tests/test-getcpinfo.cpp b/tests/test-getcpinfo.cpp index 56d36b46ae..0c8a339604 100644 --- a/tests/test-getcpinfo.cpp +++ b/tests/test-getcpinfo.cpp @@ -5,33 +5,30 @@ #include #include "getcpinfo.h" -// This test is with correct parameters -TEST(GetCPInfo,Utf8) +TEST(GetCPInfo, CodePageIsUTF8) { - CPINFO* cpinfo = new CPINFO(); - int UTF8CodePageNumber = const_cpinfo::UTF8; - BOOL result = GetCPInfoW(UTF8CodePageNumber, cpinfo); + CPINFO cpinfo; + BOOL result = GetCPInfoW(const_cpinfo::UTF8, &cpinfo); // first make sure that the function worked ASSERT_EQ(TRUE, result); - + // now compare the actual values - EXPECT_EQ(cpinfo->DefaultChar[0], '?'); - EXPECT_EQ(cpinfo->DefaultChar[1], '0'); - EXPECT_EQ(cpinfo->MaxCharSize,4); + EXPECT_EQ(cpinfo.DefaultChar[0], '?'); + EXPECT_EQ(cpinfo.DefaultChar[1], '0'); + EXPECT_EQ(cpinfo.MaxCharSize, 4); + for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++) { - EXPECT_EQ(cpinfo->LeadByte[i], '0'); + EXPECT_EQ(cpinfo.LeadByte[i], '0'); } } -// This test is with codepage not being utf8 -TEST(GetCPInfo, CodePageNotUTF8) +TEST(GetCPInfo, CodePageIsNotUTF8) { - CPINFO* cpinfo = new CPINFO();; - BOOL result = GetCPInfoW(65000, cpinfo); - + CPINFO cpinfo; + BOOL result = GetCPInfoW(const_cpinfo::UTF8+1, &cpinfo); + ASSERT_EQ(FALSE, result); ASSERT_EQ(ERROR_INVALID_PARAMETER, errno); - -} \ No newline at end of file +} From a4a9638bcd2a853dc5bf01b796d4cda0ab66f2ed Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 23 Sep 2015 15:55:44 -0700 Subject: [PATCH 179/298] Use getpwuid(geteuid()) instead of getlogin() This removes the dependency on a TTY and now does what is expected: gets the (possibly impersonated) username of the current process/thread. Implementation and tests updated, still uses reentrant versions where possible. --- src/impl/getusername.cpp | 59 ++++++++++++++++++---------------- src/tests/test-getusername.cpp | 3 +- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/impl/getusername.cpp b/src/impl/getusername.cpp index 88e5955d64..ee14d8651a 100644 --- a/src/impl/getusername.cpp +++ b/src/impl/getusername.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "getusername.h" //! @brief GetUserName retrieves the name of the user associated with @@ -40,13 +41,9 @@ //! @exception errno Passes these errors via errno to GetLastError: //! - ERROR_INVALID_PARAMETER: parameter is not valid //! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 -//! - ERROR_TOO_MANY_OPEN_FILES: already have the maximum allowed number of open files -//! - ERROR_NO_ASSOCIATION: calling process has no controlling terminal //! - ERROR_INSUFFICIENT_BUFFER: buffer not large enough to hold username string -//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file -//! - ERROR_OUTOFMEMORY: insufficient memory to allocate passwd structure -//! - ERROR_NO_ASSOCIATION: standard input didn't refer to a terminal -//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code +//! - ERROR_NO_SUCH_USER: there was no corresponding user +//! - ERROR_GEN_FAILURE: sysconf() or getpwuid() failed for unknown reasons //! //! @retval TRUE If the function succeeds, the return value is a nonzero //! value, and the variable pointed to by lpnSize contains the number @@ -61,8 +58,6 @@ //! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { - errno = FALSE; - // Check parameters if (!lpBuffer || !lpnSize) { @@ -79,39 +74,47 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) return FALSE; } - // Get username from system in a thread-safe manner - std::string username(LOGIN_NAME_MAX, 0); - int ret = getlogin_r(&username[0], username.length()); + struct passwd pwd; + struct passwd* result; + // gets the initial suggested size for buf + int buflen = sysconf(_SC_GETPW_R_SIZE_MAX); + if (buflen == -1) + { + errno = ERROR_GEN_FAILURE; + return FALSE; + } + std::string buf(buflen, 0); + + // geteuid() gets the effective user ID of the calling process, and is always successful + errno = 0; + int ret = getpwuid_r(geteuid(), &pwd, &buf[0], buflen, &result); + // Map errno to Win32 Error Codes if (ret) { switch (errno) { - case EMFILE: - case ENFILE: - errno = ERROR_TOO_MANY_OPEN_FILES; - break; - case ENXIO: - errno = ERROR_NO_ASSOCIATION; - break; - case ERANGE: - errno = ERROR_GEN_FAILURE; - break; case ENOENT: + case ESRCH: + case EBADF: + case EPERM: errno = ERROR_NO_SUCH_USER; break; - case ENOMEM: - errno = ERROR_OUTOFMEMORY; - break; - case ENOTTY: - errno = ERROR_NO_ASSOCIATION; - break; default: - errno = ERROR_INVALID_FUNCTION; + errno = ERROR_GEN_FAILURE; } return FALSE; } + // Check if no user matched + if (result == NULL) + { + errno = ERROR_NO_SUCH_USER; + return FALSE; + } + + std::string username(result->pw_name); + // Convert to UnicodeString auto username16 = icu::UnicodeString::fromUTF8(username.c_str()); // Terminate string with null diff --git a/src/tests/test-getusername.cpp b/src/tests/test-getusername.cpp index b6c0b5e776..9d238f538a 100644 --- a/src/tests/test-getusername.cpp +++ b/src/tests/test-getusername.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "getusername.h" //! Test fixture for GetUserNameW @@ -19,7 +20,7 @@ protected: std::string expectedUsername; DWORD expectedSize; - GetUserNameTest(): expectedUsername(std::string(getlogin())), + GetUserNameTest(): expectedUsername(std::string(getpwuid(geteuid())->pw_name)), expectedSize(expectedUsername.length()+1) { } From 020a768c31a8dced653649590014380228494bce Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 23 Sep 2015 15:55:44 -0700 Subject: [PATCH 180/298] Use getpwuid(geteuid()) instead of getlogin() This removes the dependency on a TTY and now does what is expected: gets the (possibly impersonated) username of the current process/thread. Implementation and tests updated, still uses reentrant versions where possible. --- impl/getusername.cpp | 59 ++++++++++++++++++++------------------ tests/test-getusername.cpp | 3 +- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 88e5955d64..ee14d8651a 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "getusername.h" //! @brief GetUserName retrieves the name of the user associated with @@ -40,13 +41,9 @@ //! @exception errno Passes these errors via errno to GetLastError: //! - ERROR_INVALID_PARAMETER: parameter is not valid //! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 -//! - ERROR_TOO_MANY_OPEN_FILES: already have the maximum allowed number of open files -//! - ERROR_NO_ASSOCIATION: calling process has no controlling terminal //! - ERROR_INSUFFICIENT_BUFFER: buffer not large enough to hold username string -//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file -//! - ERROR_OUTOFMEMORY: insufficient memory to allocate passwd structure -//! - ERROR_NO_ASSOCIATION: standard input didn't refer to a terminal -//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code +//! - ERROR_NO_SUCH_USER: there was no corresponding user +//! - ERROR_GEN_FAILURE: sysconf() or getpwuid() failed for unknown reasons //! //! @retval TRUE If the function succeeds, the return value is a nonzero //! value, and the variable pointed to by lpnSize contains the number @@ -61,8 +58,6 @@ //! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) { - errno = FALSE; - // Check parameters if (!lpBuffer || !lpnSize) { @@ -79,39 +74,47 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) return FALSE; } - // Get username from system in a thread-safe manner - std::string username(LOGIN_NAME_MAX, 0); - int ret = getlogin_r(&username[0], username.length()); + struct passwd pwd; + struct passwd* result; + // gets the initial suggested size for buf + int buflen = sysconf(_SC_GETPW_R_SIZE_MAX); + if (buflen == -1) + { + errno = ERROR_GEN_FAILURE; + return FALSE; + } + std::string buf(buflen, 0); + + // geteuid() gets the effective user ID of the calling process, and is always successful + errno = 0; + int ret = getpwuid_r(geteuid(), &pwd, &buf[0], buflen, &result); + // Map errno to Win32 Error Codes if (ret) { switch (errno) { - case EMFILE: - case ENFILE: - errno = ERROR_TOO_MANY_OPEN_FILES; - break; - case ENXIO: - errno = ERROR_NO_ASSOCIATION; - break; - case ERANGE: - errno = ERROR_GEN_FAILURE; - break; case ENOENT: + case ESRCH: + case EBADF: + case EPERM: errno = ERROR_NO_SUCH_USER; break; - case ENOMEM: - errno = ERROR_OUTOFMEMORY; - break; - case ENOTTY: - errno = ERROR_NO_ASSOCIATION; - break; default: - errno = ERROR_INVALID_FUNCTION; + errno = ERROR_GEN_FAILURE; } return FALSE; } + // Check if no user matched + if (result == NULL) + { + errno = ERROR_NO_SUCH_USER; + return FALSE; + } + + std::string username(result->pw_name); + // Convert to UnicodeString auto username16 = icu::UnicodeString::fromUTF8(username.c_str()); // Terminate string with null diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index b6c0b5e776..9d238f538a 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "getusername.h" //! Test fixture for GetUserNameW @@ -19,7 +20,7 @@ protected: std::string expectedUsername; DWORD expectedSize; - GetUserNameTest(): expectedUsername(std::string(getlogin())), + GetUserNameTest(): expectedUsername(std::string(getpwuid(geteuid())->pw_name)), expectedSize(expectedUsername.length()+1) { } From d1de7e28c52a87a0804b76445a07b1d122417436 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 30 Sep 2015 16:28:16 -0700 Subject: [PATCH 181/298] Ignore libps.so --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 45c8b7d406..38f7f820b2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ src/build/ src/monad_native src/src.kdev4 +libps.so From ad49db74e24758377c3735bf9a40fd06ea2b2b20 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 6 Oct 2015 14:08:38 -0700 Subject: [PATCH 182/298] Ignore more things --- .gitignore | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 38f7f820b2..280941f2a3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,10 @@ src/CMakeFiles/ src/build/ src/monad_native src/src.kdev4 - libps.so +CMakeCache.txt +CMakeFiles/ +Makefile +cmake_install.cmake +host_cmdline +monad_native From fd8566f111d3a1c364a808f439d47e15ebe35b01 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 20 Oct 2015 11:54:46 -0700 Subject: [PATCH 183/298] Refactor host_common into pshost static lib For reuse by psrp provider --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 003c9b9854..b534ebb94b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,18 +13,19 @@ set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername.cpp tests/test-getcpinfo.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) -set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) +set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp) # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) +add_library(pshost STATIC ${HOST_COMMON_SOURCE_FILES}) add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) # add pthread and other libs find_package(Threads) target_link_libraries(ps icuuc) target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) -target_link_libraries(host_cmdline dl icuuc) +target_link_libraries(host_cmdline pshost dl icuuc) # target specific include directories target_include_directories(monad_native PRIVATE host) From 7196afc5ad43d69f658a45bb4b72a91d5e4b8331 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 20 Oct 2015 11:54:46 -0700 Subject: [PATCH 184/298] Refactor host_common into pshost static lib For reuse by psrp provider --- src/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 003c9b9854..b534ebb94b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,18 +13,19 @@ set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername.cpp tests/test-getcpinfo.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) -set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp ${HOST_COMMON_SOURCE_FILES}) +set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp) # target definitions add_library(ps SHARED ${LIB_SOURCE_FILES}) add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) +add_library(pshost STATIC ${HOST_COMMON_SOURCE_FILES}) add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) # add pthread and other libs find_package(Threads) target_link_libraries(ps icuuc) target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) -target_link_libraries(host_cmdline dl icuuc) +target_link_libraries(host_cmdline pshost dl icuuc) # target specific include directories target_include_directories(monad_native PRIVATE host) From dccd2e9621fac9e4a3e93d80c6782bff9b658eb3 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 21 Oct 2015 15:06:54 -0700 Subject: [PATCH 185/298] Use stream in one statement This just really bugged me and I had it stashed from earlier --- src/host/cmdline/main.cpp | 100 +++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 7cc4637cee..61c1cb9e40 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -11,49 +11,49 @@ namespace Cmdline { - + void printHelp() { - std::cerr << "PS CoreCLR host" << std::endl; - std::cerr << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl; - std::cerr << " [-b base_path] assembly [...]" << std::endl; - std::cerr << std::endl; - std::cerr << "What it does:" << std::endl; - std::cerr << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl; - std::cerr << " as host_cmdline" << std::endl; - std::cerr << " + this behavior can be overridden with the -c command line argument" << std::endl; - std::cerr << "- by default the host assumes that the assembly named" << std::endl; - std::cerr << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl; - std::cerr << " platform assemblies" << std::endl; - std::cerr << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl; - std::cerr << " be provided with the -alc command line argument" << std::endl; - std::cerr << "- all additional parameters at the end of the command line are forwarded" << std::endl; - std::cerr << " to the Main function in the assembly" << std::endl; - std::cerr << "- the host will execute the Main function in the specified assembly" << std::endl; - std::cerr << " + this assembly has to be located in the search path" << std::endl; - std::cerr << "- by default the host will add the current working directory to the assembly search path" << std::endl; - std::cerr << " + this can be overridden with the -s command line argument" << std::endl; - std::cerr << " + if -c is specified, it will be added to the search path instead of the current directory" << std::endl; - std::cerr << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl; - std::cerr << " working directory" << std::endl; - std::cerr << " + this can be overridden with the -b command line argument" << std::endl; - std::cerr << "- the function signature of the Main function that gets executed must be:" << std::endl; - std::cerr << " static void Main(string[] args)" << std::endl; - std::cerr << std::endl; - std::cerr << "Options:" << std::endl; - std::cerr << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl; - std::cerr << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl; - std::cerr << "-s a list of assembly search paths, separated by :" << std::endl; - std::cerr << "-b the powershell assembly base path" << std::endl; - std::cerr << "-v verbose output, show paths" << std::endl; - std::cerr << "-tpa additional list of trusted platform assemblies, this references dll and exe files" << std::endl; - std::cerr << " separated by :" << std::endl; - std::cerr << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl; - std::cerr << " argument, must always be added to the TPA list with this parameter" << std::endl; - std::cerr << "assembly the path of the assembly to execute relative to current directory" << std::endl; - std::cerr << std::endl; - std::cerr << "Example:" << std::endl; - std::cerr << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; + std::cerr << "PS CoreCLR host" << std::endl + << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl + << " [-b base_path] assembly [...]" << std::endl + << std::endl + << "What it does:" << std::endl + << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl + << " as host_cmdline" << std::endl + << " + this behavior can be overridden with the -c command line argument" << std::endl + << "- by default the host assumes that the assembly named" << std::endl + << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl + << " platform assemblies" << std::endl + << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl + << " be provided with the -alc command line argument" << std::endl + << "- all additional parameters at the end of the command line are forwarded" << std::endl + << " to the Main function in the assembly" << std::endl + << "- the host will execute the Main function in the specified assembly" << std::endl + << " + this assembly has to be located in the search path" << std::endl + << "- by default the host will add the current working directory to the assembly search path" << std::endl + << " + this can be overridden with the -s command line argument" << std::endl + << " + if -c is specified, it will be added to the search path instead of the current directory" << std::endl + << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl + << " working directory" << std::endl + << " + this can be overridden with the -b command line argument" << std::endl + << "- the function signature of the Main function that gets executed must be:" << std::endl + << " static void Main(string[] args)" << std::endl + << std::endl + << "Options:" << std::endl + << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl + << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl + << "-s a list of assembly search paths, separated by :" << std::endl + << "-b the powershell assembly base path" << std::endl + << "-v verbose output, show paths" << std::endl + << "-tpa additional list of trusted platform assemblies, this references dll and exe files" << std::endl + << " separated by :" << std::endl + << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl + << " argument, must always be added to the TPA list with this parameter" << std::endl + << "assembly the path of the assembly to execute relative to current directory" << std::endl + << std::endl + << "Example:" << std::endl + << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; } struct Args @@ -77,15 +77,15 @@ struct Args void debugPrint() const { - std::cerr << "Args:" << std::endl; - std::cerr << "- clrPath " << clrPath << std::endl; - std::cerr << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl; - std::cerr << "- searchPaths " << searchPaths << std::endl; - std::cerr << "- basePath " << basePath << std::endl; - std::cerr << "- tpaList " << tpaList << std::endl; - std::cerr << "- entryAssemblyPath " << entryAssemblyPath << std::endl; - std::cerr << "- argc " << argc << std::endl; - std::cerr << "- verbose " << (verbose ? "true" : "false") << std::endl; + std::cerr << "Args:" << std::endl + << "- clrPath " << clrPath << std::endl + << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl + << "- searchPaths " << searchPaths << std::endl + << "- basePath " << basePath << std::endl + << "- tpaList " << tpaList << std::endl + << "- entryAssemblyPath " << entryAssemblyPath << std::endl + << "- argc " << argc << std::endl + << "- verbose " << (verbose ? "true" : "false") << std::endl; } }; From 6cddef6b1e309ec111985a593932ac4256e22f6b Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 21 Oct 2015 15:06:54 -0700 Subject: [PATCH 186/298] Use stream in one statement This just really bugged me and I had it stashed from earlier --- host/cmdline/main.cpp | 100 +++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 7cc4637cee..61c1cb9e40 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -11,49 +11,49 @@ namespace Cmdline { - + void printHelp() { - std::cerr << "PS CoreCLR host" << std::endl; - std::cerr << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl; - std::cerr << " [-b base_path] assembly [...]" << std::endl; - std::cerr << std::endl; - std::cerr << "What it does:" << std::endl; - std::cerr << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl; - std::cerr << " as host_cmdline" << std::endl; - std::cerr << " + this behavior can be overridden with the -c command line argument" << std::endl; - std::cerr << "- by default the host assumes that the assembly named" << std::endl; - std::cerr << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl; - std::cerr << " platform assemblies" << std::endl; - std::cerr << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl; - std::cerr << " be provided with the -alc command line argument" << std::endl; - std::cerr << "- all additional parameters at the end of the command line are forwarded" << std::endl; - std::cerr << " to the Main function in the assembly" << std::endl; - std::cerr << "- the host will execute the Main function in the specified assembly" << std::endl; - std::cerr << " + this assembly has to be located in the search path" << std::endl; - std::cerr << "- by default the host will add the current working directory to the assembly search path" << std::endl; - std::cerr << " + this can be overridden with the -s command line argument" << std::endl; - std::cerr << " + if -c is specified, it will be added to the search path instead of the current directory" << std::endl; - std::cerr << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl; - std::cerr << " working directory" << std::endl; - std::cerr << " + this can be overridden with the -b command line argument" << std::endl; - std::cerr << "- the function signature of the Main function that gets executed must be:" << std::endl; - std::cerr << " static void Main(string[] args)" << std::endl; - std::cerr << std::endl; - std::cerr << "Options:" << std::endl; - std::cerr << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl; - std::cerr << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl; - std::cerr << "-s a list of assembly search paths, separated by :" << std::endl; - std::cerr << "-b the powershell assembly base path" << std::endl; - std::cerr << "-v verbose output, show paths" << std::endl; - std::cerr << "-tpa additional list of trusted platform assemblies, this references dll and exe files" << std::endl; - std::cerr << " separated by :" << std::endl; - std::cerr << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl; - std::cerr << " argument, must always be added to the TPA list with this parameter" << std::endl; - std::cerr << "assembly the path of the assembly to execute relative to current directory" << std::endl; - std::cerr << std::endl; - std::cerr << "Example:" << std::endl; - std::cerr << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; + std::cerr << "PS CoreCLR host" << std::endl + << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl + << " [-b base_path] assembly [...]" << std::endl + << std::endl + << "What it does:" << std::endl + << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl + << " as host_cmdline" << std::endl + << " + this behavior can be overridden with the -c command line argument" << std::endl + << "- by default the host assumes that the assembly named" << std::endl + << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl + << " platform assemblies" << std::endl + << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl + << " be provided with the -alc command line argument" << std::endl + << "- all additional parameters at the end of the command line are forwarded" << std::endl + << " to the Main function in the assembly" << std::endl + << "- the host will execute the Main function in the specified assembly" << std::endl + << " + this assembly has to be located in the search path" << std::endl + << "- by default the host will add the current working directory to the assembly search path" << std::endl + << " + this can be overridden with the -s command line argument" << std::endl + << " + if -c is specified, it will be added to the search path instead of the current directory" << std::endl + << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl + << " working directory" << std::endl + << " + this can be overridden with the -b command line argument" << std::endl + << "- the function signature of the Main function that gets executed must be:" << std::endl + << " static void Main(string[] args)" << std::endl + << std::endl + << "Options:" << std::endl + << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl + << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl + << "-s a list of assembly search paths, separated by :" << std::endl + << "-b the powershell assembly base path" << std::endl + << "-v verbose output, show paths" << std::endl + << "-tpa additional list of trusted platform assemblies, this references dll and exe files" << std::endl + << " separated by :" << std::endl + << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl + << " argument, must always be added to the TPA list with this parameter" << std::endl + << "assembly the path of the assembly to execute relative to current directory" << std::endl + << std::endl + << "Example:" << std::endl + << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; } struct Args @@ -77,15 +77,15 @@ struct Args void debugPrint() const { - std::cerr << "Args:" << std::endl; - std::cerr << "- clrPath " << clrPath << std::endl; - std::cerr << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl; - std::cerr << "- searchPaths " << searchPaths << std::endl; - std::cerr << "- basePath " << basePath << std::endl; - std::cerr << "- tpaList " << tpaList << std::endl; - std::cerr << "- entryAssemblyPath " << entryAssemblyPath << std::endl; - std::cerr << "- argc " << argc << std::endl; - std::cerr << "- verbose " << (verbose ? "true" : "false") << std::endl; + std::cerr << "Args:" << std::endl + << "- clrPath " << clrPath << std::endl + << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl + << "- searchPaths " << searchPaths << std::endl + << "- basePath " << basePath << std::endl + << "- tpaList " << tpaList << std::endl + << "- entryAssemblyPath " << entryAssemblyPath << std::endl + << "- argc " << argc << std::endl + << "- verbose " << (verbose ? "true" : "false") << std::endl; } }; From fb9c2424c3c80b1b5b789f34fc62f97c401bf58e Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 21 Oct 2015 15:22:57 -0700 Subject: [PATCH 187/298] Reindent host code using project standards --- src/host/cmdline/main.cpp | 303 ++++++++++++++++---------------- src/host/common/coreclrutil.cpp | 229 ++++++++++++------------ src/host/common/coreclrutil.h | 87 +++++---- src/host/common/hostutil.h | 60 +++---- 4 files changed, 335 insertions(+), 344 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 61c1cb9e40..ce058b7ce7 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -11,153 +11,152 @@ namespace Cmdline { - -void printHelp() -{ - std::cerr << "PS CoreCLR host" << std::endl - << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl - << " [-b base_path] assembly [...]" << std::endl - << std::endl - << "What it does:" << std::endl - << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl - << " as host_cmdline" << std::endl - << " + this behavior can be overridden with the -c command line argument" << std::endl - << "- by default the host assumes that the assembly named" << std::endl - << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl - << " platform assemblies" << std::endl - << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl - << " be provided with the -alc command line argument" << std::endl - << "- all additional parameters at the end of the command line are forwarded" << std::endl - << " to the Main function in the assembly" << std::endl - << "- the host will execute the Main function in the specified assembly" << std::endl - << " + this assembly has to be located in the search path" << std::endl - << "- by default the host will add the current working directory to the assembly search path" << std::endl - << " + this can be overridden with the -s command line argument" << std::endl - << " + if -c is specified, it will be added to the search path instead of the current directory" << std::endl - << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl - << " working directory" << std::endl - << " + this can be overridden with the -b command line argument" << std::endl - << "- the function signature of the Main function that gets executed must be:" << std::endl - << " static void Main(string[] args)" << std::endl - << std::endl - << "Options:" << std::endl - << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl - << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl - << "-s a list of assembly search paths, separated by :" << std::endl - << "-b the powershell assembly base path" << std::endl - << "-v verbose output, show paths" << std::endl - << "-tpa additional list of trusted platform assemblies, this references dll and exe files" << std::endl - << " separated by :" << std::endl - << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl - << " argument, must always be added to the TPA list with this parameter" << std::endl - << "assembly the path of the assembly to execute relative to current directory" << std::endl - << std::endl - << "Example:" << std::endl - << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; -} - -struct Args -{ - Args() : - argc(0), - argv(nullptr), - verbose(false) + void printHelp() { + std::cerr << "PS CoreCLR host" << std::endl + << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl + << " [-b base_path] assembly [...]" << std::endl + << std::endl + << "What it does:" << std::endl + << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl + << " as host_cmdline" << std::endl + << " + this behavior can be overridden with the -c command line argument" << std::endl + << "- by default the host assumes that the assembly named" << std::endl + << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl + << " platform assemblies" << std::endl + << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl + << " be provided with the -alc command line argument" << std::endl + << "- all additional parameters at the end of the command line are forwarded" << std::endl + << " to the Main function in the assembly" << std::endl + << "- the host will execute the Main function in the specified assembly" << std::endl + << " + this assembly has to be located in the search path" << std::endl + << "- by default the host will add the current working directory to the assembly search path" << std::endl + << " + this can be overridden with the -s command line argument" << std::endl + << " + if -c is specified, it will be added to the search path instead of the current directory" << std::endl + << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl + << " working directory" << std::endl + << " + this can be overridden with the -b command line argument" << std::endl + << "- the function signature of the Main function that gets executed must be:" << std::endl + << " static void Main(string[] args)" << std::endl + << std::endl + << "Options:" << std::endl + << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl + << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl + << "-s a list of assembly search paths, separated by :" << std::endl + << "-b the powershell assembly base path" << std::endl + << "-v verbose output, show paths" << std::endl + << "-tpa additional list of trusted platform assemblies, this references dll and exe files" << std::endl + << " separated by :" << std::endl + << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl + << " argument, must always be added to the TPA list with this parameter" << std::endl + << "assembly the path of the assembly to execute relative to current directory" << std::endl + << std::endl + << "Example:" << std::endl + << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; } - std::string clrPath; - std::string assemblyLoadContextFilePath; - std::string searchPaths; - std::string basePath; - std::string tpaList; - std::string entryAssemblyPath; - int argc; - char** argv; - bool verbose; - - void debugPrint() const + struct Args { - std::cerr << "Args:" << std::endl - << "- clrPath " << clrPath << std::endl - << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl - << "- searchPaths " << searchPaths << std::endl - << "- basePath " << basePath << std::endl - << "- tpaList " << tpaList << std::endl - << "- entryAssemblyPath " << entryAssemblyPath << std::endl - << "- argc " << argc << std::endl - << "- verbose " << (verbose ? "true" : "false") << std::endl; - } -}; + Args() : + argc(0), + argv(nullptr), + verbose(false) + { + } -// this is implemented without any 3rd party lib to keep the list -// of dependencies low -bool parseCmdline(const int argc, char** argv, Args& args) -{ - if (argc <= 1) + std::string clrPath; + std::string assemblyLoadContextFilePath; + std::string searchPaths; + std::string basePath; + std::string tpaList; + std::string entryAssemblyPath; + int argc; + char** argv; + bool verbose; + + void debugPrint() const + { + std::cerr << "Args:" << std::endl + << "- clrPath " << clrPath << std::endl + << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl + << "- searchPaths " << searchPaths << std::endl + << "- basePath " << basePath << std::endl + << "- tpaList " << tpaList << std::endl + << "- entryAssemblyPath " << entryAssemblyPath << std::endl + << "- argc " << argc << std::endl + << "- verbose " << (verbose ? "true" : "false") << std::endl; + } + }; + + // this is implemented without any 3rd party lib to keep the list + // of dependencies low + bool parseCmdline(const int argc, char** argv, Args& args) { - std::cerr << "error: missing arguments" << std::endl; - return false; + if (argc <= 1) + { + std::cerr << "error: missing arguments" << std::endl; + return false; + } + + for (int i = 1; i < argc; ++i) + { + const std::string arg = argv[i]; + const bool hasNextArg = i+1 < argc; + const std::string nextArg = hasNextArg ? std::string(argv[i+1]) : std::string(""); + + if (hasNextArg && (arg == "-c" || arg == "--clr-path")) + { + args.clrPath = nextArg; + ++i; + } + else if (hasNextArg && arg == "-alc") + { + args.assemblyLoadContextFilePath = nextArg; + ++i; + } + else if (hasNextArg && arg == "-s") + { + args.searchPaths = nextArg; + ++i; + } + else if (hasNextArg && arg == "-b") + { + args.basePath = nextArg; + ++i; + } + else if (hasNextArg && arg == "-tpa") + { + args.tpaList = nextArg; + ++i; + } + else if (arg == "-v") + { + args.verbose = true; + } + else if (args.entryAssemblyPath == "") + { + args.entryAssemblyPath = arg; + } + else + { + // forward command line parameters + args.argc = argc-i; + args.argv = &argv[i]; + + // explicitly break here because the lines above consume all remaining arguments + break; + } + } + + // check for mandatory parameters + if (args.entryAssemblyPath == "") + { + std::cerr << "error: assembly_name argument missing" << std::endl; + } + + return true; } - for (int i = 1; i < argc; ++i) - { - const std::string arg = argv[i]; - const bool hasNextArg = i+1 < argc; - const std::string nextArg = hasNextArg ? std::string(argv[i+1]) : std::string(""); - - if (hasNextArg && (arg == "-c" || arg == "--clr-path")) - { - args.clrPath = nextArg; - ++i; - } - else if (hasNextArg && arg == "-alc") - { - args.assemblyLoadContextFilePath = nextArg; - ++i; - } - else if (hasNextArg && arg == "-s") - { - args.searchPaths = nextArg; - ++i; - } - else if (hasNextArg && arg == "-b") - { - args.basePath = nextArg; - ++i; - } - else if (hasNextArg && arg == "-tpa") - { - args.tpaList = nextArg; - ++i; - } - else if (arg == "-v") - { - args.verbose = true; - } - else if (args.entryAssemblyPath == "") - { - args.entryAssemblyPath = arg; - } - else - { - // forward command line parameters - args.argc = argc-i; - args.argv = &argv[i]; - - // explicitly break here because the lines above consume all remaining arguments - break; - } - } - - // check for mandatory parameters - if (args.entryAssemblyPath == "") - { - std::cerr << "error: assembly_name argument missing" << std::endl; - } - - return true; -} - } int main(int argc, char** argv) @@ -356,13 +355,13 @@ int main(int argc, char** argv) void* hostHandle; unsigned int domainId; int status = initializeCoreCLR( - currentExeAbsolutePath.c_str(), - "ps_cmdline_host", - sizeof(propertyKeys)/sizeof(propertyKeys[0]), - propertyKeys, - propertyValues, - &hostHandle, - &domainId); + currentExeAbsolutePath.c_str(), + "ps_cmdline_host", + sizeof(propertyKeys)/sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + &hostHandle, + &domainId); if (0 > status) { @@ -374,12 +373,12 @@ int main(int argc, char** argv) typedef void (*LoaderRunHelperFp)(const char16_t* appPath); LoaderRunHelperFp loaderDelegate = nullptr; status = createDelegate( - hostHandle, - domainId, - "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "System.Management.Automation.PowerShellAssemblyLoadContextInitializer", - "SetPowerShellAssemblyLoadContext", - (void**)&loaderDelegate); + hostHandle, + domainId, + "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "System.Management.Automation.PowerShellAssemblyLoadContextInitializer", + "SetPowerShellAssemblyLoadContext", + (void**)&loaderDelegate); if (0 > status) { std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index 6aa8b9896a..07509a4942 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -7,103 +7,102 @@ namespace CoreCLRUtil { - -bool GetAbsolutePath(const char* path, std::string& absolutePath) -{ - bool result = false; - - char realPath[PATH_MAX]; - if (realpath(path, realPath) != nullptr && realPath[0] != '\0') + bool GetAbsolutePath(const char* path, std::string& absolutePath) { - absolutePath.assign(realPath); - // realpath should return canonicalized path without the trailing slash - assert(absolutePath.back() != '/'); + bool result = false; - result = true; - } - - return result; -} - -bool GetDirectory(const char* absolutePath, std::string& directory) -{ - directory.assign(absolutePath); - size_t lastSlash = directory.rfind('/'); - if (lastSlash != std::string::npos) - { - directory.erase(lastSlash); - return true; - } - - return false; -} - -bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) -{ - std::string clrFilesRelativePath; - const char* clrFilesPathLocal = clrFilesPath; - if (clrFilesPathLocal == nullptr) - { - // There was no CLR files path specified, use the folder of the corerun/coreconsole - if (!GetDirectory(currentExePath, clrFilesRelativePath)) + char realPath[PATH_MAX]; + if (realpath(path, realPath) != nullptr && realPath[0] != '\0') { - perror("Failed to get directory from argv[0]"); - return false; + absolutePath.assign(realPath); + // realpath should return canonicalized path without the trailing slash + assert(absolutePath.back() != '/'); + + result = true; } - clrFilesPathLocal = clrFilesRelativePath.c_str(); - - // TODO: consider using an env variable (if defined) as a fall-back. - // The windows version of the corerun uses core_root env variable + return result; } - if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) + bool GetDirectory(const char* absolutePath, std::string& directory) { - perror("Failed to convert CLR files path to absolute path"); + directory.assign(absolutePath); + size_t lastSlash = directory.rfind('/'); + if (lastSlash != std::string::npos) + { + directory.erase(lastSlash); + return true; + } + return false; } - return true; -} - -void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) -{ - const char * const tpaExtensions[] = { - ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir - ".dll", - ".ni.exe", - ".exe", - }; - - DIR* dir = opendir(directory); - if (dir == nullptr) + bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) { - return; + std::string clrFilesRelativePath; + const char* clrFilesPathLocal = clrFilesPath; + if (clrFilesPathLocal == nullptr) + { + // There was no CLR files path specified, use the folder of the corerun/coreconsole + if (!GetDirectory(currentExePath, clrFilesRelativePath)) + { + perror("Failed to get directory from argv[0]"); + return false; + } + + clrFilesPathLocal = clrFilesRelativePath.c_str(); + + // TODO: consider using an env variable (if defined) as a fall-back. + // The windows version of the corerun uses core_root env variable + } + + if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) + { + perror("Failed to convert CLR files path to absolute path"); + return false; + } + + return true; } - std::set addedAssemblies; - - // Walk the directory for each extension separately so that we first get files with .ni.dll extension, - // then files with .dll extension, etc. - for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) { - const char* ext = tpaExtensions[extIndex]; - int extLength = strlen(ext); - - struct dirent* entry; - - // For all entries in the directory - while ((entry = readdir(dir)) != nullptr) + const char * const tpaExtensions[] = { + ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir + ".dll", + ".ni.exe", + ".exe", + }; + + DIR* dir = opendir(directory); + if (dir == nullptr) { - // We are interested in files only - switch (entry->d_type) - { - case DT_REG: - break; + return; + } - // Handle symlinks and file systems that do not support d_type - case DT_LNK: - case DT_UNKNOWN: + std::set addedAssemblies; + + // Walk the directory for each extension separately so that we first get files with .ni.dll extension, + // then files with .dll extension, etc. + for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + { + const char* ext = tpaExtensions[extIndex]; + int extLength = strlen(ext); + + struct dirent* entry; + + // For all entries in the directory + while ((entry = readdir(dir)) != nullptr) + { + // We are interested in files only + switch (entry->d_type) + { + case DT_REG: + break; + + // Handle symlinks and file systems that do not support d_type + case DT_LNK: + case DT_UNKNOWN: { std::string fullFilename; @@ -124,44 +123,42 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) } break; - default: - continue; + default: + continue; + } + + std::string filename(entry->d_name); + + // Check if the extension matches the one we are looking for + int extPos = filename.length() - extLength; + if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) + { + continue; + } + + std::string filenameWithoutExt(filename.substr(0, extPos)); + + // Make sure if we have an assembly with multiple extensions present, + // we insert only one version of it. + if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) + { + addedAssemblies.insert(filenameWithoutExt); + + tpaList.append(directory); + tpaList.append("/"); + tpaList.append(filename); + tpaList.append(":"); + } } - - std::string filename(entry->d_name); - - // Check if the extension matches the one we are looking for - int extPos = filename.length() - extLength; - if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) - { - continue; - } - - std::string filenameWithoutExt(filename.substr(0, extPos)); - - // Make sure if we have an assembly with multiple extensions present, - // we insert only one version of it. - if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) - { - addedAssemblies.insert(filenameWithoutExt); - - tpaList.append(directory); - tpaList.append("/"); - tpaList.append(filename); - tpaList.append(":"); - } - } - // Rewind the directory stream to be able to iterate over it for the next extension - rewinddir(dir); - } + // Rewind the directory stream to be able to iterate over it for the next extension + rewinddir(dir); + } - closedir(dir); + closedir(dir); - // strip any trailing : from the tpaList - if (tpaList.size() > 0 && tpaList[tpaList.size()-1] == ':') - tpaList.resize(tpaList.size()-1); + // strip any trailing : from the tpaList + if (tpaList.size() > 0 && tpaList[tpaList.size()-1] == ':') + tpaList.resize(tpaList.size()-1); + } } - -} // namespace CoreCLRUtil - diff --git a/src/host/common/coreclrutil.h b/src/host/common/coreclrutil.h index 49a45ab6e1..6236c8deea 100644 --- a/src/host/common/coreclrutil.h +++ b/src/host/common/coreclrutil.h @@ -4,60 +4,59 @@ namespace CoreCLRUtil { + // + // This code is mostly copied and modified from original CoreCLR project's + // code on github: https://github.com/dotnet/coreclr + // -// -// This code is mostly copied and modified from original CoreCLR project's -// code on github: https://github.com/dotnet/coreclr -// + // + // these function signatures are the entry point API for CoreCLR + // -// -// these function signatures are the entry point API for CoreCLR -// + // Prototype of the coreclr_initialize function from the libcoreclr.so + typedef int (*InitializeCoreCLRFunction)( + const char* exePath, + const char* appDomainFriendlyName, + int propertyCount, + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId); -// Prototype of the coreclr_initialize function from the libcoreclr.so -typedef int (*InitializeCoreCLRFunction)( - const char* exePath, - const char* appDomainFriendlyName, - int propertyCount, - const char** propertyKeys, - const char** propertyValues, - void** hostHandle, - unsigned int* domainId); + // Prototype of the coreclr_shutdown function from the libcoreclr.so + typedef int (*ShutdownCoreCLRFunction)( + void* hostHandle, + unsigned int domainId); -// Prototype of the coreclr_shutdown function from the libcoreclr.so -typedef int (*ShutdownCoreCLRFunction)( - void* hostHandle, - unsigned int domainId); + // Prototype of the coreclr_execute_assembly function from the libcoreclr.so + typedef int (*ExecuteAssemblyFunction)( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode); -// Prototype of the coreclr_execute_assembly function from the libcoreclr.so -typedef int (*ExecuteAssemblyFunction)( - void* hostHandle, - unsigned int domainId, - int argc, - const char** argv, - const char* managedAssemblyPath, - unsigned int* exitCode); + // Prototype of coreclr_create_delegate function from the libcoreclr.so + typedef int (*CreateDelegateFunction)( + void* hostHandle, + unsigned int domainId, + const char* entryPointAssemblyName, + const char* entryPointTypeName, + const char* entryPointMethodName, + void** delegate); -// Prototype of coreclr_create_delegate function from the libcoreclr.so -typedef int (*CreateDelegateFunction)( - void* hostHandle, - unsigned int domainId, - const char* entryPointAssemblyName, - const char* entryPointTypeName, - const char* entryPointMethodName, - void** delegate); - -// The name of the CoreCLR native runtime DLL + // The name of the CoreCLR native runtime DLL #if defined(__APPLE__) -constexpr char coreClrDll[] = "libcoreclr.dylib"; + constexpr char coreClrDll[] = "libcoreclr.dylib"; #else -constexpr char coreClrDll[] = "libcoreclr.so"; + constexpr char coreClrDll[] = "libcoreclr.so"; #endif -bool GetAbsolutePath(const char* path, std::string& absolutePath); -bool GetDirectory(const char* absolutePath, std::string& directory); -bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); -void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); + bool GetAbsolutePath(const char* path, std::string& absolutePath); + bool GetDirectory(const char* absolutePath, std::string& directory); + bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); + void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); } // namespace CoreCLRUtil diff --git a/src/host/common/hostutil.h b/src/host/common/hostutil.h index a8c9a208d3..60bec5519a 100644 --- a/src/host/common/hostutil.h +++ b/src/host/common/hostutil.h @@ -5,44 +5,40 @@ namespace HostUtil { - -//!\brief get a list of absolute paths separated by : from a list of relative/absolute paths separated by : -std::string getAbsolutePathList(const std::string& paths) -{ - //std::cerr << "getAbsolutePathList: paths=" << paths << std::endl; - std::string result; - - // split by : - size_t lastPos = 0; - size_t curPos = paths.find(':',lastPos); - do + //!\brief get a list of absolute paths separated by : from a list of relative/absolute paths separated by : + std::string getAbsolutePathList(const std::string& paths) { - const std::string token = paths.substr(lastPos,curPos-lastPos); - //std::cerr << "curPos=" << curPos << " lastPos=" << lastPos << " token=" << token << std::endl; + //std::cerr << "getAbsolutePathList: paths=" << paths << std::endl; + std::string result; - // skip empty tokens - if (token != "") + // split by : + size_t lastPos = 0; + size_t curPos = paths.find(':',lastPos); + do { - std::string absolutePath; - if (CoreCLRUtil::GetAbsolutePath(token.c_str(),absolutePath)) + const std::string token = paths.substr(lastPos,curPos-lastPos); + //std::cerr << "curPos=" << curPos << " lastPos=" << lastPos << " token=" << token << std::endl; + + // skip empty tokens + if (token != "") { - // add colons correctly - if (result.size() == 0) - result += absolutePath; - else - result += ":" + absolutePath; + std::string absolutePath; + if (CoreCLRUtil::GetAbsolutePath(token.c_str(),absolutePath)) + { + // add colons correctly + if (result.size() == 0) + result += absolutePath; + else + result += ":" + absolutePath; + } } + + // increment lastPos to skip the : + lastPos += token.size() + 1; + curPos = paths.find(':',lastPos); } + while (lastPos < paths.size()); - // increment lastPos to skip the : - lastPos += token.size() + 1; - curPos = paths.find(':',lastPos); + return result; } - while (lastPos < paths.size()); - - return result; } - -} - - From be95c604e6fde505c8322f93722f2c7845deaebd Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 21 Oct 2015 15:22:57 -0700 Subject: [PATCH 188/298] Reindent host code using project standards --- host/cmdline/main.cpp | 303 ++++++++++++++++++------------------ host/common/coreclrutil.cpp | 229 ++++++++++++++------------- host/common/coreclrutil.h | 87 +++++------ host/common/hostutil.h | 60 ++++--- 4 files changed, 335 insertions(+), 344 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 61c1cb9e40..ce058b7ce7 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -11,153 +11,152 @@ namespace Cmdline { - -void printHelp() -{ - std::cerr << "PS CoreCLR host" << std::endl - << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl - << " [-b base_path] assembly [...]" << std::endl - << std::endl - << "What it does:" << std::endl - << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl - << " as host_cmdline" << std::endl - << " + this behavior can be overridden with the -c command line argument" << std::endl - << "- by default the host assumes that the assembly named" << std::endl - << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl - << " platform assemblies" << std::endl - << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl - << " be provided with the -alc command line argument" << std::endl - << "- all additional parameters at the end of the command line are forwarded" << std::endl - << " to the Main function in the assembly" << std::endl - << "- the host will execute the Main function in the specified assembly" << std::endl - << " + this assembly has to be located in the search path" << std::endl - << "- by default the host will add the current working directory to the assembly search path" << std::endl - << " + this can be overridden with the -s command line argument" << std::endl - << " + if -c is specified, it will be added to the search path instead of the current directory" << std::endl - << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl - << " working directory" << std::endl - << " + this can be overridden with the -b command line argument" << std::endl - << "- the function signature of the Main function that gets executed must be:" << std::endl - << " static void Main(string[] args)" << std::endl - << std::endl - << "Options:" << std::endl - << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl - << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl - << "-s a list of assembly search paths, separated by :" << std::endl - << "-b the powershell assembly base path" << std::endl - << "-v verbose output, show paths" << std::endl - << "-tpa additional list of trusted platform assemblies, this references dll and exe files" << std::endl - << " separated by :" << std::endl - << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl - << " argument, must always be added to the TPA list with this parameter" << std::endl - << "assembly the path of the assembly to execute relative to current directory" << std::endl - << std::endl - << "Example:" << std::endl - << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; -} - -struct Args -{ - Args() : - argc(0), - argv(nullptr), - verbose(false) + void printHelp() { + std::cerr << "PS CoreCLR host" << std::endl + << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl + << " [-b base_path] assembly [...]" << std::endl + << std::endl + << "What it does:" << std::endl + << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl + << " as host_cmdline" << std::endl + << " + this behavior can be overridden with the -c command line argument" << std::endl + << "- by default the host assumes that the assembly named" << std::endl + << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl + << " platform assemblies" << std::endl + << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl + << " be provided with the -alc command line argument" << std::endl + << "- all additional parameters at the end of the command line are forwarded" << std::endl + << " to the Main function in the assembly" << std::endl + << "- the host will execute the Main function in the specified assembly" << std::endl + << " + this assembly has to be located in the search path" << std::endl + << "- by default the host will add the current working directory to the assembly search path" << std::endl + << " + this can be overridden with the -s command line argument" << std::endl + << " + if -c is specified, it will be added to the search path instead of the current directory" << std::endl + << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl + << " working directory" << std::endl + << " + this can be overridden with the -b command line argument" << std::endl + << "- the function signature of the Main function that gets executed must be:" << std::endl + << " static void Main(string[] args)" << std::endl + << std::endl + << "Options:" << std::endl + << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl + << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl + << "-s a list of assembly search paths, separated by :" << std::endl + << "-b the powershell assembly base path" << std::endl + << "-v verbose output, show paths" << std::endl + << "-tpa additional list of trusted platform assemblies, this references dll and exe files" << std::endl + << " separated by :" << std::endl + << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl + << " argument, must always be added to the TPA list with this parameter" << std::endl + << "assembly the path of the assembly to execute relative to current directory" << std::endl + << std::endl + << "Example:" << std::endl + << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; } - std::string clrPath; - std::string assemblyLoadContextFilePath; - std::string searchPaths; - std::string basePath; - std::string tpaList; - std::string entryAssemblyPath; - int argc; - char** argv; - bool verbose; - - void debugPrint() const + struct Args { - std::cerr << "Args:" << std::endl - << "- clrPath " << clrPath << std::endl - << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl - << "- searchPaths " << searchPaths << std::endl - << "- basePath " << basePath << std::endl - << "- tpaList " << tpaList << std::endl - << "- entryAssemblyPath " << entryAssemblyPath << std::endl - << "- argc " << argc << std::endl - << "- verbose " << (verbose ? "true" : "false") << std::endl; - } -}; + Args() : + argc(0), + argv(nullptr), + verbose(false) + { + } -// this is implemented without any 3rd party lib to keep the list -// of dependencies low -bool parseCmdline(const int argc, char** argv, Args& args) -{ - if (argc <= 1) + std::string clrPath; + std::string assemblyLoadContextFilePath; + std::string searchPaths; + std::string basePath; + std::string tpaList; + std::string entryAssemblyPath; + int argc; + char** argv; + bool verbose; + + void debugPrint() const + { + std::cerr << "Args:" << std::endl + << "- clrPath " << clrPath << std::endl + << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl + << "- searchPaths " << searchPaths << std::endl + << "- basePath " << basePath << std::endl + << "- tpaList " << tpaList << std::endl + << "- entryAssemblyPath " << entryAssemblyPath << std::endl + << "- argc " << argc << std::endl + << "- verbose " << (verbose ? "true" : "false") << std::endl; + } + }; + + // this is implemented without any 3rd party lib to keep the list + // of dependencies low + bool parseCmdline(const int argc, char** argv, Args& args) { - std::cerr << "error: missing arguments" << std::endl; - return false; + if (argc <= 1) + { + std::cerr << "error: missing arguments" << std::endl; + return false; + } + + for (int i = 1; i < argc; ++i) + { + const std::string arg = argv[i]; + const bool hasNextArg = i+1 < argc; + const std::string nextArg = hasNextArg ? std::string(argv[i+1]) : std::string(""); + + if (hasNextArg && (arg == "-c" || arg == "--clr-path")) + { + args.clrPath = nextArg; + ++i; + } + else if (hasNextArg && arg == "-alc") + { + args.assemblyLoadContextFilePath = nextArg; + ++i; + } + else if (hasNextArg && arg == "-s") + { + args.searchPaths = nextArg; + ++i; + } + else if (hasNextArg && arg == "-b") + { + args.basePath = nextArg; + ++i; + } + else if (hasNextArg && arg == "-tpa") + { + args.tpaList = nextArg; + ++i; + } + else if (arg == "-v") + { + args.verbose = true; + } + else if (args.entryAssemblyPath == "") + { + args.entryAssemblyPath = arg; + } + else + { + // forward command line parameters + args.argc = argc-i; + args.argv = &argv[i]; + + // explicitly break here because the lines above consume all remaining arguments + break; + } + } + + // check for mandatory parameters + if (args.entryAssemblyPath == "") + { + std::cerr << "error: assembly_name argument missing" << std::endl; + } + + return true; } - for (int i = 1; i < argc; ++i) - { - const std::string arg = argv[i]; - const bool hasNextArg = i+1 < argc; - const std::string nextArg = hasNextArg ? std::string(argv[i+1]) : std::string(""); - - if (hasNextArg && (arg == "-c" || arg == "--clr-path")) - { - args.clrPath = nextArg; - ++i; - } - else if (hasNextArg && arg == "-alc") - { - args.assemblyLoadContextFilePath = nextArg; - ++i; - } - else if (hasNextArg && arg == "-s") - { - args.searchPaths = nextArg; - ++i; - } - else if (hasNextArg && arg == "-b") - { - args.basePath = nextArg; - ++i; - } - else if (hasNextArg && arg == "-tpa") - { - args.tpaList = nextArg; - ++i; - } - else if (arg == "-v") - { - args.verbose = true; - } - else if (args.entryAssemblyPath == "") - { - args.entryAssemblyPath = arg; - } - else - { - // forward command line parameters - args.argc = argc-i; - args.argv = &argv[i]; - - // explicitly break here because the lines above consume all remaining arguments - break; - } - } - - // check for mandatory parameters - if (args.entryAssemblyPath == "") - { - std::cerr << "error: assembly_name argument missing" << std::endl; - } - - return true; -} - } int main(int argc, char** argv) @@ -356,13 +355,13 @@ int main(int argc, char** argv) void* hostHandle; unsigned int domainId; int status = initializeCoreCLR( - currentExeAbsolutePath.c_str(), - "ps_cmdline_host", - sizeof(propertyKeys)/sizeof(propertyKeys[0]), - propertyKeys, - propertyValues, - &hostHandle, - &domainId); + currentExeAbsolutePath.c_str(), + "ps_cmdline_host", + sizeof(propertyKeys)/sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + &hostHandle, + &domainId); if (0 > status) { @@ -374,12 +373,12 @@ int main(int argc, char** argv) typedef void (*LoaderRunHelperFp)(const char16_t* appPath); LoaderRunHelperFp loaderDelegate = nullptr; status = createDelegate( - hostHandle, - domainId, - "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "System.Management.Automation.PowerShellAssemblyLoadContextInitializer", - "SetPowerShellAssemblyLoadContext", - (void**)&loaderDelegate); + hostHandle, + domainId, + "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "System.Management.Automation.PowerShellAssemblyLoadContextInitializer", + "SetPowerShellAssemblyLoadContext", + (void**)&loaderDelegate); if (0 > status) { std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index 6aa8b9896a..07509a4942 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -7,103 +7,102 @@ namespace CoreCLRUtil { - -bool GetAbsolutePath(const char* path, std::string& absolutePath) -{ - bool result = false; - - char realPath[PATH_MAX]; - if (realpath(path, realPath) != nullptr && realPath[0] != '\0') + bool GetAbsolutePath(const char* path, std::string& absolutePath) { - absolutePath.assign(realPath); - // realpath should return canonicalized path without the trailing slash - assert(absolutePath.back() != '/'); + bool result = false; - result = true; - } - - return result; -} - -bool GetDirectory(const char* absolutePath, std::string& directory) -{ - directory.assign(absolutePath); - size_t lastSlash = directory.rfind('/'); - if (lastSlash != std::string::npos) - { - directory.erase(lastSlash); - return true; - } - - return false; -} - -bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) -{ - std::string clrFilesRelativePath; - const char* clrFilesPathLocal = clrFilesPath; - if (clrFilesPathLocal == nullptr) - { - // There was no CLR files path specified, use the folder of the corerun/coreconsole - if (!GetDirectory(currentExePath, clrFilesRelativePath)) + char realPath[PATH_MAX]; + if (realpath(path, realPath) != nullptr && realPath[0] != '\0') { - perror("Failed to get directory from argv[0]"); - return false; + absolutePath.assign(realPath); + // realpath should return canonicalized path without the trailing slash + assert(absolutePath.back() != '/'); + + result = true; } - clrFilesPathLocal = clrFilesRelativePath.c_str(); - - // TODO: consider using an env variable (if defined) as a fall-back. - // The windows version of the corerun uses core_root env variable + return result; } - if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) + bool GetDirectory(const char* absolutePath, std::string& directory) { - perror("Failed to convert CLR files path to absolute path"); + directory.assign(absolutePath); + size_t lastSlash = directory.rfind('/'); + if (lastSlash != std::string::npos) + { + directory.erase(lastSlash); + return true; + } + return false; } - return true; -} - -void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) -{ - const char * const tpaExtensions[] = { - ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir - ".dll", - ".ni.exe", - ".exe", - }; - - DIR* dir = opendir(directory); - if (dir == nullptr) + bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) { - return; + std::string clrFilesRelativePath; + const char* clrFilesPathLocal = clrFilesPath; + if (clrFilesPathLocal == nullptr) + { + // There was no CLR files path specified, use the folder of the corerun/coreconsole + if (!GetDirectory(currentExePath, clrFilesRelativePath)) + { + perror("Failed to get directory from argv[0]"); + return false; + } + + clrFilesPathLocal = clrFilesRelativePath.c_str(); + + // TODO: consider using an env variable (if defined) as a fall-back. + // The windows version of the corerun uses core_root env variable + } + + if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) + { + perror("Failed to convert CLR files path to absolute path"); + return false; + } + + return true; } - std::set addedAssemblies; - - // Walk the directory for each extension separately so that we first get files with .ni.dll extension, - // then files with .dll extension, etc. - for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) { - const char* ext = tpaExtensions[extIndex]; - int extLength = strlen(ext); - - struct dirent* entry; - - // For all entries in the directory - while ((entry = readdir(dir)) != nullptr) + const char * const tpaExtensions[] = { + ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir + ".dll", + ".ni.exe", + ".exe", + }; + + DIR* dir = opendir(directory); + if (dir == nullptr) { - // We are interested in files only - switch (entry->d_type) - { - case DT_REG: - break; + return; + } - // Handle symlinks and file systems that do not support d_type - case DT_LNK: - case DT_UNKNOWN: + std::set addedAssemblies; + + // Walk the directory for each extension separately so that we first get files with .ni.dll extension, + // then files with .dll extension, etc. + for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + { + const char* ext = tpaExtensions[extIndex]; + int extLength = strlen(ext); + + struct dirent* entry; + + // For all entries in the directory + while ((entry = readdir(dir)) != nullptr) + { + // We are interested in files only + switch (entry->d_type) + { + case DT_REG: + break; + + // Handle symlinks and file systems that do not support d_type + case DT_LNK: + case DT_UNKNOWN: { std::string fullFilename; @@ -124,44 +123,42 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) } break; - default: - continue; + default: + continue; + } + + std::string filename(entry->d_name); + + // Check if the extension matches the one we are looking for + int extPos = filename.length() - extLength; + if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) + { + continue; + } + + std::string filenameWithoutExt(filename.substr(0, extPos)); + + // Make sure if we have an assembly with multiple extensions present, + // we insert only one version of it. + if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) + { + addedAssemblies.insert(filenameWithoutExt); + + tpaList.append(directory); + tpaList.append("/"); + tpaList.append(filename); + tpaList.append(":"); + } } - - std::string filename(entry->d_name); - - // Check if the extension matches the one we are looking for - int extPos = filename.length() - extLength; - if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) - { - continue; - } - - std::string filenameWithoutExt(filename.substr(0, extPos)); - - // Make sure if we have an assembly with multiple extensions present, - // we insert only one version of it. - if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) - { - addedAssemblies.insert(filenameWithoutExt); - - tpaList.append(directory); - tpaList.append("/"); - tpaList.append(filename); - tpaList.append(":"); - } - } - // Rewind the directory stream to be able to iterate over it for the next extension - rewinddir(dir); - } + // Rewind the directory stream to be able to iterate over it for the next extension + rewinddir(dir); + } - closedir(dir); + closedir(dir); - // strip any trailing : from the tpaList - if (tpaList.size() > 0 && tpaList[tpaList.size()-1] == ':') - tpaList.resize(tpaList.size()-1); + // strip any trailing : from the tpaList + if (tpaList.size() > 0 && tpaList[tpaList.size()-1] == ':') + tpaList.resize(tpaList.size()-1); + } } - -} // namespace CoreCLRUtil - diff --git a/host/common/coreclrutil.h b/host/common/coreclrutil.h index 49a45ab6e1..6236c8deea 100644 --- a/host/common/coreclrutil.h +++ b/host/common/coreclrutil.h @@ -4,60 +4,59 @@ namespace CoreCLRUtil { + // + // This code is mostly copied and modified from original CoreCLR project's + // code on github: https://github.com/dotnet/coreclr + // -// -// This code is mostly copied and modified from original CoreCLR project's -// code on github: https://github.com/dotnet/coreclr -// + // + // these function signatures are the entry point API for CoreCLR + // -// -// these function signatures are the entry point API for CoreCLR -// + // Prototype of the coreclr_initialize function from the libcoreclr.so + typedef int (*InitializeCoreCLRFunction)( + const char* exePath, + const char* appDomainFriendlyName, + int propertyCount, + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId); -// Prototype of the coreclr_initialize function from the libcoreclr.so -typedef int (*InitializeCoreCLRFunction)( - const char* exePath, - const char* appDomainFriendlyName, - int propertyCount, - const char** propertyKeys, - const char** propertyValues, - void** hostHandle, - unsigned int* domainId); + // Prototype of the coreclr_shutdown function from the libcoreclr.so + typedef int (*ShutdownCoreCLRFunction)( + void* hostHandle, + unsigned int domainId); -// Prototype of the coreclr_shutdown function from the libcoreclr.so -typedef int (*ShutdownCoreCLRFunction)( - void* hostHandle, - unsigned int domainId); + // Prototype of the coreclr_execute_assembly function from the libcoreclr.so + typedef int (*ExecuteAssemblyFunction)( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode); -// Prototype of the coreclr_execute_assembly function from the libcoreclr.so -typedef int (*ExecuteAssemblyFunction)( - void* hostHandle, - unsigned int domainId, - int argc, - const char** argv, - const char* managedAssemblyPath, - unsigned int* exitCode); + // Prototype of coreclr_create_delegate function from the libcoreclr.so + typedef int (*CreateDelegateFunction)( + void* hostHandle, + unsigned int domainId, + const char* entryPointAssemblyName, + const char* entryPointTypeName, + const char* entryPointMethodName, + void** delegate); -// Prototype of coreclr_create_delegate function from the libcoreclr.so -typedef int (*CreateDelegateFunction)( - void* hostHandle, - unsigned int domainId, - const char* entryPointAssemblyName, - const char* entryPointTypeName, - const char* entryPointMethodName, - void** delegate); - -// The name of the CoreCLR native runtime DLL + // The name of the CoreCLR native runtime DLL #if defined(__APPLE__) -constexpr char coreClrDll[] = "libcoreclr.dylib"; + constexpr char coreClrDll[] = "libcoreclr.dylib"; #else -constexpr char coreClrDll[] = "libcoreclr.so"; + constexpr char coreClrDll[] = "libcoreclr.so"; #endif -bool GetAbsolutePath(const char* path, std::string& absolutePath); -bool GetDirectory(const char* absolutePath, std::string& directory); -bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); -void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); + bool GetAbsolutePath(const char* path, std::string& absolutePath); + bool GetDirectory(const char* absolutePath, std::string& directory); + bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); + void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); } // namespace CoreCLRUtil diff --git a/host/common/hostutil.h b/host/common/hostutil.h index a8c9a208d3..60bec5519a 100644 --- a/host/common/hostutil.h +++ b/host/common/hostutil.h @@ -5,44 +5,40 @@ namespace HostUtil { - -//!\brief get a list of absolute paths separated by : from a list of relative/absolute paths separated by : -std::string getAbsolutePathList(const std::string& paths) -{ - //std::cerr << "getAbsolutePathList: paths=" << paths << std::endl; - std::string result; - - // split by : - size_t lastPos = 0; - size_t curPos = paths.find(':',lastPos); - do + //!\brief get a list of absolute paths separated by : from a list of relative/absolute paths separated by : + std::string getAbsolutePathList(const std::string& paths) { - const std::string token = paths.substr(lastPos,curPos-lastPos); - //std::cerr << "curPos=" << curPos << " lastPos=" << lastPos << " token=" << token << std::endl; + //std::cerr << "getAbsolutePathList: paths=" << paths << std::endl; + std::string result; - // skip empty tokens - if (token != "") + // split by : + size_t lastPos = 0; + size_t curPos = paths.find(':',lastPos); + do { - std::string absolutePath; - if (CoreCLRUtil::GetAbsolutePath(token.c_str(),absolutePath)) + const std::string token = paths.substr(lastPos,curPos-lastPos); + //std::cerr << "curPos=" << curPos << " lastPos=" << lastPos << " token=" << token << std::endl; + + // skip empty tokens + if (token != "") { - // add colons correctly - if (result.size() == 0) - result += absolutePath; - else - result += ":" + absolutePath; + std::string absolutePath; + if (CoreCLRUtil::GetAbsolutePath(token.c_str(),absolutePath)) + { + // add colons correctly + if (result.size() == 0) + result += absolutePath; + else + result += ":" + absolutePath; + } } + + // increment lastPos to skip the : + lastPos += token.size() + 1; + curPos = paths.find(':',lastPos); } + while (lastPos < paths.size()); - // increment lastPos to skip the : - lastPos += token.size() + 1; - curPos = paths.find(':',lastPos); + return result; } - while (lastPos < paths.size()); - - return result; } - -} - - From ba972b0113d26313113f7fb0c06d6348202e5aa5 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 21 Oct 2015 19:15:05 -0700 Subject: [PATCH 189/298] Refactor most CLR code into libpshost --- src/CMakeLists.txt | 5 +- src/host/cmdline/main.cpp | 108 +++------------------- src/host/common/coreclrutil.cpp | 154 ++++++++++++++++++++++++++++++++ src/host/common/coreclrutil.h | 79 +++++++--------- 4 files changed, 201 insertions(+), 145 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b534ebb94b..8db93c175b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,8 +24,9 @@ add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) # add pthread and other libs find_package(Threads) target_link_libraries(ps icuuc) -target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) -target_link_libraries(host_cmdline pshost dl icuuc) +target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps pshost) +target_link_libraries(pshost dl icuuc) +target_link_libraries(host_cmdline pshost icuuc) # target specific include directories target_include_directories(monad_native PRIVATE host) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index ce058b7ce7..32cb4eed87 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -3,7 +3,6 @@ #include "common/coreclrutil.h" #include "common/hostutil.h" #include -#include #include #include #include @@ -195,19 +194,6 @@ int main(int argc, char** argv) if (args.verbose) std::cerr << "clrAbsolutePath=" << clrAbsolutePath << std::endl; - // the path to the CoreCLR library - // - // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac - - std::string coreClrDllPath = clrAbsolutePath + "/" + CoreCLRUtil::coreClrDll; - if (coreClrDllPath.size() >= PATH_MAX) - { - std::cerr << "Absolute path to CoreCLR library too long" << std::endl; - return 1; - } - if (args.verbose) - std::cerr << "coreClrDllPath: " << coreClrDllPath << std::endl; - // TPA list // // The list of platform assemblies must include all CoreCLR assemblies @@ -297,82 +283,21 @@ int main(int argc, char** argv) int32_t targetSize = u8str.extract(0,u8str.length(),(char*)&psBasePath16[0],(psBasePath16.size()-1)*sizeof(char16_t),"UTF-16LE"); psBasePath16.resize(targetSize/sizeof(char16_t)+1); - // open the shared library - void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); - if (coreclrLib == nullptr) - { - char* error = dlerror(); - std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; - return 2; - } - - // query the function pointers - CoreCLRUtil::InitializeCoreCLRFunction initializeCoreCLR = (CoreCLRUtil::InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); - CoreCLRUtil::ExecuteAssemblyFunction executeAssembly = (CoreCLRUtil::ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); - CoreCLRUtil::ShutdownCoreCLRFunction shutdownCoreCLR = (CoreCLRUtil::ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); - CoreCLRUtil::CreateDelegateFunction createDelegate = (CoreCLRUtil::CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); - - if (initializeCoreCLR == nullptr) - { - std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; - return 3; - } - if (executeAssembly == nullptr) - { - std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; - return 3; - } - if (shutdownCoreCLR == nullptr) - { - std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; - return 3; - } - if (createDelegate == nullptr) - { - std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; - return 3; - } - - // create list of properties to initialize CoreCLR - const char* propertyKeys[] = { - "TRUSTED_PLATFORM_ASSEMBLIES", - "APP_PATHS", - "APP_NI_PATHS", - "NATIVE_DLL_SEARCH_DIRECTORIES", - "AppDomainCompatSwitch" - }; - - const char* propertyValues[] = { - tpaList.c_str(), - appPath.c_str(), - appPath.c_str(), - nativeDllSearchDirs.c_str(), - "UseLatestBehaviorWhenTFMNotSpecified" - }; - - - // initialize CoreCLR void* hostHandle; unsigned int domainId; - int status = initializeCoreCLR( - currentExeAbsolutePath.c_str(), + int status = CoreCLRUtil::startCoreClr( + clrAbsolutePath.c_str(), + tpaList.c_str(), + appPath.c_str(), + nativeDllSearchDirs.c_str(), "ps_cmdline_host", - sizeof(propertyKeys)/sizeof(propertyKeys[0]), - propertyKeys, - propertyValues, &hostHandle, &domainId); - if (0 > status) - { - std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; - return 4; - } - // initialize the PS's custom assembly load context typedef void (*LoaderRunHelperFp)(const char16_t* appPath); LoaderRunHelperFp loaderDelegate = nullptr; - status = createDelegate( + status = CoreCLRUtil::createDelegate( hostHandle, domainId, "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", @@ -388,23 +313,12 @@ int main(int argc, char** argv) // call into Main of powershell-simple.exe unsigned int exitCode; - executeAssembly(hostHandle, domainId, args.argc, - (const char**)args.argv, - (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), - &exitCode); + CoreCLRUtil::executeAssembly(hostHandle, domainId, args.argc, + (const char**)args.argv, + (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), + &exitCode); - // shutdown CoreCLR - status = shutdownCoreCLR(hostHandle,domainId); - if (0 > status) - { - std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; - } - - // close the dynamic library - if (0 != dlclose(coreclrLib)) - { - std::cerr << "failed to close CoreCLR library" << std::endl; - } + status = CoreCLRUtil::stopCoreClr(hostHandle, domainId); return exitCode; } diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index 07509a4942..edfc0662d1 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -1,12 +1,166 @@ #include "coreclrutil.h" #include +#include #include #include #include +#include +#include #include namespace CoreCLRUtil { + // The name of the CoreCLR native runtime DLL +#if defined(__APPLE__) + constexpr char coreClrDll[] = "libcoreclr.dylib"; +#else + constexpr char coreClrDll[] = "libcoreclr.so"; +#endif + + void* coreclrLib; + + // Prototype of the coreclr_initialize function from the libcoreclr.so + typedef int (*InitializeCoreCLRFunction)( + const char* exePath, + const char* appDomainFriendlyName, + int propertyCount, + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId); + + InitializeCoreCLRFunction initializeCoreCLR; + + // Prototype of the coreclr_shutdown function from the libcoreclr.so + typedef int (*ShutdownCoreCLRFunction)( + void* hostHandle, + unsigned int domainId); + + ShutdownCoreCLRFunction shutdownCoreCLR; + + ExecuteAssemblyFunction executeAssembly; + CreateDelegateFunction createDelegate; + + int startCoreClr( + // Paths of expected things + const char* clrAbsolutePath, + // Passed to propertyValues + const char* tpaList, + const char* appPath, + const char* nativeDllSearchDirs, + // Passed to InitializeCoreCLRFunction + const char* appDomainFriendlyName, + void** hostHandle, + unsigned int* domainId) + { + // the path to the CoreCLR library + // + // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac + std::string coreClrDllPath = clrAbsolutePath; + coreClrDllPath += "/"; + coreClrDllPath += coreClrDll; + + if (coreClrDllPath.size() >= PATH_MAX) + { + std::cerr << "Absolute path to CoreCLR library too long" << std::endl; + return 1; + } + + // open the shared library + coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); + if (coreclrLib == nullptr) + { + char* error = dlerror(); + std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; + return 2; + } + + // query the function pointers + initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); + shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); + + executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); + createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); + + if (initializeCoreCLR == nullptr) + { + std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; + return 3; + } + if (executeAssembly == nullptr) + { + std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; + return 3; + } + if (shutdownCoreCLR == nullptr) + { + std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; + return 3; + } + if (createDelegate == nullptr) + { + std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; + return 3; + } + + // create list of properties to initialize CoreCLR + const char* propertyKeys[] = { + "TRUSTED_PLATFORM_ASSEMBLIES", + "APP_PATHS", + "APP_NI_PATHS", + "NATIVE_DLL_SEARCH_DIRECTORIES", + "AppDomainCompatSwitch" + }; + + const char* propertyValues[] = { + tpaList, + appPath, + appPath, + nativeDllSearchDirs, + "UseLatestBehaviorWhenTFMNotSpecified" + }; + + // get path to current executable + char exePath[PATH_MAX] = { 0 }; + readlink("/proc/self/exe", exePath, PATH_MAX); + + // initialize CoreCLR + int status = initializeCoreCLR( + exePath, + appDomainFriendlyName, + sizeof(propertyKeys)/sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + hostHandle, + domainId); + + if (0 > status) + { + std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; + return 4; + } + + return status; + } + + int stopCoreClr(void* hostHandle, unsigned int domainId) + { + // shutdown CoreCLR + int status = shutdownCoreCLR(hostHandle, domainId); + if (0 > status) + { + std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; + } + + // close the dynamic library + if (0 != dlclose(coreclrLib)) + { + std::cerr << "failed to close CoreCLR library" << std::endl; + } + + return status; + } + bool GetAbsolutePath(const char* path, std::string& absolutePath) { bool result = false; diff --git a/src/host/common/coreclrutil.h b/src/host/common/coreclrutil.h index 6236c8deea..fe0ad77fc5 100644 --- a/src/host/common/coreclrutil.h +++ b/src/host/common/coreclrutil.h @@ -4,59 +4,46 @@ namespace CoreCLRUtil { - // - // This code is mostly copied and modified from original CoreCLR project's - // code on github: https://github.com/dotnet/coreclr - // + extern "C" { + int startCoreClr( + // Paths of expected things + const char* clrAbsolutePath, + // Passed to propertyValues + const char* tpaList, + const char* appPath, + const char* nativeDllSearchDirs, + // Passed to InitializeCoreCLRFunction + const char* appDomainFriendlyName, + void** hostHandle, + unsigned int* domainId); - // - // these function signatures are the entry point API for CoreCLR - // + int stopCoreClr(void* hostHandle, unsigned int domainId); - // Prototype of the coreclr_initialize function from the libcoreclr.so - typedef int (*InitializeCoreCLRFunction)( - const char* exePath, - const char* appDomainFriendlyName, - int propertyCount, - const char** propertyKeys, - const char** propertyValues, - void** hostHandle, - unsigned int* domainId); + // Prototype of the coreclr_execute_assembly function from the libcoreclr.so + typedef int (*ExecuteAssemblyFunction)( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode); - // Prototype of the coreclr_shutdown function from the libcoreclr.so - typedef int (*ShutdownCoreCLRFunction)( - void* hostHandle, - unsigned int domainId); + extern ExecuteAssemblyFunction executeAssembly; - // Prototype of the coreclr_execute_assembly function from the libcoreclr.so - typedef int (*ExecuteAssemblyFunction)( - void* hostHandle, - unsigned int domainId, - int argc, - const char** argv, - const char* managedAssemblyPath, - unsigned int* exitCode); + // Prototype of coreclr_create_delegate function from the libcoreclr.so + typedef int (*CreateDelegateFunction)( + void* hostHandle, + unsigned int domainId, + const char* entryPointAssemblyName, + const char* entryPointTypeName, + const char* entryPointMethodName, + void** delegate); - // Prototype of coreclr_create_delegate function from the libcoreclr.so - typedef int (*CreateDelegateFunction)( - void* hostHandle, - unsigned int domainId, - const char* entryPointAssemblyName, - const char* entryPointTypeName, - const char* entryPointMethodName, - void** delegate); - - // The name of the CoreCLR native runtime DLL -#if defined(__APPLE__) - constexpr char coreClrDll[] = "libcoreclr.dylib"; -#else - constexpr char coreClrDll[] = "libcoreclr.so"; -#endif + extern CreateDelegateFunction createDelegate; + } bool GetAbsolutePath(const char* path, std::string& absolutePath); bool GetDirectory(const char* absolutePath, std::string& directory); bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); - -} // namespace CoreCLRUtil - +} From a1b9511f384b59848906931f2ee965313a58f45f Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 21 Oct 2015 19:15:05 -0700 Subject: [PATCH 190/298] Refactor most CLR code into libpshost --- CMakeLists.txt | 5 +- host/cmdline/main.cpp | 108 +++---------------------- host/common/coreclrutil.cpp | 154 ++++++++++++++++++++++++++++++++++++ host/common/coreclrutil.h | 79 ++++++++---------- 4 files changed, 201 insertions(+), 145 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b534ebb94b..8db93c175b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,8 +24,9 @@ add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) # add pthread and other libs find_package(Threads) target_link_libraries(ps icuuc) -target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps) -target_link_libraries(host_cmdline pshost dl icuuc) +target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps pshost) +target_link_libraries(pshost dl icuuc) +target_link_libraries(host_cmdline pshost icuuc) # target specific include directories target_include_directories(monad_native PRIVATE host) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index ce058b7ce7..32cb4eed87 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -3,7 +3,6 @@ #include "common/coreclrutil.h" #include "common/hostutil.h" #include -#include #include #include #include @@ -195,19 +194,6 @@ int main(int argc, char** argv) if (args.verbose) std::cerr << "clrAbsolutePath=" << clrAbsolutePath << std::endl; - // the path to the CoreCLR library - // - // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac - - std::string coreClrDllPath = clrAbsolutePath + "/" + CoreCLRUtil::coreClrDll; - if (coreClrDllPath.size() >= PATH_MAX) - { - std::cerr << "Absolute path to CoreCLR library too long" << std::endl; - return 1; - } - if (args.verbose) - std::cerr << "coreClrDllPath: " << coreClrDllPath << std::endl; - // TPA list // // The list of platform assemblies must include all CoreCLR assemblies @@ -297,82 +283,21 @@ int main(int argc, char** argv) int32_t targetSize = u8str.extract(0,u8str.length(),(char*)&psBasePath16[0],(psBasePath16.size()-1)*sizeof(char16_t),"UTF-16LE"); psBasePath16.resize(targetSize/sizeof(char16_t)+1); - // open the shared library - void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); - if (coreclrLib == nullptr) - { - char* error = dlerror(); - std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; - return 2; - } - - // query the function pointers - CoreCLRUtil::InitializeCoreCLRFunction initializeCoreCLR = (CoreCLRUtil::InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); - CoreCLRUtil::ExecuteAssemblyFunction executeAssembly = (CoreCLRUtil::ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); - CoreCLRUtil::ShutdownCoreCLRFunction shutdownCoreCLR = (CoreCLRUtil::ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); - CoreCLRUtil::CreateDelegateFunction createDelegate = (CoreCLRUtil::CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); - - if (initializeCoreCLR == nullptr) - { - std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; - return 3; - } - if (executeAssembly == nullptr) - { - std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; - return 3; - } - if (shutdownCoreCLR == nullptr) - { - std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; - return 3; - } - if (createDelegate == nullptr) - { - std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; - return 3; - } - - // create list of properties to initialize CoreCLR - const char* propertyKeys[] = { - "TRUSTED_PLATFORM_ASSEMBLIES", - "APP_PATHS", - "APP_NI_PATHS", - "NATIVE_DLL_SEARCH_DIRECTORIES", - "AppDomainCompatSwitch" - }; - - const char* propertyValues[] = { - tpaList.c_str(), - appPath.c_str(), - appPath.c_str(), - nativeDllSearchDirs.c_str(), - "UseLatestBehaviorWhenTFMNotSpecified" - }; - - - // initialize CoreCLR void* hostHandle; unsigned int domainId; - int status = initializeCoreCLR( - currentExeAbsolutePath.c_str(), + int status = CoreCLRUtil::startCoreClr( + clrAbsolutePath.c_str(), + tpaList.c_str(), + appPath.c_str(), + nativeDllSearchDirs.c_str(), "ps_cmdline_host", - sizeof(propertyKeys)/sizeof(propertyKeys[0]), - propertyKeys, - propertyValues, &hostHandle, &domainId); - if (0 > status) - { - std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; - return 4; - } - // initialize the PS's custom assembly load context typedef void (*LoaderRunHelperFp)(const char16_t* appPath); LoaderRunHelperFp loaderDelegate = nullptr; - status = createDelegate( + status = CoreCLRUtil::createDelegate( hostHandle, domainId, "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", @@ -388,23 +313,12 @@ int main(int argc, char** argv) // call into Main of powershell-simple.exe unsigned int exitCode; - executeAssembly(hostHandle, domainId, args.argc, - (const char**)args.argv, - (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), - &exitCode); + CoreCLRUtil::executeAssembly(hostHandle, domainId, args.argc, + (const char**)args.argv, + (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), + &exitCode); - // shutdown CoreCLR - status = shutdownCoreCLR(hostHandle,domainId); - if (0 > status) - { - std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; - } - - // close the dynamic library - if (0 != dlclose(coreclrLib)) - { - std::cerr << "failed to close CoreCLR library" << std::endl; - } + status = CoreCLRUtil::stopCoreClr(hostHandle, domainId); return exitCode; } diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index 07509a4942..edfc0662d1 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -1,12 +1,166 @@ #include "coreclrutil.h" #include +#include #include #include #include +#include +#include #include namespace CoreCLRUtil { + // The name of the CoreCLR native runtime DLL +#if defined(__APPLE__) + constexpr char coreClrDll[] = "libcoreclr.dylib"; +#else + constexpr char coreClrDll[] = "libcoreclr.so"; +#endif + + void* coreclrLib; + + // Prototype of the coreclr_initialize function from the libcoreclr.so + typedef int (*InitializeCoreCLRFunction)( + const char* exePath, + const char* appDomainFriendlyName, + int propertyCount, + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId); + + InitializeCoreCLRFunction initializeCoreCLR; + + // Prototype of the coreclr_shutdown function from the libcoreclr.so + typedef int (*ShutdownCoreCLRFunction)( + void* hostHandle, + unsigned int domainId); + + ShutdownCoreCLRFunction shutdownCoreCLR; + + ExecuteAssemblyFunction executeAssembly; + CreateDelegateFunction createDelegate; + + int startCoreClr( + // Paths of expected things + const char* clrAbsolutePath, + // Passed to propertyValues + const char* tpaList, + const char* appPath, + const char* nativeDllSearchDirs, + // Passed to InitializeCoreCLRFunction + const char* appDomainFriendlyName, + void** hostHandle, + unsigned int* domainId) + { + // the path to the CoreCLR library + // + // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac + std::string coreClrDllPath = clrAbsolutePath; + coreClrDllPath += "/"; + coreClrDllPath += coreClrDll; + + if (coreClrDllPath.size() >= PATH_MAX) + { + std::cerr << "Absolute path to CoreCLR library too long" << std::endl; + return 1; + } + + // open the shared library + coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); + if (coreclrLib == nullptr) + { + char* error = dlerror(); + std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; + return 2; + } + + // query the function pointers + initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); + shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); + + executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); + createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); + + if (initializeCoreCLR == nullptr) + { + std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; + return 3; + } + if (executeAssembly == nullptr) + { + std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; + return 3; + } + if (shutdownCoreCLR == nullptr) + { + std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; + return 3; + } + if (createDelegate == nullptr) + { + std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; + return 3; + } + + // create list of properties to initialize CoreCLR + const char* propertyKeys[] = { + "TRUSTED_PLATFORM_ASSEMBLIES", + "APP_PATHS", + "APP_NI_PATHS", + "NATIVE_DLL_SEARCH_DIRECTORIES", + "AppDomainCompatSwitch" + }; + + const char* propertyValues[] = { + tpaList, + appPath, + appPath, + nativeDllSearchDirs, + "UseLatestBehaviorWhenTFMNotSpecified" + }; + + // get path to current executable + char exePath[PATH_MAX] = { 0 }; + readlink("/proc/self/exe", exePath, PATH_MAX); + + // initialize CoreCLR + int status = initializeCoreCLR( + exePath, + appDomainFriendlyName, + sizeof(propertyKeys)/sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + hostHandle, + domainId); + + if (0 > status) + { + std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; + return 4; + } + + return status; + } + + int stopCoreClr(void* hostHandle, unsigned int domainId) + { + // shutdown CoreCLR + int status = shutdownCoreCLR(hostHandle, domainId); + if (0 > status) + { + std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; + } + + // close the dynamic library + if (0 != dlclose(coreclrLib)) + { + std::cerr << "failed to close CoreCLR library" << std::endl; + } + + return status; + } + bool GetAbsolutePath(const char* path, std::string& absolutePath) { bool result = false; diff --git a/host/common/coreclrutil.h b/host/common/coreclrutil.h index 6236c8deea..fe0ad77fc5 100644 --- a/host/common/coreclrutil.h +++ b/host/common/coreclrutil.h @@ -4,59 +4,46 @@ namespace CoreCLRUtil { - // - // This code is mostly copied and modified from original CoreCLR project's - // code on github: https://github.com/dotnet/coreclr - // + extern "C" { + int startCoreClr( + // Paths of expected things + const char* clrAbsolutePath, + // Passed to propertyValues + const char* tpaList, + const char* appPath, + const char* nativeDllSearchDirs, + // Passed to InitializeCoreCLRFunction + const char* appDomainFriendlyName, + void** hostHandle, + unsigned int* domainId); - // - // these function signatures are the entry point API for CoreCLR - // + int stopCoreClr(void* hostHandle, unsigned int domainId); - // Prototype of the coreclr_initialize function from the libcoreclr.so - typedef int (*InitializeCoreCLRFunction)( - const char* exePath, - const char* appDomainFriendlyName, - int propertyCount, - const char** propertyKeys, - const char** propertyValues, - void** hostHandle, - unsigned int* domainId); + // Prototype of the coreclr_execute_assembly function from the libcoreclr.so + typedef int (*ExecuteAssemblyFunction)( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode); - // Prototype of the coreclr_shutdown function from the libcoreclr.so - typedef int (*ShutdownCoreCLRFunction)( - void* hostHandle, - unsigned int domainId); + extern ExecuteAssemblyFunction executeAssembly; - // Prototype of the coreclr_execute_assembly function from the libcoreclr.so - typedef int (*ExecuteAssemblyFunction)( - void* hostHandle, - unsigned int domainId, - int argc, - const char** argv, - const char* managedAssemblyPath, - unsigned int* exitCode); + // Prototype of coreclr_create_delegate function from the libcoreclr.so + typedef int (*CreateDelegateFunction)( + void* hostHandle, + unsigned int domainId, + const char* entryPointAssemblyName, + const char* entryPointTypeName, + const char* entryPointMethodName, + void** delegate); - // Prototype of coreclr_create_delegate function from the libcoreclr.so - typedef int (*CreateDelegateFunction)( - void* hostHandle, - unsigned int domainId, - const char* entryPointAssemblyName, - const char* entryPointTypeName, - const char* entryPointMethodName, - void** delegate); - - // The name of the CoreCLR native runtime DLL -#if defined(__APPLE__) - constexpr char coreClrDll[] = "libcoreclr.dylib"; -#else - constexpr char coreClrDll[] = "libcoreclr.so"; -#endif + extern CreateDelegateFunction createDelegate; + } bool GetAbsolutePath(const char* path, std::string& absolutePath); bool GetDirectory(const char* absolutePath, std::string& directory); bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); - -} // namespace CoreCLRUtil - +} From fa79c480d049a997692bd10ebace83962012f7a1 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 11:58:35 -0700 Subject: [PATCH 191/298] Add 'src/host/unixcoreruncommon/' from commit 'a566a181a076f4fa49f4874934c080309424bd6c' git-subtree-dir: src/host/unixcoreruncommon git-subtree-mainline: ba972b0113d26313113f7fb0c06d6348202e5aa5 git-subtree-split: a566a181a076f4fa49f4874934c080309424bd6c --- host/unixcoreruncommon/.gitmirror | 1 + host/unixcoreruncommon/coreruncommon.cpp | 346 +++++++++++++++++++++++ host/unixcoreruncommon/coreruncommon.h | 46 +++ 3 files changed, 393 insertions(+) create mode 100644 host/unixcoreruncommon/.gitmirror create mode 100644 host/unixcoreruncommon/coreruncommon.cpp create mode 100644 host/unixcoreruncommon/coreruncommon.h diff --git a/host/unixcoreruncommon/.gitmirror b/host/unixcoreruncommon/.gitmirror new file mode 100644 index 0000000000..f507630f94 --- /dev/null +++ b/host/unixcoreruncommon/.gitmirror @@ -0,0 +1 @@ +Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror. \ No newline at end of file diff --git a/host/unixcoreruncommon/coreruncommon.cpp b/host/unixcoreruncommon/coreruncommon.cpp new file mode 100644 index 0000000000..ecbbf39290 --- /dev/null +++ b/host/unixcoreruncommon/coreruncommon.cpp @@ -0,0 +1,346 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +// +// Code that is used by both the Unix corerun and coreconsole. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// The name of the CoreCLR native runtime DLL +#if defined(__APPLE__) +static const char * const coreClrDll = "libcoreclr.dylib"; +#else +static const char * const coreClrDll = "libcoreclr.so"; +#endif + +#define SUCCEEDED(Status) ((Status) >= 0) + +// Prototype of the coreclr_initialize function from the libcoreclr.so +typedef int (*InitializeCoreCLRFunction)( + const char* exePath, + const char* appDomainFriendlyName, + int propertyCount, + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId); + +// Prototype of the coreclr_shutdown function from the libcoreclr.so +typedef int (*ShutdownCoreCLRFunction)( + void* hostHandle, + unsigned int domainId); + +// Prototype of the coreclr_execute_assembly function from the libcoreclr.so +typedef int (*ExecuteAssemblyFunction)( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode); + +bool GetAbsolutePath(const char* path, std::string& absolutePath) +{ + bool result = false; + + char realPath[PATH_MAX]; + if (realpath(path, realPath) != nullptr && realPath[0] != '\0') + { + absolutePath.assign(realPath); + // realpath should return canonicalized path without the trailing slash + assert(absolutePath.back() != '/'); + + result = true; + } + + return result; +} + +bool GetDirectory(const char* absolutePath, std::string& directory) +{ + directory.assign(absolutePath); + size_t lastSlash = directory.rfind('/'); + if (lastSlash != std::string::npos) + { + directory.erase(lastSlash); + return true; + } + + return false; +} + +bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) +{ + std::string clrFilesRelativePath; + const char* clrFilesPathLocal = clrFilesPath; + if (clrFilesPathLocal == nullptr) + { + // There was no CLR files path specified, use the folder of the corerun/coreconsole + if (!GetDirectory(currentExePath, clrFilesRelativePath)) + { + perror("Failed to get directory from argv[0]"); + return false; + } + + clrFilesPathLocal = clrFilesRelativePath.c_str(); + + // TODO: consider using an env variable (if defined) as a fall-back. + // The windows version of the corerun uses core_root env variable + } + + if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) + { + perror("Failed to convert CLR files path to absolute path"); + return false; + } + + return true; +} + +void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) +{ + const char * const tpaExtensions[] = { + ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir + ".dll", + ".ni.exe", + ".exe", + }; + + DIR* dir = opendir(directory); + if (dir == nullptr) + { + return; + } + + std::set addedAssemblies; + + // Walk the directory for each extension separately so that we first get files with .ni.dll extension, + // then files with .dll extension, etc. + for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + { + const char* ext = tpaExtensions[extIndex]; + int extLength = strlen(ext); + + struct dirent* entry; + + // For all entries in the directory + while ((entry = readdir(dir)) != nullptr) + { + // We are interested in files only + switch (entry->d_type) + { + case DT_REG: + break; + + // Handle symlinks and file systems that do not support d_type + case DT_LNK: + case DT_UNKNOWN: + { + std::string fullFilename; + + fullFilename.append(directory); + fullFilename.append("/"); + fullFilename.append(entry->d_name); + + struct stat sb; + if (stat(fullFilename.c_str(), &sb) == -1) + { + continue; + } + + if (!S_ISREG(sb.st_mode)) + { + continue; + } + } + break; + + default: + continue; + } + + std::string filename(entry->d_name); + + // Check if the extension matches the one we are looking for + int extPos = filename.length() - extLength; + if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) + { + continue; + } + + std::string filenameWithoutExt(filename.substr(0, extPos)); + + // Make sure if we have an assembly with multiple extensions present, + // we insert only one version of it. + if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) + { + addedAssemblies.insert(filenameWithoutExt); + + tpaList.append(directory); + tpaList.append("/"); + tpaList.append(filename); + tpaList.append(":"); + } + } + + // Rewind the directory stream to be able to iterate over it for the next extension + rewinddir(dir); + } + + closedir(dir); +} + +int ExecuteManagedAssembly( + const char* currentExeAbsolutePath, + const char* clrFilesAbsolutePath, + const char* managedAssemblyAbsolutePath, + int managedAssemblyArgc, + const char** managedAssemblyArgv) +{ + // Indicates failure + int exitCode = -1; + + std::string coreClrDllPath(clrFilesAbsolutePath); + coreClrDllPath.append("/"); + coreClrDllPath.append(coreClrDll); + + if (coreClrDllPath.length() >= PATH_MAX) + { + fprintf(stderr, "Absolute path to libcoreclr.so too long\n"); + return -1; + } + + // Get just the path component of the managed assembly path + std::string appPath; + GetDirectory(managedAssemblyAbsolutePath, appPath); + + std::string nativeDllSearchDirs(appPath); + nativeDllSearchDirs.append(":"); + nativeDllSearchDirs.append(clrFilesAbsolutePath); + + std::string tpaList; + AddFilesFromDirectoryToTpaList(clrFilesAbsolutePath, tpaList); + + void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW | RTLD_LOCAL); + if (coreclrLib != nullptr) + { + InitializeCoreCLRFunction initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib, "coreclr_initialize"); + ExecuteAssemblyFunction executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib, "coreclr_execute_assembly"); + ShutdownCoreCLRFunction shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib, "coreclr_shutdown"); + + if (initializeCoreCLR == nullptr) + { + fprintf(stderr, "Function coreclr_initialize not found in the libcoreclr.so\n"); + } + else if (executeAssembly == nullptr) + { + fprintf(stderr, "Function coreclr_execute_assembly not found in the libcoreclr.so\n"); + } + else if (shutdownCoreCLR == nullptr) + { + fprintf(stderr, "Function coreclr_shutdown not found in the libcoreclr.so\n"); + } + else + { + // Allowed property names: + // APPBASE + // - The base path of the application from which the exe and other assemblies will be loaded + // + // TRUSTED_PLATFORM_ASSEMBLIES + // - The list of complete paths to each of the fully trusted assemblies + // + // APP_PATHS + // - The list of paths which will be probed by the assembly loader + // + // APP_NI_PATHS + // - The list of additional paths that the assembly loader will probe for ngen images + // + // NATIVE_DLL_SEARCH_DIRECTORIES + // - The list of paths that will be probed for native DLLs called by PInvoke + // + const char *propertyKeys[] = { + "TRUSTED_PLATFORM_ASSEMBLIES", + "APP_PATHS", + "APP_NI_PATHS", + "NATIVE_DLL_SEARCH_DIRECTORIES", + "AppDomainCompatSwitch" + }; + const char *propertyValues[] = { + // TRUSTED_PLATFORM_ASSEMBLIES + tpaList.c_str(), + // APP_PATHS + appPath.c_str(), + // APP_NI_PATHS + appPath.c_str(), + // NATIVE_DLL_SEARCH_DIRECTORIES + nativeDllSearchDirs.c_str(), + // AppDomainCompatSwitch + "UseLatestBehaviorWhenTFMNotSpecified" + }; + + void* hostHandle; + unsigned int domainId; + + int st = initializeCoreCLR( + currentExeAbsolutePath, + "unixcorerun", + sizeof(propertyKeys) / sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + &hostHandle, + &domainId); + + if (!SUCCEEDED(st)) + { + fprintf(stderr, "coreclr_initialize failed - status: 0x%08x\n", st); + exitCode = -1; + } + else + { + st = executeAssembly( + hostHandle, + domainId, + managedAssemblyArgc, + managedAssemblyArgv, + managedAssemblyAbsolutePath, + (unsigned int*)&exitCode); + + if (!SUCCEEDED(st)) + { + fprintf(stderr, "coreclr_execute_assembly failed - status: 0x%08x\n", st); + exitCode = -1; + } + + st = shutdownCoreCLR(hostHandle, domainId); + if (!SUCCEEDED(st)) + { + fprintf(stderr, "coreclr_shutdown failed - status: 0x%08x\n", st); + exitCode = -1; + } + } + } + + if (dlclose(coreclrLib) != 0) + { + fprintf(stderr, "Warning - dlclose failed\n"); + } + } + else + { + char* error = dlerror(); + fprintf(stderr, "dlopen failed to open the libcoreclr.so with error %s\n", error); + } + + return exitCode; +} diff --git a/host/unixcoreruncommon/coreruncommon.h b/host/unixcoreruncommon/coreruncommon.h new file mode 100644 index 0000000000..b587e407fc --- /dev/null +++ b/host/unixcoreruncommon/coreruncommon.h @@ -0,0 +1,46 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +#include + +// Get absolute path from the specified path. +// Return true in case of a success, false otherwise. +bool GetAbsolutePath(const char* path, std::string& absolutePath); + +// Get directory of the specified path. +// Return true in case of a success, false otherwise. +bool GetDirectory(const char* absolutePath, std::string& directory); + +// +// Get the absolute path to use to locate libcoreclr.so and the CLR assemblies are stored. If clrFilesPath is provided, +// this function will return the absolute path to it. Otherwise, the directory of the current executable is used. +// +// Return true in case of a success, false otherwise. +// +bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); + +// Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. +void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); + +// +// Execute the specified managed assembly. +// +// Parameters: +// currentExePath - Path to the current executable +// clrFilesAbsolutePath - Absolute path to the folder where the libcoreclr.so and CLR managed assemblies are stored +// managedAssemblyPath - Path to the managed assembly to execute +// managedAssemblyArgc - Number of arguments passed to the executed assembly +// managedAssemblyArgv - Array of arguments passed to the executed assembly +// +// Returns: +// ExitCode of the assembly +// +int ExecuteManagedAssembly( + const char* currentExeAbsolutePath, + const char* clrFilesAbsolutePath, + const char* managedAssemblyAbsolutePath, + int managedAssemblyArgc, + const char** managedAssemblyArgv); + From 6eaad394c54594cb27e4f4d48f7f5ae89a91c7eb Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 12:39:59 -0700 Subject: [PATCH 192/298] Remove CoreCLRUtil namespace So that is all accessible from C --- src/host/cmdline/main.cpp | 20 +- src/host/common/coreclrutil.cpp | 511 ++++++++++++++++---------------- src/host/common/coreclrutil.h | 78 ++--- src/host/common/hostutil.h | 2 +- 4 files changed, 305 insertions(+), 306 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 32cb4eed87..f89f1a18c1 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -172,7 +172,7 @@ int main(int argc, char** argv) // get the absolute path of the current executable std::string currentExeAbsolutePath; - if (!CoreCLRUtil::GetAbsolutePath(argv[0],currentExeAbsolutePath)) + if (!GetAbsolutePath(argv[0],currentExeAbsolutePath)) { std::cerr << "could not get absolute path of current executable" << std::endl; return 1; @@ -186,7 +186,7 @@ int main(int argc, char** argv) // specified with the -c command line argument std::string clrAbsolutePath; const char* clrPathArg = args.clrPath == "" ? nullptr : args.clrPath.c_str(); - if (!CoreCLRUtil::GetClrFilesAbsolutePath(currentExeAbsolutePath.c_str(),clrPathArg,clrAbsolutePath)) + if (!GetClrFilesAbsolutePath(currentExeAbsolutePath.c_str(),clrPathArg,clrAbsolutePath)) { std::cerr << "could not find absolute CLR path" << std::endl; return 1; @@ -202,12 +202,12 @@ int main(int argc, char** argv) // if the -alc parameter was specified, add it to the TPA list here std::string tpaList; - CoreCLRUtil::AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); + AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); if (args.assemblyLoadContextFilePath != "") { std::string assemblyLoadContextAbsoluteFilePath; - if (!CoreCLRUtil::GetAbsolutePath(args.assemblyLoadContextFilePath.c_str(),assemblyLoadContextAbsoluteFilePath)) + if (!GetAbsolutePath(args.assemblyLoadContextFilePath.c_str(),assemblyLoadContextAbsoluteFilePath)) { std::cerr << "Failed to get absolute file path for assembly load context" << std::endl; return 1; @@ -229,7 +229,7 @@ int main(int argc, char** argv) // get the absolute path of the current directory std::string currentDirAbsolutePath; - if (!CoreCLRUtil::GetAbsolutePath(".",currentDirAbsolutePath)) + if (!GetAbsolutePath(".",currentDirAbsolutePath)) { std::cerr << "failed to get the absolute path from current working directory" << std::endl; return 1; @@ -267,7 +267,7 @@ int main(int argc, char** argv) std::string psBasePath = currentDirAbsolutePath; if (args.basePath != "") { - if (!CoreCLRUtil::GetAbsolutePath(args.basePath.c_str(),psBasePath)) + if (!GetAbsolutePath(args.basePath.c_str(),psBasePath)) { std::cerr << "failed to get the absolute path from the base_path argument" << std::endl; return 1; @@ -285,7 +285,7 @@ int main(int argc, char** argv) void* hostHandle; unsigned int domainId; - int status = CoreCLRUtil::startCoreClr( + int status = startCoreClr( clrAbsolutePath.c_str(), tpaList.c_str(), appPath.c_str(), @@ -297,7 +297,7 @@ int main(int argc, char** argv) // initialize the PS's custom assembly load context typedef void (*LoaderRunHelperFp)(const char16_t* appPath); LoaderRunHelperFp loaderDelegate = nullptr; - status = CoreCLRUtil::createDelegate( + status = createDelegate( hostHandle, domainId, "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", @@ -313,12 +313,12 @@ int main(int argc, char** argv) // call into Main of powershell-simple.exe unsigned int exitCode; - CoreCLRUtil::executeAssembly(hostHandle, domainId, args.argc, + executeAssembly(hostHandle, domainId, args.argc, (const char**)args.argv, (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), &exitCode); - status = CoreCLRUtil::stopCoreClr(hostHandle, domainId); + status = stopCoreClr(hostHandle, domainId); return exitCode; } diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index edfc0662d1..3e80623bf1 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -8,311 +8,308 @@ #include #include -namespace CoreCLRUtil -{ - // The name of the CoreCLR native runtime DLL +// The name of the CoreCLR native runtime DLL #if defined(__APPLE__) - constexpr char coreClrDll[] = "libcoreclr.dylib"; +constexpr char coreClrDll[] = "libcoreclr.dylib"; #else - constexpr char coreClrDll[] = "libcoreclr.so"; +constexpr char coreClrDll[] = "libcoreclr.so"; #endif - void* coreclrLib; +void* coreclrLib; - // Prototype of the coreclr_initialize function from the libcoreclr.so - typedef int (*InitializeCoreCLRFunction)( - const char* exePath, - const char* appDomainFriendlyName, - int propertyCount, - const char** propertyKeys, - const char** propertyValues, - void** hostHandle, - unsigned int* domainId); +// Prototype of the coreclr_initialize function from the libcoreclr.so +typedef int (*InitializeCoreCLRFunction)( + const char* exePath, + const char* appDomainFriendlyName, + int propertyCount, + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId); - InitializeCoreCLRFunction initializeCoreCLR; +InitializeCoreCLRFunction initializeCoreCLR; - // Prototype of the coreclr_shutdown function from the libcoreclr.so - typedef int (*ShutdownCoreCLRFunction)( - void* hostHandle, - unsigned int domainId); +// Prototype of the coreclr_shutdown function from the libcoreclr.so +typedef int (*ShutdownCoreCLRFunction)( + void* hostHandle, + unsigned int domainId); - ShutdownCoreCLRFunction shutdownCoreCLR; +ShutdownCoreCLRFunction shutdownCoreCLR; - ExecuteAssemblyFunction executeAssembly; - CreateDelegateFunction createDelegate; +ExecuteAssemblyFunction executeAssembly; +CreateDelegateFunction createDelegate; - int startCoreClr( - // Paths of expected things - const char* clrAbsolutePath, - // Passed to propertyValues - const char* tpaList, - const char* appPath, - const char* nativeDllSearchDirs, - // Passed to InitializeCoreCLRFunction - const char* appDomainFriendlyName, - void** hostHandle, - unsigned int* domainId) +int startCoreClr( + // Paths of expected things + const char* clrAbsolutePath, + // Passed to propertyValues + const char* tpaList, + const char* appPath, + const char* nativeDllSearchDirs, + // Passed to InitializeCoreCLRFunction + const char* appDomainFriendlyName, + void** hostHandle, + unsigned int* domainId) +{ + // the path to the CoreCLR library + // + // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac + std::string coreClrDllPath = clrAbsolutePath; + coreClrDllPath += "/"; + coreClrDllPath += coreClrDll; + + if (coreClrDllPath.size() >= PATH_MAX) { - // the path to the CoreCLR library - // - // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac - std::string coreClrDllPath = clrAbsolutePath; - coreClrDllPath += "/"; - coreClrDllPath += coreClrDll; - - if (coreClrDllPath.size() >= PATH_MAX) - { - std::cerr << "Absolute path to CoreCLR library too long" << std::endl; - return 1; - } - - // open the shared library - coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); - if (coreclrLib == nullptr) - { - char* error = dlerror(); - std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; - return 2; - } - - // query the function pointers - initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); - shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); - - executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); - createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); - - if (initializeCoreCLR == nullptr) - { - std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; - return 3; - } - if (executeAssembly == nullptr) - { - std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; - return 3; - } - if (shutdownCoreCLR == nullptr) - { - std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; - return 3; - } - if (createDelegate == nullptr) - { - std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; - return 3; - } - - // create list of properties to initialize CoreCLR - const char* propertyKeys[] = { - "TRUSTED_PLATFORM_ASSEMBLIES", - "APP_PATHS", - "APP_NI_PATHS", - "NATIVE_DLL_SEARCH_DIRECTORIES", - "AppDomainCompatSwitch" - }; - - const char* propertyValues[] = { - tpaList, - appPath, - appPath, - nativeDllSearchDirs, - "UseLatestBehaviorWhenTFMNotSpecified" - }; - - // get path to current executable - char exePath[PATH_MAX] = { 0 }; - readlink("/proc/self/exe", exePath, PATH_MAX); - - // initialize CoreCLR - int status = initializeCoreCLR( - exePath, - appDomainFriendlyName, - sizeof(propertyKeys)/sizeof(propertyKeys[0]), - propertyKeys, - propertyValues, - hostHandle, - domainId); - - if (0 > status) - { - std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; - return 4; - } - - return status; + std::cerr << "Absolute path to CoreCLR library too long" << std::endl; + return 1; } - int stopCoreClr(void* hostHandle, unsigned int domainId) + // open the shared library + coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); + if (coreclrLib == nullptr) { - // shutdown CoreCLR - int status = shutdownCoreCLR(hostHandle, domainId); - if (0 > status) - { - std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; - } - - // close the dynamic library - if (0 != dlclose(coreclrLib)) - { - std::cerr << "failed to close CoreCLR library" << std::endl; - } - - return status; + char* error = dlerror(); + std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; + return 2; } - bool GetAbsolutePath(const char* path, std::string& absolutePath) + // query the function pointers + initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); + shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); + + executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); + createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); + + if (initializeCoreCLR == nullptr) { - bool result = false; - - char realPath[PATH_MAX]; - if (realpath(path, realPath) != nullptr && realPath[0] != '\0') - { - absolutePath.assign(realPath); - // realpath should return canonicalized path without the trailing slash - assert(absolutePath.back() != '/'); - - result = true; - } - - return result; + std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; + return 3; + } + if (executeAssembly == nullptr) + { + std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; + return 3; + } + if (shutdownCoreCLR == nullptr) + { + std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; + return 3; + } + if (createDelegate == nullptr) + { + std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; + return 3; } - bool GetDirectory(const char* absolutePath, std::string& directory) - { - directory.assign(absolutePath); - size_t lastSlash = directory.rfind('/'); - if (lastSlash != std::string::npos) - { - directory.erase(lastSlash); - return true; - } + // create list of properties to initialize CoreCLR + const char* propertyKeys[] = { + "TRUSTED_PLATFORM_ASSEMBLIES", + "APP_PATHS", + "APP_NI_PATHS", + "NATIVE_DLL_SEARCH_DIRECTORIES", + "AppDomainCompatSwitch" + }; - return false; + const char* propertyValues[] = { + tpaList, + appPath, + appPath, + nativeDllSearchDirs, + "UseLatestBehaviorWhenTFMNotSpecified" + }; + + // get path to current executable + char exePath[PATH_MAX] = { 0 }; + readlink("/proc/self/exe", exePath, PATH_MAX); + + // initialize CoreCLR + int status = initializeCoreCLR( + exePath, + appDomainFriendlyName, + sizeof(propertyKeys)/sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + hostHandle, + domainId); + + if (0 > status) + { + std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; + return 4; } - bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) + return status; +} + +int stopCoreClr(void* hostHandle, unsigned int domainId) +{ + // shutdown CoreCLR + int status = shutdownCoreCLR(hostHandle, domainId); + if (0 > status) { - std::string clrFilesRelativePath; - const char* clrFilesPathLocal = clrFilesPath; - if (clrFilesPathLocal == nullptr) - { - // There was no CLR files path specified, use the folder of the corerun/coreconsole - if (!GetDirectory(currentExePath, clrFilesRelativePath)) - { - perror("Failed to get directory from argv[0]"); - return false; - } + std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; + } - clrFilesPathLocal = clrFilesRelativePath.c_str(); + // close the dynamic library + if (0 != dlclose(coreclrLib)) + { + std::cerr << "failed to close CoreCLR library" << std::endl; + } - // TODO: consider using an env variable (if defined) as a fall-back. - // The windows version of the corerun uses core_root env variable - } + return status; +} - if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) - { - perror("Failed to convert CLR files path to absolute path"); - return false; - } +bool GetAbsolutePath(const char* path, std::string& absolutePath) +{ + bool result = false; + char realPath[PATH_MAX]; + if (realpath(path, realPath) != nullptr && realPath[0] != '\0') + { + absolutePath.assign(realPath); + // realpath should return canonicalized path without the trailing slash + assert(absolutePath.back() != '/'); + + result = true; + } + + return result; +} + +bool GetDirectory(const char* absolutePath, std::string& directory) +{ + directory.assign(absolutePath); + size_t lastSlash = directory.rfind('/'); + if (lastSlash != std::string::npos) + { + directory.erase(lastSlash); return true; } - void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) + return false; +} + +bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) +{ + std::string clrFilesRelativePath; + const char* clrFilesPathLocal = clrFilesPath; + if (clrFilesPathLocal == nullptr) { - const char * const tpaExtensions[] = { - ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir - ".dll", - ".ni.exe", - ".exe", - }; - - DIR* dir = opendir(directory); - if (dir == nullptr) + // There was no CLR files path specified, use the folder of the corerun/coreconsole + if (!GetDirectory(currentExePath, clrFilesRelativePath)) { - return; + perror("Failed to get directory from argv[0]"); + return false; } - std::set addedAssemblies; + clrFilesPathLocal = clrFilesRelativePath.c_str(); - // Walk the directory for each extension separately so that we first get files with .ni.dll extension, - // then files with .dll extension, etc. - for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + // TODO: consider using an env variable (if defined) as a fall-back. + // The windows version of the corerun uses core_root env variable + } + + if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) + { + perror("Failed to convert CLR files path to absolute path"); + return false; + } + + return true; +} + +void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) +{ + const char * const tpaExtensions[] = { + ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir + ".dll", + ".ni.exe", + ".exe", + }; + + DIR* dir = opendir(directory); + if (dir == nullptr) + { + return; + } + + std::set addedAssemblies; + + // Walk the directory for each extension separately so that we first get files with .ni.dll extension, + // then files with .dll extension, etc. + for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + { + const char* ext = tpaExtensions[extIndex]; + int extLength = strlen(ext); + + struct dirent* entry; + + // For all entries in the directory + while ((entry = readdir(dir)) != nullptr) { - const char* ext = tpaExtensions[extIndex]; - int extLength = strlen(ext); - - struct dirent* entry; - - // For all entries in the directory - while ((entry = readdir(dir)) != nullptr) + // We are interested in files only + switch (entry->d_type) { - // We are interested in files only - switch (entry->d_type) - { - case DT_REG: - break; - - // Handle symlinks and file systems that do not support d_type - case DT_LNK: - case DT_UNKNOWN: - { - std::string fullFilename; - - fullFilename.append(directory); - fullFilename.append("/"); - fullFilename.append(entry->d_name); - - struct stat sb; - if (stat(fullFilename.c_str(), &sb) == -1) - { - continue; - } - - if (!S_ISREG(sb.st_mode)) - { - continue; - } - } + case DT_REG: break; - default: - continue; - } + // Handle symlinks and file systems that do not support d_type + case DT_LNK: + case DT_UNKNOWN: + { + std::string fullFilename; - std::string filename(entry->d_name); + fullFilename.append(directory); + fullFilename.append("/"); + fullFilename.append(entry->d_name); - // Check if the extension matches the one we are looking for - int extPos = filename.length() - extLength; - if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) + struct stat sb; + if (stat(fullFilename.c_str(), &sb) == -1) { continue; } - std::string filenameWithoutExt(filename.substr(0, extPos)); - - // Make sure if we have an assembly with multiple extensions present, - // we insert only one version of it. - if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) + if (!S_ISREG(sb.st_mode)) { - addedAssemblies.insert(filenameWithoutExt); - - tpaList.append(directory); - tpaList.append("/"); - tpaList.append(filename); - tpaList.append(":"); + continue; } } - - // Rewind the directory stream to be able to iterate over it for the next extension - rewinddir(dir); - } - - closedir(dir); + break; - // strip any trailing : from the tpaList - if (tpaList.size() > 0 && tpaList[tpaList.size()-1] == ':') - tpaList.resize(tpaList.size()-1); + default: + continue; + } + + std::string filename(entry->d_name); + + // Check if the extension matches the one we are looking for + int extPos = filename.length() - extLength; + if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) + { + continue; + } + + std::string filenameWithoutExt(filename.substr(0, extPos)); + + // Make sure if we have an assembly with multiple extensions present, + // we insert only one version of it. + if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) + { + addedAssemblies.insert(filenameWithoutExt); + + tpaList.append(directory); + tpaList.append("/"); + tpaList.append(filename); + tpaList.append(":"); + } + } + + // Rewind the directory stream to be able to iterate over it for the next extension + rewinddir(dir); } + + closedir(dir); + + // strip any trailing : from the tpaList + if (tpaList.size() > 0 && tpaList[tpaList.size()-1] == ':') + tpaList.resize(tpaList.size()-1); } diff --git a/src/host/common/coreclrutil.h b/src/host/common/coreclrutil.h index fe0ad77fc5..e1a481c568 100644 --- a/src/host/common/coreclrutil.h +++ b/src/host/common/coreclrutil.h @@ -1,49 +1,51 @@ #pragma once +#ifdef __cplusplus #include +#endif -namespace CoreCLRUtil +extern "C" { - extern "C" { - int startCoreClr( - // Paths of expected things - const char* clrAbsolutePath, - // Passed to propertyValues - const char* tpaList, - const char* appPath, - const char* nativeDllSearchDirs, - // Passed to InitializeCoreCLRFunction - const char* appDomainFriendlyName, - void** hostHandle, - unsigned int* domainId); + int startCoreClr( + // Paths of expected things + const char* clrAbsolutePath, + // Passed to propertyValues + const char* tpaList, + const char* appPath, + const char* nativeDllSearchDirs, + // Passed to InitializeCoreCLRFunction + const char* appDomainFriendlyName, + void** hostHandle, + unsigned int* domainId); - int stopCoreClr(void* hostHandle, unsigned int domainId); + int stopCoreClr(void* hostHandle, unsigned int domainId); - // Prototype of the coreclr_execute_assembly function from the libcoreclr.so - typedef int (*ExecuteAssemblyFunction)( - void* hostHandle, - unsigned int domainId, - int argc, - const char** argv, - const char* managedAssemblyPath, - unsigned int* exitCode); + // Prototype of the coreclr_execute_assembly function from the libcoreclr.so + typedef int (*ExecuteAssemblyFunction)( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode); - extern ExecuteAssemblyFunction executeAssembly; + extern ExecuteAssemblyFunction executeAssembly; - // Prototype of coreclr_create_delegate function from the libcoreclr.so - typedef int (*CreateDelegateFunction)( - void* hostHandle, - unsigned int domainId, - const char* entryPointAssemblyName, - const char* entryPointTypeName, - const char* entryPointMethodName, - void** delegate); + // Prototype of coreclr_create_delegate function from the libcoreclr.so + typedef int (*CreateDelegateFunction)( + void* hostHandle, + unsigned int domainId, + const char* entryPointAssemblyName, + const char* entryPointTypeName, + const char* entryPointMethodName, + void** delegate); - extern CreateDelegateFunction createDelegate; - } - - bool GetAbsolutePath(const char* path, std::string& absolutePath); - bool GetDirectory(const char* absolutePath, std::string& directory); - bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); - void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); + extern CreateDelegateFunction createDelegate; } + +#ifdef __cplusplus +bool GetAbsolutePath(const char* path, std::string& absolutePath); +bool GetDirectory(const char* absolutePath, std::string& directory); +bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); +void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); +#endif diff --git a/src/host/common/hostutil.h b/src/host/common/hostutil.h index 60bec5519a..6a07469c07 100644 --- a/src/host/common/hostutil.h +++ b/src/host/common/hostutil.h @@ -23,7 +23,7 @@ namespace HostUtil if (token != "") { std::string absolutePath; - if (CoreCLRUtil::GetAbsolutePath(token.c_str(),absolutePath)) + if (GetAbsolutePath(token.c_str(),absolutePath)) { // add colons correctly if (result.size() == 0) From 27563ab7b7a2568c8b02b2179ba15fa8a377bd33 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 12:39:59 -0700 Subject: [PATCH 193/298] Remove CoreCLRUtil namespace So that is all accessible from C --- host/cmdline/main.cpp | 20 +- host/common/coreclrutil.cpp | 511 ++++++++++++++++++------------------ host/common/coreclrutil.h | 78 +++--- host/common/hostutil.h | 2 +- 4 files changed, 305 insertions(+), 306 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 32cb4eed87..f89f1a18c1 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -172,7 +172,7 @@ int main(int argc, char** argv) // get the absolute path of the current executable std::string currentExeAbsolutePath; - if (!CoreCLRUtil::GetAbsolutePath(argv[0],currentExeAbsolutePath)) + if (!GetAbsolutePath(argv[0],currentExeAbsolutePath)) { std::cerr << "could not get absolute path of current executable" << std::endl; return 1; @@ -186,7 +186,7 @@ int main(int argc, char** argv) // specified with the -c command line argument std::string clrAbsolutePath; const char* clrPathArg = args.clrPath == "" ? nullptr : args.clrPath.c_str(); - if (!CoreCLRUtil::GetClrFilesAbsolutePath(currentExeAbsolutePath.c_str(),clrPathArg,clrAbsolutePath)) + if (!GetClrFilesAbsolutePath(currentExeAbsolutePath.c_str(),clrPathArg,clrAbsolutePath)) { std::cerr << "could not find absolute CLR path" << std::endl; return 1; @@ -202,12 +202,12 @@ int main(int argc, char** argv) // if the -alc parameter was specified, add it to the TPA list here std::string tpaList; - CoreCLRUtil::AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); + AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); if (args.assemblyLoadContextFilePath != "") { std::string assemblyLoadContextAbsoluteFilePath; - if (!CoreCLRUtil::GetAbsolutePath(args.assemblyLoadContextFilePath.c_str(),assemblyLoadContextAbsoluteFilePath)) + if (!GetAbsolutePath(args.assemblyLoadContextFilePath.c_str(),assemblyLoadContextAbsoluteFilePath)) { std::cerr << "Failed to get absolute file path for assembly load context" << std::endl; return 1; @@ -229,7 +229,7 @@ int main(int argc, char** argv) // get the absolute path of the current directory std::string currentDirAbsolutePath; - if (!CoreCLRUtil::GetAbsolutePath(".",currentDirAbsolutePath)) + if (!GetAbsolutePath(".",currentDirAbsolutePath)) { std::cerr << "failed to get the absolute path from current working directory" << std::endl; return 1; @@ -267,7 +267,7 @@ int main(int argc, char** argv) std::string psBasePath = currentDirAbsolutePath; if (args.basePath != "") { - if (!CoreCLRUtil::GetAbsolutePath(args.basePath.c_str(),psBasePath)) + if (!GetAbsolutePath(args.basePath.c_str(),psBasePath)) { std::cerr << "failed to get the absolute path from the base_path argument" << std::endl; return 1; @@ -285,7 +285,7 @@ int main(int argc, char** argv) void* hostHandle; unsigned int domainId; - int status = CoreCLRUtil::startCoreClr( + int status = startCoreClr( clrAbsolutePath.c_str(), tpaList.c_str(), appPath.c_str(), @@ -297,7 +297,7 @@ int main(int argc, char** argv) // initialize the PS's custom assembly load context typedef void (*LoaderRunHelperFp)(const char16_t* appPath); LoaderRunHelperFp loaderDelegate = nullptr; - status = CoreCLRUtil::createDelegate( + status = createDelegate( hostHandle, domainId, "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", @@ -313,12 +313,12 @@ int main(int argc, char** argv) // call into Main of powershell-simple.exe unsigned int exitCode; - CoreCLRUtil::executeAssembly(hostHandle, domainId, args.argc, + executeAssembly(hostHandle, domainId, args.argc, (const char**)args.argv, (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), &exitCode); - status = CoreCLRUtil::stopCoreClr(hostHandle, domainId); + status = stopCoreClr(hostHandle, domainId); return exitCode; } diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index edfc0662d1..3e80623bf1 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -8,311 +8,308 @@ #include #include -namespace CoreCLRUtil -{ - // The name of the CoreCLR native runtime DLL +// The name of the CoreCLR native runtime DLL #if defined(__APPLE__) - constexpr char coreClrDll[] = "libcoreclr.dylib"; +constexpr char coreClrDll[] = "libcoreclr.dylib"; #else - constexpr char coreClrDll[] = "libcoreclr.so"; +constexpr char coreClrDll[] = "libcoreclr.so"; #endif - void* coreclrLib; +void* coreclrLib; - // Prototype of the coreclr_initialize function from the libcoreclr.so - typedef int (*InitializeCoreCLRFunction)( - const char* exePath, - const char* appDomainFriendlyName, - int propertyCount, - const char** propertyKeys, - const char** propertyValues, - void** hostHandle, - unsigned int* domainId); +// Prototype of the coreclr_initialize function from the libcoreclr.so +typedef int (*InitializeCoreCLRFunction)( + const char* exePath, + const char* appDomainFriendlyName, + int propertyCount, + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId); - InitializeCoreCLRFunction initializeCoreCLR; +InitializeCoreCLRFunction initializeCoreCLR; - // Prototype of the coreclr_shutdown function from the libcoreclr.so - typedef int (*ShutdownCoreCLRFunction)( - void* hostHandle, - unsigned int domainId); +// Prototype of the coreclr_shutdown function from the libcoreclr.so +typedef int (*ShutdownCoreCLRFunction)( + void* hostHandle, + unsigned int domainId); - ShutdownCoreCLRFunction shutdownCoreCLR; +ShutdownCoreCLRFunction shutdownCoreCLR; - ExecuteAssemblyFunction executeAssembly; - CreateDelegateFunction createDelegate; +ExecuteAssemblyFunction executeAssembly; +CreateDelegateFunction createDelegate; - int startCoreClr( - // Paths of expected things - const char* clrAbsolutePath, - // Passed to propertyValues - const char* tpaList, - const char* appPath, - const char* nativeDllSearchDirs, - // Passed to InitializeCoreCLRFunction - const char* appDomainFriendlyName, - void** hostHandle, - unsigned int* domainId) +int startCoreClr( + // Paths of expected things + const char* clrAbsolutePath, + // Passed to propertyValues + const char* tpaList, + const char* appPath, + const char* nativeDllSearchDirs, + // Passed to InitializeCoreCLRFunction + const char* appDomainFriendlyName, + void** hostHandle, + unsigned int* domainId) +{ + // the path to the CoreCLR library + // + // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac + std::string coreClrDllPath = clrAbsolutePath; + coreClrDllPath += "/"; + coreClrDllPath += coreClrDll; + + if (coreClrDllPath.size() >= PATH_MAX) { - // the path to the CoreCLR library - // - // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac - std::string coreClrDllPath = clrAbsolutePath; - coreClrDllPath += "/"; - coreClrDllPath += coreClrDll; - - if (coreClrDllPath.size() >= PATH_MAX) - { - std::cerr << "Absolute path to CoreCLR library too long" << std::endl; - return 1; - } - - // open the shared library - coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); - if (coreclrLib == nullptr) - { - char* error = dlerror(); - std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; - return 2; - } - - // query the function pointers - initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); - shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); - - executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); - createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); - - if (initializeCoreCLR == nullptr) - { - std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; - return 3; - } - if (executeAssembly == nullptr) - { - std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; - return 3; - } - if (shutdownCoreCLR == nullptr) - { - std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; - return 3; - } - if (createDelegate == nullptr) - { - std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; - return 3; - } - - // create list of properties to initialize CoreCLR - const char* propertyKeys[] = { - "TRUSTED_PLATFORM_ASSEMBLIES", - "APP_PATHS", - "APP_NI_PATHS", - "NATIVE_DLL_SEARCH_DIRECTORIES", - "AppDomainCompatSwitch" - }; - - const char* propertyValues[] = { - tpaList, - appPath, - appPath, - nativeDllSearchDirs, - "UseLatestBehaviorWhenTFMNotSpecified" - }; - - // get path to current executable - char exePath[PATH_MAX] = { 0 }; - readlink("/proc/self/exe", exePath, PATH_MAX); - - // initialize CoreCLR - int status = initializeCoreCLR( - exePath, - appDomainFriendlyName, - sizeof(propertyKeys)/sizeof(propertyKeys[0]), - propertyKeys, - propertyValues, - hostHandle, - domainId); - - if (0 > status) - { - std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; - return 4; - } - - return status; + std::cerr << "Absolute path to CoreCLR library too long" << std::endl; + return 1; } - int stopCoreClr(void* hostHandle, unsigned int domainId) + // open the shared library + coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); + if (coreclrLib == nullptr) { - // shutdown CoreCLR - int status = shutdownCoreCLR(hostHandle, domainId); - if (0 > status) - { - std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; - } - - // close the dynamic library - if (0 != dlclose(coreclrLib)) - { - std::cerr << "failed to close CoreCLR library" << std::endl; - } - - return status; + char* error = dlerror(); + std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; + return 2; } - bool GetAbsolutePath(const char* path, std::string& absolutePath) + // query the function pointers + initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); + shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); + + executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); + createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); + + if (initializeCoreCLR == nullptr) { - bool result = false; - - char realPath[PATH_MAX]; - if (realpath(path, realPath) != nullptr && realPath[0] != '\0') - { - absolutePath.assign(realPath); - // realpath should return canonicalized path without the trailing slash - assert(absolutePath.back() != '/'); - - result = true; - } - - return result; + std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; + return 3; + } + if (executeAssembly == nullptr) + { + std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; + return 3; + } + if (shutdownCoreCLR == nullptr) + { + std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; + return 3; + } + if (createDelegate == nullptr) + { + std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; + return 3; } - bool GetDirectory(const char* absolutePath, std::string& directory) - { - directory.assign(absolutePath); - size_t lastSlash = directory.rfind('/'); - if (lastSlash != std::string::npos) - { - directory.erase(lastSlash); - return true; - } + // create list of properties to initialize CoreCLR + const char* propertyKeys[] = { + "TRUSTED_PLATFORM_ASSEMBLIES", + "APP_PATHS", + "APP_NI_PATHS", + "NATIVE_DLL_SEARCH_DIRECTORIES", + "AppDomainCompatSwitch" + }; - return false; + const char* propertyValues[] = { + tpaList, + appPath, + appPath, + nativeDllSearchDirs, + "UseLatestBehaviorWhenTFMNotSpecified" + }; + + // get path to current executable + char exePath[PATH_MAX] = { 0 }; + readlink("/proc/self/exe", exePath, PATH_MAX); + + // initialize CoreCLR + int status = initializeCoreCLR( + exePath, + appDomainFriendlyName, + sizeof(propertyKeys)/sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + hostHandle, + domainId); + + if (0 > status) + { + std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; + return 4; } - bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) + return status; +} + +int stopCoreClr(void* hostHandle, unsigned int domainId) +{ + // shutdown CoreCLR + int status = shutdownCoreCLR(hostHandle, domainId); + if (0 > status) { - std::string clrFilesRelativePath; - const char* clrFilesPathLocal = clrFilesPath; - if (clrFilesPathLocal == nullptr) - { - // There was no CLR files path specified, use the folder of the corerun/coreconsole - if (!GetDirectory(currentExePath, clrFilesRelativePath)) - { - perror("Failed to get directory from argv[0]"); - return false; - } + std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; + } - clrFilesPathLocal = clrFilesRelativePath.c_str(); + // close the dynamic library + if (0 != dlclose(coreclrLib)) + { + std::cerr << "failed to close CoreCLR library" << std::endl; + } - // TODO: consider using an env variable (if defined) as a fall-back. - // The windows version of the corerun uses core_root env variable - } + return status; +} - if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) - { - perror("Failed to convert CLR files path to absolute path"); - return false; - } +bool GetAbsolutePath(const char* path, std::string& absolutePath) +{ + bool result = false; + char realPath[PATH_MAX]; + if (realpath(path, realPath) != nullptr && realPath[0] != '\0') + { + absolutePath.assign(realPath); + // realpath should return canonicalized path without the trailing slash + assert(absolutePath.back() != '/'); + + result = true; + } + + return result; +} + +bool GetDirectory(const char* absolutePath, std::string& directory) +{ + directory.assign(absolutePath); + size_t lastSlash = directory.rfind('/'); + if (lastSlash != std::string::npos) + { + directory.erase(lastSlash); return true; } - void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) + return false; +} + +bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) +{ + std::string clrFilesRelativePath; + const char* clrFilesPathLocal = clrFilesPath; + if (clrFilesPathLocal == nullptr) { - const char * const tpaExtensions[] = { - ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir - ".dll", - ".ni.exe", - ".exe", - }; - - DIR* dir = opendir(directory); - if (dir == nullptr) + // There was no CLR files path specified, use the folder of the corerun/coreconsole + if (!GetDirectory(currentExePath, clrFilesRelativePath)) { - return; + perror("Failed to get directory from argv[0]"); + return false; } - std::set addedAssemblies; + clrFilesPathLocal = clrFilesRelativePath.c_str(); - // Walk the directory for each extension separately so that we first get files with .ni.dll extension, - // then files with .dll extension, etc. - for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + // TODO: consider using an env variable (if defined) as a fall-back. + // The windows version of the corerun uses core_root env variable + } + + if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) + { + perror("Failed to convert CLR files path to absolute path"); + return false; + } + + return true; +} + +void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) +{ + const char * const tpaExtensions[] = { + ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir + ".dll", + ".ni.exe", + ".exe", + }; + + DIR* dir = opendir(directory); + if (dir == nullptr) + { + return; + } + + std::set addedAssemblies; + + // Walk the directory for each extension separately so that we first get files with .ni.dll extension, + // then files with .dll extension, etc. + for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + { + const char* ext = tpaExtensions[extIndex]; + int extLength = strlen(ext); + + struct dirent* entry; + + // For all entries in the directory + while ((entry = readdir(dir)) != nullptr) { - const char* ext = tpaExtensions[extIndex]; - int extLength = strlen(ext); - - struct dirent* entry; - - // For all entries in the directory - while ((entry = readdir(dir)) != nullptr) + // We are interested in files only + switch (entry->d_type) { - // We are interested in files only - switch (entry->d_type) - { - case DT_REG: - break; - - // Handle symlinks and file systems that do not support d_type - case DT_LNK: - case DT_UNKNOWN: - { - std::string fullFilename; - - fullFilename.append(directory); - fullFilename.append("/"); - fullFilename.append(entry->d_name); - - struct stat sb; - if (stat(fullFilename.c_str(), &sb) == -1) - { - continue; - } - - if (!S_ISREG(sb.st_mode)) - { - continue; - } - } + case DT_REG: break; - default: - continue; - } + // Handle symlinks and file systems that do not support d_type + case DT_LNK: + case DT_UNKNOWN: + { + std::string fullFilename; - std::string filename(entry->d_name); + fullFilename.append(directory); + fullFilename.append("/"); + fullFilename.append(entry->d_name); - // Check if the extension matches the one we are looking for - int extPos = filename.length() - extLength; - if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) + struct stat sb; + if (stat(fullFilename.c_str(), &sb) == -1) { continue; } - std::string filenameWithoutExt(filename.substr(0, extPos)); - - // Make sure if we have an assembly with multiple extensions present, - // we insert only one version of it. - if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) + if (!S_ISREG(sb.st_mode)) { - addedAssemblies.insert(filenameWithoutExt); - - tpaList.append(directory); - tpaList.append("/"); - tpaList.append(filename); - tpaList.append(":"); + continue; } } - - // Rewind the directory stream to be able to iterate over it for the next extension - rewinddir(dir); - } - - closedir(dir); + break; - // strip any trailing : from the tpaList - if (tpaList.size() > 0 && tpaList[tpaList.size()-1] == ':') - tpaList.resize(tpaList.size()-1); + default: + continue; + } + + std::string filename(entry->d_name); + + // Check if the extension matches the one we are looking for + int extPos = filename.length() - extLength; + if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) + { + continue; + } + + std::string filenameWithoutExt(filename.substr(0, extPos)); + + // Make sure if we have an assembly with multiple extensions present, + // we insert only one version of it. + if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) + { + addedAssemblies.insert(filenameWithoutExt); + + tpaList.append(directory); + tpaList.append("/"); + tpaList.append(filename); + tpaList.append(":"); + } + } + + // Rewind the directory stream to be able to iterate over it for the next extension + rewinddir(dir); } + + closedir(dir); + + // strip any trailing : from the tpaList + if (tpaList.size() > 0 && tpaList[tpaList.size()-1] == ':') + tpaList.resize(tpaList.size()-1); } diff --git a/host/common/coreclrutil.h b/host/common/coreclrutil.h index fe0ad77fc5..e1a481c568 100644 --- a/host/common/coreclrutil.h +++ b/host/common/coreclrutil.h @@ -1,49 +1,51 @@ #pragma once +#ifdef __cplusplus #include +#endif -namespace CoreCLRUtil +extern "C" { - extern "C" { - int startCoreClr( - // Paths of expected things - const char* clrAbsolutePath, - // Passed to propertyValues - const char* tpaList, - const char* appPath, - const char* nativeDllSearchDirs, - // Passed to InitializeCoreCLRFunction - const char* appDomainFriendlyName, - void** hostHandle, - unsigned int* domainId); + int startCoreClr( + // Paths of expected things + const char* clrAbsolutePath, + // Passed to propertyValues + const char* tpaList, + const char* appPath, + const char* nativeDllSearchDirs, + // Passed to InitializeCoreCLRFunction + const char* appDomainFriendlyName, + void** hostHandle, + unsigned int* domainId); - int stopCoreClr(void* hostHandle, unsigned int domainId); + int stopCoreClr(void* hostHandle, unsigned int domainId); - // Prototype of the coreclr_execute_assembly function from the libcoreclr.so - typedef int (*ExecuteAssemblyFunction)( - void* hostHandle, - unsigned int domainId, - int argc, - const char** argv, - const char* managedAssemblyPath, - unsigned int* exitCode); + // Prototype of the coreclr_execute_assembly function from the libcoreclr.so + typedef int (*ExecuteAssemblyFunction)( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode); - extern ExecuteAssemblyFunction executeAssembly; + extern ExecuteAssemblyFunction executeAssembly; - // Prototype of coreclr_create_delegate function from the libcoreclr.so - typedef int (*CreateDelegateFunction)( - void* hostHandle, - unsigned int domainId, - const char* entryPointAssemblyName, - const char* entryPointTypeName, - const char* entryPointMethodName, - void** delegate); + // Prototype of coreclr_create_delegate function from the libcoreclr.so + typedef int (*CreateDelegateFunction)( + void* hostHandle, + unsigned int domainId, + const char* entryPointAssemblyName, + const char* entryPointTypeName, + const char* entryPointMethodName, + void** delegate); - extern CreateDelegateFunction createDelegate; - } - - bool GetAbsolutePath(const char* path, std::string& absolutePath); - bool GetDirectory(const char* absolutePath, std::string& directory); - bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); - void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); + extern CreateDelegateFunction createDelegate; } + +#ifdef __cplusplus +bool GetAbsolutePath(const char* path, std::string& absolutePath); +bool GetDirectory(const char* absolutePath, std::string& directory); +bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); +void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); +#endif diff --git a/host/common/hostutil.h b/host/common/hostutil.h index 60bec5519a..6a07469c07 100644 --- a/host/common/hostutil.h +++ b/host/common/hostutil.h @@ -23,7 +23,7 @@ namespace HostUtil if (token != "") { std::string absolutePath; - if (CoreCLRUtil::GetAbsolutePath(token.c_str(),absolutePath)) + if (GetAbsolutePath(token.c_str(),absolutePath)) { // add colons correctly if (result.size() == 0) From bdb06b08d6549972ea501a406cb1430880ae66bd Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 13:31:22 -0700 Subject: [PATCH 194/298] Rename to (start|stop)CoreCLR() --- src/host/cmdline/main.cpp | 4 ++-- src/host/common/coreclrutil.cpp | 8 +++----- src/host/common/coreclrutil.h | 4 ++-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index f89f1a18c1..2443df6234 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -285,7 +285,7 @@ int main(int argc, char** argv) void* hostHandle; unsigned int domainId; - int status = startCoreClr( + int status = startCoreCLR( clrAbsolutePath.c_str(), tpaList.c_str(), appPath.c_str(), @@ -318,7 +318,7 @@ int main(int argc, char** argv) (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), &exitCode); - status = stopCoreClr(hostHandle, domainId); + status = stopCoreCLR(hostHandle, domainId); return exitCode; } diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index 3e80623bf1..ed2d64453f 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -27,19 +27,17 @@ typedef int (*InitializeCoreCLRFunction)( void** hostHandle, unsigned int* domainId); -InitializeCoreCLRFunction initializeCoreCLR; - // Prototype of the coreclr_shutdown function from the libcoreclr.so typedef int (*ShutdownCoreCLRFunction)( void* hostHandle, unsigned int domainId); +InitializeCoreCLRFunction initializeCoreCLR; ShutdownCoreCLRFunction shutdownCoreCLR; - ExecuteAssemblyFunction executeAssembly; CreateDelegateFunction createDelegate; -int startCoreClr( +int startCoreCLR( // Paths of expected things const char* clrAbsolutePath, // Passed to propertyValues @@ -141,7 +139,7 @@ int startCoreClr( return status; } -int stopCoreClr(void* hostHandle, unsigned int domainId) +int stopCoreCLR(void* hostHandle, unsigned int domainId) { // shutdown CoreCLR int status = shutdownCoreCLR(hostHandle, domainId); diff --git a/src/host/common/coreclrutil.h b/src/host/common/coreclrutil.h index e1a481c568..5e9768325d 100644 --- a/src/host/common/coreclrutil.h +++ b/src/host/common/coreclrutil.h @@ -6,8 +6,8 @@ extern "C" { - int startCoreClr( // Paths of expected things + int startCoreCLR( const char* clrAbsolutePath, // Passed to propertyValues const char* tpaList, @@ -18,7 +18,7 @@ extern "C" void** hostHandle, unsigned int* domainId); - int stopCoreClr(void* hostHandle, unsigned int domainId); + int stopCoreCLR(void* hostHandle, unsigned int domainId); // Prototype of the coreclr_execute_assembly function from the libcoreclr.so typedef int (*ExecuteAssemblyFunction)( From 80c68707aa422d986f3141c110ac59b89f632921 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 13:31:22 -0700 Subject: [PATCH 195/298] Rename to (start|stop)CoreCLR() --- host/cmdline/main.cpp | 4 ++-- host/common/coreclrutil.cpp | 8 +++----- host/common/coreclrutil.h | 4 ++-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index f89f1a18c1..2443df6234 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -285,7 +285,7 @@ int main(int argc, char** argv) void* hostHandle; unsigned int domainId; - int status = startCoreClr( + int status = startCoreCLR( clrAbsolutePath.c_str(), tpaList.c_str(), appPath.c_str(), @@ -318,7 +318,7 @@ int main(int argc, char** argv) (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), &exitCode); - status = stopCoreClr(hostHandle, domainId); + status = stopCoreCLR(hostHandle, domainId); return exitCode; } diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index 3e80623bf1..ed2d64453f 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -27,19 +27,17 @@ typedef int (*InitializeCoreCLRFunction)( void** hostHandle, unsigned int* domainId); -InitializeCoreCLRFunction initializeCoreCLR; - // Prototype of the coreclr_shutdown function from the libcoreclr.so typedef int (*ShutdownCoreCLRFunction)( void* hostHandle, unsigned int domainId); +InitializeCoreCLRFunction initializeCoreCLR; ShutdownCoreCLRFunction shutdownCoreCLR; - ExecuteAssemblyFunction executeAssembly; CreateDelegateFunction createDelegate; -int startCoreClr( +int startCoreCLR( // Paths of expected things const char* clrAbsolutePath, // Passed to propertyValues @@ -141,7 +139,7 @@ int startCoreClr( return status; } -int stopCoreClr(void* hostHandle, unsigned int domainId) +int stopCoreCLR(void* hostHandle, unsigned int domainId) { // shutdown CoreCLR int status = shutdownCoreCLR(hostHandle, domainId); diff --git a/host/common/coreclrutil.h b/host/common/coreclrutil.h index e1a481c568..5e9768325d 100644 --- a/host/common/coreclrutil.h +++ b/host/common/coreclrutil.h @@ -6,8 +6,8 @@ extern "C" { - int startCoreClr( // Paths of expected things + int startCoreCLR( const char* clrAbsolutePath, // Passed to propertyValues const char* tpaList, @@ -18,7 +18,7 @@ extern "C" void** hostHandle, unsigned int* domainId); - int stopCoreClr(void* hostHandle, unsigned int domainId); + int stopCoreCLR(void* hostHandle, unsigned int domainId); // Prototype of the coreclr_execute_assembly function from the libcoreclr.so typedef int (*ExecuteAssemblyFunction)( From 4fd752cee63e06b35ac0ae0b5e0840dfe31663c1 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 13:35:00 -0700 Subject: [PATCH 196/298] Reconcile with coreruncommon.cpp --- src/host/common/coreclrutil.cpp | 14 +++++++------- src/host/common/coreclrutil.h | 34 ++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index ed2d64453f..29c039d476 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -157,6 +157,10 @@ int stopCoreCLR(void* hostHandle, unsigned int domainId) return status; } +// +// Below is from unixcoreruncommon/coreruncommon.cpp +// + bool GetAbsolutePath(const char* path, std::string& absolutePath) { bool result = false; @@ -223,7 +227,7 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) ".ni.exe", ".exe", }; - + DIR* dir = opendir(directory); if (dir == nullptr) { @@ -300,14 +304,10 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) tpaList.append(":"); } } - + // Rewind the directory stream to be able to iterate over it for the next extension rewinddir(dir); } - - closedir(dir); - // strip any trailing : from the tpaList - if (tpaList.size() > 0 && tpaList[tpaList.size()-1] == ':') - tpaList.resize(tpaList.size()-1); + closedir(dir); } diff --git a/src/host/common/coreclrutil.h b/src/host/common/coreclrutil.h index 5e9768325d..ca055df738 100644 --- a/src/host/common/coreclrutil.h +++ b/src/host/common/coreclrutil.h @@ -4,23 +4,30 @@ #include #endif +/* PowerShell on Linux custom host interface + * + * startCoreCLR() and stopCoreCLR() wrap the initialization of CoreCLR + * and use of ExecuteAssemblyFunction() and CreateDelegateFunction() + * should be sandwiched in between them + * + */ extern "C" { - // Paths of expected things int startCoreCLR( + /* Paths of expected things */ const char* clrAbsolutePath, - // Passed to propertyValues + /* Passed to propertyValues */ const char* tpaList, const char* appPath, const char* nativeDllSearchDirs, - // Passed to InitializeCoreCLRFunction + /* Passed to InitializeCoreCLRFunction */ const char* appDomainFriendlyName, void** hostHandle, unsigned int* domainId); int stopCoreCLR(void* hostHandle, unsigned int domainId); - // Prototype of the coreclr_execute_assembly function from the libcoreclr.so + /* Prototype of the coreclr_execute_assembly function from the libcoreclr.so */ typedef int (*ExecuteAssemblyFunction)( void* hostHandle, unsigned int domainId, @@ -29,9 +36,7 @@ extern "C" const char* managedAssemblyPath, unsigned int* exitCode); - extern ExecuteAssemblyFunction executeAssembly; - - // Prototype of coreclr_create_delegate function from the libcoreclr.so + /* Prototype of coreclr_create_delegate function from the libcoreclr.so */ typedef int (*CreateDelegateFunction)( void* hostHandle, unsigned int domainId, @@ -40,12 +45,27 @@ extern "C" const char* entryPointMethodName, void** delegate); + extern ExecuteAssemblyFunction executeAssembly; extern CreateDelegateFunction createDelegate; } #ifdef __cplusplus +// Get absolute path from the specified path. +// Return true in case of a success, false otherwise. bool GetAbsolutePath(const char* path, std::string& absolutePath); + +// Get directory of the specified path. +// Return true in case of a success, false otherwise. bool GetDirectory(const char* absolutePath, std::string& directory); + +// +// Get the absolute path to use to locate libcoreclr.so and the CLR assemblies are stored. If clrFilesPath is provided, +// this function will return the absolute path to it. Otherwise, the directory of the current executable is used. +// +// Return true in case of a success, false otherwise. +// bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); + +// Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); #endif From 2c4b99455ad9cd5ee5c4098a30a43abab9c47a3b Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 13:35:00 -0700 Subject: [PATCH 197/298] Reconcile with coreruncommon.cpp --- host/common/coreclrutil.cpp | 14 +++++++------- host/common/coreclrutil.h | 34 +++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index ed2d64453f..29c039d476 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -157,6 +157,10 @@ int stopCoreCLR(void* hostHandle, unsigned int domainId) return status; } +// +// Below is from unixcoreruncommon/coreruncommon.cpp +// + bool GetAbsolutePath(const char* path, std::string& absolutePath) { bool result = false; @@ -223,7 +227,7 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) ".ni.exe", ".exe", }; - + DIR* dir = opendir(directory); if (dir == nullptr) { @@ -300,14 +304,10 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) tpaList.append(":"); } } - + // Rewind the directory stream to be able to iterate over it for the next extension rewinddir(dir); } - - closedir(dir); - // strip any trailing : from the tpaList - if (tpaList.size() > 0 && tpaList[tpaList.size()-1] == ':') - tpaList.resize(tpaList.size()-1); + closedir(dir); } diff --git a/host/common/coreclrutil.h b/host/common/coreclrutil.h index 5e9768325d..ca055df738 100644 --- a/host/common/coreclrutil.h +++ b/host/common/coreclrutil.h @@ -4,23 +4,30 @@ #include #endif +/* PowerShell on Linux custom host interface + * + * startCoreCLR() and stopCoreCLR() wrap the initialization of CoreCLR + * and use of ExecuteAssemblyFunction() and CreateDelegateFunction() + * should be sandwiched in between them + * + */ extern "C" { - // Paths of expected things int startCoreCLR( + /* Paths of expected things */ const char* clrAbsolutePath, - // Passed to propertyValues + /* Passed to propertyValues */ const char* tpaList, const char* appPath, const char* nativeDllSearchDirs, - // Passed to InitializeCoreCLRFunction + /* Passed to InitializeCoreCLRFunction */ const char* appDomainFriendlyName, void** hostHandle, unsigned int* domainId); int stopCoreCLR(void* hostHandle, unsigned int domainId); - // Prototype of the coreclr_execute_assembly function from the libcoreclr.so + /* Prototype of the coreclr_execute_assembly function from the libcoreclr.so */ typedef int (*ExecuteAssemblyFunction)( void* hostHandle, unsigned int domainId, @@ -29,9 +36,7 @@ extern "C" const char* managedAssemblyPath, unsigned int* exitCode); - extern ExecuteAssemblyFunction executeAssembly; - - // Prototype of coreclr_create_delegate function from the libcoreclr.so + /* Prototype of coreclr_create_delegate function from the libcoreclr.so */ typedef int (*CreateDelegateFunction)( void* hostHandle, unsigned int domainId, @@ -40,12 +45,27 @@ extern "C" const char* entryPointMethodName, void** delegate); + extern ExecuteAssemblyFunction executeAssembly; extern CreateDelegateFunction createDelegate; } #ifdef __cplusplus +// Get absolute path from the specified path. +// Return true in case of a success, false otherwise. bool GetAbsolutePath(const char* path, std::string& absolutePath); + +// Get directory of the specified path. +// Return true in case of a success, false otherwise. bool GetDirectory(const char* absolutePath, std::string& directory); + +// +// Get the absolute path to use to locate libcoreclr.so and the CLR assemblies are stored. If clrFilesPath is provided, +// this function will return the absolute path to it. Otherwise, the directory of the current executable is used. +// +// Return true in case of a success, false otherwise. +// bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); + +// Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); #endif From f81aec00b3064d902488420dc540b398f0a8b44d Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 13:57:37 -0700 Subject: [PATCH 198/298] Move start/stop functions --- src/host/common/coreclrutil.cpp | 244 ++++++++++++++++---------------- 1 file changed, 124 insertions(+), 120 deletions(-) diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index 29c039d476..47ff418b29 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -37,126 +37,6 @@ ShutdownCoreCLRFunction shutdownCoreCLR; ExecuteAssemblyFunction executeAssembly; CreateDelegateFunction createDelegate; -int startCoreCLR( - // Paths of expected things - const char* clrAbsolutePath, - // Passed to propertyValues - const char* tpaList, - const char* appPath, - const char* nativeDllSearchDirs, - // Passed to InitializeCoreCLRFunction - const char* appDomainFriendlyName, - void** hostHandle, - unsigned int* domainId) -{ - // the path to the CoreCLR library - // - // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac - std::string coreClrDllPath = clrAbsolutePath; - coreClrDllPath += "/"; - coreClrDllPath += coreClrDll; - - if (coreClrDllPath.size() >= PATH_MAX) - { - std::cerr << "Absolute path to CoreCLR library too long" << std::endl; - return 1; - } - - // open the shared library - coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); - if (coreclrLib == nullptr) - { - char* error = dlerror(); - std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; - return 2; - } - - // query the function pointers - initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); - shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); - - executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); - createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); - - if (initializeCoreCLR == nullptr) - { - std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; - return 3; - } - if (executeAssembly == nullptr) - { - std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; - return 3; - } - if (shutdownCoreCLR == nullptr) - { - std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; - return 3; - } - if (createDelegate == nullptr) - { - std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; - return 3; - } - - // create list of properties to initialize CoreCLR - const char* propertyKeys[] = { - "TRUSTED_PLATFORM_ASSEMBLIES", - "APP_PATHS", - "APP_NI_PATHS", - "NATIVE_DLL_SEARCH_DIRECTORIES", - "AppDomainCompatSwitch" - }; - - const char* propertyValues[] = { - tpaList, - appPath, - appPath, - nativeDllSearchDirs, - "UseLatestBehaviorWhenTFMNotSpecified" - }; - - // get path to current executable - char exePath[PATH_MAX] = { 0 }; - readlink("/proc/self/exe", exePath, PATH_MAX); - - // initialize CoreCLR - int status = initializeCoreCLR( - exePath, - appDomainFriendlyName, - sizeof(propertyKeys)/sizeof(propertyKeys[0]), - propertyKeys, - propertyValues, - hostHandle, - domainId); - - if (0 > status) - { - std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; - return 4; - } - - return status; -} - -int stopCoreCLR(void* hostHandle, unsigned int domainId) -{ - // shutdown CoreCLR - int status = shutdownCoreCLR(hostHandle, domainId); - if (0 > status) - { - std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; - } - - // close the dynamic library - if (0 != dlclose(coreclrLib)) - { - std::cerr << "failed to close CoreCLR library" << std::endl; - } - - return status; -} - // // Below is from unixcoreruncommon/coreruncommon.cpp // @@ -311,3 +191,127 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) closedir(dir); } + +// +// Below is our custom start/stop interface +// + +int startCoreCLR( + // Paths of expected things + const char* clrAbsolutePath, + // Passed to propertyValues + const char* tpaList, + const char* appPath, + const char* nativeDllSearchDirs, + // Passed to InitializeCoreCLRFunction + const char* appDomainFriendlyName, + void** hostHandle, + unsigned int* domainId) +{ + // the path to the CoreCLR library + // + // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac + std::string coreClrDllPath = clrAbsolutePath; + coreClrDllPath += "/"; + coreClrDllPath += coreClrDll; + + if (coreClrDllPath.size() >= PATH_MAX) + { + std::cerr << "Absolute path to CoreCLR library too long" << std::endl; + return 1; + } + + // open the shared library + coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); + if (coreclrLib == nullptr) + { + char* error = dlerror(); + std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; + return 2; + } + + // query the function pointers + initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); + shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); + + executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); + createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); + + if (initializeCoreCLR == nullptr) + { + std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; + return 3; + } + if (executeAssembly == nullptr) + { + std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; + return 3; + } + if (shutdownCoreCLR == nullptr) + { + std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; + return 3; + } + if (createDelegate == nullptr) + { + std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; + return 3; + } + + // create list of properties to initialize CoreCLR + const char* propertyKeys[] = { + "TRUSTED_PLATFORM_ASSEMBLIES", + "APP_PATHS", + "APP_NI_PATHS", + "NATIVE_DLL_SEARCH_DIRECTORIES", + "AppDomainCompatSwitch" + }; + + const char* propertyValues[] = { + tpaList, + appPath, + appPath, + nativeDllSearchDirs, + "UseLatestBehaviorWhenTFMNotSpecified" + }; + + // get path to current executable + char exePath[PATH_MAX] = { 0 }; + readlink("/proc/self/exe", exePath, PATH_MAX); + + // initialize CoreCLR + int status = initializeCoreCLR( + exePath, + appDomainFriendlyName, + sizeof(propertyKeys)/sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + hostHandle, + domainId); + + if (0 > status) + { + std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; + return 4; + } + + return status; +} + +int stopCoreCLR(void* hostHandle, unsigned int domainId) +{ + // shutdown CoreCLR + int status = shutdownCoreCLR(hostHandle, domainId); + if (0 > status) + { + std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; + } + + // close the dynamic library + if (0 != dlclose(coreclrLib)) + { + std::cerr << "failed to close CoreCLR library" << std::endl; + } + + return status; +} From 4e6b7a8e6e270b43bfa2c5b2a97eb9e7117c6e74 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 13:57:37 -0700 Subject: [PATCH 199/298] Move start/stop functions --- host/common/coreclrutil.cpp | 244 ++++++++++++++++++------------------ 1 file changed, 124 insertions(+), 120 deletions(-) diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index 29c039d476..47ff418b29 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -37,126 +37,6 @@ ShutdownCoreCLRFunction shutdownCoreCLR; ExecuteAssemblyFunction executeAssembly; CreateDelegateFunction createDelegate; -int startCoreCLR( - // Paths of expected things - const char* clrAbsolutePath, - // Passed to propertyValues - const char* tpaList, - const char* appPath, - const char* nativeDllSearchDirs, - // Passed to InitializeCoreCLRFunction - const char* appDomainFriendlyName, - void** hostHandle, - unsigned int* domainId) -{ - // the path to the CoreCLR library - // - // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac - std::string coreClrDllPath = clrAbsolutePath; - coreClrDllPath += "/"; - coreClrDllPath += coreClrDll; - - if (coreClrDllPath.size() >= PATH_MAX) - { - std::cerr << "Absolute path to CoreCLR library too long" << std::endl; - return 1; - } - - // open the shared library - coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); - if (coreclrLib == nullptr) - { - char* error = dlerror(); - std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; - return 2; - } - - // query the function pointers - initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); - shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); - - executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); - createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); - - if (initializeCoreCLR == nullptr) - { - std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; - return 3; - } - if (executeAssembly == nullptr) - { - std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; - return 3; - } - if (shutdownCoreCLR == nullptr) - { - std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; - return 3; - } - if (createDelegate == nullptr) - { - std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; - return 3; - } - - // create list of properties to initialize CoreCLR - const char* propertyKeys[] = { - "TRUSTED_PLATFORM_ASSEMBLIES", - "APP_PATHS", - "APP_NI_PATHS", - "NATIVE_DLL_SEARCH_DIRECTORIES", - "AppDomainCompatSwitch" - }; - - const char* propertyValues[] = { - tpaList, - appPath, - appPath, - nativeDllSearchDirs, - "UseLatestBehaviorWhenTFMNotSpecified" - }; - - // get path to current executable - char exePath[PATH_MAX] = { 0 }; - readlink("/proc/self/exe", exePath, PATH_MAX); - - // initialize CoreCLR - int status = initializeCoreCLR( - exePath, - appDomainFriendlyName, - sizeof(propertyKeys)/sizeof(propertyKeys[0]), - propertyKeys, - propertyValues, - hostHandle, - domainId); - - if (0 > status) - { - std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; - return 4; - } - - return status; -} - -int stopCoreCLR(void* hostHandle, unsigned int domainId) -{ - // shutdown CoreCLR - int status = shutdownCoreCLR(hostHandle, domainId); - if (0 > status) - { - std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; - } - - // close the dynamic library - if (0 != dlclose(coreclrLib)) - { - std::cerr << "failed to close CoreCLR library" << std::endl; - } - - return status; -} - // // Below is from unixcoreruncommon/coreruncommon.cpp // @@ -311,3 +191,127 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) closedir(dir); } + +// +// Below is our custom start/stop interface +// + +int startCoreCLR( + // Paths of expected things + const char* clrAbsolutePath, + // Passed to propertyValues + const char* tpaList, + const char* appPath, + const char* nativeDllSearchDirs, + // Passed to InitializeCoreCLRFunction + const char* appDomainFriendlyName, + void** hostHandle, + unsigned int* domainId) +{ + // the path to the CoreCLR library + // + // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac + std::string coreClrDllPath = clrAbsolutePath; + coreClrDllPath += "/"; + coreClrDllPath += coreClrDll; + + if (coreClrDllPath.size() >= PATH_MAX) + { + std::cerr << "Absolute path to CoreCLR library too long" << std::endl; + return 1; + } + + // open the shared library + coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); + if (coreclrLib == nullptr) + { + char* error = dlerror(); + std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; + return 2; + } + + // query the function pointers + initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); + shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); + + executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); + createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); + + if (initializeCoreCLR == nullptr) + { + std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; + return 3; + } + if (executeAssembly == nullptr) + { + std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; + return 3; + } + if (shutdownCoreCLR == nullptr) + { + std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; + return 3; + } + if (createDelegate == nullptr) + { + std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; + return 3; + } + + // create list of properties to initialize CoreCLR + const char* propertyKeys[] = { + "TRUSTED_PLATFORM_ASSEMBLIES", + "APP_PATHS", + "APP_NI_PATHS", + "NATIVE_DLL_SEARCH_DIRECTORIES", + "AppDomainCompatSwitch" + }; + + const char* propertyValues[] = { + tpaList, + appPath, + appPath, + nativeDllSearchDirs, + "UseLatestBehaviorWhenTFMNotSpecified" + }; + + // get path to current executable + char exePath[PATH_MAX] = { 0 }; + readlink("/proc/self/exe", exePath, PATH_MAX); + + // initialize CoreCLR + int status = initializeCoreCLR( + exePath, + appDomainFriendlyName, + sizeof(propertyKeys)/sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + hostHandle, + domainId); + + if (0 > status) + { + std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; + return 4; + } + + return status; +} + +int stopCoreCLR(void* hostHandle, unsigned int domainId) +{ + // shutdown CoreCLR + int status = shutdownCoreCLR(hostHandle, domainId); + if (0 > status) + { + std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; + } + + // close the dynamic library + if (0 != dlclose(coreclrLib)) + { + std::cerr << "failed to close CoreCLR library" << std::endl; + } + + return status; +} From 684c849c4b37289bc75eb83bbd4523ec4ecb7594 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 14:23:48 -0700 Subject: [PATCH 200/298] Remove coreclr_path Obtained via CORE_ROOT, like on Windows. --- src/host/cmdline/main.cpp | 34 +++++++----------------- src/host/common/coreclrutil.cpp | 46 +++++++++++++++++++-------------- src/host/common/coreclrutil.h | 10 ------- 3 files changed, 35 insertions(+), 55 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 2443df6234..f231072501 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -13,13 +13,12 @@ namespace Cmdline void printHelp() { std::cerr << "PS CoreCLR host" << std::endl - << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl + << "Usage: host_cmdline [-alc load_context_assembly] [-s search_paths]" << std::endl << " [-b base_path] assembly [...]" << std::endl << std::endl << "What it does:" << std::endl << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl << " as host_cmdline" << std::endl - << " + this behavior can be overridden with the -c command line argument" << std::endl << "- by default the host assumes that the assembly named" << std::endl << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl << " platform assemblies" << std::endl @@ -31,7 +30,6 @@ namespace Cmdline << " + this assembly has to be located in the search path" << std::endl << "- by default the host will add the current working directory to the assembly search path" << std::endl << " + this can be overridden with the -s command line argument" << std::endl - << " + if -c is specified, it will be added to the search path instead of the current directory" << std::endl << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl << " working directory" << std::endl << " + this can be overridden with the -b command line argument" << std::endl @@ -39,7 +37,6 @@ namespace Cmdline << " static void Main(string[] args)" << std::endl << std::endl << "Options:" << std::endl - << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl << "-s a list of assembly search paths, separated by :" << std::endl << "-b the powershell assembly base path" << std::endl @@ -51,7 +48,7 @@ namespace Cmdline << "assembly the path of the assembly to execute relative to current directory" << std::endl << std::endl << "Example:" << std::endl - << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; + << "CORE_ROOT=/test/coreclr ./host_cmdline -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; } struct Args @@ -63,7 +60,6 @@ namespace Cmdline { } - std::string clrPath; std::string assemblyLoadContextFilePath; std::string searchPaths; std::string basePath; @@ -76,7 +72,6 @@ namespace Cmdline void debugPrint() const { std::cerr << "Args:" << std::endl - << "- clrPath " << clrPath << std::endl << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl << "- searchPaths " << searchPaths << std::endl << "- basePath " << basePath << std::endl @@ -103,12 +98,7 @@ namespace Cmdline const bool hasNextArg = i+1 < argc; const std::string nextArg = hasNextArg ? std::string(argv[i+1]) : std::string(""); - if (hasNextArg && (arg == "-c" || arg == "--clr-path")) - { - args.clrPath = nextArg; - ++i; - } - else if (hasNextArg && arg == "-alc") + if (hasNextArg && arg == "-alc") { args.assemblyLoadContextFilePath = nextArg; ++i; @@ -180,15 +170,10 @@ int main(int argc, char** argv) if (args.verbose) std::cerr << "currentExeAbsolutePath=" << currentExeAbsolutePath << std::endl; - // CLR absolute folder path - // - // This path is created from the location of this executable or a path - // specified with the -c command line argument std::string clrAbsolutePath; - const char* clrPathArg = args.clrPath == "" ? nullptr : args.clrPath.c_str(); - if (!GetClrFilesAbsolutePath(currentExeAbsolutePath.c_str(),clrPathArg,clrAbsolutePath)) + if (!GetAbsolutePath(std::getenv("CORE_ROOT"), clrAbsolutePath)) { - std::cerr << "could not find absolute CLR path" << std::endl; + std::cerr << "could not get absolute path of CoreCLR" << std::endl; return 1; } if (args.verbose) @@ -237,12 +222,12 @@ int main(int argc, char** argv) // assembly search paths // - // add the current directory, and optionally the CoreCLR directory if -c was specified - // and anything specified with the -s option + // add the current directory, the CoreCLR directory, and anything + // specified with the -s option std::string appPath = currentDirAbsolutePath; - if (args.clrPath != "") - appPath += ":" + clrAbsolutePath; + + appPath += ":" + clrAbsolutePath; if (args.searchPaths != "") { std::string searchAbsolutePathList = HostUtil::getAbsolutePathList(args.searchPaths); @@ -286,7 +271,6 @@ int main(int argc, char** argv) void* hostHandle; unsigned int domainId; int status = startCoreCLR( - clrAbsolutePath.c_str(), tpaList.c_str(), appPath.c_str(), nativeDllSearchDirs.c_str(), diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index 47ff418b29..96b4326257 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -71,23 +72,28 @@ bool GetDirectory(const char* absolutePath, std::string& directory) return false; } -bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) +// Modified to use CORE_ROOT environment variable + +// +// Get the absolute path to use to locate libcoreclr.so and the CLR assemblies are stored. If clrFilesPath is provided, +// this function will return the absolute path to it. Otherwise, the directory of the current executable is used. +// +// Return true in case of a success, false otherwise. +// +bool GetClrFilesAbsolutePath(const char* currentExePath, std::string& clrFilesAbsolutePath) { std::string clrFilesRelativePath; - const char* clrFilesPathLocal = clrFilesPath; + const char* clrFilesPathLocal = std::getenv("CORE_ROOT");; if (clrFilesPathLocal == nullptr) { - // There was no CLR files path specified, use the folder of the corerun/coreconsole + // There was no CLR files path specified, use the folder of the host if (!GetDirectory(currentExePath, clrFilesRelativePath)) { - perror("Failed to get directory from argv[0]"); + std::cerr << "Failed to get directory from currentExePath" << std::endl; return false; } clrFilesPathLocal = clrFilesRelativePath.c_str(); - - // TODO: consider using an env variable (if defined) as a fall-back. - // The windows version of the corerun uses core_root env variable } if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) @@ -195,10 +201,7 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) // // Below is our custom start/stop interface // - int startCoreCLR( - // Paths of expected things - const char* clrAbsolutePath, // Passed to propertyValues const char* tpaList, const char* appPath, @@ -208,12 +211,19 @@ int startCoreCLR( void** hostHandle, unsigned int* domainId) { - // the path to the CoreCLR library - // - // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac - std::string coreClrDllPath = clrAbsolutePath; - coreClrDllPath += "/"; - coreClrDllPath += coreClrDll; + // get path to current executable + char exePath[PATH_MAX] = { 0 }; + readlink("/proc/self/exe", exePath, PATH_MAX); + + std::string clrFilesAbsolutePath; + if(!GetClrFilesAbsolutePath(exePath, clrFilesAbsolutePath)) + { + return -1; + } + + std::string coreClrDllPath(clrFilesAbsolutePath); + coreClrDllPath.append("/"); + coreClrDllPath.append(coreClrDll); if (coreClrDllPath.size() >= PATH_MAX) { @@ -275,10 +285,6 @@ int startCoreCLR( "UseLatestBehaviorWhenTFMNotSpecified" }; - // get path to current executable - char exePath[PATH_MAX] = { 0 }; - readlink("/proc/self/exe", exePath, PATH_MAX); - // initialize CoreCLR int status = initializeCoreCLR( exePath, diff --git a/src/host/common/coreclrutil.h b/src/host/common/coreclrutil.h index ca055df738..c482707435 100644 --- a/src/host/common/coreclrutil.h +++ b/src/host/common/coreclrutil.h @@ -14,8 +14,6 @@ extern "C" { int startCoreCLR( - /* Paths of expected things */ - const char* clrAbsolutePath, /* Passed to propertyValues */ const char* tpaList, const char* appPath, @@ -58,14 +56,6 @@ bool GetAbsolutePath(const char* path, std::string& absolutePath); // Return true in case of a success, false otherwise. bool GetDirectory(const char* absolutePath, std::string& directory); -// -// Get the absolute path to use to locate libcoreclr.so and the CLR assemblies are stored. If clrFilesPath is provided, -// this function will return the absolute path to it. Otherwise, the directory of the current executable is used. -// -// Return true in case of a success, false otherwise. -// -bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); - // Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); #endif From 6b1f0d98479fa6b5c99c1f1ff9781efca765df0c Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 14:23:48 -0700 Subject: [PATCH 201/298] Remove coreclr_path Obtained via CORE_ROOT, like on Windows. --- host/cmdline/main.cpp | 34 ++++++++------------------- host/common/coreclrutil.cpp | 46 +++++++++++++++++++++---------------- host/common/coreclrutil.h | 10 -------- 3 files changed, 35 insertions(+), 55 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 2443df6234..f231072501 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -13,13 +13,12 @@ namespace Cmdline void printHelp() { std::cerr << "PS CoreCLR host" << std::endl - << "Usage: host_cmdline [-c coreclr_path] [-alc load_context_assembly] [-s search_paths]" << std::endl + << "Usage: host_cmdline [-alc load_context_assembly] [-s search_paths]" << std::endl << " [-b base_path] assembly [...]" << std::endl << std::endl << "What it does:" << std::endl << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl << " as host_cmdline" << std::endl - << " + this behavior can be overridden with the -c command line argument" << std::endl << "- by default the host assumes that the assembly named" << std::endl << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl << " platform assemblies" << std::endl @@ -31,7 +30,6 @@ namespace Cmdline << " + this assembly has to be located in the search path" << std::endl << "- by default the host will add the current working directory to the assembly search path" << std::endl << " + this can be overridden with the -s command line argument" << std::endl - << " + if -c is specified, it will be added to the search path instead of the current directory" << std::endl << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl << " working directory" << std::endl << " + this can be overridden with the -b command line argument" << std::endl @@ -39,7 +37,6 @@ namespace Cmdline << " static void Main(string[] args)" << std::endl << std::endl << "Options:" << std::endl - << "-c, --clr-path path to libcoreclr.so and the managed CLR assemblies" << std::endl << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl << "-s a list of assembly search paths, separated by :" << std::endl << "-b the powershell assembly base path" << std::endl @@ -51,7 +48,7 @@ namespace Cmdline << "assembly the path of the assembly to execute relative to current directory" << std::endl << std::endl << "Example:" << std::endl - << "./host_cmdline -c /test/coreclr -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; + << "CORE_ROOT=/test/coreclr ./host_cmdline -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; } struct Args @@ -63,7 +60,6 @@ namespace Cmdline { } - std::string clrPath; std::string assemblyLoadContextFilePath; std::string searchPaths; std::string basePath; @@ -76,7 +72,6 @@ namespace Cmdline void debugPrint() const { std::cerr << "Args:" << std::endl - << "- clrPath " << clrPath << std::endl << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl << "- searchPaths " << searchPaths << std::endl << "- basePath " << basePath << std::endl @@ -103,12 +98,7 @@ namespace Cmdline const bool hasNextArg = i+1 < argc; const std::string nextArg = hasNextArg ? std::string(argv[i+1]) : std::string(""); - if (hasNextArg && (arg == "-c" || arg == "--clr-path")) - { - args.clrPath = nextArg; - ++i; - } - else if (hasNextArg && arg == "-alc") + if (hasNextArg && arg == "-alc") { args.assemblyLoadContextFilePath = nextArg; ++i; @@ -180,15 +170,10 @@ int main(int argc, char** argv) if (args.verbose) std::cerr << "currentExeAbsolutePath=" << currentExeAbsolutePath << std::endl; - // CLR absolute folder path - // - // This path is created from the location of this executable or a path - // specified with the -c command line argument std::string clrAbsolutePath; - const char* clrPathArg = args.clrPath == "" ? nullptr : args.clrPath.c_str(); - if (!GetClrFilesAbsolutePath(currentExeAbsolutePath.c_str(),clrPathArg,clrAbsolutePath)) + if (!GetAbsolutePath(std::getenv("CORE_ROOT"), clrAbsolutePath)) { - std::cerr << "could not find absolute CLR path" << std::endl; + std::cerr << "could not get absolute path of CoreCLR" << std::endl; return 1; } if (args.verbose) @@ -237,12 +222,12 @@ int main(int argc, char** argv) // assembly search paths // - // add the current directory, and optionally the CoreCLR directory if -c was specified - // and anything specified with the -s option + // add the current directory, the CoreCLR directory, and anything + // specified with the -s option std::string appPath = currentDirAbsolutePath; - if (args.clrPath != "") - appPath += ":" + clrAbsolutePath; + + appPath += ":" + clrAbsolutePath; if (args.searchPaths != "") { std::string searchAbsolutePathList = HostUtil::getAbsolutePathList(args.searchPaths); @@ -286,7 +271,6 @@ int main(int argc, char** argv) void* hostHandle; unsigned int domainId; int status = startCoreCLR( - clrAbsolutePath.c_str(), tpaList.c_str(), appPath.c_str(), nativeDllSearchDirs.c_str(), diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index 47ff418b29..96b4326257 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -71,23 +72,28 @@ bool GetDirectory(const char* absolutePath, std::string& directory) return false; } -bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) +// Modified to use CORE_ROOT environment variable + +// +// Get the absolute path to use to locate libcoreclr.so and the CLR assemblies are stored. If clrFilesPath is provided, +// this function will return the absolute path to it. Otherwise, the directory of the current executable is used. +// +// Return true in case of a success, false otherwise. +// +bool GetClrFilesAbsolutePath(const char* currentExePath, std::string& clrFilesAbsolutePath) { std::string clrFilesRelativePath; - const char* clrFilesPathLocal = clrFilesPath; + const char* clrFilesPathLocal = std::getenv("CORE_ROOT");; if (clrFilesPathLocal == nullptr) { - // There was no CLR files path specified, use the folder of the corerun/coreconsole + // There was no CLR files path specified, use the folder of the host if (!GetDirectory(currentExePath, clrFilesRelativePath)) { - perror("Failed to get directory from argv[0]"); + std::cerr << "Failed to get directory from currentExePath" << std::endl; return false; } clrFilesPathLocal = clrFilesRelativePath.c_str(); - - // TODO: consider using an env variable (if defined) as a fall-back. - // The windows version of the corerun uses core_root env variable } if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) @@ -195,10 +201,7 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) // // Below is our custom start/stop interface // - int startCoreCLR( - // Paths of expected things - const char* clrAbsolutePath, // Passed to propertyValues const char* tpaList, const char* appPath, @@ -208,12 +211,19 @@ int startCoreCLR( void** hostHandle, unsigned int* domainId) { - // the path to the CoreCLR library - // - // This is typically libcoreclr.so on Linux and libcoreclr.dylib on Mac - std::string coreClrDllPath = clrAbsolutePath; - coreClrDllPath += "/"; - coreClrDllPath += coreClrDll; + // get path to current executable + char exePath[PATH_MAX] = { 0 }; + readlink("/proc/self/exe", exePath, PATH_MAX); + + std::string clrFilesAbsolutePath; + if(!GetClrFilesAbsolutePath(exePath, clrFilesAbsolutePath)) + { + return -1; + } + + std::string coreClrDllPath(clrFilesAbsolutePath); + coreClrDllPath.append("/"); + coreClrDllPath.append(coreClrDll); if (coreClrDllPath.size() >= PATH_MAX) { @@ -275,10 +285,6 @@ int startCoreCLR( "UseLatestBehaviorWhenTFMNotSpecified" }; - // get path to current executable - char exePath[PATH_MAX] = { 0 }; - readlink("/proc/self/exe", exePath, PATH_MAX); - // initialize CoreCLR int status = initializeCoreCLR( exePath, diff --git a/host/common/coreclrutil.h b/host/common/coreclrutil.h index ca055df738..c482707435 100644 --- a/host/common/coreclrutil.h +++ b/host/common/coreclrutil.h @@ -14,8 +14,6 @@ extern "C" { int startCoreCLR( - /* Paths of expected things */ - const char* clrAbsolutePath, /* Passed to propertyValues */ const char* tpaList, const char* appPath, @@ -58,14 +56,6 @@ bool GetAbsolutePath(const char* path, std::string& absolutePath); // Return true in case of a success, false otherwise. bool GetDirectory(const char* absolutePath, std::string& directory); -// -// Get the absolute path to use to locate libcoreclr.so and the CLR assemblies are stored. If clrFilesPath is provided, -// this function will return the absolute path to it. Otherwise, the directory of the current executable is used. -// -// Return true in case of a success, false otherwise. -// -bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); - // Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); #endif From e55277d2d6d0efb7bd84544f53e1829ca1de0f39 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 14:24:53 -0700 Subject: [PATCH 202/298] Fix warning in GetDirectory() --- src/host/common/coreclrutil.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index 96b4326257..8e26cf6243 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -59,6 +59,7 @@ bool GetAbsolutePath(const char* path, std::string& absolutePath) return result; } +// TODO use dirname bool GetDirectory(const char* absolutePath, std::string& directory) { directory.assign(absolutePath); @@ -124,7 +125,7 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) // Walk the directory for each extension separately so that we first get files with .ni.dll extension, // then files with .dll extension, etc. - for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + for (unsigned int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) { const char* ext = tpaExtensions[extIndex]; int extLength = strlen(ext); From b4b0f70ad111261a877cb0de11436f5ddb1c05d4 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 14:24:53 -0700 Subject: [PATCH 203/298] Fix warning in GetDirectory() --- host/common/coreclrutil.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index 96b4326257..8e26cf6243 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -59,6 +59,7 @@ bool GetAbsolutePath(const char* path, std::string& absolutePath) return result; } +// TODO use dirname bool GetDirectory(const char* absolutePath, std::string& directory) { directory.assign(absolutePath); @@ -124,7 +125,7 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) // Walk the directory for each extension separately so that we first get files with .ni.dll extension, // then files with .dll extension, etc. - for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) + for (unsigned int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) { const char* ext = tpaExtensions[extIndex]; int extLength = strlen(ext); From 33a09baf03b986d02322f48765a05bfd57ad7cb1 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 14:25:38 -0700 Subject: [PATCH 204/298] Remove currentExeAbsolutePath --- src/host/cmdline/main.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index f231072501..e77e1d7f37 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -160,16 +160,6 @@ int main(int argc, char** argv) if (args.verbose) args.debugPrint(); - // get the absolute path of the current executable - std::string currentExeAbsolutePath; - if (!GetAbsolutePath(argv[0],currentExeAbsolutePath)) - { - std::cerr << "could not get absolute path of current executable" << std::endl; - return 1; - } - if (args.verbose) - std::cerr << "currentExeAbsolutePath=" << currentExeAbsolutePath << std::endl; - std::string clrAbsolutePath; if (!GetAbsolutePath(std::getenv("CORE_ROOT"), clrAbsolutePath)) { From cb3fe8d16eec1420527f9a2fc3951a8528083969 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 14:25:38 -0700 Subject: [PATCH 205/298] Remove currentExeAbsolutePath --- host/cmdline/main.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index f231072501..e77e1d7f37 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -160,16 +160,6 @@ int main(int argc, char** argv) if (args.verbose) args.debugPrint(); - // get the absolute path of the current executable - std::string currentExeAbsolutePath; - if (!GetAbsolutePath(argv[0],currentExeAbsolutePath)) - { - std::cerr << "could not get absolute path of current executable" << std::endl; - return 1; - } - if (args.verbose) - std::cerr << "currentExeAbsolutePath=" << currentExeAbsolutePath << std::endl; - std::string clrAbsolutePath; if (!GetAbsolutePath(std::getenv("CORE_ROOT"), clrAbsolutePath)) { From e30f05983884c9ab870b954ad8d5dafcbc5d50f6 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 15:18:21 -0700 Subject: [PATCH 206/298] Refactor into GetEnvAbsolutePath() --- src/host/common/coreclrutil.cpp | 35 +++++++++++---------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index 8e26cf6243..79e753fd05 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -73,33 +73,23 @@ bool GetDirectory(const char* absolutePath, std::string& directory) return false; } -// Modified to use CORE_ROOT environment variable - // -// Get the absolute path to use to locate libcoreclr.so and the CLR assemblies are stored. If clrFilesPath is provided, -// this function will return the absolute path to it. Otherwise, the directory of the current executable is used. +// Get the absolute path given the environment variable. // // Return true in case of a success, false otherwise. // -bool GetClrFilesAbsolutePath(const char* currentExePath, std::string& clrFilesAbsolutePath) +bool GetEnvAbsolutePath(const char* env_var, std::string& absolutePath) { - std::string clrFilesRelativePath; - const char* clrFilesPathLocal = std::getenv("CORE_ROOT");; - if (clrFilesPathLocal == nullptr) + const char* filesPathLocal = std::getenv(env_var);; + if (filesPathLocal == nullptr) { - // There was no CLR files path specified, use the folder of the host - if (!GetDirectory(currentExePath, clrFilesRelativePath)) - { - std::cerr << "Failed to get directory from currentExePath" << std::endl; - return false; - } - - clrFilesPathLocal = clrFilesRelativePath.c_str(); + std::cerr << "$" << env_var << " was empty" << std::endl; + return false; } - if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) + if (!GetAbsolutePath(filesPathLocal, absolutePath)) { - perror("Failed to convert CLR files path to absolute path"); + std::cerr << "Failed to get absolute path for " << env_var << std::endl; return false; } @@ -203,11 +193,9 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) // Below is our custom start/stop interface // int startCoreCLR( - // Passed to propertyValues const char* tpaList, const char* appPath, const char* nativeDllSearchDirs, - // Passed to InitializeCoreCLRFunction const char* appDomainFriendlyName, void** hostHandle, unsigned int* domainId) @@ -216,12 +204,14 @@ int startCoreCLR( char exePath[PATH_MAX] = { 0 }; readlink("/proc/self/exe", exePath, PATH_MAX); + // get the CoreCLR root path std::string clrFilesAbsolutePath; - if(!GetClrFilesAbsolutePath(exePath, clrFilesAbsolutePath)) + if(!GetEnvAbsolutePath("CORE_ROOT", clrFilesAbsolutePath)) { return -1; } + // get the CoreCLR shared library path std::string coreClrDllPath(clrFilesAbsolutePath); coreClrDllPath.append("/"); coreClrDllPath.append(coreClrDll); @@ -241,10 +231,9 @@ int startCoreCLR( return 2; } - // query the function pointers + // query and verify the function pointers initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); - executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); From e570c2a0a8b3cccd2461a317e06b060141322323 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 15:18:21 -0700 Subject: [PATCH 207/298] Refactor into GetEnvAbsolutePath() --- host/common/coreclrutil.cpp | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index 8e26cf6243..79e753fd05 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -73,33 +73,23 @@ bool GetDirectory(const char* absolutePath, std::string& directory) return false; } -// Modified to use CORE_ROOT environment variable - // -// Get the absolute path to use to locate libcoreclr.so and the CLR assemblies are stored. If clrFilesPath is provided, -// this function will return the absolute path to it. Otherwise, the directory of the current executable is used. +// Get the absolute path given the environment variable. // // Return true in case of a success, false otherwise. // -bool GetClrFilesAbsolutePath(const char* currentExePath, std::string& clrFilesAbsolutePath) +bool GetEnvAbsolutePath(const char* env_var, std::string& absolutePath) { - std::string clrFilesRelativePath; - const char* clrFilesPathLocal = std::getenv("CORE_ROOT");; - if (clrFilesPathLocal == nullptr) + const char* filesPathLocal = std::getenv(env_var);; + if (filesPathLocal == nullptr) { - // There was no CLR files path specified, use the folder of the host - if (!GetDirectory(currentExePath, clrFilesRelativePath)) - { - std::cerr << "Failed to get directory from currentExePath" << std::endl; - return false; - } - - clrFilesPathLocal = clrFilesRelativePath.c_str(); + std::cerr << "$" << env_var << " was empty" << std::endl; + return false; } - if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) + if (!GetAbsolutePath(filesPathLocal, absolutePath)) { - perror("Failed to convert CLR files path to absolute path"); + std::cerr << "Failed to get absolute path for " << env_var << std::endl; return false; } @@ -203,11 +193,9 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) // Below is our custom start/stop interface // int startCoreCLR( - // Passed to propertyValues const char* tpaList, const char* appPath, const char* nativeDllSearchDirs, - // Passed to InitializeCoreCLRFunction const char* appDomainFriendlyName, void** hostHandle, unsigned int* domainId) @@ -216,12 +204,14 @@ int startCoreCLR( char exePath[PATH_MAX] = { 0 }; readlink("/proc/self/exe", exePath, PATH_MAX); + // get the CoreCLR root path std::string clrFilesAbsolutePath; - if(!GetClrFilesAbsolutePath(exePath, clrFilesAbsolutePath)) + if(!GetEnvAbsolutePath("CORE_ROOT", clrFilesAbsolutePath)) { return -1; } + // get the CoreCLR shared library path std::string coreClrDllPath(clrFilesAbsolutePath); coreClrDllPath.append("/"); coreClrDllPath.append(coreClrDll); @@ -241,10 +231,9 @@ int startCoreCLR( return 2; } - // query the function pointers + // query and verify the function pointers initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); - executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); From 4ba2ac196aeb7d6760378196bdf9758ce5bb22b5 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 18:17:15 -0700 Subject: [PATCH 208/298] Refactor tpaList into libpshost --- src/host/cmdline/main.cpp | 48 ++------------------------------- src/host/common/coreclrutil.cpp | 21 +++++++++++++-- src/host/common/coreclrutil.h | 4 --- 3 files changed, 21 insertions(+), 52 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index e77e1d7f37..b29935cc17 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -40,15 +40,11 @@ namespace Cmdline << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl << "-s a list of assembly search paths, separated by :" << std::endl << "-b the powershell assembly base path" << std::endl - << "-v verbose output, show paths" << std::endl - << "-tpa additional list of trusted platform assemblies, this references dll and exe files" << std::endl - << " separated by :" << std::endl - << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl - << " argument, must always be added to the TPA list with this parameter" << std::endl + << "-v verbose output" << std::endl << "assembly the path of the assembly to execute relative to current directory" << std::endl << std::endl << "Example:" << std::endl - << "CORE_ROOT=/test/coreclr ./host_cmdline -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; + << "CORE_ROOT=/test/coreclr PWRSH_ROOT=/test/powershell ./host_cmdline -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps powershell-simple 'get-process'" << std::endl; } struct Args @@ -63,7 +59,6 @@ namespace Cmdline std::string assemblyLoadContextFilePath; std::string searchPaths; std::string basePath; - std::string tpaList; std::string entryAssemblyPath; int argc; char** argv; @@ -75,7 +70,6 @@ namespace Cmdline << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl << "- searchPaths " << searchPaths << std::endl << "- basePath " << basePath << std::endl - << "- tpaList " << tpaList << std::endl << "- entryAssemblyPath " << entryAssemblyPath << std::endl << "- argc " << argc << std::endl << "- verbose " << (verbose ? "true" : "false") << std::endl; @@ -113,11 +107,6 @@ namespace Cmdline args.basePath = nextArg; ++i; } - else if (hasNextArg && arg == "-tpa") - { - args.tpaList = nextArg; - ++i; - } else if (arg == "-v") { args.verbose = true; @@ -169,38 +158,6 @@ int main(int argc, char** argv) if (args.verbose) std::cerr << "clrAbsolutePath=" << clrAbsolutePath << std::endl; - // TPA list - // - // The list of platform assemblies must include all CoreCLR assemblies - // and the Microsoft.PowerShell.CoreCLR.AssemblyLoadContext - // - // if the -alc parameter was specified, add it to the TPA list here - - std::string tpaList; - AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); - - if (args.assemblyLoadContextFilePath != "") - { - std::string assemblyLoadContextAbsoluteFilePath; - if (!GetAbsolutePath(args.assemblyLoadContextFilePath.c_str(),assemblyLoadContextAbsoluteFilePath)) - { - std::cerr << "Failed to get absolute file path for assembly load context" << std::endl; - return 1; - } - tpaList += ":" + assemblyLoadContextAbsoluteFilePath; - } - - // add the -tpa command line argument - if (args.tpaList != "") - { - std::string tpaAbsolutePathList = HostUtil::getAbsolutePathList(args.tpaList); - if (tpaAbsolutePathList != "") - tpaList += ":" + tpaAbsolutePathList; - } - - if (args.verbose) - std::cerr << "tpaList: " << tpaList << std::endl; - // get the absolute path of the current directory std::string currentDirAbsolutePath; @@ -261,7 +218,6 @@ int main(int argc, char** argv) void* hostHandle; unsigned int domainId; int status = startCoreCLR( - tpaList.c_str(), appPath.c_str(), nativeDllSearchDirs.c_str(), "ps_cmdline_host", diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index 79e753fd05..cccd0efd39 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -96,6 +96,7 @@ bool GetEnvAbsolutePath(const char* env_var, std::string& absolutePath) return true; } +// Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) { const char * const tpaExtensions[] = { @@ -193,7 +194,6 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) // Below is our custom start/stop interface // int startCoreCLR( - const char* tpaList, const char* appPath, const char* nativeDllSearchDirs, const char* appDomainFriendlyName, @@ -258,6 +258,23 @@ int startCoreCLR( return 3; } + // generate the Trusted Platform Assemblies list + std::string tpaList; + + // add assemblies in the CoreCLR root path + AddFilesFromDirectoryToTpaList(clrFilesAbsolutePath.c_str(), tpaList); + + // get path to AssemblyLoadContext.dll + std::string psFilesAbsolutePath; + if(!GetEnvAbsolutePath("PWRSH_ROOT", psFilesAbsolutePath)) + { + return -1; + } + std::string assemblyLoadContextAbsoluteFilePath(psFilesAbsolutePath + "/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"); + + // add AssemblyLoadContext + tpaList.append(assemblyLoadContextAbsoluteFilePath); + // create list of properties to initialize CoreCLR const char* propertyKeys[] = { "TRUSTED_PLATFORM_ASSEMBLIES", @@ -268,7 +285,7 @@ int startCoreCLR( }; const char* propertyValues[] = { - tpaList, + tpaList.c_str(), appPath, appPath, nativeDllSearchDirs, diff --git a/src/host/common/coreclrutil.h b/src/host/common/coreclrutil.h index c482707435..018f5a5f5d 100644 --- a/src/host/common/coreclrutil.h +++ b/src/host/common/coreclrutil.h @@ -15,7 +15,6 @@ extern "C" { int startCoreCLR( /* Passed to propertyValues */ - const char* tpaList, const char* appPath, const char* nativeDllSearchDirs, /* Passed to InitializeCoreCLRFunction */ @@ -55,7 +54,4 @@ bool GetAbsolutePath(const char* path, std::string& absolutePath); // Get directory of the specified path. // Return true in case of a success, false otherwise. bool GetDirectory(const char* absolutePath, std::string& directory); - -// Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. -void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); #endif From da69d4a8c7d75365c94dd8f08ea624c322273cb1 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 18:17:15 -0700 Subject: [PATCH 209/298] Refactor tpaList into libpshost --- host/cmdline/main.cpp | 48 ++----------------------------------- host/common/coreclrutil.cpp | 21 ++++++++++++++-- host/common/coreclrutil.h | 4 ---- 3 files changed, 21 insertions(+), 52 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index e77e1d7f37..b29935cc17 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -40,15 +40,11 @@ namespace Cmdline << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl << "-s a list of assembly search paths, separated by :" << std::endl << "-b the powershell assembly base path" << std::endl - << "-v verbose output, show paths" << std::endl - << "-tpa additional list of trusted platform assemblies, this references dll and exe files" << std::endl - << " separated by :" << std::endl - << " unless part of the same folder as CoreCLR, the main assembly referenced with the assembly_name" << std::endl - << " argument, must always be added to the TPA list with this parameter" << std::endl + << "-v verbose output" << std::endl << "assembly the path of the assembly to execute relative to current directory" << std::endl << std::endl << "Example:" << std::endl - << "CORE_ROOT=/test/coreclr ./host_cmdline -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps -tpa /test/ps/powershell-simple.exe 'powershell-simple, version=1.0.0.0, culture=neutral, PublicKeyToken=null' 'get-process'" << std::endl; + << "CORE_ROOT=/test/coreclr PWRSH_ROOT=/test/powershell ./host_cmdline -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps powershell-simple 'get-process'" << std::endl; } struct Args @@ -63,7 +59,6 @@ namespace Cmdline std::string assemblyLoadContextFilePath; std::string searchPaths; std::string basePath; - std::string tpaList; std::string entryAssemblyPath; int argc; char** argv; @@ -75,7 +70,6 @@ namespace Cmdline << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl << "- searchPaths " << searchPaths << std::endl << "- basePath " << basePath << std::endl - << "- tpaList " << tpaList << std::endl << "- entryAssemblyPath " << entryAssemblyPath << std::endl << "- argc " << argc << std::endl << "- verbose " << (verbose ? "true" : "false") << std::endl; @@ -113,11 +107,6 @@ namespace Cmdline args.basePath = nextArg; ++i; } - else if (hasNextArg && arg == "-tpa") - { - args.tpaList = nextArg; - ++i; - } else if (arg == "-v") { args.verbose = true; @@ -169,38 +158,6 @@ int main(int argc, char** argv) if (args.verbose) std::cerr << "clrAbsolutePath=" << clrAbsolutePath << std::endl; - // TPA list - // - // The list of platform assemblies must include all CoreCLR assemblies - // and the Microsoft.PowerShell.CoreCLR.AssemblyLoadContext - // - // if the -alc parameter was specified, add it to the TPA list here - - std::string tpaList; - AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(),tpaList); - - if (args.assemblyLoadContextFilePath != "") - { - std::string assemblyLoadContextAbsoluteFilePath; - if (!GetAbsolutePath(args.assemblyLoadContextFilePath.c_str(),assemblyLoadContextAbsoluteFilePath)) - { - std::cerr << "Failed to get absolute file path for assembly load context" << std::endl; - return 1; - } - tpaList += ":" + assemblyLoadContextAbsoluteFilePath; - } - - // add the -tpa command line argument - if (args.tpaList != "") - { - std::string tpaAbsolutePathList = HostUtil::getAbsolutePathList(args.tpaList); - if (tpaAbsolutePathList != "") - tpaList += ":" + tpaAbsolutePathList; - } - - if (args.verbose) - std::cerr << "tpaList: " << tpaList << std::endl; - // get the absolute path of the current directory std::string currentDirAbsolutePath; @@ -261,7 +218,6 @@ int main(int argc, char** argv) void* hostHandle; unsigned int domainId; int status = startCoreCLR( - tpaList.c_str(), appPath.c_str(), nativeDllSearchDirs.c_str(), "ps_cmdline_host", diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index 79e753fd05..cccd0efd39 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -96,6 +96,7 @@ bool GetEnvAbsolutePath(const char* env_var, std::string& absolutePath) return true; } +// Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) { const char * const tpaExtensions[] = { @@ -193,7 +194,6 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) // Below is our custom start/stop interface // int startCoreCLR( - const char* tpaList, const char* appPath, const char* nativeDllSearchDirs, const char* appDomainFriendlyName, @@ -258,6 +258,23 @@ int startCoreCLR( return 3; } + // generate the Trusted Platform Assemblies list + std::string tpaList; + + // add assemblies in the CoreCLR root path + AddFilesFromDirectoryToTpaList(clrFilesAbsolutePath.c_str(), tpaList); + + // get path to AssemblyLoadContext.dll + std::string psFilesAbsolutePath; + if(!GetEnvAbsolutePath("PWRSH_ROOT", psFilesAbsolutePath)) + { + return -1; + } + std::string assemblyLoadContextAbsoluteFilePath(psFilesAbsolutePath + "/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"); + + // add AssemblyLoadContext + tpaList.append(assemblyLoadContextAbsoluteFilePath); + // create list of properties to initialize CoreCLR const char* propertyKeys[] = { "TRUSTED_PLATFORM_ASSEMBLIES", @@ -268,7 +285,7 @@ int startCoreCLR( }; const char* propertyValues[] = { - tpaList, + tpaList.c_str(), appPath, appPath, nativeDllSearchDirs, diff --git a/host/common/coreclrutil.h b/host/common/coreclrutil.h index c482707435..018f5a5f5d 100644 --- a/host/common/coreclrutil.h +++ b/host/common/coreclrutil.h @@ -15,7 +15,6 @@ extern "C" { int startCoreCLR( /* Passed to propertyValues */ - const char* tpaList, const char* appPath, const char* nativeDllSearchDirs, /* Passed to InitializeCoreCLRFunction */ @@ -55,7 +54,4 @@ bool GetAbsolutePath(const char* path, std::string& absolutePath); // Get directory of the specified path. // Return true in case of a success, false otherwise. bool GetDirectory(const char* absolutePath, std::string& directory); - -// Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. -void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); #endif From 6fb372c72a88c99db1ef868358b1d9f2be9eb688 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 18:17:27 -0700 Subject: [PATCH 210/298] Remove base_path and load_context_assembly - libpshost resolves the absolute path to the PowerShell binaries from the environment variable PWRSH_ROOT - libpshost assumes that PowerShell's AssemblyLoadContext.dll exists in PWRSH_ROOT and loads during `startCoreCLR()` - libicu is now only used by libpshost; note that an icu::UnicodeString is UTF-16, and endianness does not matter (see http://userguide.icu-project.org/strings#TOC-ICU:-16-bit-Unicode-strings) --- src/CMakeLists.txt | 2 +- src/host/cmdline/main.cpp | 88 +++++---------------------------- src/host/common/coreclrutil.cpp | 28 +++++++++-- 3 files changed, 38 insertions(+), 80 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8db93c175b..9d568377fc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,7 +26,7 @@ find_package(Threads) target_link_libraries(ps icuuc) target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps pshost) target_link_libraries(pshost dl icuuc) -target_link_libraries(host_cmdline pshost icuuc) +target_link_libraries(host_cmdline pshost) # target specific include directories target_include_directories(monad_native PRIVATE host) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index b29935cc17..ac9df809e8 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -13,38 +13,29 @@ namespace Cmdline void printHelp() { std::cerr << "PS CoreCLR host" << std::endl - << "Usage: host_cmdline [-alc load_context_assembly] [-s search_paths]" << std::endl - << " [-b base_path] assembly [...]" << std::endl + << "Usage: host_cmdline [-s search_paths] assembly [...]" << std::endl << std::endl << "What it does:" << std::endl - << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl - << " as host_cmdline" << std::endl + << "- the host assumes that CoreCLR is located $CORE_ROOT" << std::endl << "- by default the host assumes that the assembly named" << std::endl - << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl - << " platform assemblies" << std::endl - << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl - << " be provided with the -alc command line argument" << std::endl + << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is " << std::endl + << " located in $PWRSH_ROOT" << std::endl << "- all additional parameters at the end of the command line are forwarded" << std::endl << " to the Main function in the assembly" << std::endl << "- the host will execute the Main function in the specified assembly" << std::endl << " + this assembly has to be located in the search path" << std::endl << "- by default the host will add the current working directory to the assembly search path" << std::endl << " + this can be overridden with the -s command line argument" << std::endl - << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl - << " working directory" << std::endl - << " + this can be overridden with the -b command line argument" << std::endl << "- the function signature of the Main function that gets executed must be:" << std::endl << " static void Main(string[] args)" << std::endl << std::endl << "Options:" << std::endl - << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl << "-s a list of assembly search paths, separated by :" << std::endl - << "-b the powershell assembly base path" << std::endl << "-v verbose output" << std::endl << "assembly the path of the assembly to execute relative to current directory" << std::endl << std::endl << "Example:" << std::endl - << "CORE_ROOT=/test/coreclr PWRSH_ROOT=/test/powershell ./host_cmdline -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps powershell-simple 'get-process'" << std::endl; + << "CORE_ROOT=/test/coreclr PWRSH_ROOT=/test/powershell ./host_cmdline -s /test/ps powershell-simple 'get-process'" << std::endl; } struct Args @@ -56,9 +47,7 @@ namespace Cmdline { } - std::string assemblyLoadContextFilePath; std::string searchPaths; - std::string basePath; std::string entryAssemblyPath; int argc; char** argv; @@ -67,9 +56,7 @@ namespace Cmdline void debugPrint() const { std::cerr << "Args:" << std::endl - << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl << "- searchPaths " << searchPaths << std::endl - << "- basePath " << basePath << std::endl << "- entryAssemblyPath " << entryAssemblyPath << std::endl << "- argc " << argc << std::endl << "- verbose " << (verbose ? "true" : "false") << std::endl; @@ -92,21 +79,11 @@ namespace Cmdline const bool hasNextArg = i+1 < argc; const std::string nextArg = hasNextArg ? std::string(argv[i+1]) : std::string(""); - if (hasNextArg && arg == "-alc") - { - args.assemblyLoadContextFilePath = nextArg; - ++i; - } - else if (hasNextArg && arg == "-s") + if (hasNextArg && arg == "-s") { args.searchPaths = nextArg; ++i; } - else if (hasNextArg && arg == "-b") - { - args.basePath = nextArg; - ++i; - } else if (arg == "-v") { args.verbose = true; @@ -190,31 +167,6 @@ int main(int argc, char** argv) // Add both the CoreCLR directory and the regular search paths to this list std::string nativeDllSearchDirs = appPath + ":" + clrAbsolutePath; - // convert the app base to utf-16 - // - // this is needed as a utf-16 LE string by CoreCLR/PS's assembly load context interface - // it is either: - // - the current dir's absolute path - // - the path specified through the -b argument - std::string psBasePath = currentDirAbsolutePath; - if (args.basePath != "") - { - if (!GetAbsolutePath(args.basePath.c_str(),psBasePath)) - { - std::cerr << "failed to get the absolute path from the base_path argument" << std::endl; - return 1; - } - } - if (args.verbose) - std::cerr << "psBasePath=" << psBasePath << std::endl; - - // make sure to leave 1 byte at the end for null termination - std::basic_string psBasePath16(PATH_MAX+1,0); - - UnicodeString u8str = UnicodeString(psBasePath.c_str(),"UTF-8"); - int32_t targetSize = u8str.extract(0,u8str.length(),(char*)&psBasePath16[0],(psBasePath16.size()-1)*sizeof(char16_t),"UTF-16LE"); - psBasePath16.resize(targetSize/sizeof(char16_t)+1); - void* hostHandle; unsigned int domainId; int status = startCoreCLR( @@ -224,29 +176,13 @@ int main(int argc, char** argv) &hostHandle, &domainId); - // initialize the PS's custom assembly load context - typedef void (*LoaderRunHelperFp)(const char16_t* appPath); - LoaderRunHelperFp loaderDelegate = nullptr; - status = createDelegate( - hostHandle, - domainId, - "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "System.Management.Automation.PowerShellAssemblyLoadContextInitializer", - "SetPowerShellAssemblyLoadContext", - (void**)&loaderDelegate); - if (0 > status) - { - std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; - return 4; - } - loaderDelegate(psBasePath16.c_str()); - - // call into Main of powershell-simple.exe + // call into Main of assembly unsigned int exitCode; - executeAssembly(hostHandle, domainId, args.argc, - (const char**)args.argv, - (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), - &exitCode); + executeAssembly( + hostHandle, domainId, args.argc, + (const char**)args.argv, + (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), + &exitCode); status = stopCoreCLR(hostHandle, domainId); diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index cccd0efd39..95af993fe5 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -8,6 +8,7 @@ #include #include #include +#include // The name of the CoreCLR native runtime DLL #if defined(__APPLE__) @@ -265,12 +266,12 @@ int startCoreCLR( AddFilesFromDirectoryToTpaList(clrFilesAbsolutePath.c_str(), tpaList); // get path to AssemblyLoadContext.dll - std::string psFilesAbsolutePath; - if(!GetEnvAbsolutePath("PWRSH_ROOT", psFilesAbsolutePath)) + std::string psAbsolutePath; + if(!GetEnvAbsolutePath("PWRSH_ROOT", psAbsolutePath)) { return -1; } - std::string assemblyLoadContextAbsoluteFilePath(psFilesAbsolutePath + "/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"); + std::string assemblyLoadContextAbsoluteFilePath(psAbsolutePath + "/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"); // add AssemblyLoadContext tpaList.append(assemblyLoadContextAbsoluteFilePath); @@ -308,6 +309,27 @@ int startCoreCLR( return 4; } + // initialize PowerShell's custom assembly load context + typedef void (*LoaderRunHelperFp)(const char16_t* appPath); + LoaderRunHelperFp loaderDelegate = nullptr; + status = createDelegate( + *hostHandle, + *domainId, + "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "System.Management.Automation.PowerShellAssemblyLoadContextInitializer", + "SetPowerShellAssemblyLoadContext", + (void**)&loaderDelegate); + + if (status < 0) + { + std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; + return 4; + } + + icu::UnicodeString psUnicodeAbsolutePath = icu::UnicodeString::fromUTF8(psAbsolutePath.c_str()); + + loaderDelegate((const char16_t*)psUnicodeAbsolutePath.getTerminatedBuffer()); + return status; } From b897e08d217d7d87e98361669512b15c1caf163e Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 22 Oct 2015 18:17:27 -0700 Subject: [PATCH 211/298] Remove base_path and load_context_assembly - libpshost resolves the absolute path to the PowerShell binaries from the environment variable PWRSH_ROOT - libpshost assumes that PowerShell's AssemblyLoadContext.dll exists in PWRSH_ROOT and loads during `startCoreCLR()` - libicu is now only used by libpshost; note that an icu::UnicodeString is UTF-16, and endianness does not matter (see http://userguide.icu-project.org/strings#TOC-ICU:-16-bit-Unicode-strings) --- CMakeLists.txt | 2 +- host/cmdline/main.cpp | 88 +++++-------------------------------- host/common/coreclrutil.cpp | 28 ++++++++++-- 3 files changed, 38 insertions(+), 80 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8db93c175b..9d568377fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ find_package(Threads) target_link_libraries(ps icuuc) target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps pshost) target_link_libraries(pshost dl icuuc) -target_link_libraries(host_cmdline pshost icuuc) +target_link_libraries(host_cmdline pshost) # target specific include directories target_include_directories(monad_native PRIVATE host) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index b29935cc17..ac9df809e8 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -13,38 +13,29 @@ namespace Cmdline void printHelp() { std::cerr << "PS CoreCLR host" << std::endl - << "Usage: host_cmdline [-alc load_context_assembly] [-s search_paths]" << std::endl - << " [-b base_path] assembly [...]" << std::endl + << "Usage: host_cmdline [-s search_paths] assembly [...]" << std::endl << std::endl << "What it does:" << std::endl - << "- by default the host assumes that CoreCLR is located in the same folder" << std::endl - << " as host_cmdline" << std::endl + << "- the host assumes that CoreCLR is located $CORE_ROOT" << std::endl << "- by default the host assumes that the assembly named" << std::endl - << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is part of the" << std::endl - << " platform assemblies" << std::endl - << " + a custom assembly containing the PowerShellAssemblyLoadContext can" << std::endl - << " be provided with the -alc command line argument" << std::endl + << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is " << std::endl + << " located in $PWRSH_ROOT" << std::endl << "- all additional parameters at the end of the command line are forwarded" << std::endl << " to the Main function in the assembly" << std::endl << "- the host will execute the Main function in the specified assembly" << std::endl << " + this assembly has to be located in the search path" << std::endl << "- by default the host will add the current working directory to the assembly search path" << std::endl << " + this can be overridden with the -s command line argument" << std::endl - << "- by default the host assumes the PS base path for the assembly load context is the current" << std::endl - << " working directory" << std::endl - << " + this can be overridden with the -b command line argument" << std::endl << "- the function signature of the Main function that gets executed must be:" << std::endl << " static void Main(string[] args)" << std::endl << std::endl << "Options:" << std::endl - << "-alc path to a dll containing Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" << std::endl << "-s a list of assembly search paths, separated by :" << std::endl - << "-b the powershell assembly base path" << std::endl << "-v verbose output" << std::endl << "assembly the path of the assembly to execute relative to current directory" << std::endl << std::endl << "Example:" << std::endl - << "CORE_ROOT=/test/coreclr PWRSH_ROOT=/test/powershell ./host_cmdline -alc /test/ps/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll -s /test/ps -b /test/ps powershell-simple 'get-process'" << std::endl; + << "CORE_ROOT=/test/coreclr PWRSH_ROOT=/test/powershell ./host_cmdline -s /test/ps powershell-simple 'get-process'" << std::endl; } struct Args @@ -56,9 +47,7 @@ namespace Cmdline { } - std::string assemblyLoadContextFilePath; std::string searchPaths; - std::string basePath; std::string entryAssemblyPath; int argc; char** argv; @@ -67,9 +56,7 @@ namespace Cmdline void debugPrint() const { std::cerr << "Args:" << std::endl - << "- assemblyLoadContextFilePath " << assemblyLoadContextFilePath << std::endl << "- searchPaths " << searchPaths << std::endl - << "- basePath " << basePath << std::endl << "- entryAssemblyPath " << entryAssemblyPath << std::endl << "- argc " << argc << std::endl << "- verbose " << (verbose ? "true" : "false") << std::endl; @@ -92,21 +79,11 @@ namespace Cmdline const bool hasNextArg = i+1 < argc; const std::string nextArg = hasNextArg ? std::string(argv[i+1]) : std::string(""); - if (hasNextArg && arg == "-alc") - { - args.assemblyLoadContextFilePath = nextArg; - ++i; - } - else if (hasNextArg && arg == "-s") + if (hasNextArg && arg == "-s") { args.searchPaths = nextArg; ++i; } - else if (hasNextArg && arg == "-b") - { - args.basePath = nextArg; - ++i; - } else if (arg == "-v") { args.verbose = true; @@ -190,31 +167,6 @@ int main(int argc, char** argv) // Add both the CoreCLR directory and the regular search paths to this list std::string nativeDllSearchDirs = appPath + ":" + clrAbsolutePath; - // convert the app base to utf-16 - // - // this is needed as a utf-16 LE string by CoreCLR/PS's assembly load context interface - // it is either: - // - the current dir's absolute path - // - the path specified through the -b argument - std::string psBasePath = currentDirAbsolutePath; - if (args.basePath != "") - { - if (!GetAbsolutePath(args.basePath.c_str(),psBasePath)) - { - std::cerr << "failed to get the absolute path from the base_path argument" << std::endl; - return 1; - } - } - if (args.verbose) - std::cerr << "psBasePath=" << psBasePath << std::endl; - - // make sure to leave 1 byte at the end for null termination - std::basic_string psBasePath16(PATH_MAX+1,0); - - UnicodeString u8str = UnicodeString(psBasePath.c_str(),"UTF-8"); - int32_t targetSize = u8str.extract(0,u8str.length(),(char*)&psBasePath16[0],(psBasePath16.size()-1)*sizeof(char16_t),"UTF-16LE"); - psBasePath16.resize(targetSize/sizeof(char16_t)+1); - void* hostHandle; unsigned int domainId; int status = startCoreCLR( @@ -224,29 +176,13 @@ int main(int argc, char** argv) &hostHandle, &domainId); - // initialize the PS's custom assembly load context - typedef void (*LoaderRunHelperFp)(const char16_t* appPath); - LoaderRunHelperFp loaderDelegate = nullptr; - status = createDelegate( - hostHandle, - domainId, - "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "System.Management.Automation.PowerShellAssemblyLoadContextInitializer", - "SetPowerShellAssemblyLoadContext", - (void**)&loaderDelegate); - if (0 > status) - { - std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; - return 4; - } - loaderDelegate(psBasePath16.c_str()); - - // call into Main of powershell-simple.exe + // call into Main of assembly unsigned int exitCode; - executeAssembly(hostHandle, domainId, args.argc, - (const char**)args.argv, - (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), - &exitCode); + executeAssembly( + hostHandle, domainId, args.argc, + (const char**)args.argv, + (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), + &exitCode); status = stopCoreCLR(hostHandle, domainId); diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index cccd0efd39..95af993fe5 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -8,6 +8,7 @@ #include #include #include +#include // The name of the CoreCLR native runtime DLL #if defined(__APPLE__) @@ -265,12 +266,12 @@ int startCoreCLR( AddFilesFromDirectoryToTpaList(clrFilesAbsolutePath.c_str(), tpaList); // get path to AssemblyLoadContext.dll - std::string psFilesAbsolutePath; - if(!GetEnvAbsolutePath("PWRSH_ROOT", psFilesAbsolutePath)) + std::string psAbsolutePath; + if(!GetEnvAbsolutePath("PWRSH_ROOT", psAbsolutePath)) { return -1; } - std::string assemblyLoadContextAbsoluteFilePath(psFilesAbsolutePath + "/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"); + std::string assemblyLoadContextAbsoluteFilePath(psAbsolutePath + "/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"); // add AssemblyLoadContext tpaList.append(assemblyLoadContextAbsoluteFilePath); @@ -308,6 +309,27 @@ int startCoreCLR( return 4; } + // initialize PowerShell's custom assembly load context + typedef void (*LoaderRunHelperFp)(const char16_t* appPath); + LoaderRunHelperFp loaderDelegate = nullptr; + status = createDelegate( + *hostHandle, + *domainId, + "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "System.Management.Automation.PowerShellAssemblyLoadContextInitializer", + "SetPowerShellAssemblyLoadContext", + (void**)&loaderDelegate); + + if (status < 0) + { + std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; + return 4; + } + + icu::UnicodeString psUnicodeAbsolutePath = icu::UnicodeString::fromUTF8(psAbsolutePath.c_str()); + + loaderDelegate((const char16_t*)psUnicodeAbsolutePath.getTerminatedBuffer()); + return status; } From 54a4a2ae6ca8dfbaace2f5a4ad1ba3a95c1d5c3b Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 00:01:48 -0700 Subject: [PATCH 212/298] Clean up error codes --- src/host/cmdline/main.cpp | 11 +++++++++++ src/host/common/coreclrutil.cpp | 26 ++++++++++---------------- src/host/common/coreclrutil.h | 2 ++ 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index ac9df809e8..9e61b31eea 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -176,6 +176,12 @@ int main(int argc, char** argv) &hostHandle, &domainId); + if (!SUCCEEDED(status)) + { + std::cerr << "could not start CoreCLR" << std::endl; + return -1; + } + // call into Main of assembly unsigned int exitCode; executeAssembly( @@ -185,6 +191,11 @@ int main(int argc, char** argv) &exitCode); status = stopCoreCLR(hostHandle, domainId); + if (!SUCCEEDED(status)) + { + std::cerr << "could not stop CoreCLR" << std::endl; + return -1; + } return exitCode; } diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index 95af993fe5..65d187b361 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -217,19 +217,13 @@ int startCoreCLR( coreClrDllPath.append("/"); coreClrDllPath.append(coreClrDll); - if (coreClrDllPath.size() >= PATH_MAX) - { - std::cerr << "Absolute path to CoreCLR library too long" << std::endl; - return 1; - } - // open the shared library coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); if (coreclrLib == nullptr) { char* error = dlerror(); std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; - return 2; + return -1; } // query and verify the function pointers @@ -241,22 +235,22 @@ int startCoreCLR( if (initializeCoreCLR == nullptr) { std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; - return 3; + return -1; } if (executeAssembly == nullptr) { std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; - return 3; + return -1; } if (shutdownCoreCLR == nullptr) { std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; - return 3; + return -1; } if (createDelegate == nullptr) { std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; - return 3; + return -1; } // generate the Trusted Platform Assemblies list @@ -303,10 +297,10 @@ int startCoreCLR( hostHandle, domainId); - if (0 > status) + if (!SUCCEEDED(status)) { std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; - return 4; + return -1; } // initialize PowerShell's custom assembly load context @@ -320,10 +314,10 @@ int startCoreCLR( "SetPowerShellAssemblyLoadContext", (void**)&loaderDelegate); - if (status < 0) + if (!SUCCEEDED(status)) { std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; - return 4; + return -1; } icu::UnicodeString psUnicodeAbsolutePath = icu::UnicodeString::fromUTF8(psAbsolutePath.c_str()); @@ -337,7 +331,7 @@ int stopCoreCLR(void* hostHandle, unsigned int domainId) { // shutdown CoreCLR int status = shutdownCoreCLR(hostHandle, domainId); - if (0 > status) + if (!SUCCEEDED(status)) { std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; } diff --git a/src/host/common/coreclrutil.h b/src/host/common/coreclrutil.h index 018f5a5f5d..b01844e95c 100644 --- a/src/host/common/coreclrutil.h +++ b/src/host/common/coreclrutil.h @@ -4,6 +4,8 @@ #include #endif +#define SUCCEEDED(Status) ((Status) >= 0) + /* PowerShell on Linux custom host interface * * startCoreCLR() and stopCoreCLR() wrap the initialization of CoreCLR From 5573c58a75b7a4f04dab1bdad90ab0efd9b126fb Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 00:01:48 -0700 Subject: [PATCH 213/298] Clean up error codes --- host/cmdline/main.cpp | 11 +++++++++++ host/common/coreclrutil.cpp | 26 ++++++++++---------------- host/common/coreclrutil.h | 2 ++ 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index ac9df809e8..9e61b31eea 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -176,6 +176,12 @@ int main(int argc, char** argv) &hostHandle, &domainId); + if (!SUCCEEDED(status)) + { + std::cerr << "could not start CoreCLR" << std::endl; + return -1; + } + // call into Main of assembly unsigned int exitCode; executeAssembly( @@ -185,6 +191,11 @@ int main(int argc, char** argv) &exitCode); status = stopCoreCLR(hostHandle, domainId); + if (!SUCCEEDED(status)) + { + std::cerr << "could not stop CoreCLR" << std::endl; + return -1; + } return exitCode; } diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index 95af993fe5..65d187b361 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -217,19 +217,13 @@ int startCoreCLR( coreClrDllPath.append("/"); coreClrDllPath.append(coreClrDll); - if (coreClrDllPath.size() >= PATH_MAX) - { - std::cerr << "Absolute path to CoreCLR library too long" << std::endl; - return 1; - } - // open the shared library coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); if (coreclrLib == nullptr) { char* error = dlerror(); std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; - return 2; + return -1; } // query and verify the function pointers @@ -241,22 +235,22 @@ int startCoreCLR( if (initializeCoreCLR == nullptr) { std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; - return 3; + return -1; } if (executeAssembly == nullptr) { std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; - return 3; + return -1; } if (shutdownCoreCLR == nullptr) { std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; - return 3; + return -1; } if (createDelegate == nullptr) { std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; - return 3; + return -1; } // generate the Trusted Platform Assemblies list @@ -303,10 +297,10 @@ int startCoreCLR( hostHandle, domainId); - if (0 > status) + if (!SUCCEEDED(status)) { std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; - return 4; + return -1; } // initialize PowerShell's custom assembly load context @@ -320,10 +314,10 @@ int startCoreCLR( "SetPowerShellAssemblyLoadContext", (void**)&loaderDelegate); - if (status < 0) + if (!SUCCEEDED(status)) { std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; - return 4; + return -1; } icu::UnicodeString psUnicodeAbsolutePath = icu::UnicodeString::fromUTF8(psAbsolutePath.c_str()); @@ -337,7 +331,7 @@ int stopCoreCLR(void* hostHandle, unsigned int domainId) { // shutdown CoreCLR int status = shutdownCoreCLR(hostHandle, domainId); - if (0 > status) + if (!SUCCEEDED(status)) { std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; } diff --git a/host/common/coreclrutil.h b/host/common/coreclrutil.h index 018f5a5f5d..b01844e95c 100644 --- a/host/common/coreclrutil.h +++ b/host/common/coreclrutil.h @@ -4,6 +4,8 @@ #include #endif +#define SUCCEEDED(Status) ((Status) >= 0) + /* PowerShell on Linux custom host interface * * startCoreCLR() and stopCoreCLR() wrap the initialization of CoreCLR From 9abf5d276eef4eae21a9b510b3c987c811bcfcdc Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 00:36:47 -0700 Subject: [PATCH 214/298] Move appPath and nativeDllSearchDirs to libpshost - for PowerShell, the `appPath` is the path to the PowerShell libraries and consoles, i.e., `PWRSH_ROOT` - the `nativeDllSearchDirs` is just `appPath` plus `CORE_ROOT` - probably should parse and add `LD_LIBRARY_PATH` to `appPath` This refactors the last vestiges of command line arguments out of the command-line host and into libpshost, where all necessary questions are answered either automatically or through the two introduced environment variables (`CORE_ROOT` and `PWRSH_ROOT`). --- src/host/cmdline/main.cpp | 51 ++++----------------------------- src/host/common/coreclrutil.cpp | 16 +++++++---- src/host/common/coreclrutil.h | 4 --- 3 files changed, 17 insertions(+), 54 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 9e61b31eea..80a1f700ae 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -13,24 +13,22 @@ namespace Cmdline void printHelp() { std::cerr << "PS CoreCLR host" << std::endl - << "Usage: host_cmdline [-s search_paths] assembly [...]" << std::endl + << "Usage: host_cmdline assembly [...]" << std::endl << std::endl << "What it does:" << std::endl << "- the host assumes that CoreCLR is located $CORE_ROOT" << std::endl - << "- by default the host assumes that the assembly named" << std::endl + << "- the host assumes that the assembly named" << std::endl << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is " << std::endl << " located in $PWRSH_ROOT" << std::endl << "- all additional parameters at the end of the command line are forwarded" << std::endl << " to the Main function in the assembly" << std::endl << "- the host will execute the Main function in the specified assembly" << std::endl << " + this assembly has to be located in the search path" << std::endl - << "- by default the host will add the current working directory to the assembly search path" << std::endl - << " + this can be overridden with the -s command line argument" << std::endl + << "- the host will add $PWRSH_ROOT to the assembly search path" << std::endl << "- the function signature of the Main function that gets executed must be:" << std::endl << " static void Main(string[] args)" << std::endl << std::endl << "Options:" << std::endl - << "-s a list of assembly search paths, separated by :" << std::endl << "-v verbose output" << std::endl << "assembly the path of the assembly to execute relative to current directory" << std::endl << std::endl @@ -56,7 +54,6 @@ namespace Cmdline void debugPrint() const { std::cerr << "Args:" << std::endl - << "- searchPaths " << searchPaths << std::endl << "- entryAssemblyPath " << entryAssemblyPath << std::endl << "- argc " << argc << std::endl << "- verbose " << (verbose ? "true" : "false") << std::endl; @@ -79,9 +76,9 @@ namespace Cmdline const bool hasNextArg = i+1 < argc; const std::string nextArg = hasNextArg ? std::string(argv[i+1]) : std::string(""); - if (hasNextArg && arg == "-s") + if (hasNextArg && arg == "--File") { - args.searchPaths = nextArg; + std::cerr << "TODO: should launch script " << nextArg << std::endl; ++i; } else if (arg == "-v") @@ -126,52 +123,17 @@ int main(int argc, char** argv) if (args.verbose) args.debugPrint(); - std::string clrAbsolutePath; - if (!GetAbsolutePath(std::getenv("CORE_ROOT"), clrAbsolutePath)) - { - std::cerr << "could not get absolute path of CoreCLR" << std::endl; - return 1; - } - if (args.verbose) - std::cerr << "clrAbsolutePath=" << clrAbsolutePath << std::endl; - // get the absolute path of the current directory - std::string currentDirAbsolutePath; - if (!GetAbsolutePath(".",currentDirAbsolutePath)) + if (!GetAbsolutePath(".", currentDirAbsolutePath)) { std::cerr << "failed to get the absolute path from current working directory" << std::endl; return 1; } - // assembly search paths - // - // add the current directory, the CoreCLR directory, and anything - // specified with the -s option - - std::string appPath = currentDirAbsolutePath; - - appPath += ":" + clrAbsolutePath; - if (args.searchPaths != "") - { - std::string searchAbsolutePathList = HostUtil::getAbsolutePathList(args.searchPaths); - if (searchAbsolutePathList != "") - appPath += ":" + searchAbsolutePathList; - } - - if (args.verbose) - std::cerr << "appPath: " << appPath << std::endl; - - // search paths for native dlls - // - // Add both the CoreCLR directory and the regular search paths to this list - std::string nativeDllSearchDirs = appPath + ":" + clrAbsolutePath; - void* hostHandle; unsigned int domainId; int status = startCoreCLR( - appPath.c_str(), - nativeDllSearchDirs.c_str(), "ps_cmdline_host", &hostHandle, &domainId); @@ -199,4 +161,3 @@ int main(int argc, char** argv) return exitCode; } - diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index 65d187b361..597e3fd752 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -195,8 +195,6 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) // Below is our custom start/stop interface // int startCoreCLR( - const char* appPath, - const char* nativeDllSearchDirs, const char* appDomainFriendlyName, void** hostHandle, unsigned int* domainId) @@ -270,6 +268,14 @@ int startCoreCLR( // add AssemblyLoadContext tpaList.append(assemblyLoadContextAbsoluteFilePath); + // generate the assembly search paths + std::string appPath(psAbsolutePath); + // TODO: add LD_LIBRARY_PATH? + + std::string nativeDllSearchDirs(appPath); + nativeDllSearchDirs.append(":"); + nativeDllSearchDirs.append(clrFilesAbsolutePath); + // create list of properties to initialize CoreCLR const char* propertyKeys[] = { "TRUSTED_PLATFORM_ASSEMBLIES", @@ -281,9 +287,9 @@ int startCoreCLR( const char* propertyValues[] = { tpaList.c_str(), - appPath, - appPath, - nativeDllSearchDirs, + appPath.c_str(), + appPath.c_str(), + nativeDllSearchDirs.c_str(), "UseLatestBehaviorWhenTFMNotSpecified" }; diff --git a/src/host/common/coreclrutil.h b/src/host/common/coreclrutil.h index b01844e95c..f31da19aab 100644 --- a/src/host/common/coreclrutil.h +++ b/src/host/common/coreclrutil.h @@ -16,10 +16,6 @@ extern "C" { int startCoreCLR( - /* Passed to propertyValues */ - const char* appPath, - const char* nativeDllSearchDirs, - /* Passed to InitializeCoreCLRFunction */ const char* appDomainFriendlyName, void** hostHandle, unsigned int* domainId); From 762930f61eba34a53d8706a603fe21345b3f978c Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 00:36:47 -0700 Subject: [PATCH 215/298] Move appPath and nativeDllSearchDirs to libpshost - for PowerShell, the `appPath` is the path to the PowerShell libraries and consoles, i.e., `PWRSH_ROOT` - the `nativeDllSearchDirs` is just `appPath` plus `CORE_ROOT` - probably should parse and add `LD_LIBRARY_PATH` to `appPath` This refactors the last vestiges of command line arguments out of the command-line host and into libpshost, where all necessary questions are answered either automatically or through the two introduced environment variables (`CORE_ROOT` and `PWRSH_ROOT`). --- host/cmdline/main.cpp | 51 +++++-------------------------------- host/common/coreclrutil.cpp | 16 ++++++++---- host/common/coreclrutil.h | 4 --- 3 files changed, 17 insertions(+), 54 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 9e61b31eea..80a1f700ae 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -13,24 +13,22 @@ namespace Cmdline void printHelp() { std::cerr << "PS CoreCLR host" << std::endl - << "Usage: host_cmdline [-s search_paths] assembly [...]" << std::endl + << "Usage: host_cmdline assembly [...]" << std::endl << std::endl << "What it does:" << std::endl << "- the host assumes that CoreCLR is located $CORE_ROOT" << std::endl - << "- by default the host assumes that the assembly named" << std::endl + << "- the host assumes that the assembly named" << std::endl << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is " << std::endl << " located in $PWRSH_ROOT" << std::endl << "- all additional parameters at the end of the command line are forwarded" << std::endl << " to the Main function in the assembly" << std::endl << "- the host will execute the Main function in the specified assembly" << std::endl << " + this assembly has to be located in the search path" << std::endl - << "- by default the host will add the current working directory to the assembly search path" << std::endl - << " + this can be overridden with the -s command line argument" << std::endl + << "- the host will add $PWRSH_ROOT to the assembly search path" << std::endl << "- the function signature of the Main function that gets executed must be:" << std::endl << " static void Main(string[] args)" << std::endl << std::endl << "Options:" << std::endl - << "-s a list of assembly search paths, separated by :" << std::endl << "-v verbose output" << std::endl << "assembly the path of the assembly to execute relative to current directory" << std::endl << std::endl @@ -56,7 +54,6 @@ namespace Cmdline void debugPrint() const { std::cerr << "Args:" << std::endl - << "- searchPaths " << searchPaths << std::endl << "- entryAssemblyPath " << entryAssemblyPath << std::endl << "- argc " << argc << std::endl << "- verbose " << (verbose ? "true" : "false") << std::endl; @@ -79,9 +76,9 @@ namespace Cmdline const bool hasNextArg = i+1 < argc; const std::string nextArg = hasNextArg ? std::string(argv[i+1]) : std::string(""); - if (hasNextArg && arg == "-s") + if (hasNextArg && arg == "--File") { - args.searchPaths = nextArg; + std::cerr << "TODO: should launch script " << nextArg << std::endl; ++i; } else if (arg == "-v") @@ -126,52 +123,17 @@ int main(int argc, char** argv) if (args.verbose) args.debugPrint(); - std::string clrAbsolutePath; - if (!GetAbsolutePath(std::getenv("CORE_ROOT"), clrAbsolutePath)) - { - std::cerr << "could not get absolute path of CoreCLR" << std::endl; - return 1; - } - if (args.verbose) - std::cerr << "clrAbsolutePath=" << clrAbsolutePath << std::endl; - // get the absolute path of the current directory - std::string currentDirAbsolutePath; - if (!GetAbsolutePath(".",currentDirAbsolutePath)) + if (!GetAbsolutePath(".", currentDirAbsolutePath)) { std::cerr << "failed to get the absolute path from current working directory" << std::endl; return 1; } - // assembly search paths - // - // add the current directory, the CoreCLR directory, and anything - // specified with the -s option - - std::string appPath = currentDirAbsolutePath; - - appPath += ":" + clrAbsolutePath; - if (args.searchPaths != "") - { - std::string searchAbsolutePathList = HostUtil::getAbsolutePathList(args.searchPaths); - if (searchAbsolutePathList != "") - appPath += ":" + searchAbsolutePathList; - } - - if (args.verbose) - std::cerr << "appPath: " << appPath << std::endl; - - // search paths for native dlls - // - // Add both the CoreCLR directory and the regular search paths to this list - std::string nativeDllSearchDirs = appPath + ":" + clrAbsolutePath; - void* hostHandle; unsigned int domainId; int status = startCoreCLR( - appPath.c_str(), - nativeDllSearchDirs.c_str(), "ps_cmdline_host", &hostHandle, &domainId); @@ -199,4 +161,3 @@ int main(int argc, char** argv) return exitCode; } - diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index 65d187b361..597e3fd752 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -195,8 +195,6 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) // Below is our custom start/stop interface // int startCoreCLR( - const char* appPath, - const char* nativeDllSearchDirs, const char* appDomainFriendlyName, void** hostHandle, unsigned int* domainId) @@ -270,6 +268,14 @@ int startCoreCLR( // add AssemblyLoadContext tpaList.append(assemblyLoadContextAbsoluteFilePath); + // generate the assembly search paths + std::string appPath(psAbsolutePath); + // TODO: add LD_LIBRARY_PATH? + + std::string nativeDllSearchDirs(appPath); + nativeDllSearchDirs.append(":"); + nativeDllSearchDirs.append(clrFilesAbsolutePath); + // create list of properties to initialize CoreCLR const char* propertyKeys[] = { "TRUSTED_PLATFORM_ASSEMBLIES", @@ -281,9 +287,9 @@ int startCoreCLR( const char* propertyValues[] = { tpaList.c_str(), - appPath, - appPath, - nativeDllSearchDirs, + appPath.c_str(), + appPath.c_str(), + nativeDllSearchDirs.c_str(), "UseLatestBehaviorWhenTFMNotSpecified" }; diff --git a/host/common/coreclrutil.h b/host/common/coreclrutil.h index b01844e95c..f31da19aab 100644 --- a/host/common/coreclrutil.h +++ b/host/common/coreclrutil.h @@ -16,10 +16,6 @@ extern "C" { int startCoreCLR( - /* Passed to propertyValues */ - const char* appPath, - const char* nativeDllSearchDirs, - /* Passed to InitializeCoreCLRFunction */ const char* appDomainFriendlyName, void** hostHandle, unsigned int* domainId); From 6fffdd341e4498cba2ca372d971819f54eb91f0b Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 00:40:26 -0700 Subject: [PATCH 216/298] fixup! Clean up error codes --- src/host/common/coreclrutil.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index 597e3fd752..eb4a0017dd 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -45,19 +45,17 @@ CreateDelegateFunction createDelegate; bool GetAbsolutePath(const char* path, std::string& absolutePath) { - bool result = false; - char realPath[PATH_MAX]; if (realpath(path, realPath) != nullptr && realPath[0] != '\0') { absolutePath.assign(realPath); // realpath should return canonicalized path without the trailing slash assert(absolutePath.back() != '/'); - - result = true; + return true; } - return result; + std::cerr << "failed to get absolute path for " << path << std::endl; + return false; } // TODO use dirname @@ -71,6 +69,7 @@ bool GetDirectory(const char* absolutePath, std::string& directory) return true; } + std::cerr << "failed to get directory for " << absolutePath << std::endl; return false; } @@ -84,13 +83,13 @@ bool GetEnvAbsolutePath(const char* env_var, std::string& absolutePath) const char* filesPathLocal = std::getenv(env_var);; if (filesPathLocal == nullptr) { - std::cerr << "$" << env_var << " was empty" << std::endl; + std::cerr << "failed because $" << env_var << " was empty" << std::endl; return false; } if (!GetAbsolutePath(filesPathLocal, absolutePath)) { - std::cerr << "Failed to get absolute path for " << env_var << std::endl; + std::cerr << "failed to get absolute path for " << env_var << std::endl; return false; } From cfb8f2e59f0cfaed4feb1e79d5a7cf6730f392f1 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 00:40:26 -0700 Subject: [PATCH 217/298] fixup! Clean up error codes --- host/common/coreclrutil.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index 597e3fd752..eb4a0017dd 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -45,19 +45,17 @@ CreateDelegateFunction createDelegate; bool GetAbsolutePath(const char* path, std::string& absolutePath) { - bool result = false; - char realPath[PATH_MAX]; if (realpath(path, realPath) != nullptr && realPath[0] != '\0') { absolutePath.assign(realPath); // realpath should return canonicalized path without the trailing slash assert(absolutePath.back() != '/'); - - result = true; + return true; } - return result; + std::cerr << "failed to get absolute path for " << path << std::endl; + return false; } // TODO use dirname @@ -71,6 +69,7 @@ bool GetDirectory(const char* absolutePath, std::string& directory) return true; } + std::cerr << "failed to get directory for " << absolutePath << std::endl; return false; } @@ -84,13 +83,13 @@ bool GetEnvAbsolutePath(const char* env_var, std::string& absolutePath) const char* filesPathLocal = std::getenv(env_var);; if (filesPathLocal == nullptr) { - std::cerr << "$" << env_var << " was empty" << std::endl; + std::cerr << "failed because $" << env_var << " was empty" << std::endl; return false; } if (!GetAbsolutePath(filesPathLocal, absolutePath)) { - std::cerr << "Failed to get absolute path for " << env_var << std::endl; + std::cerr << "failed to get absolute path for " << env_var << std::endl; return false; } From aeacd0f047b282f1cd600d55c6b3cc430a7c8a21 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 00:49:25 -0700 Subject: [PATCH 218/298] Rename variables and reorganize --- src/host/common/coreclrutil.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/host/common/coreclrutil.cpp b/src/host/common/coreclrutil.cpp index eb4a0017dd..d53433e3bf 100644 --- a/src/host/common/coreclrutil.cpp +++ b/src/host/common/coreclrutil.cpp @@ -198,19 +198,15 @@ int startCoreCLR( void** hostHandle, unsigned int* domainId) { - // get path to current executable - char exePath[PATH_MAX] = { 0 }; - readlink("/proc/self/exe", exePath, PATH_MAX); - // get the CoreCLR root path - std::string clrFilesAbsolutePath; - if(!GetEnvAbsolutePath("CORE_ROOT", clrFilesAbsolutePath)) + std::string clrAbsolutePath; + if(!GetEnvAbsolutePath("CORE_ROOT", clrAbsolutePath)) { return -1; } // get the CoreCLR shared library path - std::string coreClrDllPath(clrFilesAbsolutePath); + std::string coreClrDllPath(clrAbsolutePath); coreClrDllPath.append("/"); coreClrDllPath.append(coreClrDll); @@ -254,7 +250,7 @@ int startCoreCLR( std::string tpaList; // add assemblies in the CoreCLR root path - AddFilesFromDirectoryToTpaList(clrFilesAbsolutePath.c_str(), tpaList); + AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(), tpaList); // get path to AssemblyLoadContext.dll std::string psAbsolutePath; @@ -262,10 +258,12 @@ int startCoreCLR( { return -1; } - std::string assemblyLoadContextAbsoluteFilePath(psAbsolutePath + "/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"); + std::string alcAbsolutePath(psAbsolutePath); + alcAbsolutePath.append("/"); + alcAbsolutePath.append("Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"); // add AssemblyLoadContext - tpaList.append(assemblyLoadContextAbsoluteFilePath); + tpaList.append(alcAbsolutePath); // generate the assembly search paths std::string appPath(psAbsolutePath); @@ -273,7 +271,7 @@ int startCoreCLR( std::string nativeDllSearchDirs(appPath); nativeDllSearchDirs.append(":"); - nativeDllSearchDirs.append(clrFilesAbsolutePath); + nativeDllSearchDirs.append(clrAbsolutePath); // create list of properties to initialize CoreCLR const char* propertyKeys[] = { @@ -292,6 +290,10 @@ int startCoreCLR( "UseLatestBehaviorWhenTFMNotSpecified" }; + // get path to current executable + char exePath[PATH_MAX] = { 0 }; + readlink("/proc/self/exe", exePath, PATH_MAX); + // initialize CoreCLR int status = initializeCoreCLR( exePath, From 9b308fa600e064dd95ecab6019059cff1135829f Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 00:49:25 -0700 Subject: [PATCH 219/298] Rename variables and reorganize --- host/common/coreclrutil.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/host/common/coreclrutil.cpp b/host/common/coreclrutil.cpp index eb4a0017dd..d53433e3bf 100644 --- a/host/common/coreclrutil.cpp +++ b/host/common/coreclrutil.cpp @@ -198,19 +198,15 @@ int startCoreCLR( void** hostHandle, unsigned int* domainId) { - // get path to current executable - char exePath[PATH_MAX] = { 0 }; - readlink("/proc/self/exe", exePath, PATH_MAX); - // get the CoreCLR root path - std::string clrFilesAbsolutePath; - if(!GetEnvAbsolutePath("CORE_ROOT", clrFilesAbsolutePath)) + std::string clrAbsolutePath; + if(!GetEnvAbsolutePath("CORE_ROOT", clrAbsolutePath)) { return -1; } // get the CoreCLR shared library path - std::string coreClrDllPath(clrFilesAbsolutePath); + std::string coreClrDllPath(clrAbsolutePath); coreClrDllPath.append("/"); coreClrDllPath.append(coreClrDll); @@ -254,7 +250,7 @@ int startCoreCLR( std::string tpaList; // add assemblies in the CoreCLR root path - AddFilesFromDirectoryToTpaList(clrFilesAbsolutePath.c_str(), tpaList); + AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(), tpaList); // get path to AssemblyLoadContext.dll std::string psAbsolutePath; @@ -262,10 +258,12 @@ int startCoreCLR( { return -1; } - std::string assemblyLoadContextAbsoluteFilePath(psAbsolutePath + "/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"); + std::string alcAbsolutePath(psAbsolutePath); + alcAbsolutePath.append("/"); + alcAbsolutePath.append("Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"); // add AssemblyLoadContext - tpaList.append(assemblyLoadContextAbsoluteFilePath); + tpaList.append(alcAbsolutePath); // generate the assembly search paths std::string appPath(psAbsolutePath); @@ -273,7 +271,7 @@ int startCoreCLR( std::string nativeDllSearchDirs(appPath); nativeDllSearchDirs.append(":"); - nativeDllSearchDirs.append(clrFilesAbsolutePath); + nativeDllSearchDirs.append(clrAbsolutePath); // create list of properties to initialize CoreCLR const char* propertyKeys[] = { @@ -292,6 +290,10 @@ int startCoreCLR( "UseLatestBehaviorWhenTFMNotSpecified" }; + // get path to current executable + char exePath[PATH_MAX] = { 0 }; + readlink("/proc/self/exe", exePath, PATH_MAX); + // initialize CoreCLR int status = initializeCoreCLR( exePath, From 6432bb94b8dbca376a2e3296bb894978b604c3b1 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 00:57:17 -0700 Subject: [PATCH 220/298] Remove deprecated hostutil and tests --- src/CMakeLists.txt | 3 +-- src/host/cmdline/main.cpp | 1 - src/host/common/hostutil.h | 44 -------------------------------- src/tests/host/test-hostutil.cpp | 35 ------------------------- 4 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 src/host/common/hostutil.h delete mode 100644 src/tests/host/test-hostutil.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9d568377fc..e2b1cad536 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,8 +10,7 @@ link_directories(${monad_native_BINARY_DIR}) # source file definitions set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp impl/getcomputername.cpp impl/getcpinfo.cpp) set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) -set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername.cpp tests/test-getcpinfo.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername.cpp tests/test-getcpinfo.cpp ${HOST_COMMON_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 80a1f700ae..7ce3b36dee 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -1,7 +1,6 @@ #include #include #include "common/coreclrutil.h" -#include "common/hostutil.h" #include #include #include diff --git a/src/host/common/hostutil.h b/src/host/common/hostutil.h deleted file mode 100644 index 6a07469c07..0000000000 --- a/src/host/common/hostutil.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include -#include "common/coreclrutil.h" - -namespace HostUtil -{ - //!\brief get a list of absolute paths separated by : from a list of relative/absolute paths separated by : - std::string getAbsolutePathList(const std::string& paths) - { - //std::cerr << "getAbsolutePathList: paths=" << paths << std::endl; - std::string result; - - // split by : - size_t lastPos = 0; - size_t curPos = paths.find(':',lastPos); - do - { - const std::string token = paths.substr(lastPos,curPos-lastPos); - //std::cerr << "curPos=" << curPos << " lastPos=" << lastPos << " token=" << token << std::endl; - - // skip empty tokens - if (token != "") - { - std::string absolutePath; - if (GetAbsolutePath(token.c_str(),absolutePath)) - { - // add colons correctly - if (result.size() == 0) - result += absolutePath; - else - result += ":" + absolutePath; - } - } - - // increment lastPos to skip the : - lastPos += token.size() + 1; - curPos = paths.find(':',lastPos); - } - while (lastPos < paths.size()); - - return result; - } -} diff --git a/src/tests/host/test-hostutil.cpp b/src/tests/host/test-hostutil.cpp deleted file mode 100644 index 7a8b6b473b..0000000000 --- a/src/tests/host/test-hostutil.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include "common/hostutil.h" - -TEST(HostUtilTest,simple) -{ - // syntactical corner cases - ASSERT_EQ("",HostUtil::getAbsolutePathList("")); - ASSERT_EQ("",HostUtil::getAbsolutePathList(":")); - ASSERT_EQ("",HostUtil::getAbsolutePathList("::")); - ASSERT_EQ("",HostUtil::getAbsolutePathList(":::::")); - - // current directory - char* cwd = get_current_dir_name(); - ASSERT_EQ(std::string(cwd),HostUtil::getAbsolutePathList(".")); - - // relative and absolute paths that don't exist - ASSERT_EQ("",HostUtil::getAbsolutePathList("/something/that/does/not/exist")); - ASSERT_EQ("",HostUtil::getAbsolutePathList(":/something/that/does/not/exist:")); - ASSERT_EQ("",HostUtil::getAbsolutePathList("something/relative/that/does/not/exist")); - ASSERT_EQ("",HostUtil::getAbsolutePathList(":something/relative/that/does/not/exist:")); - - // absolute existing paths - ASSERT_EQ("/tmp",HostUtil::getAbsolutePathList("/tmp")); - ASSERT_EQ("/tmp:/tmp",HostUtil::getAbsolutePathList("/tmp:/tmp")); - - // relative paths - chdir("/"); - ASSERT_EQ("/tmp",HostUtil::getAbsolutePathList("tmp")); - ASSERT_EQ("/tmp:/tmp",HostUtil::getAbsolutePathList("/tmp:tmp:")); - chdir(cwd); - - // cleanup - free(cwd); -} - From 556f423aa7e60a3e99fb611987fb9b1b4f66e769 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 00:57:17 -0700 Subject: [PATCH 221/298] Remove deprecated hostutil and tests --- CMakeLists.txt | 3 +-- host/cmdline/main.cpp | 1 - host/common/hostutil.h | 44 ------------------------------------ tests/host/test-hostutil.cpp | 35 ---------------------------- 4 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 host/common/hostutil.h delete mode 100644 tests/host/test-hostutil.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d568377fc..e2b1cad536 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,7 @@ link_directories(${monad_native_BINARY_DIR}) # source file definitions set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp impl/getcomputername.cpp impl/getcpinfo.cpp) set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) -set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername.cpp tests/test-getcpinfo.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername.cpp tests/test-getcpinfo.cpp ${HOST_COMMON_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 80a1f700ae..7ce3b36dee 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -1,7 +1,6 @@ #include #include #include "common/coreclrutil.h" -#include "common/hostutil.h" #include #include #include diff --git a/host/common/hostutil.h b/host/common/hostutil.h deleted file mode 100644 index 6a07469c07..0000000000 --- a/host/common/hostutil.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include -#include "common/coreclrutil.h" - -namespace HostUtil -{ - //!\brief get a list of absolute paths separated by : from a list of relative/absolute paths separated by : - std::string getAbsolutePathList(const std::string& paths) - { - //std::cerr << "getAbsolutePathList: paths=" << paths << std::endl; - std::string result; - - // split by : - size_t lastPos = 0; - size_t curPos = paths.find(':',lastPos); - do - { - const std::string token = paths.substr(lastPos,curPos-lastPos); - //std::cerr << "curPos=" << curPos << " lastPos=" << lastPos << " token=" << token << std::endl; - - // skip empty tokens - if (token != "") - { - std::string absolutePath; - if (GetAbsolutePath(token.c_str(),absolutePath)) - { - // add colons correctly - if (result.size() == 0) - result += absolutePath; - else - result += ":" + absolutePath; - } - } - - // increment lastPos to skip the : - lastPos += token.size() + 1; - curPos = paths.find(':',lastPos); - } - while (lastPos < paths.size()); - - return result; - } -} diff --git a/tests/host/test-hostutil.cpp b/tests/host/test-hostutil.cpp deleted file mode 100644 index 7a8b6b473b..0000000000 --- a/tests/host/test-hostutil.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include "common/hostutil.h" - -TEST(HostUtilTest,simple) -{ - // syntactical corner cases - ASSERT_EQ("",HostUtil::getAbsolutePathList("")); - ASSERT_EQ("",HostUtil::getAbsolutePathList(":")); - ASSERT_EQ("",HostUtil::getAbsolutePathList("::")); - ASSERT_EQ("",HostUtil::getAbsolutePathList(":::::")); - - // current directory - char* cwd = get_current_dir_name(); - ASSERT_EQ(std::string(cwd),HostUtil::getAbsolutePathList(".")); - - // relative and absolute paths that don't exist - ASSERT_EQ("",HostUtil::getAbsolutePathList("/something/that/does/not/exist")); - ASSERT_EQ("",HostUtil::getAbsolutePathList(":/something/that/does/not/exist:")); - ASSERT_EQ("",HostUtil::getAbsolutePathList("something/relative/that/does/not/exist")); - ASSERT_EQ("",HostUtil::getAbsolutePathList(":something/relative/that/does/not/exist:")); - - // absolute existing paths - ASSERT_EQ("/tmp",HostUtil::getAbsolutePathList("/tmp")); - ASSERT_EQ("/tmp:/tmp",HostUtil::getAbsolutePathList("/tmp:/tmp")); - - // relative paths - chdir("/"); - ASSERT_EQ("/tmp",HostUtil::getAbsolutePathList("tmp")); - ASSERT_EQ("/tmp:/tmp",HostUtil::getAbsolutePathList("/tmp:tmp:")); - chdir(cwd); - - // cleanup - free(cwd); -} - From 6a1b9f3e598d1fe686c8e3f5124d63851ea06134 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 00:57:55 -0700 Subject: [PATCH 222/298] Remove deprecated functions from coreclrutil Using `getcwd()` in main for resolving relative to the current working directory removed the last public use of `GetAbsolutePath()`, so `coreclrutil.h` is now stricly `extern "C"`. --- src/host/cmdline/main.cpp | 15 +++------------ src/host/common/coreclrutil.h | 14 -------------- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/src/host/cmdline/main.cpp b/src/host/cmdline/main.cpp index 7ce3b36dee..938a02275d 100644 --- a/src/host/cmdline/main.cpp +++ b/src/host/cmdline/main.cpp @@ -1,11 +1,7 @@ +#include #include #include #include "common/coreclrutil.h" -#include -#include -#include -#include -#include namespace Cmdline { @@ -123,12 +119,7 @@ int main(int argc, char** argv) args.debugPrint(); // get the absolute path of the current directory - std::string currentDirAbsolutePath; - if (!GetAbsolutePath(".", currentDirAbsolutePath)) - { - std::cerr << "failed to get the absolute path from current working directory" << std::endl; - return 1; - } + std::string cwd(getcwd(nullptr, 0)); void* hostHandle; unsigned int domainId; @@ -148,7 +139,7 @@ int main(int argc, char** argv) executeAssembly( hostHandle, domainId, args.argc, (const char**)args.argv, - (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), + (cwd + "/" + args.entryAssemblyPath).c_str(), &exitCode); status = stopCoreCLR(hostHandle, domainId); diff --git a/src/host/common/coreclrutil.h b/src/host/common/coreclrutil.h index f31da19aab..17e3537ebe 100644 --- a/src/host/common/coreclrutil.h +++ b/src/host/common/coreclrutil.h @@ -1,9 +1,5 @@ #pragma once -#ifdef __cplusplus -#include -#endif - #define SUCCEEDED(Status) ((Status) >= 0) /* PowerShell on Linux custom host interface @@ -43,13 +39,3 @@ extern "C" extern ExecuteAssemblyFunction executeAssembly; extern CreateDelegateFunction createDelegate; } - -#ifdef __cplusplus -// Get absolute path from the specified path. -// Return true in case of a success, false otherwise. -bool GetAbsolutePath(const char* path, std::string& absolutePath); - -// Get directory of the specified path. -// Return true in case of a success, false otherwise. -bool GetDirectory(const char* absolutePath, std::string& directory); -#endif From 8d399e84c242b503856b9a69e3af1556cdc3974a Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 00:57:55 -0700 Subject: [PATCH 223/298] Remove deprecated functions from coreclrutil Using `getcwd()` in main for resolving relative to the current working directory removed the last public use of `GetAbsolutePath()`, so `coreclrutil.h` is now stricly `extern "C"`. --- host/cmdline/main.cpp | 15 +++------------ host/common/coreclrutil.h | 14 -------------- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/host/cmdline/main.cpp b/host/cmdline/main.cpp index 7ce3b36dee..938a02275d 100644 --- a/host/cmdline/main.cpp +++ b/host/cmdline/main.cpp @@ -1,11 +1,7 @@ +#include #include #include #include "common/coreclrutil.h" -#include -#include -#include -#include -#include namespace Cmdline { @@ -123,12 +119,7 @@ int main(int argc, char** argv) args.debugPrint(); // get the absolute path of the current directory - std::string currentDirAbsolutePath; - if (!GetAbsolutePath(".", currentDirAbsolutePath)) - { - std::cerr << "failed to get the absolute path from current working directory" << std::endl; - return 1; - } + std::string cwd(getcwd(nullptr, 0)); void* hostHandle; unsigned int domainId; @@ -148,7 +139,7 @@ int main(int argc, char** argv) executeAssembly( hostHandle, domainId, args.argc, (const char**)args.argv, - (currentDirAbsolutePath+"/"+args.entryAssemblyPath).c_str(), + (cwd + "/" + args.entryAssemblyPath).c_str(), &exitCode); status = stopCoreCLR(hostHandle, domainId); diff --git a/host/common/coreclrutil.h b/host/common/coreclrutil.h index f31da19aab..17e3537ebe 100644 --- a/host/common/coreclrutil.h +++ b/host/common/coreclrutil.h @@ -1,9 +1,5 @@ #pragma once -#ifdef __cplusplus -#include -#endif - #define SUCCEEDED(Status) ((Status) >= 0) /* PowerShell on Linux custom host interface @@ -43,13 +39,3 @@ extern "C" extern ExecuteAssemblyFunction executeAssembly; extern CreateDelegateFunction createDelegate; } - -#ifdef __cplusplus -// Get absolute path from the specified path. -// Return true in case of a success, false otherwise. -bool GetAbsolutePath(const char* path, std::string& absolutePath); - -// Get directory of the specified path. -// Return true in case of a success, false otherwise. -bool GetDirectory(const char* absolutePath, std::string& directory); -#endif From 4767d46b389c7a062aacfc97559637529b0f3f54 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 01:04:45 -0700 Subject: [PATCH 224/298] Update libpshost comments --- src/host/common/coreclrutil.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/host/common/coreclrutil.h b/src/host/common/coreclrutil.h index 17e3537ebe..f00b6519d6 100644 --- a/src/host/common/coreclrutil.h +++ b/src/host/common/coreclrutil.h @@ -4,11 +4,19 @@ /* PowerShell on Linux custom host interface * - * startCoreCLR() and stopCoreCLR() wrap the initialization of CoreCLR - * and use of ExecuteAssemblyFunction() and CreateDelegateFunction() - * should be sandwiched in between them + * startCoreCLR() takes a friendly name, e.g. "powershell", and a + * writable pointer and identifier * + * executeAssmbly() will be made available after starting CoreCLR, and + * is used to launch assemblies with a main function + * + * createDelegate() works similarly but provides a reverse P/Invoke + * given an assembly, type, and method; note that on Linux, + * PublicKeyToken must be null + * + * stopCoreCLR() will deinitialize given the handle and identifier */ + extern "C" { int startCoreCLR( From 460f51fa7f45dd87062d178ebbb8ca80af5adfe6 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 01:04:45 -0700 Subject: [PATCH 225/298] Update libpshost comments --- host/common/coreclrutil.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/host/common/coreclrutil.h b/host/common/coreclrutil.h index 17e3537ebe..f00b6519d6 100644 --- a/host/common/coreclrutil.h +++ b/host/common/coreclrutil.h @@ -4,11 +4,19 @@ /* PowerShell on Linux custom host interface * - * startCoreCLR() and stopCoreCLR() wrap the initialization of CoreCLR - * and use of ExecuteAssemblyFunction() and CreateDelegateFunction() - * should be sandwiched in between them + * startCoreCLR() takes a friendly name, e.g. "powershell", and a + * writable pointer and identifier * + * executeAssmbly() will be made available after starting CoreCLR, and + * is used to launch assemblies with a main function + * + * createDelegate() works similarly but provides a reverse P/Invoke + * given an assembly, type, and method; note that on Linux, + * PublicKeyToken must be null + * + * stopCoreCLR() will deinitialize given the handle and identifier */ + extern "C" { int startCoreCLR( From 43c7bdd137c7bde591727ceea621f8746d9bf026 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Fri, 23 Oct 2015 10:55:55 -0700 Subject: [PATCH 226/298] New GetLinkCount() --- CMakeLists.txt | 2 +- impl/getlinkcount.cpp | 120 ++++++++++++++++++++++++++++++++++++++++++ impl/getlinkcount.h | 9 ++++ impl/pal.h | 7 +++ 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 impl/getlinkcount.cpp create mode 100644 impl/getlinkcount.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b534ebb94b..6b8b426ddc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ include_directories(../ext-src/gtest/fused-src impl) link_directories(${monad_native_BINARY_DIR}) # source file definitions -set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp impl/getcomputername.cpp impl/getcpinfo.cpp) +set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp impl/getcomputername.cpp impl/getcpinfo.cpp impl/getlinkcount.cpp) set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername.cpp tests/test-getcpinfo.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) diff --git a/impl/getlinkcount.cpp b/impl/getlinkcount.cpp new file mode 100644 index 0000000000..1af39b69c5 --- /dev/null +++ b/impl/getlinkcount.cpp @@ -0,0 +1,120 @@ +//! @file getlinkcount.cpp +//! @author George FLeming +//! @brief Retrieve link count of a file + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "getlinkcount.h" + +//! @brief GetLinkCount retrieves the file link count (number of hard links) +//! for the given file +//! +//! GetLinkCountW is the Unicode variation. See [MSDN documentation]. +//! +//! @param[in] fileName +//! @parblock +//! A pointer to the buffer that contains the file name +//! +//! WCHAR_T* is a Unicode [LPTSTR]. +//! @endparblock +//! +//! @param[out] count +//! @parblock +//! This function returns the number of hard links associated with this file +//! +//! TCHAR is a Unicode 16-bit [WCHAR]. +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_INVALID_PARAMETER: parameter is not valid +//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 +//! - ERROR_FILE_NOT_FOUND: file does not exist +//! - ERROR_ACCESS_DENIED: access is denied +//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified +//! - ERROR_INVALID_ADDRESS: attempt to access invalid address +//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link +//! - ERROR_GEN_FAILURE: device attached to the system is not functioning +//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file +//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect +//! - ERROR_BUFFER_OVERFLOW: file name is too long +//! - ERROR_INVALID_FUNCTION: incorrect function +//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters +//! +//! @retval TRUE If the function succeeds, the return value is a nonzero +//! value, and the variable pointed to by buffer contains infomation about the files +//! @retval FALSE If the function fails, the return value is zero. To get +//! extended error information, call GetLastError. +//! + +BOOL GetLinkCountW(char* fileName, LPDWORD count) +{ + errno = 0; + + // Check parameters + if (!fileName) + { + errno = ERROR_INVALID_PARAMETER; + return FALSE; + } + + // Select locale from environment + setlocale(LC_ALL, ""); + // Check that locale is UTF-8 + if (nl_langinfo(CODESET) != std::string("UTF-8")) + { + errno = ERROR_BAD_ENVIRONMENT; + return FALSE; + } + + struct stat statBuf; + + int returnCode = lstat(fileName, &statBuf); + + if (returnCode != 0) + { + switch(errno) + { + case EACCES: + errno = ERROR_ACCESS_DENIED; + break; + case EBADF: + errno = ERROR_FILE_NOT_FOUND; + break; + case EFAULT: + errno = ERROR_INVALID_ADDRESS; + break; + case ELOOP: + errno = ERROR_STOPPED_ON_SYMLINK; + break; + case ENAMETOOLONG: + errno = ERROR_GEN_FAILURE; + break; + case ENOENT: + errno = ERROR_FILE_NOT_FOUND; + break; + case ENOMEM: + errno = ERROR_NO_SUCH_USER; + break; + case ENOTDIR: + errno = ERROR_INVALID_NAME; + break; + case EOVERFLOW: + errno = ERROR_BUFFER_OVERFLOW; + break; + default: + errno = ERROR_INVALID_FUNCTION; + } + return FALSE; + } + + *count = statBuf.st_nlink; + return TRUE; + +} + diff --git a/impl/getlinkcount.h b/impl/getlinkcount.h new file mode 100644 index 0000000000..47243c969d --- /dev/null +++ b/impl/getlinkcount.h @@ -0,0 +1,9 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +BOOL GetLinkCountW(char* fileName, LPDWORD count); + +PAL_END_EXTERNC diff --git a/impl/pal.h b/impl/pal.h index 944336ab0e..c53c985a8c 100644 --- a/impl/pal.h +++ b/impl/pal.h @@ -82,6 +82,13 @@ #define MAX_PATH 0x00000104 #define ERROR_INVALID_ADDRESS 0x000001e7 #define ERROR_GEN_FAILURE 0x0000001F + #define ERROR_ACCESS_DENIED 0x00000005 + #define ERROR_INVALID_NAME 0x0000007B + #define ERROR_STOPPED_ON_SYMLINK 0x000002A9 + #define ERROR_BUFFER_OVERFLOW 0x0000006F + #define ERROR_FILE_NOT_FOUND 0x00000002 + #define ERROR_BAD_PATH_NAME 0x000000A1 + typedef unsigned long long uint64; #endif From cf9b390faaddb2306030bb2cfdcef15b27b3f722 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Fri, 23 Oct 2015 15:48:48 -0700 Subject: [PATCH 227/298] Adding native tests --- CMakeLists.txt | 2 +- tests/test-getlinkcount.cpp | 90 +++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 tests/test-getlinkcount.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b8b426ddc..034bb2a89f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ link_directories(${monad_native_BINARY_DIR}) set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp impl/getcomputername.cpp impl/getcpinfo.cpp impl/getlinkcount.cpp) set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) set(HOST_COMMON_TEST_SOURCE_FILES tests/host/test-hostutil.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername.cpp tests/test-getcpinfo.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) +set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername.cpp tests/test-getcpinfo.cpp tests/test-getlinkcount.cpp ${HOST_COMMON_SOURCE_FILES} ${HOST_COMMON_TEST_SOURCE_FILES}) set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp) diff --git a/tests/test-getlinkcount.cpp b/tests/test-getlinkcount.cpp new file mode 100644 index 0000000000..081b0474e0 --- /dev/null +++ b/tests/test-getlinkcount.cpp @@ -0,0 +1,90 @@ +//! @file test-getlinkcount.cpp +//! @author George Fleming +//! @brief Implements test for getLinkCount() + +#include +#include +#include +#include +#include +#include +#include +#include "getlinkcount.h" + +class getLinkCountTest : public ::testing::Test +{ + protected: + + std::string file; + const std::string fileTemplate = "/tmp/createFile.XXXXXXX"; + ulong count; + + getLinkCountTest() + { + file = fileTemplate; + file = mktemp(const_cast(file.c_str())); + std::ifstream fileCondition(file); + EXPECT_EQ(0, fileCondition.good()); + } + + void createFileForTesting(std::string theFile) + { + std::ofstream ofs; + ofs.open(theFile, std::ofstream::out); + ofs << "hi there, ms ostc!"; + ofs.close(); + } + + std::string createHardLink(std::string origFile) + { + std::string newFile = origFile + "_link"; + int ret = link(const_cast(origFile.c_str()), const_cast(newFile.c_str())); + EXPECT_EQ(0, ret); + + return newFile; + } + + void removeFile(std::string fileName) + { + int ret = unlink(const_cast(fileName.c_str())); + EXPECT_EQ(0, ret); + } +}; + +TEST_F(getLinkCountTest, FilePathNameIsNull) +{ + bool retVal = GetLinkCountW(NULL, &count ); + ASSERT_FALSE(retVal); + EXPECT_EQ(ERROR_INVALID_PARAMETER, errno); +} + +TEST_F(getLinkCountTest, FilePathNameDoesNotExist) +{ + std::string invalidFile = "/tmp/createFile"; + bool retVal = GetLinkCountW(const_cast(invalidFile.c_str()), &count); + ASSERT_FALSE(retVal); + EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno); +} + +TEST_F(getLinkCountTest, LinkCountOfSinglyLinkedFile) +{ + createFileForTesting(file); + bool retVal = GetLinkCountW(const_cast(file.c_str()), &count); + ASSERT_TRUE(retVal); + EXPECT_EQ(1, count); + + removeFile(file); +} + +TEST_F(getLinkCountTest, LinkCountOfMultipliLinkedFile) +{ + createFileForTesting(file); + std::string newFile = createHardLink(file); + bool retVal = GetLinkCountW(const_cast(file.c_str()), &count); + ASSERT_TRUE(retVal); + EXPECT_EQ(2, count); + + removeFile(file); + removeFile(newFile); +} + From 6af36478fd564bf99f6b4385c20fff641b892ba2 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 15:59:06 -0700 Subject: [PATCH 228/298] Conditionalize extern "C" --- host/common/coreclrutil.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/host/common/coreclrutil.h b/host/common/coreclrutil.h index f00b6519d6..d344873107 100644 --- a/host/common/coreclrutil.h +++ b/host/common/coreclrutil.h @@ -17,8 +17,10 @@ * stopCoreCLR() will deinitialize given the handle and identifier */ +#ifdef __cplusplus extern "C" { +#endif int startCoreCLR( const char* appDomainFriendlyName, void** hostHandle, @@ -46,4 +48,6 @@ extern "C" extern ExecuteAssemblyFunction executeAssembly; extern CreateDelegateFunction createDelegate; +#ifdef __cplusplus } +#endif From a3a3e2b5c985e9cb19368d5146c54e6165bb224e Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 23 Oct 2015 15:59:06 -0700 Subject: [PATCH 229/298] Conditionalize extern "C" --- src/host/common/coreclrutil.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/host/common/coreclrutil.h b/src/host/common/coreclrutil.h index f00b6519d6..d344873107 100644 --- a/src/host/common/coreclrutil.h +++ b/src/host/common/coreclrutil.h @@ -17,8 +17,10 @@ * stopCoreCLR() will deinitialize given the handle and identifier */ +#ifdef __cplusplus extern "C" { +#endif int startCoreCLR( const char* appDomainFriendlyName, void** hostHandle, @@ -46,4 +48,6 @@ extern "C" extern ExecuteAssemblyFunction executeAssembly; extern CreateDelegateFunction createDelegate; +#ifdef __cplusplus } +#endif From b91c1173137881f7cb478e758f31388569d04af8 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sat, 24 Oct 2015 21:30:42 -0700 Subject: [PATCH 230/298] GetLinkCount is not Unicode --- impl/getlinkcount.cpp | 10 ++++------ impl/getlinkcount.h | 2 +- tests/test-getlinkcount.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/impl/getlinkcount.cpp b/impl/getlinkcount.cpp index 1af39b69c5..2dde56bba3 100644 --- a/impl/getlinkcount.cpp +++ b/impl/getlinkcount.cpp @@ -16,20 +16,19 @@ //! @brief GetLinkCount retrieves the file link count (number of hard links) //! for the given file //! -//! GetLinkCountW is the Unicode variation. See [MSDN documentation]. +//! GetLinkCount //! //! @param[in] fileName //! @parblock //! A pointer to the buffer that contains the file name //! -//! WCHAR_T* is a Unicode [LPTSTR]. +//! char* is marshaled as an LPStr, which on Linux is UTF-8. //! @endparblock //! //! @param[out] count //! @parblock //! This function returns the number of hard links associated with this file -//! -//! TCHAR is a Unicode 16-bit [WCHAR]. +//! @endparblock //! //! @exception errno Passes these errors via errno to GetLastError: //! - ERROR_INVALID_PARAMETER: parameter is not valid @@ -52,7 +51,7 @@ //! extended error information, call GetLastError. //! -BOOL GetLinkCountW(char* fileName, LPDWORD count) +BOOL GetLinkCount(char* fileName, LPDWORD count) { errno = 0; @@ -117,4 +116,3 @@ BOOL GetLinkCountW(char* fileName, LPDWORD count) return TRUE; } - diff --git a/impl/getlinkcount.h b/impl/getlinkcount.h index 47243c969d..738a606c6c 100644 --- a/impl/getlinkcount.h +++ b/impl/getlinkcount.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetLinkCountW(char* fileName, LPDWORD count); +BOOL GetLinkCount(char* fileName, LPDWORD count); PAL_END_EXTERNC diff --git a/tests/test-getlinkcount.cpp b/tests/test-getlinkcount.cpp index 081b0474e0..0c7a3d0c50 100644 --- a/tests/test-getlinkcount.cpp +++ b/tests/test-getlinkcount.cpp @@ -53,7 +53,7 @@ class getLinkCountTest : public ::testing::Test TEST_F(getLinkCountTest, FilePathNameIsNull) { - bool retVal = GetLinkCountW(NULL, &count ); + bool retVal = GetLinkCount(NULL, &count ); ASSERT_FALSE(retVal); EXPECT_EQ(ERROR_INVALID_PARAMETER, errno); } @@ -61,7 +61,7 @@ TEST_F(getLinkCountTest, FilePathNameIsNull) TEST_F(getLinkCountTest, FilePathNameDoesNotExist) { std::string invalidFile = "/tmp/createFile"; - bool retVal = GetLinkCountW(const_cast(invalidFile.c_str()), &count); + bool retVal = GetLinkCount(const_cast(invalidFile.c_str()), &count); ASSERT_FALSE(retVal); EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno); } @@ -69,7 +69,7 @@ TEST_F(getLinkCountTest, FilePathNameDoesNotExist) TEST_F(getLinkCountTest, LinkCountOfSinglyLinkedFile) { createFileForTesting(file); - bool retVal = GetLinkCountW(const_cast(file.c_str()), &count); + bool retVal = GetLinkCount(const_cast(file.c_str()), &count); ASSERT_TRUE(retVal); EXPECT_EQ(1, count); @@ -80,7 +80,7 @@ TEST_F(getLinkCountTest, LinkCountOfMultipliLinkedFile) { createFileForTesting(file); std::string newFile = createHardLink(file); - bool retVal = GetLinkCountW(const_cast(file.c_str()), &count); + bool retVal = GetLinkCount(const_cast(file.c_str()), &count); ASSERT_TRUE(retVal); EXPECT_EQ(2, count); From 5ed81a0a41b7cf51c137730bdebafcf7395e6780 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sat, 24 Oct 2015 22:12:05 -0700 Subject: [PATCH 231/298] Return char* for GetUserName The UTF-8 char* is marshaled to a UTF-16 string automatically. It must be allocated on the heap as the CLR will free the returned memory. This removes entire classes of possible errors, greatly reducing the code complexity and number of tests. --- impl/getusername.cpp | 81 +++------------------- impl/getusername.h | 2 +- tests/test-getusername.cpp | 136 ++----------------------------------- 3 files changed, 15 insertions(+), 204 deletions(-) diff --git a/impl/getusername.cpp b/impl/getusername.cpp index ee14d8651a..a4590bfde9 100644 --- a/impl/getusername.cpp +++ b/impl/getusername.cpp @@ -1,6 +1,6 @@ //! @file getusername.cpp //! @author Andrew Schwartzmeyer -//! @brief Implements GetUserName Win32 API +//! @brief Implements GetUserName for Linux #include #include @@ -14,56 +14,16 @@ //! @brief GetUserName retrieves the name of the user associated with //! the current thread. //! -//! GetUserNameW is the Unicode variation. See [MSDN documentation]. -//! -//! @param[out] lpBuffer -//! @parblock -//! A pointer to the buffer to receive the user's -//! logon name. If this buffer is not large enough to contain the -//! entire user name, the function fails. -//! -//! WCHAR_T* is a Unicode [LPTSTR]. -//! @endparblock -//! -//! @param[in, out] lpnSize -//! @parblock -//! On input, this variable specifies the size of the lpBuffer buffer, -//! in TCHARs. On output, the variable receives the number of TCHARs -//! copied to the buffer, including the terminating null character. -//! -//! TCHAR is a Unicode 16-bit [WCHAR]. -//! -//! If lpBuffer is too small, the function fails and GetLastError -//! returns ERROR_INSUFFICIENT_BUFFER. This parameter receives the -//! required buffer size, including the terminating null character. -//! @endparblock -//! //! @exception errno Passes these errors via errno to GetLastError: //! - ERROR_INVALID_PARAMETER: parameter is not valid //! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 -//! - ERROR_INSUFFICIENT_BUFFER: buffer not large enough to hold username string //! - ERROR_NO_SUCH_USER: there was no corresponding user //! - ERROR_GEN_FAILURE: sysconf() or getpwuid() failed for unknown reasons //! -//! @retval TRUE If the function succeeds, the return value is a nonzero -//! value, and the variable pointed to by lpnSize contains the number -//! of TCHARs copied to the buffer specified by lpBuffer, including -//! the terminating null character. -//! -//! @retval FALSE If the function fails, the return value is zero. To get -//! extended error information, call GetLastError. -//! -//! [MSDN documentation]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx -//! [WCHAR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#WCHAR -//! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR -BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) +//! @retval username as UTF-8 string, or null if unsuccessful +char* GetUserName() { - // Check parameters - if (!lpBuffer || !lpnSize) - { - errno = ERROR_INVALID_PARAMETER; - return FALSE; - } + errno = 0; // Select locale from environment setlocale(LC_ALL, ""); @@ -71,7 +31,7 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) if (nl_langinfo(CODESET) != std::string("UTF-8")) { errno = ERROR_BAD_ENVIRONMENT; - return FALSE; + return NULL; } struct passwd pwd; @@ -86,7 +46,6 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) std::string buf(buflen, 0); // geteuid() gets the effective user ID of the calling process, and is always successful - errno = 0; int ret = getpwuid_r(geteuid(), &pwd, &buf[0], buflen, &result); // Map errno to Win32 Error Codes @@ -103,38 +62,16 @@ BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) default: errno = ERROR_GEN_FAILURE; } - return FALSE; + return NULL; } // Check if no user matched if (result == NULL) { errno = ERROR_NO_SUCH_USER; - return FALSE; + return NULL; } - std::string username(result->pw_name); - - // Convert to UnicodeString - auto username16 = icu::UnicodeString::fromUTF8(username.c_str()); - // Terminate string with null - username16.append('\0'); - - // Size in WCHARs including null - const DWORD size = username16.length(); - if (size > *lpnSize) - { - errno = ERROR_INSUFFICIENT_BUFFER; - // Set lpnSize if buffer is too small to inform user - // of necessary size - *lpnSize = size; - return FALSE; - } - - // Extract string as UTF-16LE to buffer - username16.extract(0, size, reinterpret_cast(lpBuffer), "UTF-16LE"); - - *lpnSize = size; - - return TRUE; + // allocate copy on heap so CLR can free it + return strdup(result->pw_name); } diff --git a/impl/getusername.h b/impl/getusername.h index 6083078bc0..1326298f42 100644 --- a/impl/getusername.h +++ b/impl/getusername.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetUserNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize); +char* GetUserName(); PAL_END_EXTERNC diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index 9d238f538a..50c2d1feab 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -10,144 +10,18 @@ #include #include "getusername.h" -//! Test fixture for GetUserNameW +//! Test fixture for GetUserName class GetUserNameTest : public ::testing::Test { protected: - DWORD lpnSize; - std::vector lpBuffer; - BOOL result; - std::string expectedUsername; - DWORD expectedSize; + std::string UserName; - GetUserNameTest(): expectedUsername(std::string(getpwuid(geteuid())->pw_name)), - expectedSize(expectedUsername.length()+1) + GetUserNameTest(): UserName(std::string(getpwuid(geteuid())->pw_name)) { } - - //! Invokes GetUserNameW with lpnSize and lpBuffer, saves result. - //! - //! @param size Assigns to lpnSize and allocates lpBuffer with - //! size number of null characters. - void TestWithSize(DWORD size) - { - lpnSize = size; - // allocate a WCHAR_T buffer to receive username - lpBuffer.assign(lpnSize, 0); - result = GetUserNameW(&lpBuffer[0], &lpnSize); - } - - //! Checks the effects of GetUserNameW for success. - void TestSuccess() - { - SCOPED_TRACE(""); - - //! Returns TRUE on success. - EXPECT_EQ(TRUE, result); - - //! Sets lpnSize to number of WCHARs including null. - ASSERT_EQ(expectedSize, lpnSize); - - // Read lpBuffer into UnicodeString (without null) - const char* begin = reinterpret_cast(&lpBuffer[0]); - icu::UnicodeString username16(begin, (lpnSize-1)*sizeof(UChar), "UTF-16LE"); - ASSERT_EQ(expectedUsername.length(), username16.length()); - // Convert to UTF-8 for comparison - std::string username; - username16.toUTF8String(username); - ASSERT_EQ(expectedUsername.length(), username.length()); - - //! Returned username (after conversion) is what was expected. - EXPECT_EQ(expectedUsername, username); - } - - //! Checks the effects of GetUserNameW on failure with invalid parameters. - void TestInvalidParameter() - { - SCOPED_TRACE(""); - - //! Returns FALSE on failure. - EXPECT_EQ(FALSE, result); - - //! Sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null - //! (which is the case for an empty vector). - EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); - } - - //! Checks the effects of GetUserNameW on failure with a buffer that is too small. - void TestInsufficientBuffer() - { - SCOPED_TRACE(""); - - //! Returns FALSE on failure. - EXPECT_EQ(FALSE, result); - - //! Sets errno to ERROR_INSUFFICIENT_BUFFER. - EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); - - //! Sets lpnSize to length of username plus null. - EXPECT_EQ(expectedSize, lpnSize); - } }; -TEST_F(GetUserNameTest, BufferAsNullButNotBufferSize) +TEST_F(GetUserNameTest, Success) { - lpnSize = 1; - result = GetUserNameW(NULL, &lpnSize); - - TestInvalidParameter(); - // does not reset lpnSize - EXPECT_EQ(1, lpnSize); -} - -TEST_F(GetUserNameTest, BufferSizeAsNullButNotBuffer) -{ - lpBuffer.push_back('\0'); - result = GetUserNameW(&lpBuffer[0], NULL); - - TestInvalidParameter(); -} - -TEST_F(GetUserNameTest, BufferSizeAsZero) -{ - TestWithSize(0); - TestInvalidParameter(); - // does not reset lpnSize - EXPECT_EQ(0, lpnSize); -} - -TEST_F(GetUserNameTest, BufferSizeAsOne) -{ - // theoretically this should never fail because any non-empty - // username length will be >1 with trailing null - TestWithSize(1); - TestInsufficientBuffer(); -} - -TEST_F(GetUserNameTest, BufferSizeAsUsername) -{ - // the buffer is too small because it does not account for null - TestWithSize(expectedUsername.length()); - TestInsufficientBuffer(); -} - -TEST_F(GetUserNameTest, BufferSizeAsUsernamePlusOne) -{ - // includes null and so should be sufficient - TestWithSize(expectedUsername.length()+1); - TestSuccess(); -} - -TEST_F(GetUserNameTest, BufferSizeAsExpectedSize) -{ - // expectedSize is the same as username.size()+1 - TestWithSize(expectedSize); - TestSuccess(); -} - -TEST_F(GetUserNameTest, BufferSizeAsLoginNameMax) -{ - // LoginNameMax is big enough to hold any username, including null - TestWithSize(LOGIN_NAME_MAX); - TestSuccess(); + ASSERT_EQ(GetUserName(), UserName); } From 81984534b8514ad5f9258b13cf26cf4109497976 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sun, 25 Oct 2015 12:03:49 -0700 Subject: [PATCH 232/298] Refactor CMake build system and host files Use CMakeLists.txt file for each directory. Setup to be consumed by monad-linux's CMake. Utilize GoogleTest's CMake. Refactor host files layout. --- CMakeLists.txt | 35 +++++-------------------------- host/CMakeLists.txt | 5 +++++ host/{common => }/coreclrutil.cpp | 0 host/{common => }/coreclrutil.h | 0 host/{cmdline => }/main.cpp | 2 +- impl/CMakeLists.txt | 8 +++++++ tests/CMakeLists.txt | 12 +++++++++++ tests/googletest | 1 + main.cpp => tests/main.cpp | 2 +- 9 files changed, 33 insertions(+), 32 deletions(-) create mode 100644 host/CMakeLists.txt rename host/{common => }/coreclrutil.cpp (100%) rename host/{common => }/coreclrutil.h (100%) rename host/{cmdline => }/main.cpp (99%) create mode 100644 impl/CMakeLists.txt create mode 100644 tests/CMakeLists.txt create mode 160000 tests/googletest rename main.cpp => tests/main.cpp (98%) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2b1cad536..07c6632190 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,32 +1,7 @@ -cmake_minimum_required(VERSION 2.8.4) -project(monad_native) +project(MONAD_NATIVE) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall") +add_compile_options(-std=c++11 -Wall) -#include gtest -include_directories(../ext-src/gtest/fused-src impl) -link_directories(${monad_native_BINARY_DIR}) - -# source file definitions -set(LIB_SOURCE_FILES impl/getcurrentprocessorid.cpp impl/getusername.cpp impl/terminal.cpp impl/getcomputername.cpp impl/getcpinfo.cpp) -set(HOST_COMMON_SOURCE_FILES host/common/coreclrutil.cpp) -set(TEST_SOURCE_FILES tests/test-getcurrentprocessid.cpp tests/test-getusername.cpp tests/test-getcomputername.cpp tests/test-getcpinfo.cpp ${HOST_COMMON_SOURCE_FILES}) -set(SOURCE_FILES main.cpp ../ext-src/gtest/fused-src/gtest/gtest-all.cc) -set(HOST_CMDLINE_SOURCE_FILES host/cmdline/main.cpp) - -# target definitions -add_library(ps SHARED ${LIB_SOURCE_FILES}) -add_executable(monad_native ${SOURCE_FILES} ${TEST_SOURCE_FILES}) -add_library(pshost STATIC ${HOST_COMMON_SOURCE_FILES}) -add_executable(host_cmdline ${HOST_CMDLINE_SOURCE_FILES}) - -# add pthread and other libs -find_package(Threads) -target_link_libraries(ps icuuc) -target_link_libraries(monad_native ${CMAKE_THREAD_LIBS_INIT} ps pshost) -target_link_libraries(pshost dl icuuc) -target_link_libraries(host_cmdline pshost) - -# target specific include directories -target_include_directories(monad_native PRIVATE host) -target_include_directories(host_cmdline PRIVATE host) +add_subdirectory(impl) +add_subdirectory(host) +add_subdirectory(tests) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt new file mode 100644 index 0000000000..0ddbf88f7f --- /dev/null +++ b/host/CMakeLists.txt @@ -0,0 +1,5 @@ +add_library(pshost STATIC coreclrutil.cpp) +target_link_libraries(pshost dl icuuc) + +add_executable(host_cmdline main.cpp) +target_link_libraries(host_cmdline pshost) diff --git a/host/common/coreclrutil.cpp b/host/coreclrutil.cpp similarity index 100% rename from host/common/coreclrutil.cpp rename to host/coreclrutil.cpp diff --git a/host/common/coreclrutil.h b/host/coreclrutil.h similarity index 100% rename from host/common/coreclrutil.h rename to host/coreclrutil.h diff --git a/host/cmdline/main.cpp b/host/main.cpp similarity index 99% rename from host/cmdline/main.cpp rename to host/main.cpp index 938a02275d..06e7ad0407 100644 --- a/host/cmdline/main.cpp +++ b/host/main.cpp @@ -1,7 +1,7 @@ #include #include #include -#include "common/coreclrutil.h" +#include "coreclrutil.h" namespace Cmdline { diff --git a/impl/CMakeLists.txt b/impl/CMakeLists.txt new file mode 100644 index 0000000000..0eeb2e8fa8 --- /dev/null +++ b/impl/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(ps SHARED + getcurrentprocessorid.cpp + getusername.cpp + getcomputername.cpp + terminal.cpp) + +target_link_libraries(ps icuuc) +target_include_directories (ps PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000000..396e121c50 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,12 @@ +add_subdirectory(googletest) + +add_executable(monad_native + main.cpp + test-getcurrentprocessid.cpp + test-getusername.cpp + test-getcomputername.cpp) + +target_include_directories(monad_native PRIVATE ${gtest_SOURCE_DIR}/include) + +find_package(Threads) +target_link_libraries(monad_native ps gtest) diff --git a/tests/googletest b/tests/googletest new file mode 160000 index 0000000000..c99458533a --- /dev/null +++ b/tests/googletest @@ -0,0 +1 @@ +Subproject commit c99458533a9b4c743ed51537e25989ea55944908 diff --git a/main.cpp b/tests/main.cpp similarity index 98% rename from main.cpp rename to tests/main.cpp index e59bea0572..9bb465e024 100644 --- a/main.cpp +++ b/tests/main.cpp @@ -4,4 +4,4 @@ int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} \ No newline at end of file +} From 807760f06dcaf98d68ae02d516889791e032acca Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sun, 25 Oct 2015 12:06:47 -0700 Subject: [PATCH 233/298] Remove deprecated GetCPInfo code --- impl/getcpinfo.cpp | 118 --------------------------------------- impl/getcpinfo.h | 27 --------- tests/test-getcpinfo.cpp | 34 ----------- 3 files changed, 179 deletions(-) delete mode 100644 impl/getcpinfo.cpp delete mode 100644 impl/getcpinfo.h delete mode 100644 tests/test-getcpinfo.cpp diff --git a/impl/getcpinfo.cpp b/impl/getcpinfo.cpp deleted file mode 100644 index 79f39ea25e..0000000000 --- a/impl/getcpinfo.cpp +++ /dev/null @@ -1,118 +0,0 @@ -//! @file getcpinfo.cpp -//! @author Aaron Ktaz -//! @brief Implements GetCpInfoW Win32 API - -#include -#include -#include -#include "getcpinfo.h" - -//! @brief GetCPInfoW retrieves the name of the code page associated with -//! the current thread. -//! -//! GetCpInfoW the Unicode variation. See [MSDN documentation]. -//! -//! @param[in] codepage -//! @parblock -//! An UINT Identifier for the code page for which to retrieve information. -//! See Code Page Identifiers for details -//! 65001 in the number for UTF8. It is the only valid input parameter -//!because Linux and Unix only use UTF8 for codepage -//! -//! @endparblock -//! -//! @param[out] cpinfo -//! @parblock -//! Pointer to a CPINFO structure that receives information about the code page -//! -//! LPCPINFO is a pointer to the structure _cpinfo used to contain the information -//! about a code page -//! -//! -//! typedef struct _cpinfo { -//! UINT MaxCharSize; -//! BYTE DefaultChar[MAX_DEFAULTCHAR]; -//! BYTE LeadByte[MAX_LEADBYTES]; -//! } CPINFO, *LPCPINFO; -//! -//! _cpinfo is a struct that comprises -//! -//! UINT MaxCharSize; -//! Maximum length, in bytes, of a character in the code page. -//! The length can be 1 for a single-byte character set (SBCS), -//! 2 for a double-byte character set (DBCS), or a value larger -//! than 2 for other character set types. The function cannot -//! use the size to distinguish an SBCS or a DBCS from other -//! character sets because of other factors, for example, -//! the use of ISCII or ISO-2022-xx code pages. -//! -//! BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; -//! Default character used when translating character -//! strings to the specific code page. This character is used by -//! the WideCharToMultiByte function if an explicit default -//! character is not specified. The default is usually the "?" -//! character for the code page -//! -//! BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; -//! A fixed-length array of lead byte ranges, for which the number -//! of lead byte ranges is variable. If the code page has no lead -//! bytes, every element of the array is set to NULL. If the code -//! page has lead bytes, the array specifies a starting value and -//! an ending value for each range. Ranges are inclusive, and the -//! maximum number of ranges for any code page is five. The array -//! uses two bytes to describe each range, with two null bytes as -//! a terminator after the last range. -//! -//! MAX_DEFAULTCHAR is an int of size 2 -//! MAX_LEADBYTES is an int of size 12 -//! -//! -//! @exception errno Passes these errors via errno to GetLastError: -//! - ERROR_INVALID_PARAMETER: parameter is not valid -//! -//! @retval TRUE If the function succeeds, the return value is a nonzero -//! value, and cpinfo is population with information about the code page -//! -//! @retval FALSE If the function fails, the return value is zero. To get -//! extended error information, call GetLastError. -//! -//! [MSDN documentation]:https://msdn.microsoft.com/en-us/library/windows/desktop/dd318078%28v=vs.85%29.aspx -//! [_cpinfo]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317780(v=vs.85).aspx -//! [CodePageIdentifiers] https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx - -BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo) -{ - errno = FALSE; - - // Select locale from environment - setlocale(LC_ALL, ""); - - // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != std::string("UTF-8")) - { - errno = ERROR_BAD_ENVIRONMENT; - return FALSE; - } - - if (codepage != const_cpinfo::UTF8) - { - //If other value is used return error because Linux and Unix only used UTF-8 for codepage - errno = ERROR_INVALID_PARAMETER; - return FALSE; - } - - // UTF-8 uses the default char for DefaultChar[0] which is '?' - cpinfo->DefaultChar[0] = '?'; - cpinfo->DefaultChar[1] = '0'; - cpinfo->MaxCharSize = 4; - - for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ ) - { - // UTF-8 uses the default has no LeadByte as result LeadByte is '0' - cpinfo->LeadByte[i] = '0'; - } - - return TRUE; - -} - diff --git a/impl/getcpinfo.h b/impl/getcpinfo.h deleted file mode 100644 index cd0883d7b4..0000000000 --- a/impl/getcpinfo.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "pal.h" - -//!* NameSpace - -namespace const_cpinfo -{ - constexpr int MAX_DEFAULTCHAR = 2; - constexpr int MAX_LEADBYTES = 12; - constexpr int UTF8 = 65001; -} - -//!* Structs - -typedef struct _cpinfo -{ - UINT MaxCharSize; - BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR]; - BYTE LeadByte[const_cpinfo::MAX_LEADBYTES]; -} CPINFO; - -PAL_BEGIN_EXTERNC - -BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo); - -PAL_END_EXTERNC diff --git a/tests/test-getcpinfo.cpp b/tests/test-getcpinfo.cpp deleted file mode 100644 index 0c8a339604..0000000000 --- a/tests/test-getcpinfo.cpp +++ /dev/null @@ -1,34 +0,0 @@ -//! @file test-getcpinfo.cpp -//! @author Aaron Ktaz -//! @brief Implements Unit test for GetCPInfoW - -#include -#include "getcpinfo.h" - -TEST(GetCPInfo, CodePageIsUTF8) -{ - CPINFO cpinfo; - BOOL result = GetCPInfoW(const_cpinfo::UTF8, &cpinfo); - - // first make sure that the function worked - ASSERT_EQ(TRUE, result); - - // now compare the actual values - EXPECT_EQ(cpinfo.DefaultChar[0], '?'); - EXPECT_EQ(cpinfo.DefaultChar[1], '0'); - EXPECT_EQ(cpinfo.MaxCharSize, 4); - - for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++) - { - EXPECT_EQ(cpinfo.LeadByte[i], '0'); - } -} - -TEST(GetCPInfo, CodePageIsNotUTF8) -{ - CPINFO cpinfo; - BOOL result = GetCPInfoW(const_cpinfo::UTF8+1, &cpinfo); - - ASSERT_EQ(FALSE, result); - ASSERT_EQ(ERROR_INVALID_PARAMETER, errno); -} From a548455918df5bf3f33508f466c124352bd0fa00 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sun, 25 Oct 2015 12:09:49 -0700 Subject: [PATCH 234/298] Rename host_cmdline to powershell --- host/CMakeLists.txt | 4 ++-- host/main.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 0ddbf88f7f..a44effc5f8 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -1,5 +1,5 @@ add_library(pshost STATIC coreclrutil.cpp) target_link_libraries(pshost dl icuuc) -add_executable(host_cmdline main.cpp) -target_link_libraries(host_cmdline pshost) +add_executable(powershell main.cpp) +target_link_libraries(powershell pshost) diff --git a/host/main.cpp b/host/main.cpp index 06e7ad0407..04ad61ea99 100644 --- a/host/main.cpp +++ b/host/main.cpp @@ -7,8 +7,8 @@ namespace Cmdline { void printHelp() { - std::cerr << "PS CoreCLR host" << std::endl - << "Usage: host_cmdline assembly [...]" << std::endl + std::cerr << "PowerShell on Linux host" << std::endl + << "Usage: powershell assembly [...]" << std::endl << std::endl << "What it does:" << std::endl << "- the host assumes that CoreCLR is located $CORE_ROOT" << std::endl From c1a5e9fb533006a70b0723a7148f986512d02af2 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sun, 25 Oct 2015 12:15:21 -0700 Subject: [PATCH 235/298] Resurrect .gitmodules after subtree split Removed src intermediate directory --- .gitmodules | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..44d6d26f4a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "tests/googletest"] + path = tests/googletest + url = https://github.com/google/googletest.git + ignore = dirty From 569de14c1e59ba8194fd46eebcbec7a4d57885f3 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sun, 25 Oct 2015 12:16:34 -0700 Subject: [PATCH 236/298] Rename libps to libpsnative And impl to native --- CMakeLists.txt | 2 +- impl/CMakeLists.txt | 9 --------- native/CMakeLists.txt | 9 +++++++++ {impl => native}/getcomputername.cpp | 0 {impl => native}/getcomputername.h | 0 {impl => native}/getcurrentprocessorid.cpp | 0 {impl => native}/getcurrentprocessorid.h | 0 {impl => native}/getcurrentthreadid.cpp | 0 {impl => native}/getcurrentthreadid.h | 0 {impl => native}/getlinkcount.cpp | 0 {impl => native}/getlinkcount.h | 0 {impl => native}/getusername.cpp | 0 {impl => native}/getusername.h | 0 {impl => native}/pal.h | 0 {impl => native}/terminal.cpp | 0 {impl => native}/terminal.h | 0 tests/CMakeLists.txt | 2 +- 17 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 impl/CMakeLists.txt create mode 100644 native/CMakeLists.txt rename {impl => native}/getcomputername.cpp (100%) rename {impl => native}/getcomputername.h (100%) rename {impl => native}/getcurrentprocessorid.cpp (100%) rename {impl => native}/getcurrentprocessorid.h (100%) rename {impl => native}/getcurrentthreadid.cpp (100%) rename {impl => native}/getcurrentthreadid.h (100%) rename {impl => native}/getlinkcount.cpp (100%) rename {impl => native}/getlinkcount.h (100%) rename {impl => native}/getusername.cpp (100%) rename {impl => native}/getusername.h (100%) rename {impl => native}/pal.h (100%) rename {impl => native}/terminal.cpp (100%) rename {impl => native}/terminal.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07c6632190..5de641170e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,6 @@ project(MONAD_NATIVE) add_compile_options(-std=c++11 -Wall) -add_subdirectory(impl) +add_subdirectory(native) add_subdirectory(host) add_subdirectory(tests) diff --git a/impl/CMakeLists.txt b/impl/CMakeLists.txt deleted file mode 100644 index 5b9c123fbe..0000000000 --- a/impl/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -add_library(ps SHARED - getcurrentprocessorid.cpp - getusername.cpp - getcomputername.cpp - getlinkcount.cpp - terminal.cpp) - -target_link_libraries(ps icuuc) -target_include_directories (ps PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt new file mode 100644 index 0000000000..c2523c3a3f --- /dev/null +++ b/native/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(psnative SHARED + getcurrentprocessorid.cpp + getusername.cpp + getcomputername.cpp + getlinkcount.cpp + terminal.cpp) + +target_link_libraries(psnative icuuc) +target_include_directories (psnative PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/impl/getcomputername.cpp b/native/getcomputername.cpp similarity index 100% rename from impl/getcomputername.cpp rename to native/getcomputername.cpp diff --git a/impl/getcomputername.h b/native/getcomputername.h similarity index 100% rename from impl/getcomputername.h rename to native/getcomputername.h diff --git a/impl/getcurrentprocessorid.cpp b/native/getcurrentprocessorid.cpp similarity index 100% rename from impl/getcurrentprocessorid.cpp rename to native/getcurrentprocessorid.cpp diff --git a/impl/getcurrentprocessorid.h b/native/getcurrentprocessorid.h similarity index 100% rename from impl/getcurrentprocessorid.h rename to native/getcurrentprocessorid.h diff --git a/impl/getcurrentthreadid.cpp b/native/getcurrentthreadid.cpp similarity index 100% rename from impl/getcurrentthreadid.cpp rename to native/getcurrentthreadid.cpp diff --git a/impl/getcurrentthreadid.h b/native/getcurrentthreadid.h similarity index 100% rename from impl/getcurrentthreadid.h rename to native/getcurrentthreadid.h diff --git a/impl/getlinkcount.cpp b/native/getlinkcount.cpp similarity index 100% rename from impl/getlinkcount.cpp rename to native/getlinkcount.cpp diff --git a/impl/getlinkcount.h b/native/getlinkcount.h similarity index 100% rename from impl/getlinkcount.h rename to native/getlinkcount.h diff --git a/impl/getusername.cpp b/native/getusername.cpp similarity index 100% rename from impl/getusername.cpp rename to native/getusername.cpp diff --git a/impl/getusername.h b/native/getusername.h similarity index 100% rename from impl/getusername.h rename to native/getusername.h diff --git a/impl/pal.h b/native/pal.h similarity index 100% rename from impl/pal.h rename to native/pal.h diff --git a/impl/terminal.cpp b/native/terminal.cpp similarity index 100% rename from impl/terminal.cpp rename to native/terminal.cpp diff --git a/impl/terminal.h b/native/terminal.h similarity index 100% rename from impl/terminal.h rename to native/terminal.h diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4ff914ae08..53580614de 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,4 +10,4 @@ add_executable(monad_native target_include_directories(monad_native PRIVATE ${gtest_SOURCE_DIR}/include) find_package(Threads) -target_link_libraries(monad_native ps gtest) +target_link_libraries(monad_native psnative gtest) From 523279f6e2afb97daed064505400e8dea4eafed8 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sun, 25 Oct 2015 12:19:28 -0700 Subject: [PATCH 237/298] Resurrect .gitignore --- .gitignore | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..280941f2a3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +.idea +src/.kdev4/ +src/CMakeFiles/ +src/build/ +src/monad_native +src/src.kdev4 +libps.so +CMakeCache.txt +CMakeFiles/ +Makefile +cmake_install.cmake +host_cmdline +monad_native From af813b9a08e60ab54ecdb270cb0ef199d8b4a62e Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sun, 25 Oct 2015 12:49:19 -0700 Subject: [PATCH 238/298] Enable unit testing via CMake --- tests/CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 53580614de..96d06674da 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,13 +1,16 @@ add_subdirectory(googletest) -add_executable(monad_native +add_executable(psnative-test test-getcurrentprocessid.cpp test-getusername.cpp test-getcomputername.cpp test-getlinkcount.cpp main.cpp) -target_include_directories(monad_native PRIVATE ${gtest_SOURCE_DIR}/include) +# manually include gtest headers +target_include_directories(psnative-test PRIVATE ${gtest_SOURCE_DIR}/include) -find_package(Threads) -target_link_libraries(monad_native psnative gtest) +target_link_libraries(psnative-test psnative gtest) + +add_test(NAME psnative-test + COMMAND psnative-test --gtest_output=xml:${MONAD_LINUX_SOURCE_DIR}/native-tests.xml) From 1c247171bd9a7430ac58ae23214a2a9fe276d8d5 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sun, 25 Oct 2015 12:49:49 -0700 Subject: [PATCH 239/298] Update gitignore --- .gitignore | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 280941f2a3..2afa8a81fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,8 @@ -.idea -src/.kdev4/ -src/CMakeFiles/ -src/build/ -src/monad_native -src/src.kdev4 -libps.so CMakeCache.txt -CMakeFiles/ +CMakeFiles +CMakeScripts Makefile cmake_install.cmake -host_cmdline -monad_native +install_manifest.txt +CTestTestfile.cmake +Testing/ \ No newline at end of file From c6ca4db6a448db8a279815f78b1021c66741949a Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sun, 25 Oct 2015 17:59:14 -0700 Subject: [PATCH 240/298] Output psnative and pshost to monad-linux/bin But leave test artifacts in monad-native. --- .gitignore | 3 ++- CMakeLists.txt | 14 +++++++++++++- tests/CMakeLists.txt | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 2afa8a81fc..b4b9d12490 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ Makefile cmake_install.cmake install_manifest.txt CTestTestfile.cmake -Testing/ \ No newline at end of file +Testing/ +tests/psnative-test diff --git a/CMakeLists.txt b/CMakeLists.txt index 5de641170e..51d4665de6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,19 @@ +cmake_minimum_required(VERSION 2.8.4) project(MONAD_NATIVE) add_compile_options(-std=c++11 -Wall) +# resolve superproject directory +set(MONAD ${CMAKE_SOURCE_DIR}/../../) + +# test in BUILD_DIR +enable_testing() +add_subdirectory(tests) + +# output psnative and pshost to superproject +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${MONAD}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${MONAD}/lib) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${MONAD}/lib) + add_subdirectory(native) add_subdirectory(host) -add_subdirectory(tests) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 96d06674da..c9630dda17 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -13,4 +13,4 @@ target_include_directories(psnative-test PRIVATE ${gtest_SOURCE_DIR}/include) target_link_libraries(psnative-test psnative gtest) add_test(NAME psnative-test - COMMAND psnative-test --gtest_output=xml:${MONAD_LINUX_SOURCE_DIR}/native-tests.xml) + COMMAND psnative-test --gtest_output=xml:${MONAD}/native-tests.xml) From 28dfd36a58dce69a5ab21fd6a89e3ba04986521b Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sun, 25 Oct 2015 20:32:42 -0700 Subject: [PATCH 241/298] Require absolute path to assembly Rather than assuming that it's in the current directory. Later this will be refactoring to choose the appropriate host assembly (for an interactive shell, script, command list, or self-test) from the `PWRSH_ROOT` path. --- host/main.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/host/main.cpp b/host/main.cpp index 04ad61ea99..79539603aa 100644 --- a/host/main.cpp +++ b/host/main.cpp @@ -18,14 +18,12 @@ namespace Cmdline << "- all additional parameters at the end of the command line are forwarded" << std::endl << " to the Main function in the assembly" << std::endl << "- the host will execute the Main function in the specified assembly" << std::endl - << " + this assembly has to be located in the search path" << std::endl - << "- the host will add $PWRSH_ROOT to the assembly search path" << std::endl + << " + this must be an absolute path to the assembly" << std::endl << "- the function signature of the Main function that gets executed must be:" << std::endl << " static void Main(string[] args)" << std::endl << std::endl << "Options:" << std::endl << "-v verbose output" << std::endl - << "assembly the path of the assembly to execute relative to current directory" << std::endl << std::endl << "Example:" << std::endl << "CORE_ROOT=/test/coreclr PWRSH_ROOT=/test/powershell ./host_cmdline -s /test/ps powershell-simple 'get-process'" << std::endl; @@ -40,7 +38,6 @@ namespace Cmdline { } - std::string searchPaths; std::string entryAssemblyPath; int argc; char** argv; @@ -118,9 +115,6 @@ int main(int argc, char** argv) if (args.verbose) args.debugPrint(); - // get the absolute path of the current directory - std::string cwd(getcwd(nullptr, 0)); - void* hostHandle; unsigned int domainId; int status = startCoreCLR( @@ -139,7 +133,7 @@ int main(int argc, char** argv) executeAssembly( hostHandle, domainId, args.argc, (const char**)args.argv, - (cwd + "/" + args.entryAssemblyPath).c_str(), + args.entryAssemblyPath.c_str(), &exitCode); status = stopCoreCLR(hostHandle, domainId); From 18a047408def7e86e45473c33c9e15160222c12d Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Mon, 26 Oct 2015 12:08:16 -0700 Subject: [PATCH 242/298] Compile pshost with -fPIC So that libpshost can be linked with shared libraries (like the OMI provider). --- host/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index a44effc5f8..7d472915da 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -1,5 +1,6 @@ add_library(pshost STATIC coreclrutil.cpp) target_link_libraries(pshost dl icuuc) +target_compile_options(pshost PRIVATE -fPIC) add_executable(powershell main.cpp) target_link_libraries(powershell pshost) From 845c4483b64d1939a6f93340554b6bc44df36661 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Tue, 27 Oct 2015 09:19:41 -0700 Subject: [PATCH 243/298] Simpliefied GetComputerName --- native/getcomputername.cpp | 82 +++-------------------- native/getcomputername.h | 4 +- tests/test-getcomputername.cpp | 117 ++------------------------------- 3 files changed, 16 insertions(+), 187 deletions(-) diff --git a/native/getcomputername.cpp b/native/getcomputername.cpp index 818623ddfe..6c5f8853a9 100644 --- a/native/getcomputername.cpp +++ b/native/getcomputername.cpp @@ -7,69 +7,24 @@ #include #include #include -#include +#include #include "getcomputername.h" //! @brief GetComputerName retrieves the name of the host associated with //! the current thread. //! -//! GetComputerNameW is the Unicode variation. See [MSDN documentation]. -//! -//! @param[out] lpBuffer -//! @parblock -//! A pointer to the buffer to receive the hosts's -//! name. If this buffer is not large enough to contain the -//! entire user hosts name, the function fails. -//! -//! WCHAR_T* is a Unicode [LPTSTR]. -//! @endparblock -//! -//! @param[in, out] lpnSize -//! @parblock -//! On input, this variable specifies the size of the lpBuffer buffer, -//! in TCHARs. On output, the variable receives the number of TCHARs -//! copied to the buffer, including the terminating null character. -//! -//! TCHAR is a Unicode 16-bit [WCHAR]. -//! -//! If lpBuffer is too small, the function fails and GetLastError -//! returns ERROR_INSUFFICIENT_BUFFER. This parameter receives the -//! required buffer size, including the terminating null character. -//! @endparblock -//! //! @exception errno Passes these errors via errno to GetLastError: -//! - ERROR_INVALID_PARAMETER: parameter is not valid //! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 -//! - ERROR_TOO_MANY_OPEN_FILES: already have the maximum allowed number of open files -//! - ERROR_NO_ASSOCIATION: calling process has no controlling terminal -//! - ERROR_INSUFFICIENT_BUFFER: buffer not large enough to hold username string -//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file -//! - ERROR_OUTOFMEMORY: insufficient memory to allocate passwd structure -//! - ERROR_NO_ASSOCIATION: standard input didn't refer to a terminal //! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code +//! - ERROR_INVALID_ADDRESS: buffer is an invalid address +//! - ERROR_GEN_FAILURE: buffer not large enough //! -//! @retval TRUE If the function succeeds, the return value is a nonzero -//! value, and the variable pointed to by lpnSize contains the number -//! of TCHARs copied to the buffer specified by lpBuffer, including -//! the terminating null character. -//! -//! @retval FALSE If the function fails, the return value is zero. To get -//! extended error information, call GetLastError. -//! -//! [MSDN documentation]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724295%28v=vs.85%29.aspx -//! [WCHAR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#WCHAR -//! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR -BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) +//! @retval username as UTF-8 string, or null if unsuccessful + +char* GetComputerNameW() { errno = 0; - // Check parameters - if (!lpBuffer || !lpnSize) - { - errno = ERROR_INVALID_PARAMETER; - return FALSE; - } - // Select locale from environment setlocale(LC_ALL, ""); // Check that locale is UTF-8 @@ -99,29 +54,8 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize) return FALSE; } - // Convert to UnicodeString - auto computername16 = icu::UnicodeString::fromUTF8(computername.c_str()); - // Terminate string with null - computername16.append('\0'); - - // Size in WCHARs including null - const DWORD size = computername16.length(); - - //Check if parameters passed enough buffer space - if (size > *lpnSize) - { - errno = ERROR_INSUFFICIENT_BUFFER; - // Set lpnSize if buffer is too small to inform user - // of necessary size - *lpnSize= size; - return FALSE; - } - - // Extract string as UTF-16LE to buffer - computername16.extract(0, size, reinterpret_cast(lpBuffer), "UTF-16LE"); - - *lpnSize = size; - return TRUE; + std::cerr << "GetComputerName: " << computername.c_str() << std::endl; + return strdup(computername.c_str()); } diff --git a/native/getcomputername.h b/native/getcomputername.h index 8d39d3f9fa..b760b6c5a0 100644 --- a/native/getcomputername.h +++ b/native/getcomputername.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize); +char* GetComputerNameW(); -PAL_END_EXTERNC \ No newline at end of file +PAL_END_EXTERNC diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index 51ebd0cccf..9ee3a6f823 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -3,132 +3,27 @@ //! @brief Unit tests for GetComputerNameW #include -#include -#include #include #include -#include #include "getcomputername.h" //! Test fixture for GetComputerNameTest class GetComputerNameTest : public ::testing::Test { protected: - DWORD lpnSize; - std::vector lpBuffer; - BOOL result; - std::string expectedComputerName; - DWORD expectedSize; + char expectedComputerName[HOST_NAME_MAX]; //Get expected result from using linux call GetComputerNameTest() { - expectedComputerName.resize(HOST_NAME_MAX); - BOOL ret = gethostname(&expectedComputerName[0], expectedComputerName.length()); + BOOL ret = gethostname(expectedComputerName, HOST_NAME_MAX); EXPECT_EQ(0, ret); - expectedSize = std::strlen(expectedComputerName.c_str()) + 1; - expectedComputerName.resize(expectedSize - 1); - } - - //! Invokes GetComputerNameW with lpnSize and lpBuffer, saves result. - //! - //! @param size Assigns to lpnSize and allocates lpBuffer with - //! size number of null characters. - void TestWithSize(DWORD size) - { - lpnSize = size; - lpBuffer.assign(lpnSize, 0); - result = GetComputerNameW(&lpBuffer[0], &lpnSize); - } - - void TestSuccess() - { - SCOPED_TRACE(""); - - //! Returns TRUE on success. - EXPECT_EQ(TRUE, result); - - //! Sets lpnSize to number of WCHARs including null. - ASSERT_EQ(expectedSize, lpnSize); - - // Read lpBuffer into UnicodeString (without null) - const char* begin = reinterpret_cast(&lpBuffer[0]); - icu::UnicodeString computername16(begin, (lpnSize-1)*sizeof(UChar), "UTF-16LE"); - // Convert to UTF-8 for comparison - std::string computername; - computername16.toUTF8String(computername); - - ASSERT_EQ(expectedSize, computername.length() + 1); - - //! Returned computername(after conversion) is what was expected. - EXPECT_EQ(expectedComputerName, computername); - } - - void TestInvalidParameter() - { - SCOPED_TRACE(""); - - // returns FALSE on failure - EXPECT_EQ(FALSE, result); - - // sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null - EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); - } - - void TestInsufficientBuffer() - { - SCOPED_TRACE(""); - - // returns FALSE on failure - EXPECT_EQ(FALSE, result); - - // sets errno to ERROR_INSUFFICIENT_BUFFER - EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER); - - // sets lpnSize to length of username + null - ASSERT_EQ(expectedSize, lpnSize); + std::cout << "Expected Name:" << expectedComputerName << std::endl; } }; -TEST_F(GetComputerNameTest, BufferAsNullButNotBufferSize) +TEST_F(GetComputerNameTest, Success) { - lpnSize = 1; - result = GetComputerNameW(NULL, &lpnSize); - TestInvalidParameter(); - // does not reset lpnSize - EXPECT_EQ(1, lpnSize); + std::cout << "Actual Name:" << GetComputerNameW() << std::endl; + ASSERT_STREQ(GetComputerNameW(), expectedComputerName); } - -TEST_F(GetComputerNameTest, BufferSizeAsNullButNotBuffer) -{ - lpBuffer.push_back('\0'); - result = GetComputerNameW(&lpBuffer[0], NULL); - TestInvalidParameter(); -} - -TEST_F(GetComputerNameTest, BufferSizeAsZero) -{ - TestWithSize(0); - EXPECT_EQ(errno, ERROR_INVALID_PARAMETER); -} - -TEST_F(GetComputerNameTest, BufferSizeAsUserNameMinusOne) -{ - // the buffer is also too small - TestWithSize(expectedSize-1); - TestInsufficientBuffer(); -} - -TEST_F(GetComputerNameTest, BufferSizeAsUserNamePlusOne) -{ - // the buffer is exactly big enough - TestWithSize(expectedSize+1); - TestSuccess(); -} - -TEST_F(GetComputerNameTest, BufferSizeAsLoginNameMax) -{ - // the buffer larger than needed - TestWithSize(HOST_NAME_MAX); - TestSuccess(); -} \ No newline at end of file From 9718cd02abad03143711fa56979c33e8691e2276 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Tue, 27 Oct 2015 10:48:31 -0700 Subject: [PATCH 244/298] Remove W suffix of native function --- native/getcomputername.cpp | 2 +- native/getcomputername.h | 2 +- tests/test-getcomputername.cpp | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/native/getcomputername.cpp b/native/getcomputername.cpp index 6c5f8853a9..47fc634d3d 100644 --- a/native/getcomputername.cpp +++ b/native/getcomputername.cpp @@ -21,7 +21,7 @@ //! //! @retval username as UTF-8 string, or null if unsuccessful -char* GetComputerNameW() +char* GetComputerName() { errno = 0; diff --git a/native/getcomputername.h b/native/getcomputername.h index b760b6c5a0..66b0c352b3 100644 --- a/native/getcomputername.h +++ b/native/getcomputername.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -char* GetComputerNameW(); +char* GetComputerName(); PAL_END_EXTERNC diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index 9ee3a6f823..961cee7963 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -18,12 +18,10 @@ protected: { BOOL ret = gethostname(expectedComputerName, HOST_NAME_MAX); EXPECT_EQ(0, ret); - std::cout << "Expected Name:" << expectedComputerName << std::endl; } }; TEST_F(GetComputerNameTest, Success) { - std::cout << "Actual Name:" << GetComputerNameW() << std::endl; - ASSERT_STREQ(GetComputerNameW(), expectedComputerName); + ASSERT_STREQ(GetComputerName(), expectedComputerName); } From b7260951f1b2066885d738a0098ffa5b55be3154 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Tue, 27 Oct 2015 10:55:27 -0700 Subject: [PATCH 245/298] Remove debug output --- native/getcomputername.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/native/getcomputername.cpp b/native/getcomputername.cpp index 47fc634d3d..68fd89953f 100644 --- a/native/getcomputername.cpp +++ b/native/getcomputername.cpp @@ -54,7 +54,6 @@ char* GetComputerName() return FALSE; } - std::cerr << "GetComputerName: " << computername.c_str() << std::endl; return strdup(computername.c_str()); } From 81f833cf2531d81c5ce2511570a3b338fd0b911b Mon Sep 17 00:00:00 2001 From: George Fleming Date: Tue, 27 Oct 2015 10:57:02 -0700 Subject: [PATCH 246/298] Remove --- native/getcomputername.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/native/getcomputername.cpp b/native/getcomputername.cpp index 68fd89953f..0c8ac06a0e 100644 --- a/native/getcomputername.cpp +++ b/native/getcomputername.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include "getcomputername.h" //! @brief GetComputerName retrieves the name of the host associated with From 7f6a494bf0103bd43d66315ed7ca35d972bab1de Mon Sep 17 00:00:00 2001 From: George Fleming Date: Tue, 27 Oct 2015 14:21:25 -0700 Subject: [PATCH 247/298] Modify return value --- native/getcomputername.cpp | 4 ++-- native/getusername.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/native/getcomputername.cpp b/native/getcomputername.cpp index 0c8ac06a0e..51f1cf5bf6 100644 --- a/native/getcomputername.cpp +++ b/native/getcomputername.cpp @@ -30,7 +30,7 @@ char* GetComputerName() if (nl_langinfo(CODESET) != std::string("UTF-8")) { errno = ERROR_BAD_ENVIRONMENT; - return FALSE; + return NULL; } // Get computername from system in a thread-safe manner @@ -50,7 +50,7 @@ char* GetComputerName() default: errno = ERROR_INVALID_FUNCTION; } - return FALSE; + return NULL; } return strdup(computername.c_str()); diff --git a/native/getusername.cpp b/native/getusername.cpp index a4590bfde9..30c2b8a149 100644 --- a/native/getusername.cpp +++ b/native/getusername.cpp @@ -41,7 +41,7 @@ char* GetUserName() if (buflen == -1) { errno = ERROR_GEN_FAILURE; - return FALSE; + return NULL; } std::string buf(buflen, 0); From 11bcfb06d38fd743f535ade424ce4b0d43cf3953 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Tue, 27 Oct 2015 14:56:57 -0700 Subject: [PATCH 248/298] Add GetFullyQualifiedName() --- native/CMakeLists.txt | 1 + native/getfullyqualifiedname.cpp | 57 ++++++++++++++++++++++++++++++++ native/getfullyqualifiedname.h | 9 +++++ native/pal.h | 1 + 4 files changed, 68 insertions(+) create mode 100644 native/getfullyqualifiedname.cpp create mode 100644 native/getfullyqualifiedname.h diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index c2523c3a3f..76682aa849 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(psnative SHARED getusername.cpp getcomputername.cpp getlinkcount.cpp + getfullyqualifiedname.cpp terminal.cpp) target_link_libraries(psnative icuuc) diff --git a/native/getfullyqualifiedname.cpp b/native/getfullyqualifiedname.cpp new file mode 100644 index 0000000000..936127f468 --- /dev/null +++ b/native/getfullyqualifiedname.cpp @@ -0,0 +1,57 @@ +//! @file getfullyqualifiedname.cpp +//! @author George Fleming +//! @brief Implements GetFullyQualifiedName on Linux + +#include +#include +#include +#include +#include "getfullyqualifiedname.h" + +extern char* GetComputerName(); + +//! @brief GetFullyQualifiedName retrieves the full name of the host associated with +//! the current thread. +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 +//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code +//! - ERROR_INVALID_ADDRESS: buffer is an invalid address +//! - ERROR_GEN_FAILURE: buffer not large enough +//! - ERROR_BAD_NET_NAME: Cannot determine network short name +//! +//! @retval username as UTF-8 string, or null if unsuccessful + +char* GetFullyQualifiedName() +{ + errno = 0; + + char *computerName = GetComputerName(); + if (NULL == computerName) + { + return NULL; + } + + struct addrinfo hints, *info; + int gai_result; + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; /*either IPV4 or IPV6*/ + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + + if ((gai_result = getaddrinfo(computerName, "http", &hints, &info)) != 0) + { + errno = ERROR_BAD_NET_NAME; + return NULL; + } + + // info is actually a link-list. We'll just return the first full name + + char *fullName = strdup(info->ai_canonname); + + freeaddrinfo(info); + free(computerName); + return fullName; +} + diff --git a/native/getfullyqualifiedname.h b/native/getfullyqualifiedname.h new file mode 100644 index 0000000000..4db1fd2e76 --- /dev/null +++ b/native/getfullyqualifiedname.h @@ -0,0 +1,9 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +char* GetFullyQualifiedName(); + +PAL_END_EXTERNC diff --git a/native/pal.h b/native/pal.h index c53c985a8c..d74f52d717 100644 --- a/native/pal.h +++ b/native/pal.h @@ -88,6 +88,7 @@ #define ERROR_BUFFER_OVERFLOW 0x0000006F #define ERROR_FILE_NOT_FOUND 0x00000002 #define ERROR_BAD_PATH_NAME 0x000000A1 + #define ERROR_BAD_NET_NAME 0x00000043 typedef unsigned long long uint64; #endif From 1759f9a2f6d7c3b83acfd8aff5163a8529e6d124 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Tue, 27 Oct 2015 15:33:25 -0700 Subject: [PATCH 249/298] Changes per Zack comments --- native/getcomputername.cpp | 2 +- tests/test-getcomputername.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/native/getcomputername.cpp b/native/getcomputername.cpp index 51f1cf5bf6..3d4e7eda3e 100644 --- a/native/getcomputername.cpp +++ b/native/getcomputername.cpp @@ -1,5 +1,5 @@ //! @file getcomputername.cpp -//! @author Aaron Katz +//! @author George Fleming //! @brief Implements GetComputerName Win32 API #include diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index 961cee7963..c783ff003e 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -1,6 +1,6 @@ //! @file test-getcomputername.cpp -//! @author Aaron Katz -//! @brief Unit tests for GetComputerNameW +//! @author George Fleming +//! @brief Unit tests for GetComputerName #include #include @@ -21,7 +21,7 @@ protected: } }; -TEST_F(GetComputerNameTest, Success) +TEST_F(GetComputerNameTest, ValidateLinuxGetHostnameSystemCall) { ASSERT_STREQ(GetComputerName(), expectedComputerName); } From e776d01cc8f4e9b1297f527c0e27c3f3a4f2125c Mon Sep 17 00:00:00 2001 From: George Fleming Date: Tue, 27 Oct 2015 16:43:43 -0700 Subject: [PATCH 250/298] Change reference of GetComputerName --- native/getfullyqualifiedname.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/native/getfullyqualifiedname.cpp b/native/getfullyqualifiedname.cpp index 936127f468..a4e98a664e 100644 --- a/native/getfullyqualifiedname.cpp +++ b/native/getfullyqualifiedname.cpp @@ -6,10 +6,9 @@ #include #include #include +#include "getcomputername.h" #include "getfullyqualifiedname.h" -extern char* GetComputerName(); - //! @brief GetFullyQualifiedName retrieves the full name of the host associated with //! the current thread. //! From 4d2b184892793b3a1849ac1265b27a6d89a2104d Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 27 Oct 2015 23:21:44 -0700 Subject: [PATCH 251/298] Add sensible defaults for powershell and coreclr --- host/coreclrutil.cpp | 53 ++++++++++++++++++++++++++++++++++---------- host/main.cpp | 7 +++--- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/host/coreclrutil.cpp b/host/coreclrutil.cpp index d53433e3bf..eabd73f042 100644 --- a/host/coreclrutil.cpp +++ b/host/coreclrutil.cpp @@ -18,6 +18,7 @@ constexpr char coreClrDll[] = "libcoreclr.so"; #endif void* coreclrLib; +char exePath[PATH_MAX]; // Prototype of the coreclr_initialize function from the libcoreclr.so typedef int (*InitializeCoreCLRFunction)( @@ -78,24 +79,53 @@ bool GetDirectory(const char* absolutePath, std::string& directory) // // Return true in case of a success, false otherwise. // -bool GetEnvAbsolutePath(const char* env_var, std::string& absolutePath) +bool GetEnvAbsolutePath(const char* envVar, std::string& absolutePath) { - const char* filesPathLocal = std::getenv(env_var);; + const char* filesPathLocal = std::getenv(envVar);; if (filesPathLocal == nullptr) { - std::cerr << "failed because $" << env_var << " was empty" << std::endl; return false; } - if (!GetAbsolutePath(filesPathLocal, absolutePath)) + return GetAbsolutePath(filesPathLocal, absolutePath); +} + +// +// Get the a root path given an environment variable and default +// relative to exePath +// +bool GetRootPath(const char* envVar, + const char* relativePath, + std::string& absolutePath) +{ + if (!GetEnvAbsolutePath(envVar, absolutePath)) { - std::cerr << "failed to get absolute path for " << env_var << std::endl; - return false; + // Default to bin/relativePath + std::string path; + if (!GetDirectory(exePath, path)) + { + return false; + } + path.append("/"); + path.append(relativePath); + return GetAbsolutePath(path.c_str(), absolutePath); } return true; } +// Get the PowerShell root path, with sensible default +bool GetPwrshRoot(std::string& absolutePath) +{ + return GetRootPath("PWRSH_ROOT", "../lib/powershell", absolutePath); +} + +// Get the CoreCLR root path, with sensible default +bool GetCoreRoot(std::string& absolutePath) +{ + return GetRootPath("CORE_ROOT", "../lib/coreclr", absolutePath); +} + // Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) { @@ -198,9 +228,12 @@ int startCoreCLR( void** hostHandle, unsigned int* domainId) { + // get path to current executable + readlink("/proc/self/exe", exePath, PATH_MAX); + // get the CoreCLR root path std::string clrAbsolutePath; - if(!GetEnvAbsolutePath("CORE_ROOT", clrAbsolutePath)) + if(!GetCoreRoot(clrAbsolutePath)) { return -1; } @@ -254,7 +287,7 @@ int startCoreCLR( // get path to AssemblyLoadContext.dll std::string psAbsolutePath; - if(!GetEnvAbsolutePath("PWRSH_ROOT", psAbsolutePath)) + if(!GetPwrshRoot(psAbsolutePath)) { return -1; } @@ -290,10 +323,6 @@ int startCoreCLR( "UseLatestBehaviorWhenTFMNotSpecified" }; - // get path to current executable - char exePath[PATH_MAX] = { 0 }; - readlink("/proc/self/exe", exePath, PATH_MAX); - // initialize CoreCLR int status = initializeCoreCLR( exePath, diff --git a/host/main.cpp b/host/main.cpp index 79539603aa..0b7728d4e7 100644 --- a/host/main.cpp +++ b/host/main.cpp @@ -11,10 +11,11 @@ namespace Cmdline << "Usage: powershell assembly [...]" << std::endl << std::endl << "What it does:" << std::endl - << "- the host assumes that CoreCLR is located $CORE_ROOT" << std::endl + << "- the host assumes that CoreCLR is located $CORE_ROOT," << std::endl + << " else in lib/coreclr" << "- the host assumes that the assembly named" << std::endl << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is " << std::endl - << " located in $PWRSH_ROOT" << std::endl + << " located in $PWRSH_ROOT, else in lib/powershell" << std::endl << "- all additional parameters at the end of the command line are forwarded" << std::endl << " to the Main function in the assembly" << std::endl << "- the host will execute the Main function in the specified assembly" << std::endl @@ -26,7 +27,7 @@ namespace Cmdline << "-v verbose output" << std::endl << std::endl << "Example:" << std::endl - << "CORE_ROOT=/test/coreclr PWRSH_ROOT=/test/powershell ./host_cmdline -s /test/ps powershell-simple 'get-process'" << std::endl; + << "CORE_ROOT=/test/coreclr PWRSH_ROOT=/test/powershell ./powershell powershell-simple 'get-process'" << std::endl; } struct Args From 29d496e3ac26030ee06d2661d6fc695910546a89 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Wed, 28 Oct 2015 10:24:43 -0700 Subject: [PATCH 252/298] Adding additional comments --- native/getfullyqualifiedname.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/native/getfullyqualifiedname.cpp b/native/getfullyqualifiedname.cpp index a4e98a664e..7e5831e6db 100644 --- a/native/getfullyqualifiedname.cpp +++ b/native/getfullyqualifiedname.cpp @@ -9,17 +9,20 @@ #include "getcomputername.h" #include "getfullyqualifiedname.h" -//! @brief GetFullyQualifiedName retrieves the full name of the host associated with -//! the current thread. +//! @brief GetFullyQualifiedName retrieves the fully qualifed dns name of the host //! //! @exception errno Passes these errors via errno to GetLastError: -//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 -//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code -//! - ERROR_INVALID_ADDRESS: buffer is an invalid address -//! - ERROR_GEN_FAILURE: buffer not large enough +//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 (from GetComputerName) +//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code (from GetComputerName) +//! - ERROR_INVALID_ADDRESS: buffer is an invalid address (from GetComputerName) +//! - ERROR_GEN_FAILURE: buffer not large enough (from GetComputerName) //! - ERROR_BAD_NET_NAME: Cannot determine network short name //! //! @retval username as UTF-8 string, or null if unsuccessful +//! +//! Note on testing: Since there's no easy way to override the domain name, no unit testing will be +//! provided. Instead, manual end-to-end testing should be done to verify domain name matches expected +//! value. char* GetFullyQualifiedName() { @@ -39,6 +42,12 @@ char* GetFullyQualifiedName() hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; + /* There are several ways to get the domain name: + * uname(2), gethostbyname(3), resolver(3), getdomainname(2), + * and getaddrinfo(3). Some of these are not portable, some aren't + * POSIX compliant, and some are being deprecated. Getaddrinfo seems + * to be the best choice right now. + */ if ((gai_result = getaddrinfo(computerName, "http", &hints, &info)) != 0) { errno = ERROR_BAD_NET_NAME; From 2d442eb73279a24638e63c4a82344de5717e5a70 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Wed, 28 Oct 2015 16:41:24 -0700 Subject: [PATCH 253/298] Skip getaddrinfo if hostname is already FQDN --- native/getfullyqualifiedname.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/native/getfullyqualifiedname.cpp b/native/getfullyqualifiedname.cpp index 7e5831e6db..5d711c2f39 100644 --- a/native/getfullyqualifiedname.cpp +++ b/native/getfullyqualifiedname.cpp @@ -20,9 +20,6 @@ //! //! @retval username as UTF-8 string, or null if unsuccessful //! -//! Note on testing: Since there's no easy way to override the domain name, no unit testing will be -//! provided. Instead, manual end-to-end testing should be done to verify domain name matches expected -//! value. char* GetFullyQualifiedName() { @@ -34,6 +31,11 @@ char* GetFullyQualifiedName() return NULL; } + if (strchr(computerName, '.') != NULL) + { + return computerName; + } + struct addrinfo hints, *info; int gai_result; From 2eaf911346212bd4fdec64d64ea2a562fa2a8d18 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Wed, 28 Oct 2015 16:42:15 -0700 Subject: [PATCH 254/298] Add new getfullyqualifiedname test --- tests/CMakeLists.txt | 1 + tests/test-getfullyqualifiedname.cpp | 35 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/test-getfullyqualifiedname.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c9630dda17..3dfb4fdd48 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,6 +5,7 @@ add_executable(psnative-test test-getusername.cpp test-getcomputername.cpp test-getlinkcount.cpp + test-getfullyqualifiedname.cpp main.cpp) # manually include gtest headers diff --git a/tests/test-getfullyqualifiedname.cpp b/tests/test-getfullyqualifiedname.cpp new file mode 100644 index 0000000000..484fd8d653 --- /dev/null +++ b/tests/test-getfullyqualifiedname.cpp @@ -0,0 +1,35 @@ +//! @file test-getfullyqualifiedname.cpp +//! @author George Fleming +//! @brief Unit tests for GetFullyQualifiedName + +#include +#include +#include "getfullyqualifiedname.h" + +//! Test fixture for GetComputerNameTest +class GetFullyQualifiedNameTest : public ::testing::Test +{ +}; + +TEST_F(GetFullyQualifiedNameTest, ValidateLinuxGetFullyQualifiedDomainName) +{ + char expectedComputerName[HOST_NAME_MAX]; + + //Get expected result from using linux command + + FILE *fPtr = popen("/bin/hostname --fqdn", "r"); + ASSERT_TRUE(fPtr != NULL); + + char *linePtr = fgets(expectedComputerName, sizeof(expectedComputerName), fPtr); + ASSERT_TRUE(linePtr != NULL); + + // There's a tendency to have \n at end of fgets string, so remove it before compare + size_t sz = strlen(expectedComputerName); + if (sz > 0 && expectedComputerName[sz - 1] == '\n') + { + expectedComputerName[sz - 1] = '\0'; + } + pclose(fPtr); + + ASSERT_STREQ(GetFullyQualifiedName(), expectedComputerName); +} From 3a02f1b3a00dc0b3764d77f429825559fcf0ecc0 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Thu, 29 Oct 2015 08:47:36 -0700 Subject: [PATCH 255/298] Change /bin/hostname to just hostname, and let sh figure out the path --- tests/test-getfullyqualifiedname.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-getfullyqualifiedname.cpp b/tests/test-getfullyqualifiedname.cpp index 484fd8d653..9ec01e27f9 100644 --- a/tests/test-getfullyqualifiedname.cpp +++ b/tests/test-getfullyqualifiedname.cpp @@ -17,7 +17,7 @@ TEST_F(GetFullyQualifiedNameTest, ValidateLinuxGetFullyQualifiedDomainName) //Get expected result from using linux command - FILE *fPtr = popen("/bin/hostname --fqdn", "r"); + FILE *fPtr = popen("hostname --fqdn", "r"); ASSERT_TRUE(fPtr != NULL); char *linePtr = fgets(expectedComputerName, sizeof(expectedComputerName), fPtr); From 2de4fe9be6ad791a5e406bf98efd7ec3d5258c01 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Fri, 30 Oct 2015 11:47:44 -0700 Subject: [PATCH 256/298] Adding new isSymLink() function --- native/CMakeLists.txt | 1 + native/issymlink.cpp | 108 +++++++++++++++++++++++++++++++++++++++ native/issymlink.h | 9 ++++ tests/CMakeLists.txt | 1 + tests/test-issymlink.cpp | 104 +++++++++++++++++++++++++++++++++++++ 5 files changed, 223 insertions(+) create mode 100644 native/issymlink.cpp create mode 100644 native/issymlink.h create mode 100644 tests/test-issymlink.cpp diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index 76682aa849..1b57c13d23 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -4,6 +4,7 @@ add_library(psnative SHARED getcomputername.cpp getlinkcount.cpp getfullyqualifiedname.cpp + issymlink.cpp terminal.cpp) target_link_libraries(psnative icuuc) diff --git a/native/issymlink.cpp b/native/issymlink.cpp new file mode 100644 index 0000000000..0d3a1f387d --- /dev/null +++ b/native/issymlink.cpp @@ -0,0 +1,108 @@ +//! @file isSymLink.cpp +//! @author George FLeming +//! @brief returns whether a path is a symbolic link + +#include +#include +#include +#include +#include +#include +#include +#include +#include "issymlink.h" + +//! @brief IsSymLink determines if path is a symbolic link +//! +//! IsSymLink +//! +//! @param[in] fileName +//! @parblock +//! A pointer to the buffer that contains the file name +//! +//! char* is marshaled as an LPStr, which on Linux is UTF-8. +//! @endparblock +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_INVALID_PARAMETER: parameter is not valid +//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 +//! - ERROR_FILE_NOT_FOUND: file does not exist +//! - ERROR_ACCESS_DENIED: access is denied +//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified +//! - ERROR_INVALID_ADDRESS: attempt to access invalid address +//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link +//! - ERROR_GEN_FAILURE: device attached to the system is not functioning +//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file +//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect +//! - ERROR_BUFFER_OVERFLOW: file name is too long +//! - ERROR_INVALID_FUNCTION: incorrect function +//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters +//! +//! @retval 1 if path is a symbolic link +//! @retval 0 if path is not a symbolic link +//! @retval -1 If the function fails.. To get extended error information, call GetLastError. +//! + +long IsSymLink(const char* fileName) +{ + errno = 0; + + // Check parameters + if (!fileName) + { + errno = ERROR_INVALID_PARAMETER; + return -1; + } + + // Select locale from environment + setlocale(LC_ALL, ""); + // Check that locale is UTF-8 + if (nl_langinfo(CODESET) != std::string("UTF-8")) + { + errno = ERROR_BAD_ENVIRONMENT; + return -1; + } + + struct stat statBuf; + + int returnCode = lstat(fileName, &statBuf); + + if (returnCode != 0) + { + switch(errno) + { + case EACCES: + errno = ERROR_ACCESS_DENIED; + break; + case EBADF: + errno = ERROR_FILE_NOT_FOUND; + break; + case EFAULT: + errno = ERROR_INVALID_ADDRESS; + break; + case ELOOP: + errno = ERROR_STOPPED_ON_SYMLINK; + break; + case ENAMETOOLONG: + errno = ERROR_GEN_FAILURE; + break; + case ENOENT: + errno = ERROR_FILE_NOT_FOUND; + break; + case ENOMEM: + errno = ERROR_NO_SUCH_USER; + break; + case ENOTDIR: + errno = ERROR_INVALID_NAME; + break; + case EOVERFLOW: + errno = ERROR_BUFFER_OVERFLOW; + break; + default: + errno = ERROR_INVALID_FUNCTION; + } + return -1; + } + + return S_ISLNK(statBuf.st_mode) ? 1 : 0; +} diff --git a/native/issymlink.h b/native/issymlink.h new file mode 100644 index 0000000000..3ba5e48ac7 --- /dev/null +++ b/native/issymlink.h @@ -0,0 +1,9 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +long IsSymLink(const char* fileName); + +PAL_END_EXTERNC diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3dfb4fdd48..b9bba62a2e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,6 +6,7 @@ add_executable(psnative-test test-getcomputername.cpp test-getlinkcount.cpp test-getfullyqualifiedname.cpp + test-issymlink.cpp main.cpp) # manually include gtest headers diff --git a/tests/test-issymlink.cpp b/tests/test-issymlink.cpp new file mode 100644 index 0000000000..41515fbc38 --- /dev/null +++ b/tests/test-issymlink.cpp @@ -0,0 +1,104 @@ +//! @file test-issymlink.cpp +//! @author George Fleming +//! @brief Implements test for isSymLink() + +#include +#include +#include +#include "issymlink.h" + +using namespace std; + +class isSymLinkTest : public ::testing::Test +{ +protected: + + static const int bufSize = 64; + const string fileTemplate = "/tmp/symlinktest.fXXXXXXX"; + const string dirTemplate = "/tmp/symlinktest.dXXXXXXX"; + const string fileSymLink = "/tmp/symlinktest.flink"; + const string dirSymLink = "/tmp/symlinktest.dlink"; + char *file, *dir; + char fileTemplateBuf[bufSize], dirTemplateBuf[bufSize]; + + isSymLinkTest() + { + // since mkstemp and mkdtemp modifies the template string, let's give them writable buffers + strcpy(fileTemplateBuf, fileTemplate.c_str()); + strcpy(dirTemplateBuf, dirTemplate.c_str()); + + // First create a file + int fd = mkstemp(fileTemplateBuf); + EXPECT_TRUE(fd != -1); + file = fileTemplateBuf; + + // Create a temp directory + dir = mkdtemp(dirTemplateBuf); + EXPECT_TRUE(dir != NULL); + + // Create symbolic link to file + int ret1 = symlink(file, fileSymLink.c_str()); + EXPECT_EQ(ret1, 0); + + // Create symbolic link to directory + int ret2 = symlink(dir, dirSymLink.c_str()); + EXPECT_EQ(ret2, 0); + } + + ~isSymLinkTest() + { + int ret; + + ret = unlink(fileSymLink.c_str()); + EXPECT_EQ(0, ret); + + ret = unlink(dirSymLink.c_str()); + EXPECT_EQ(0, ret); + + ret = unlink(file); + EXPECT_EQ(0, ret); + + ret = rmdir(dir); + EXPECT_EQ(0, ret); + } +}; + +TEST_F(isSymLinkTest, FilePathNameIsNull) +{ + int retVal = IsSymLink(NULL); + EXPECT_EQ(retVal, -1); + EXPECT_EQ(ERROR_INVALID_PARAMETER, errno); +} + +TEST_F(isSymLinkTest, FilePathNameDoesNotExist) +{ + std::string invalidFile = "/tmp/symlinktest_invalidFile"; + int retVal = IsSymLink(invalidFile.c_str()); + EXPECT_EQ(retVal, -1); + EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno); +} + +TEST_F(isSymLinkTest, NormalFileIsNotSymLink) +{ + int retVal = IsSymLink(file); + EXPECT_EQ(0, retVal); +} + +TEST_F(isSymLinkTest, SymLinkToFile) +{ + int retVal = IsSymLink(fileSymLink.c_str()); + EXPECT_EQ(1, retVal); +} + +TEST_F(isSymLinkTest, NormalDirectoryIsNotSymbLink) +{ + int retVal = IsSymLink(dir); + EXPECT_EQ(0, retVal); +} + +TEST_F(isSymLinkTest, SymLinkToDirectory) +{ + int retVal = IsSymLink(dirSymLink.c_str()); + EXPECT_EQ(1, retVal); +} + From 9bb5b7e52c3f1a18cac367c7fb7579406c6786fc Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 27 Oct 2015 17:01:23 -0700 Subject: [PATCH 257/298] Use `make install` target Instead of manually and always resolving to monad-linux/{bin,lib}, we use the CMake `install()` command to generate a `make install` target which places powershell, libpshost, and libpsnative in ${CMAKE_INSTALL_PREFIX}/{bin,lib} respectively. CMAKE_INSTALL_PREFIX defaults to `/usr/local` which we will want upon actual package installation. During development, we will override this to be the path to monad-linux in the superproject's Makefile. Also move test output so monad-native Jenkins job can pick it up. --- .gitignore | 4 ++++ CMakeLists.txt | 9 --------- host/CMakeLists.txt | 4 ++++ native/CMakeLists.txt | 3 +++ tests/CMakeLists.txt | 2 +- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index b4b9d12490..45177e796c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,7 @@ install_manifest.txt CTestTestfile.cmake Testing/ tests/psnative-test +host/powershell +host/libpshost.a +native/libpsnative.so +tests/native-tests.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index 51d4665de6..b61395b0c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,17 +3,8 @@ project(MONAD_NATIVE) add_compile_options(-std=c++11 -Wall) -# resolve superproject directory -set(MONAD ${CMAKE_SOURCE_DIR}/../../) - # test in BUILD_DIR enable_testing() add_subdirectory(tests) - -# output psnative and pshost to superproject -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${MONAD}/bin) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${MONAD}/lib) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${MONAD}/lib) - add_subdirectory(native) add_subdirectory(host) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 7d472915da..cdca0049d9 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -4,3 +4,7 @@ target_compile_options(pshost PRIVATE -fPIC) add_executable(powershell main.cpp) target_link_libraries(powershell pshost) + +install(TARGETS powershell pshost + RUNTIME DESTINATION bin + ARCHIVE DESTINATION lib) diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index 1b57c13d23..73a1dcdfe4 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -9,3 +9,6 @@ add_library(psnative SHARED target_link_libraries(psnative icuuc) target_include_directories (psnative PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +install(TARGETS psnative + LIBRARY DESTINATION lib) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b9bba62a2e..43918bee16 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,4 +15,4 @@ target_include_directories(psnative-test PRIVATE ${gtest_SOURCE_DIR}/include) target_link_libraries(psnative-test psnative gtest) add_test(NAME psnative-test - COMMAND psnative-test --gtest_output=xml:${MONAD}/native-tests.xml) + COMMAND psnative-test --gtest_output=xml:native-tests.xml) From 43f2d476f5027f9aa986def8af5f8a4749f4ff7b Mon Sep 17 00:00:00 2001 From: George Fleming Date: Mon, 2 Nov 2015 15:23:29 -0800 Subject: [PATCH 258/298] New IsExecutable function --- native/CMakeLists.txt | 1 + native/isexecutable.cpp | 99 +++++++++++++++++++++++++++++++++++++ native/isexecutable.h | 9 ++++ native/pal.h | 2 +- tests/CMakeLists.txt | 1 + tests/test-isexecutable.cpp | 94 +++++++++++++++++++++++++++++++++++ 6 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 native/isexecutable.cpp create mode 100644 native/isexecutable.h create mode 100644 tests/test-isexecutable.cpp diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index 73a1dcdfe4..9efaec93c2 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -5,6 +5,7 @@ add_library(psnative SHARED getlinkcount.cpp getfullyqualifiedname.cpp issymlink.cpp + isexecutable.cpp terminal.cpp) target_link_libraries(psnative icuuc) diff --git a/native/isexecutable.cpp b/native/isexecutable.cpp new file mode 100644 index 0000000000..dab5362954 --- /dev/null +++ b/native/isexecutable.cpp @@ -0,0 +1,99 @@ +//! @file isExecutable.cpp +//! @author George FLeming +//! @brief returns whether a path is executable + +#include +#include +#include +#include +#include +#include "isexecutable.h" + +//! @brief IsExecutable determines if path is executable +//! +//! IsExecutable +//! +//! @param[in] fileName +//! @parblock +//! A pointer to the buffer that contains the file name +//! +//! char* is marshaled as an LPStr, which on Linux is UTF-8. +//! @endparblock +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_INVALID_PARAMETER: parameter is not valid +//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 +//! - ERROR_FILE_NOT_FOUND: file does not exist +//! - ERROR_ACCESS_DENIED: access is denied +//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified +//! - ERROR_INVALID_ADDRESS: attempt to access invalid address +//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link +//! - ERROR_GEN_FAILURE: device attached to the system is not functioning +//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file +//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect +//! - ERROR_BUFFER_OVERFLOW: file name is too long +//! - ERROR_INVALID_FUNCTION: incorrect function +//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters +//! +//! @retval 1 if path is an executable +//! @retval 0 if path is not a executable +//! @retval -1 If the function fails.. To get extended error information, call GetLastError. +//! + +int32_t IsExecutable(const char* fileName) +{ + errno = 0; + + // Check parameters + if (!fileName) + { + errno = ERROR_INVALID_PARAMETER; + return -1; + } + + // Select locale from environment + setlocale(LC_ALL, ""); + // Check that locale is UTF-8 + if (nl_langinfo(CODESET) != std::string("UTF-8")) + { + errno = ERROR_BAD_ENVIRONMENT; + return -1; + } + + int returnCode = access(fileName, X_OK); + + if (returnCode == 0) + { + return 1; + } + + switch(errno) + { + case EACCES: + return 0; + case EBADF: + case ENOENT: + errno = ERROR_FILE_NOT_FOUND; + break; + case EFAULT: + errno = ERROR_INVALID_ADDRESS; + break; + case ELOOP: + errno = ERROR_STOPPED_ON_SYMLINK; + break; + case EIO: + case ENOMEM: + errno = ERROR_GEN_FAILURE; + break; + case ENOTDIR: + case ENAMETOOLONG: + errno = ERROR_INVALID_NAME; + break; + case EINVAL: + errno = ERROR_INVALID_PARAMETER; + break; + default: + errno = ERROR_INVALID_FUNCTION; + } + return -1; +} diff --git a/native/isexecutable.h b/native/isexecutable.h new file mode 100644 index 0000000000..da4e9f8f36 --- /dev/null +++ b/native/isexecutable.h @@ -0,0 +1,9 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +int32_t IsExecutable(const char* fileName); + +PAL_END_EXTERNC diff --git a/native/pal.h b/native/pal.h index d74f52d717..7df0b32bb4 100644 --- a/native/pal.h +++ b/native/pal.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #ifndef NAME_MAX # define NAME_MAX 255 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 43918bee16..a065c66c1d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,6 +7,7 @@ add_executable(psnative-test test-getlinkcount.cpp test-getfullyqualifiedname.cpp test-issymlink.cpp + test-isexecutable.cpp main.cpp) # manually include gtest headers diff --git a/tests/test-isexecutable.cpp b/tests/test-isexecutable.cpp new file mode 100644 index 0000000000..36955912ff --- /dev/null +++ b/tests/test-isexecutable.cpp @@ -0,0 +1,94 @@ +//! @file test-isexecutable.cpp +//! @author George Fleming +//! @brief Implements test for isexecutable() + +#include +#include +#include +#include +#include "isexecutable.h" + +using namespace std; + +class IsExecutableTest : public ::testing::Test +{ +protected: + + static const int bufSize = 64; + const string fileTemplate = "/tmp/isexecutabletest.fXXXXXXX"; + const mode_t mode_700 = S_IRUSR | S_IWUSR | S_IXUSR; + const mode_t mode_070 = S_IRGRP | S_IWGRP | S_IXGRP; + const mode_t mode_007 = S_IROTH | S_IWOTH | S_IXOTH; + const mode_t mode_777 = mode_700 | mode_070 | mode_007; + const mode_t mode_444 = S_IRUSR | S_IRGRP | S_IROTH; + + char *file; + char fileTemplateBuf[bufSize]; + + IsExecutableTest() + { + // since mkstemp modifies the template string, let's give it writable buffers + strcpy(fileTemplateBuf, fileTemplate.c_str()); + + // First create a file + int fd = mkstemp(fileTemplateBuf); + EXPECT_TRUE(fd != -1); + file = fileTemplateBuf; + } + + ~IsExecutableTest() + { + int ret; + + ret = unlink(file); + EXPECT_EQ(0, ret); + } + + void ChangeFilePermission(const char* file, mode_t mode) + { + int ret = chmod(file, mode); + EXPECT_EQ(ret, 0); + } +}; + +TEST_F(IsExecutableTest, FilePathNameIsNull) +{ + int32_t retVal = IsExecutable(NULL); + EXPECT_EQ(retVal, -1); + EXPECT_EQ(ERROR_INVALID_PARAMETER, errno); +} + +TEST_F(IsExecutableTest, FilePathNameDoesNotExist) +{ + std::string invalidFile = "/tmp/isexecutabletest_invalidFile"; + int32_t retVal = IsExecutable(invalidFile.c_str()); + EXPECT_EQ(retVal, -1); + EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno); +} + +TEST_F(IsExecutableTest, NormalFileIsNotIsexecutable) +{ + int32_t retVal = IsExecutable(file); + EXPECT_EQ(0, retVal); + + ChangeFilePermission(file, mode_444); + + retVal = IsExecutable(file); + EXPECT_EQ(0, retVal); +} + +TEST_F(IsExecutableTest, FilePermission_700) +{ + ChangeFilePermission(file, mode_700); + + int32_t retVal = IsExecutable(file); + EXPECT_EQ(1, retVal); +} + +TEST_F(IsExecutableTest, FilePermission_777) +{ + ChangeFilePermission(file, mode_777); + + int32_t retVal = IsExecutable(file); + EXPECT_EQ(1, retVal); +} From 8747ba1e4775565c28a1192ad2161b93510127ba Mon Sep 17 00:00:00 2001 From: George Fleming Date: Mon, 2 Nov 2015 16:40:28 -0800 Subject: [PATCH 259/298] Clean up of pal.h --- native/getcomputername.cpp | 2 +- native/getcurrentprocessorid.cpp | 6 +- native/getcurrentprocessorid.h | 2 +- native/getlinkcount.cpp | 13 +- native/getlinkcount.h | 2 +- native/issymlink.cpp | 2 +- native/pal.h | 577 +-------------------------- native/terminal.cpp | 4 +- native/terminal.h | 4 +- tests/test-getcomputername.cpp | 29 +- tests/test-getcurrentprocessid.cpp | 6 +- tests/test-getfullyqualifiedname.cpp | 3 +- tests/test-getlinkcount.cpp | 37 +- tests/test-issymlink.cpp | 4 +- 14 files changed, 81 insertions(+), 610 deletions(-) diff --git a/native/getcomputername.cpp b/native/getcomputername.cpp index 3d4e7eda3e..67e3d870dd 100644 --- a/native/getcomputername.cpp +++ b/native/getcomputername.cpp @@ -34,7 +34,7 @@ char* GetComputerName() } // Get computername from system in a thread-safe manner - std::string computername(HOST_NAME_MAX, 0); + std::string computername(NAME_MAX, 0); int err = gethostname(&computername[0], computername.length()); // Map errno to Win32 Error Codes if (err != 0) diff --git a/native/getcurrentprocessorid.cpp b/native/getcurrentprocessorid.cpp index 409f2c258f..eea80937b9 100644 --- a/native/getcurrentprocessorid.cpp +++ b/native/getcurrentprocessorid.cpp @@ -1,9 +1,9 @@ #include "getcurrentprocessorid.h" #include -HANDLE GetCurrentProcessId() +int32_t GetCurrentProcessId() { - pid_t pid = getpid(); - return reinterpret_cast(pid); + pid_t pid = getpid(); + return static_cast(pid); } diff --git a/native/getcurrentprocessorid.h b/native/getcurrentprocessorid.h index fa3f35534e..3c768e72e5 100644 --- a/native/getcurrentprocessorid.h +++ b/native/getcurrentprocessorid.h @@ -4,7 +4,7 @@ PAL_BEGIN_EXTERNC -HANDLE GetCurrentProcessId(); +int32_t GetCurrentProcessId(); PAL_END_EXTERNC diff --git a/native/getlinkcount.cpp b/native/getlinkcount.cpp index 50e7263a8e..dd9ffbb020 100644 --- a/native/getlinkcount.cpp +++ b/native/getlinkcount.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include "getlinkcount.h" //! @brief GetLinkCount retrieves the file link count (number of hard links) @@ -45,13 +44,13 @@ //! - ERROR_INVALID_FUNCTION: incorrect function //! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters //! -//! @retval TRUE If the function succeeds, the return value is a nonzero -//! value, and the variable pointed to by buffer contains infomation about the files -//! @retval FALSE If the function fails, the return value is zero. To get +//! @retval 1 If the function succeeds, and the variable pointed to by buffer contains +//! infomation about the files +//! @retval 0 If the function fails, the return value is zero. To get //! extended error information, call GetLastError. //! -BOOL GetLinkCount(char* fileName, LPDWORD count) +int32_t GetLinkCount(const char* fileName, int32_t *count) { errno = 0; @@ -109,10 +108,10 @@ BOOL GetLinkCount(char* fileName, LPDWORD count) default: errno = ERROR_INVALID_FUNCTION; } - return FALSE; + return 0; } *count = statBuf.st_nlink; - return TRUE; + return 1; } diff --git a/native/getlinkcount.h b/native/getlinkcount.h index 738a606c6c..6a3c8b8e41 100644 --- a/native/getlinkcount.h +++ b/native/getlinkcount.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -BOOL GetLinkCount(char* fileName, LPDWORD count); +int32_t GetLinkCount(const char* fileName, int32_t *count); PAL_END_EXTERNC diff --git a/native/issymlink.cpp b/native/issymlink.cpp index 0d3a1f387d..4a4ae54484 100644 --- a/native/issymlink.cpp +++ b/native/issymlink.cpp @@ -43,7 +43,7 @@ //! @retval -1 If the function fails.. To get extended error information, call GetLastError. //! -long IsSymLink(const char* fileName) +int32_t IsSymLink(const char* fileName) { errno = 0; diff --git a/native/pal.h b/native/pal.h index 7df0b32bb4..421bbf0a83 100644 --- a/native/pal.h +++ b/native/pal.h @@ -1,57 +1,14 @@ -/* -**============================================================================== -** -** Open Management Infrastructure (OMI) -** -** Copyright (c) Microsoft Corporation -** -** 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 -** -** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -** MERCHANTABLITY OR NON-INFRINGEMENT. -** -** See the Apache 2 License for the specific language governing permissions -** and limitations under the License. -** -**============================================================================== -*/ - #pragma once -#include -#include #include #include -#include -#include #include #ifndef NAME_MAX # define NAME_MAX 255 #endif -/* -**============================================================================== -** -** Windows-specific types. Defined here for PAL on Non-Windows platforms. -** -**============================================================================== -*/ - -#ifdef _MSC_VER - #ifndef WIN32_FROM_HRESULT - #define WIN32_FROM_HRESULT(hr) (HRESULT_FACILITY(hr) == FACILITY_WIN32 ? HRESULT_CODE(hr) : hr) - #endif -#else - #define WIN32_FROM_HRESULT(hr) hr - #define HRESULT_FROM_WIN32(error) error - typedef unsigned long DWORD, *LPDWORD; +/* typedef unsigned long DWORD, *LPDWORD; typedef char BOOL; typedef unsigned short WCHAR_T; typedef unsigned int UINT32; @@ -71,110 +28,26 @@ #define S_OK 0 #define TRUE 1 #define FALSE 0 - #define ERROR_INVALID_PARAMETER 87 - #define ERROR_OUTOFMEMORY 14 - #define ERROR_BAD_ENVIRONMENT 0x0000000A - #define ERROR_TOO_MANY_OPEN_FILES 0x00000004 - #define ERROR_INSUFFICIENT_BUFFER 0x0000007A - #define ERROR_NO_ASSOCIATION 0x00000483 - #define ERROR_NO_SUCH_USER 0x00000525 - #define ERROR_INVALID_FUNCTION 0x00000001 - #define MAX_PATH 0x00000104 - #define ERROR_INVALID_ADDRESS 0x000001e7 - #define ERROR_GEN_FAILURE 0x0000001F - #define ERROR_ACCESS_DENIED 0x00000005 - #define ERROR_INVALID_NAME 0x0000007B - #define ERROR_STOPPED_ON_SYMLINK 0x000002A9 - #define ERROR_BUFFER_OVERFLOW 0x0000006F - #define ERROR_FILE_NOT_FOUND 0x00000002 - #define ERROR_BAD_PATH_NAME 0x000000A1 - #define ERROR_BAD_NET_NAME 0x00000043 - - typedef unsigned long long uint64; -#endif - -/* -**============================================================================== -** -** __FUNCTION__ -** -**============================================================================== */ -#if !defined(CONFIG_HAVE_FUNCTION_MACRO) -# if !defined(_MSC_VER) && !defined(__FUNCTION__) -# define __FUNCTION__ "" -# endif -#endif - -/* -**============================================================================== -** -** PAL_32BIT -** PAL_64BIT -** -**============================================================================== -*/ -#if defined(__GNUC__) -# if defined(__i386__) -# define PAL_32BIT -# elif defined(__x86_64__) -# define PAL_64BIT -# elif defined(__ppc__) -# define PAL_32BIT -# elif defined(__ppc64__) -# define PAL_64BIT -# elif ((ULONG_MAX) == (UINT_MAX) && (ULONG_MAX == 0xFFFFFFFF)) -# define PAL_32BIT -# else -# define PAL_64BIT -# endif -#elif defined(_MSC_VER) -# if defined(_WIN64) -# define PAL_64BIT -# else -# define PAL_32BIT -# endif -#elif ((ULONG_MAX) == (UINT_MAX) && (ULONG_MAX == 0xFFFFFFFF)) -# define PAL_32BIT -#else -# define PAL_64BIT -#endif - -/* -**============================================================================== -** -** PAL_CALL macro -** -**============================================================================== -*/ -#ifdef _MSC_VER -# define PAL_CALL __stdcall -#else -# define PAL_CALL -#endif - -/* -**============================================================================== -** -** PAL_EXPORT_API, PAL_IMPORT_API macros -** -**============================================================================== -*/ - -#if defined(_MSC_VER) -# define PAL_EXPORT_API __declspec(dllexport) -# define PAL_IMPORT_API __declspec(dllimport) -#elif defined(__GNUC__) -# define PAL_EXPORT_API __attribute__((visibility("default"))) -# define PAL_IMPORT_API /* empty */ -#elif defined(sun) -# define PAL_EXPORT_API __global -# define PAL_IMPORT_API /* empty */ -#else -# define PAL_EXPORT_API /* empty */ -# define PAL_IMPORT_API /* empty */ -#endif +#define ERROR_INVALID_PARAMETER 87 +#define ERROR_OUTOFMEMORY 14 +#define ERROR_BAD_ENVIRONMENT 0x0000000A +#define ERROR_TOO_MANY_OPEN_FILES 0x00000004 +#define ERROR_INSUFFICIENT_BUFFER 0x0000007A +#define ERROR_NO_ASSOCIATION 0x00000483 +#define ERROR_NO_SUCH_USER 0x00000525 +#define ERROR_INVALID_FUNCTION 0x00000001 +#define MAX_PATH 0x00000104 +#define ERROR_INVALID_ADDRESS 0x000001e7 +#define ERROR_GEN_FAILURE 0x0000001F +#define ERROR_ACCESS_DENIED 0x00000005 +#define ERROR_INVALID_NAME 0x0000007B +#define ERROR_STOPPED_ON_SYMLINK 0x000002A9 +#define ERROR_BUFFER_OVERFLOW 0x0000006F +#define ERROR_FILE_NOT_FOUND 0x00000002 +#define ERROR_BAD_PATH_NAME 0x000000A1 +#define ERROR_BAD_NET_NAME 0x00000043 /* **============================================================================== @@ -193,415 +66,3 @@ # define PAL_END_EXTERNC #endif -/* -**============================================================================== -** -** PAL_EXTERN_C -** -**============================================================================== -*/ -#ifdef __cplusplus -# define PAL_EXTERN_C extern "C" -#else -# define PAL_EXTERN_C extern -#endif /* __cplusplus */ - -/* -**============================================================================== -** -** PAL_INLINE macro -** -**============================================================================== -*/ - -#if defined(_MSC_VER) -# define PAL_INLINE static __inline -#elif defined(__GNUC__) -# define PAL_INLINE static __inline -#elif defined(sun) -# define PAL_INLINE static inline -#elif defined(__PPC) -# define PAL_INLINE __inline__ -#else -# define PAL_INLINE static __inline -#endif - -/* -**============================================================================== -** -** PAL string -** -**============================================================================== -*/ - -#if defined(CONFIG_ENABLE_WCHAR) -typedef wchar_t PAL_Char; -#else -typedef char PAL_Char; -#endif - -typedef PAL_Char TChar; - -/* -**============================================================================== -** -** PAL_T() -** -**============================================================================== -*/ - -#if defined(CONFIG_ENABLE_WCHAR) -# define __PAL_T(STR) L ## STR -# define PAL_T(STR) __PAL_T(STR) -#else -# define PAL_T(STR) STR -#endif - -/* -**============================================================================== -** -** PAL_UNUSED -** -**============================================================================== -*/ - -#define PAL_UNUSED(X) ((void)X) - -/* -**============================================================================== -** -** PAL_HAVE_POSIX -** -**============================================================================== -*/ - -#if defined(linux) || defined(sun) || defined(hpux) || defined(aix) -# define PAL_HAVE_POSIX -#endif - -/* -**============================================================================== -** -** PAL_HAVE_PTHREADS -** -**============================================================================== -*/ - -#if defined(linux) | defined(sun) | defined(hpux) | defined(aix) -# define PAL_HAVE_PTHREADS -#endif - -/* -**============================================================================== -** -** Basic types -** -**============================================================================== -*/ - -typedef unsigned char PAL_Uint8; -#define PAL_UINT8_MAX (UCHAR_MAX) - -typedef signed char PAL_Sint8; -#define PAL_SINT8_MIN (SCHAR_MIN) -#define PAL_SINT8_MAX (SCHAR_MAX) - -typedef unsigned short PAL_Uint16; -#define PAL_UINT16_MAX (USHRT_MAX) - -typedef signed short PAL_Sint16; -#define PAL_SINT16_MIN (SHRT_MIN) -#define PAL_SINT16_MAX (SHRT_MAX) - -typedef unsigned int PAL_Uint32; -#define PAL_UINT32_MAX (UINT_MAX) - -typedef signed int PAL_Sint32; -#define PAL_SINT32_MIN (INT_MIN) -#define PAL_SINT32_MAX (INT_MAX) - -#if defined(_MSC_VER) -typedef unsigned __int64 PAL_Uint64; -typedef signed __int64 PAL_Sint64; -#else -typedef unsigned long long PAL_Uint64; -typedef signed long long PAL_Sint64; -#endif -#define PAL_UINT64_MIN ((PAL_Uint64) 0ULL) -#define PAL_UINT64_MAX ((PAL_Uint64) 18446744073709551615ULL) -#define PAL_SINT64_MIN ((PAL_Sint64) (-9223372036854775807LL - 1LL)) -#define PAL_SINT64_MAX ((PAL_Sint64) 9223372036854775807LL ) - -typedef unsigned char PAL_Boolean; - -#define PAL_TRUE ((PAL_Boolean)1) -#define PAL_FALSE ((PAL_Boolean)0) - -/* -**============================================================================== -** -** Function calling conventions -** -**============================================================================== -*/ - -#ifdef _MSC_VER -# define PAL_CDECLAPI __cdecl -#else -# define PAL_CDECLAPI -#endif - -#define ATEXIT_API PAL_CDECLAPI - -/* -**============================================================================== -** -** SAL Notation for non-Windows platforms -** -**============================================================================== -*/ - -#if !defined(_MSC_VER) - -# ifndef _In_ -# define _In_ -# endif - -# ifndef _Out_ -# define _Out_ -# endif - -# ifndef _Inout_ -# define _Inout_ -# endif - -# ifndef _Return_type_success_ -# define _Return_type_success_(x) -# endif - -# ifndef _Acquires_lock_ -# define _Acquires_lock_(x) -# endif - -# ifndef _Releases_lock_ -# define _Releases_lock_(x) -# endif - -# ifndef _In_z_ -# define _In_z_ -# endif - -# ifndef _Post_z_ -# define _Post_z_ -# endif - -# ifndef _Out_writes_ -# define _Out_writes_(size) -# endif - -# ifndef _Out_writes_z_ -# define _Out_writes_z_(size) -# endif - -# ifndef _Null_terminated_ -# define _Null_terminated_ -# endif - -# ifndef _Use_decl_annotations_ -# define _Use_decl_annotations_ -# endif - -# ifndef _Out_opt_ -# define _Out_opt_ -# endif - -# ifndef _Deref_post_z_ -# define _Deref_post_z_ -# endif - -# ifndef _Inout_updates_z_ -# define _Inout_updates_z_(count) -# endif - -# ifndef _Inout_opt_z_ -# define _Inout_opt_z_ -# endif - -# ifndef _Deref_prepost_opt_z_ -# define _Deref_prepost_opt_z_ -# endif - -# ifndef _In_opt_ -# define _In_opt_ -# endif - -# ifndef _In_opt_z_ -# define _In_opt_z_ -# endif - -# ifndef _Ret_maybenull_ -# define _Ret_maybenull_ -# endif - -# ifndef _Check_return_ -# define _Check_return_ -# endif - -# ifndef _Must_inspect_result_ -# define _Must_inspect_result_ -# endif - -# ifndef _Frees_ptr_opt_ -# define _Frees_ptr_opt_ -# endif - -# ifndef _Frees_ptr_ -# define _Frees_ptr_ -# endif - -# ifndef _Const_ -# define _Const_ -# endif - -# ifndef _Post_writable_byte_size -# define _Post_writable_byte_size(size) -# endif - -# ifndef _Analysis_assume_ -# define _Analysis_assume_(expr) -# endif - -# ifndef _Always_ -# define _Always_(expr) -# endif - -# ifndef _Outptr_ -# define _Outptr_ -# endif - -# ifndef _Outptr_result_buffer_ -# define _Outptr_result_buffer_(size) -# endif - -# ifndef _Outptr_result_nullonfailure_ -# define _Outptr_result_nullonfailure_ -# endif - -# ifndef _Maybenull_ -# define _Maybenull_ -# endif - -# ifndef _Notnull_ -# define _Notnull_ -# endif - -# ifndef _Valid_ -# define _Valid_ -# endif - -# ifndef _Analysis_noreturn_ -# define _Analysis_noreturn_ -# endif - -# ifndef _Ret_writes_maybenull_z_ -# define _Ret_writes_maybenull_z_(count) -# endif - -# ifndef _String_length_ -# define _String_length_(str) -# endif - -# ifndef _Success_ -# define _Success_ -# endif - -# ifndef _Field_range_ -# define _Field_range_(min, max) -# endif - -# ifndef _In_range_ -# define _In_range_(min, max) -# endif - -# ifndef _Field_size_ -# define _Field_size_(count) -# endif - -# ifndef _Field_size_opt_ -# define _Field_size_opt_(count) -# endif - -# ifndef _Field_size_full_opt_ -# define _Field_size_full_opt_(count) -# endif - -# ifndef _Field_size_bytes_opt_ -# define _Field_size_bytes_opt_(size) -# endif - -# ifndef _Readable_elements_ -# define _Readable_elements_(count) -# endif - -# ifndef _Writable_elements_ -# define _Writable_elements_(count) -# endif - -# ifndef _Struct_size_bytes_ -# define _Struct_size_bytes_(size) -# endif - -# ifndef _At_ -# define _At_(target, annotation) -# endif - -# ifndef _Pre_satisfies_ -# define _Pre_satisfies_(expr) -# endif - -# ifndef _On_failure_ -# define _On_failure_(expr) -# endif - -# ifndef _In_bytecount_ -# define _In_bytecount_(size) -# endif - -# ifndef _Out_writes_bytes_to_opt_ -# define _Out_writes_bytes_to_opt_(buffLen, bufferNeeded) -# endif - -# ifndef _When_ -# define _When_(expr, annotation) -# endif - -# ifndef _Analysis_assume_nullterminated_ -# define _Analysis_assume_nullterminated_(expr) -# endif - - -#endif /* !defined(_MSC_VER) */ - -/* -**============================================================================== -** -** PAL_MAX_PATH_SIZE -** -**============================================================================== -*/ - -#define PAL_MAX_PATH_SIZE 1024 - -/* -**============================================================================== -** -** PAL_COUNT -** -**============================================================================== -*/ - -#ifdef _MSC_VER -# define PAL_COUNT(ARR) _countof(ARR) -#else -# define PAL_COUNT(ARR) (sizeof(ARR) / sizeof(ARR[0])) -#endif diff --git a/native/terminal.cpp b/native/terminal.cpp index c321928020..44fadd0846 100644 --- a/native/terminal.cpp +++ b/native/terminal.cpp @@ -1,7 +1,7 @@ #include "terminal.h" #include -INT32 GetTerminalWidth() +int32_t GetTerminalWidth() { struct winsize ws; if (-1 == ioctl(0,TIOCGWINSZ,&ws)) @@ -10,7 +10,7 @@ INT32 GetTerminalWidth() return ws.ws_col; } -INT32 GetTerminalHeight() +int32_t GetTerminalHeight() { struct winsize ws; if (-1 == ioctl(0,TIOCGWINSZ,&ws)) diff --git a/native/terminal.h b/native/terminal.h index 00332e9bf5..e036bc8492 100644 --- a/native/terminal.h +++ b/native/terminal.h @@ -4,8 +4,8 @@ PAL_BEGIN_EXTERNC -INT32 GetTerminalWidth(); -INT32 GetTerminalHeight(); +int32_t GetTerminalWidth(); +int32_t GetTerminalHeight(); PAL_END_EXTERNC diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index c783ff003e..2a6bf5e0fe 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -2,26 +2,33 @@ //! @author George Fleming //! @brief Unit tests for GetComputerName -#include -#include #include #include "getcomputername.h" //! Test fixture for GetComputerNameTest class GetComputerNameTest : public ::testing::Test { -protected: - char expectedComputerName[HOST_NAME_MAX]; - - //Get expected result from using linux call - GetComputerNameTest() - { - BOOL ret = gethostname(expectedComputerName, HOST_NAME_MAX); - EXPECT_EQ(0, ret); - } }; TEST_F(GetComputerNameTest, ValidateLinuxGetHostnameSystemCall) { + char expectedComputerName[NAME_MAX]; + + //Get expected result from using linux command + + FILE *fPtr = popen("hostname -s", "r"); + ASSERT_TRUE(fPtr != NULL); + + char *linePtr = fgets(expectedComputerName, sizeof(expectedComputerName), fPtr); + ASSERT_TRUE(linePtr != NULL); + + // There's a tendency to have \n at end of fgets string, so remove it before compare + size_t sz = strlen(expectedComputerName); + if (sz > 0 && expectedComputerName[sz - 1] == '\n') + { + expectedComputerName[sz - 1] = '\0'; + } + pclose(fPtr); + ASSERT_STREQ(GetComputerName(), expectedComputerName); } diff --git a/tests/test-getcurrentprocessid.cpp b/tests/test-getcurrentprocessid.cpp index 9803b6612c..a1d10a0bee 100644 --- a/tests/test-getcurrentprocessid.cpp +++ b/tests/test-getcurrentprocessid.cpp @@ -4,13 +4,13 @@ // This is a very simple test case to show how tests can be written TEST(GetCurrentProcessId,simple) { - const HANDLE currentProcessId = GetCurrentProcessId(); + const int32_t currentProcessId = GetCurrentProcessId(); const pid_t pid = getpid(); // first make sure that on this platform those types are of the same size - ASSERT_TRUE(sizeof(HANDLE) >= sizeof(pid_t)); + ASSERT_TRUE(sizeof(int32_t) >= sizeof(pid_t)); // now compare the actual values - ASSERT_EQ(currentProcessId,reinterpret_cast(pid)); + ASSERT_EQ(currentProcessId,static_cast(pid)); } diff --git a/tests/test-getfullyqualifiedname.cpp b/tests/test-getfullyqualifiedname.cpp index 9ec01e27f9..dc49114d03 100644 --- a/tests/test-getfullyqualifiedname.cpp +++ b/tests/test-getfullyqualifiedname.cpp @@ -2,7 +2,6 @@ //! @author George Fleming //! @brief Unit tests for GetFullyQualifiedName -#include #include #include "getfullyqualifiedname.h" @@ -13,7 +12,7 @@ class GetFullyQualifiedNameTest : public ::testing::Test TEST_F(GetFullyQualifiedNameTest, ValidateLinuxGetFullyQualifiedDomainName) { - char expectedComputerName[HOST_NAME_MAX]; + char expectedComputerName[NAME_MAX]; //Get expected result from using linux command diff --git a/tests/test-getlinkcount.cpp b/tests/test-getlinkcount.cpp index b01ddbbeeb..fbe1a001fc 100644 --- a/tests/test-getlinkcount.cpp +++ b/tests/test-getlinkcount.cpp @@ -15,19 +15,24 @@ class getLinkCountTest : public ::testing::Test { protected: - std::string file; - const std::string fileTemplate = "/tmp/createFile.XXXXXXX"; - ulong count; + static const int bufSize = 64; + const std::string fileTemplate = "/tmp/createFile.XXXXXX"; + char fileTemplateBuf[bufSize]; + + int32_t count; + char *file; getLinkCountTest() { - file = fileTemplate; - file = mktemp(const_cast(file.c_str())); - std::ifstream fileCondition(file); - EXPECT_EQ(0, fileCondition.good()); + // since mkstemp modifies the template string, let's give it writable buffer + strcpy(fileTemplateBuf, fileTemplate.c_str()); + + int fd = mkstemp(fileTemplateBuf); + EXPECT_TRUE(fd != -1); + file = fileTemplateBuf; } - void createFileForTesting(std::string theFile) + void createFileForTesting(const std::string &theFile) { std::ofstream ofs; ofs.open(theFile, std::ofstream::out); @@ -35,25 +40,25 @@ protected: ofs.close(); } - std::string createHardLink(std::string origFile) + std::string createHardLink(const std::string &origFile) { std::string newFile = origFile + "_link"; - int ret = link(const_cast(origFile.c_str()), const_cast(newFile.c_str())); + int ret = link(origFile.c_str(), newFile.c_str()); EXPECT_EQ(0, ret); return newFile; } - void removeFile(std::string fileName) + void removeFile(const std::string &fileName) { - int ret = unlink(const_cast(fileName.c_str())); + int ret = unlink(fileName.c_str()); EXPECT_EQ(0, ret); } }; TEST_F(getLinkCountTest, FilePathNameIsNull) { - bool retVal = GetLinkCount(NULL, &count ); + int32_t retVal = GetLinkCount(NULL, &count ); ASSERT_FALSE(retVal); EXPECT_EQ(ERROR_INVALID_PARAMETER, errno); } @@ -61,7 +66,7 @@ TEST_F(getLinkCountTest, FilePathNameIsNull) TEST_F(getLinkCountTest, FilePathNameDoesNotExist) { std::string invalidFile = "/tmp/createFile"; - bool retVal = GetLinkCount(const_cast(invalidFile.c_str()), &count); + int32_t retVal = GetLinkCount(invalidFile.c_str(), &count); ASSERT_FALSE(retVal); EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno); } @@ -69,7 +74,7 @@ TEST_F(getLinkCountTest, FilePathNameDoesNotExist) TEST_F(getLinkCountTest, LinkCountOfSinglyLinkedFile) { createFileForTesting(file); - bool retVal = GetLinkCount(const_cast(file.c_str()), &count); + int32_t retVal = GetLinkCount(file, &count); ASSERT_TRUE(retVal); EXPECT_EQ(1, count); @@ -80,7 +85,7 @@ TEST_F(getLinkCountTest, LinkCountOfMultipliLinkedFile) { createFileForTesting(file); std::string newFile = createHardLink(file); - bool retVal = GetLinkCount(const_cast(file.c_str()), &count); + int32_t retVal = GetLinkCount(file, &count); ASSERT_TRUE(retVal); EXPECT_EQ(2, count); diff --git a/tests/test-issymlink.cpp b/tests/test-issymlink.cpp index 41515fbc38..4aaa3eb541 100644 --- a/tests/test-issymlink.cpp +++ b/tests/test-issymlink.cpp @@ -14,8 +14,8 @@ class isSymLinkTest : public ::testing::Test protected: static const int bufSize = 64; - const string fileTemplate = "/tmp/symlinktest.fXXXXXXX"; - const string dirTemplate = "/tmp/symlinktest.dXXXXXXX"; + const string fileTemplate = "/tmp/symlinktest.fXXXXXX"; + const string dirTemplate = "/tmp/symlinktest.dXXXXXX"; const string fileSymLink = "/tmp/symlinktest.flink"; const string dirSymLink = "/tmp/symlinktest.dlink"; char *file, *dir; From 102f6163a17afec6e27107ec0fdfec5fd458c706 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Tue, 3 Nov 2015 08:26:36 -0800 Subject: [PATCH 260/298] Remove unnecessary code --- native/isexecutable.cpp | 10 ++-------- native/issymlink.h | 2 +- native/pal.h | 22 ---------------------- 3 files changed, 3 insertions(+), 31 deletions(-) diff --git a/native/isexecutable.cpp b/native/isexecutable.cpp index dab5362954..be49afb3c3 100644 --- a/native/isexecutable.cpp +++ b/native/isexecutable.cpp @@ -1,6 +1,6 @@ //! @file isExecutable.cpp //! @author George FLeming -//! @brief returns whether a path is executable +//! @brief returns whether a file is executable #include #include @@ -21,19 +21,13 @@ //! @endparblock //! //! @exception errno Passes these errors via errno to GetLastError: -//! - ERROR_INVALID_PARAMETER: parameter is not valid //! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 -//! - ERROR_FILE_NOT_FOUND: file does not exist -//! - ERROR_ACCESS_DENIED: access is denied //! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified //! - ERROR_INVALID_ADDRESS: attempt to access invalid address -//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link //! - ERROR_GEN_FAILURE: device attached to the system is not functioning -//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file //! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect -//! - ERROR_BUFFER_OVERFLOW: file name is too long //! - ERROR_INVALID_FUNCTION: incorrect function -//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters +//! - ERROR_INVALID_PARAMETER: parameter to access(2) call is incorrect //! //! @retval 1 if path is an executable //! @retval 0 if path is not a executable diff --git a/native/issymlink.h b/native/issymlink.h index 3ba5e48ac7..066a4060c1 100644 --- a/native/issymlink.h +++ b/native/issymlink.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -long IsSymLink(const char* fileName); +int32_t IsSymLink(const char* fileName); PAL_END_EXTERNC diff --git a/native/pal.h b/native/pal.h index 421bbf0a83..2b97aee1d1 100644 --- a/native/pal.h +++ b/native/pal.h @@ -8,28 +8,6 @@ # define NAME_MAX 255 #endif -/* typedef unsigned long DWORD, *LPDWORD; - typedef char BOOL; - typedef unsigned short WCHAR_T; - typedef unsigned int UINT32; - typedef int INT32; - typedef unsigned long HRESULT; - typedef const wchar_t *PCWSTR; - typedef wchar_t *PWSTR; - typedef const char *PCSTR; - typedef char *PSTR; - typedef void *PVOID; - typedef PVOID HANDLE; - typedef uint32_t UINT; - typedef char BYTE; - #define NO_ERROR 0 - #define INFINITE 0xFFFFFFFF - #define WINAPI - #define S_OK 0 - #define TRUE 1 - #define FALSE 0 -*/ - #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 #define ERROR_BAD_ENVIRONMENT 0x0000000A From dfea2bf9274ecf42ae6f06714c65c17947a5426d Mon Sep 17 00:00:00 2001 From: George Fleming Date: Wed, 4 Nov 2015 08:53:54 -0800 Subject: [PATCH 261/298] Further cleanup of pal.h --- native/pal.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/native/pal.h b/native/pal.h index 2b97aee1d1..d47b2845e2 100644 --- a/native/pal.h +++ b/native/pal.h @@ -3,10 +3,7 @@ #include #include #include - -#ifndef NAME_MAX -# define NAME_MAX 255 -#endif +#include #define ERROR_INVALID_PARAMETER 87 #define ERROR_OUTOFMEMORY 14 @@ -16,7 +13,6 @@ #define ERROR_NO_ASSOCIATION 0x00000483 #define ERROR_NO_SUCH_USER 0x00000525 #define ERROR_INVALID_FUNCTION 0x00000001 -#define MAX_PATH 0x00000104 #define ERROR_INVALID_ADDRESS 0x000001e7 #define ERROR_GEN_FAILURE 0x0000001F #define ERROR_ACCESS_DENIED 0x00000005 From d5c0ad08cb3f8438ce599152c2fe3868046b67ee Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 4 Nov 2015 20:30:52 -0800 Subject: [PATCH 262/298] Fix test since gethostname gets the nodename The nodename is not necessarily the short name returned by hostname. --- native/getcomputername.cpp | 3 ++- tests/test-getcomputername.cpp | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/native/getcomputername.cpp b/native/getcomputername.cpp index 67e3d870dd..70a52a6845 100644 --- a/native/getcomputername.cpp +++ b/native/getcomputername.cpp @@ -33,7 +33,8 @@ char* GetComputerName() return NULL; } - // Get computername from system in a thread-safe manner + // Get computername from system, not that gethostname gets the + // nodename from uname std::string computername(NAME_MAX, 0); int err = gethostname(&computername[0], computername.length()); // Map errno to Win32 Error Codes diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index 2a6bf5e0fe..5820d05655 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -10,13 +10,12 @@ class GetComputerNameTest : public ::testing::Test { }; -TEST_F(GetComputerNameTest, ValidateLinuxGetHostnameSystemCall) +TEST_F(GetComputerNameTest, Success) { char expectedComputerName[NAME_MAX]; - //Get expected result from using linux command - - FILE *fPtr = popen("hostname -s", "r"); + // the gethostname system call gets the nodename from uname + FILE *fPtr = popen("uname -n", "r"); ASSERT_TRUE(fPtr != NULL); char *linePtr = fgets(expectedComputerName, sizeof(expectedComputerName), fPtr); From 8c9c9b2284b4bbd79163a303548e2462e97e82b6 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 4 Nov 2015 20:47:28 -0800 Subject: [PATCH 263/298] Fix username tests by checking for null --- tests/test-getusername.cpp | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index 50c2d1feab..cab8cb98bf 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -10,18 +10,9 @@ #include #include "getusername.h" -//! Test fixture for GetUserName -class GetUserNameTest : public ::testing::Test +TEST(GetUserName, Success) { -protected: - std::string UserName; - - GetUserNameTest(): UserName(std::string(getpwuid(geteuid())->pw_name)) - { - } -}; - -TEST_F(GetUserNameTest, Success) -{ - ASSERT_EQ(GetUserName(), UserName); + char* expected = getpwuid(geteuid())->pw_name; + ASSERT_TRUE(expected != NULL); + ASSERT_EQ(GetUserName(), std::string(expected)); } From 9c6edbc7a1432d993d82ac86f0d8a7daeff97e0e Mon Sep 17 00:00:00 2001 From: Alex Jordan Date: Fri, 6 Nov 2015 23:03:45 +0000 Subject: [PATCH 264/298] Added -Werror to treat all warnings as errors to monad-native CMake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b61395b0c0..e0e4a7ab90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8.4) project(MONAD_NATIVE) -add_compile_options(-std=c++11 -Wall) +add_compile_options(-std=c++11 -Wall -Werror) # test in BUILD_DIR enable_testing() From 96cda45f342fd82adb4b9604892885b922bb7279 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 6 Nov 2015 19:55:19 -0800 Subject: [PATCH 265/298] Expose pshost's pwrshPath (PowerShell libraries) It's the determined path of the PowerShell libraries (whether specified via PWRSH_ROOT or found relative to the native bin/powershell executable). Like exePath, this is available only after a call to startCoreCLR. --- host/coreclrutil.cpp | 6 +++++- host/coreclrutil.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/host/coreclrutil.cpp b/host/coreclrutil.cpp index eabd73f042..0324105f43 100644 --- a/host/coreclrutil.cpp +++ b/host/coreclrutil.cpp @@ -19,6 +19,7 @@ constexpr char coreClrDll[] = "libcoreclr.so"; void* coreclrLib; char exePath[PATH_MAX]; +char pwrshPath[PATH_MAX]; // Prototype of the coreclr_initialize function from the libcoreclr.so typedef int (*InitializeCoreCLRFunction)( @@ -285,12 +286,15 @@ int startCoreCLR( // add assemblies in the CoreCLR root path AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(), tpaList); - // get path to AssemblyLoadContext.dll + // get path to PowerShell libraries std::string psAbsolutePath; if(!GetPwrshRoot(psAbsolutePath)) { return -1; } + psAbsolutePath.copy(pwrshPath, psAbsolutePath.size(), 0); + + // get path to AssemblyLoadContext.dll std::string alcAbsolutePath(psAbsolutePath); alcAbsolutePath.append("/"); alcAbsolutePath.append("Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"); diff --git a/host/coreclrutil.h b/host/coreclrutil.h index d344873107..843a440ad5 100644 --- a/host/coreclrutil.h +++ b/host/coreclrutil.h @@ -48,6 +48,7 @@ extern "C" extern ExecuteAssemblyFunction executeAssembly; extern CreateDelegateFunction createDelegate; + extern char pwrshPath[]; #ifdef __cplusplus } #endif From 0e119de0c95e4a242982c18caadb314ebe89264f Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 6 Nov 2015 19:59:04 -0800 Subject: [PATCH 266/298] Refactor argument parsing for new interface Only one argument is accepted by the native host, which is an optional path to a managed host assembly (aka the PowerShell console). If not specified, lib/powershell/powershell.exe is used by default. All other arguments are forwarded as-is to the managed host. --- host/main.cpp | 102 ++++++++++++++++++-------------------------------- 1 file changed, 36 insertions(+), 66 deletions(-) diff --git a/host/main.cpp b/host/main.cpp index 0b7728d4e7..1721b2a143 100644 --- a/host/main.cpp +++ b/host/main.cpp @@ -35,86 +35,48 @@ namespace Cmdline Args() : argc(0), argv(nullptr), - verbose(false) + assembly() { } - std::string entryAssemblyPath; int argc; char** argv; - bool verbose; - - void debugPrint() const - { - std::cerr << "Args:" << std::endl - << "- entryAssemblyPath " << entryAssemblyPath << std::endl - << "- argc " << argc << std::endl - << "- verbose " << (verbose ? "true" : "false") << std::endl; - } + std::string assembly; }; - // this is implemented without any 3rd party lib to keep the list - // of dependencies low - bool parseCmdline(const int argc, char** argv, Args& args) + // checks if string ends with ".exe" + bool isExe(std::string arg) { - if (argc <= 1) - { - std::cerr << "error: missing arguments" << std::endl; - return false; - } - - for (int i = 1; i < argc; ++i) - { - const std::string arg = argv[i]; - const bool hasNextArg = i+1 < argc; - const std::string nextArg = hasNextArg ? std::string(argv[i+1]) : std::string(""); - - if (hasNextArg && arg == "--File") - { - std::cerr << "TODO: should launch script " << nextArg << std::endl; - ++i; - } - else if (arg == "-v") - { - args.verbose = true; - } - else if (args.entryAssemblyPath == "") - { - args.entryAssemblyPath = arg; - } - else - { - // forward command line parameters - args.argc = argc-i; - args.argv = &argv[i]; - - // explicitly break here because the lines above consume all remaining arguments - break; - } - } - - // check for mandatory parameters - if (args.entryAssemblyPath == "") - { - std::cerr << "error: assembly_name argument missing" << std::endl; - } - - return true; + std::size_t dot = arg.find_last_of("."); + return dot == std::string::npos ? false : arg.substr(dot) == ".exe"; } + // simple extraction of assembly.exe so we can run other hosts + void parseCmdline(int argc, char** argv, Args& args) + { + // index of arguments to forward (skip zeroth) + int i = 1; + // if we have any arguments + if (argc > 1) + { + // check if the first is an assembly.exe + const std::string arg = argv[i]; + if (isExe(arg)) + { + args.assembly.assign(arg); + ++i; // don't forward the first argument + } + } + // forward arguments + args.argc = argc - i; + args.argv = &argv[i]; + } } int main(int argc, char** argv) { - // parse the command line arguments Cmdline::Args args; - if (!Cmdline::parseCmdline(argc,argv,args)) - { - Cmdline::printHelp(); - return 1; - } - if (args.verbose) - args.debugPrint(); + Cmdline::parseCmdline(argc, argv, args); void* hostHandle; unsigned int domainId; @@ -129,12 +91,20 @@ int main(int argc, char** argv) return -1; } + // default to powershell.exe if no host specified + if (args.assembly.empty()) + { + args.assembly.assign(pwrshPath); + args.assembly.append("/"); + args.assembly.append("powershell.exe"); + } + // call into Main of assembly unsigned int exitCode; executeAssembly( hostHandle, domainId, args.argc, (const char**)args.argv, - args.entryAssemblyPath.c_str(), + args.assembly.c_str(), &exitCode); status = stopCoreCLR(hostHandle, domainId); From 48af92c286572eb7bfc4552a9dbd3cded995b9b3 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 6 Nov 2015 20:01:29 -0800 Subject: [PATCH 267/298] Update usage text --- host/main.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/host/main.cpp b/host/main.cpp index 1721b2a143..8d76579ce7 100644 --- a/host/main.cpp +++ b/host/main.cpp @@ -7,8 +7,8 @@ namespace Cmdline { void printHelp() { - std::cerr << "PowerShell on Linux host" << std::endl - << "Usage: powershell assembly [...]" << std::endl + std::cerr << "PowerShell on Linux native host" << std::endl + << "Usage: powershell [assembly] [...]" << std::endl << std::endl << "What it does:" << std::endl << "- the host assumes that CoreCLR is located $CORE_ROOT," << std::endl @@ -16,18 +16,14 @@ namespace Cmdline << "- the host assumes that the assembly named" << std::endl << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is " << std::endl << " located in $PWRSH_ROOT, else in lib/powershell" << std::endl + << "- the host will launch $PWRSH_ROOT/powershell.exe" << std::endl + << " if not given an explicit assembly.exe" << std::endl << "- all additional parameters at the end of the command line are forwarded" << std::endl << " to the Main function in the assembly" << std::endl << "- the host will execute the Main function in the specified assembly" << std::endl - << " + this must be an absolute path to the assembly" << std::endl - << "- the function signature of the Main function that gets executed must be:" << std::endl - << " static void Main(string[] args)" << std::endl - << std::endl - << "Options:" << std::endl - << "-v verbose output" << std::endl << std::endl << "Example:" << std::endl - << "CORE_ROOT=/test/coreclr PWRSH_ROOT=/test/powershell ./powershell powershell-simple 'get-process'" << std::endl; + << "CORE_ROOT=/test/coreclr PWRSH_ROOT=/test/powershell ./powershell get-process" << std::endl; } struct Args From 22cc11e2d96ae7cd9f131eb5e5e12c71b56fa27b Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 6 Nov 2015 20:01:41 -0800 Subject: [PATCH 268/298] Rename appDomainFriendlyName to psl_cmdline_host --- host/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/main.cpp b/host/main.cpp index 8d76579ce7..36bee13dae 100644 --- a/host/main.cpp +++ b/host/main.cpp @@ -77,7 +77,7 @@ int main(int argc, char** argv) void* hostHandle; unsigned int domainId; int status = startCoreCLR( - "ps_cmdline_host", + "psl_cmdline_host", &hostHandle, &domainId); From 3bdcf50465b78e781278b630b87dda282a04114a Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Mon, 9 Nov 2015 09:46:53 -0800 Subject: [PATCH 269/298] Use HOST_NAME_MAX as specified in gethostname(2) NAME_MAX is the "maximum number of bytes in a filename," which is irrelevant to the gethostname libc function. --- native/getcomputername.cpp | 2 +- tests/test-getcomputername.cpp | 2 +- tests/test-getfullyqualifiedname.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/native/getcomputername.cpp b/native/getcomputername.cpp index 67e3d870dd..3d4e7eda3e 100644 --- a/native/getcomputername.cpp +++ b/native/getcomputername.cpp @@ -34,7 +34,7 @@ char* GetComputerName() } // Get computername from system in a thread-safe manner - std::string computername(NAME_MAX, 0); + std::string computername(HOST_NAME_MAX, 0); int err = gethostname(&computername[0], computername.length()); // Map errno to Win32 Error Codes if (err != 0) diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index 2a6bf5e0fe..1a170c67da 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -12,7 +12,7 @@ class GetComputerNameTest : public ::testing::Test TEST_F(GetComputerNameTest, ValidateLinuxGetHostnameSystemCall) { - char expectedComputerName[NAME_MAX]; + char expectedComputerName[HOST_NAME_MAX]; //Get expected result from using linux command diff --git a/tests/test-getfullyqualifiedname.cpp b/tests/test-getfullyqualifiedname.cpp index dc49114d03..c34419ab60 100644 --- a/tests/test-getfullyqualifiedname.cpp +++ b/tests/test-getfullyqualifiedname.cpp @@ -12,7 +12,7 @@ class GetFullyQualifiedNameTest : public ::testing::Test TEST_F(GetFullyQualifiedNameTest, ValidateLinuxGetFullyQualifiedDomainName) { - char expectedComputerName[NAME_MAX]; + char expectedComputerName[HOST_NAME_MAX]; //Get expected result from using linux command From f1c8f15fb5541a1a27e9d543bed24018fc4ed81c Mon Sep 17 00:00:00 2001 From: George Fleming Date: Thu, 12 Nov 2015 16:31:30 -0800 Subject: [PATCH 270/298] SetDate function --- native/CMakeLists.txt | 1 + native/setdate.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++ native/setdate.h | 22 +++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 native/setdate.cpp create mode 100644 native/setdate.h diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index 9efaec93c2..e2841943d0 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -6,6 +6,7 @@ add_library(psnative SHARED getfullyqualifiedname.cpp issymlink.cpp isexecutable.cpp + setdate.cpp terminal.cpp) target_link_libraries(psnative icuuc) diff --git a/native/setdate.cpp b/native/setdate.cpp new file mode 100644 index 0000000000..cc9757815f --- /dev/null +++ b/native/setdate.cpp @@ -0,0 +1,73 @@ +//! @file setdate.cpp +//! @author George FLeming +//! @brief set local/system date and time + +#include +#include +#include +#include +#include +#include +#include "setdate.h" + +//! @brief SetDate sets the date and time on local computer. You must +//! be super-user to set the time. +//! +//! SetDate +//! +//! @param[in] info +//! @parblock +//! A struct that contains program to execute and its parameters +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 +//! - ERROR_INVALID_PARAMETER: time was not passed in correctly +//! - ERROR_ACCESS_DENIED: you must be super-user to set the date +//! +//! @retval 0 process successfully started and finished (if we are waiting for process) +//! @retval -1 if failure occurred. To get extended error information, call GetLastError. +//! + + int32_t SetDate(const SetDateInfo &info) +{ + errno = 0; + + // Select locale from environment + setlocale(LC_ALL, ""); + // Check that locale is UTF-8 + if (nl_langinfo(CODESET) != std::string("UTF-8")) + { + errno = ERROR_BAD_ENVIRONMENT; + return -1; + } + + struct tm bdTime; + struct timeval tv; + + bdTime.tm_year = info.Year - 1900; + bdTime.tm_mon = info.Month - 1; // This is zero-based + bdTime.tm_mday = info.Day; + bdTime.tm_hour = info.Hour; + bdTime.tm_min = info.Minute; + bdTime.tm_min = info.Second; + bdTime.tm_isdst = info.DST; + + time_t newTime = mktime(&bdTime); + if (newTime == -1) + { + errno = ERROR_INVALID_PARAMETER; + return -1; + } + + tv.tv_sec = newTime; + tv.tv_usec = info.Millisecond * 1000; + + int result = settimeofday(&tv, NULL); + if (result == -1) + { + errno = ERROR_ACCESS_DENIED; + return -1; + } + + return 0; +} diff --git a/native/setdate.h b/native/setdate.h new file mode 100644 index 0000000000..b55a7d1e7a --- /dev/null +++ b/native/setdate.h @@ -0,0 +1,22 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +typedef struct setDateInfo +{ + // the order of members does matter here + int32_t Year; + int32_t Month; + int32_t Day; + int32_t Hour; + int32_t Minute; + int32_t Second; + int32_t Millisecond; + int32_t DST; +} SetDateInfo; + +int32_t SetDate(const SetDateInfo &info); + +PAL_END_EXTERNC From f2b70e32ba17ffc33a0df0d90c65c203ba644625 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Fri, 13 Nov 2015 10:05:55 -0800 Subject: [PATCH 271/298] Remove microsecond --- native/setdate.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/native/setdate.cpp b/native/setdate.cpp index cc9757815f..81bfa3417e 100644 --- a/native/setdate.cpp +++ b/native/setdate.cpp @@ -24,11 +24,11 @@ //! - ERROR_INVALID_PARAMETER: time was not passed in correctly //! - ERROR_ACCESS_DENIED: you must be super-user to set the date //! -//! @retval 0 process successfully started and finished (if we are waiting for process) +//! @retval 0 successfully set date //! @retval -1 if failure occurred. To get extended error information, call GetLastError. //! - int32_t SetDate(const SetDateInfo &info) +int32_t SetDate(const SetDateInfo &info) { errno = 0; @@ -49,7 +49,7 @@ bdTime.tm_mday = info.Day; bdTime.tm_hour = info.Hour; bdTime.tm_min = info.Minute; - bdTime.tm_min = info.Second; + bdTime.tm_sec = info.Second; bdTime.tm_isdst = info.DST; time_t newTime = mktime(&bdTime); @@ -60,7 +60,7 @@ } tv.tv_sec = newTime; - tv.tv_usec = info.Millisecond * 1000; + tv.tv_usec = 0; int result = settimeofday(&tv, NULL); if (result == -1) From 284f28f52b900534531134a2fee33982d36b44ad Mon Sep 17 00:00:00 2001 From: Alex Jordan Date: Tue, 24 Nov 2015 23:37:12 +0000 Subject: [PATCH 272/298] Removing explicit test of en_US.UTF-8 in native code and moving to a unit test --- native/getcomputername.cpp | 12 ------------ native/getlinkcount.cpp | 9 --------- native/getusername.cpp | 9 --------- native/isexecutable.cpp | 10 ---------- native/issymlink.cpp | 11 ----------- tests/CMakeLists.txt | 1 + tests/test-locale.cpp | 22 ++++++++++++++++++++++ 7 files changed, 23 insertions(+), 51 deletions(-) create mode 100644 tests/test-locale.cpp diff --git a/native/getcomputername.cpp b/native/getcomputername.cpp index 9feecf01cc..29094e4903 100644 --- a/native/getcomputername.cpp +++ b/native/getcomputername.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include "getcomputername.h" @@ -22,17 +21,6 @@ char* GetComputerName() { - errno = 0; - - // Select locale from environment - setlocale(LC_ALL, ""); - // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != std::string("UTF-8")) - { - errno = ERROR_BAD_ENVIRONMENT; - return NULL; - } - // Get computername from system, note that gethostname(2) gets the // nodename from uname std::string computername(HOST_NAME_MAX, 0); diff --git a/native/getlinkcount.cpp b/native/getlinkcount.cpp index dd9ffbb020..9a828216b1 100644 --- a/native/getlinkcount.cpp +++ b/native/getlinkcount.cpp @@ -61,15 +61,6 @@ int32_t GetLinkCount(const char* fileName, int32_t *count) return FALSE; } - // Select locale from environment - setlocale(LC_ALL, ""); - // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != std::string("UTF-8")) - { - errno = ERROR_BAD_ENVIRONMENT; - return FALSE; - } - struct stat statBuf; int returnCode = lstat(fileName, &statBuf); diff --git a/native/getusername.cpp b/native/getusername.cpp index 30c2b8a149..ce2b865bd4 100644 --- a/native/getusername.cpp +++ b/native/getusername.cpp @@ -25,15 +25,6 @@ char* GetUserName() { errno = 0; - // Select locale from environment - setlocale(LC_ALL, ""); - // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != std::string("UTF-8")) - { - errno = ERROR_BAD_ENVIRONMENT; - return NULL; - } - struct passwd pwd; struct passwd* result; // gets the initial suggested size for buf diff --git a/native/isexecutable.cpp b/native/isexecutable.cpp index be49afb3c3..78ffea47b5 100644 --- a/native/isexecutable.cpp +++ b/native/isexecutable.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include "isexecutable.h" @@ -45,15 +44,6 @@ int32_t IsExecutable(const char* fileName) return -1; } - // Select locale from environment - setlocale(LC_ALL, ""); - // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != std::string("UTF-8")) - { - errno = ERROR_BAD_ENVIRONMENT; - return -1; - } - int returnCode = access(fileName, X_OK); if (returnCode == 0) diff --git a/native/issymlink.cpp b/native/issymlink.cpp index 4a4ae54484..c0787ec6b7 100644 --- a/native/issymlink.cpp +++ b/native/issymlink.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -45,7 +44,6 @@ int32_t IsSymLink(const char* fileName) { - errno = 0; // Check parameters if (!fileName) @@ -54,15 +52,6 @@ int32_t IsSymLink(const char* fileName) return -1; } - // Select locale from environment - setlocale(LC_ALL, ""); - // Check that locale is UTF-8 - if (nl_langinfo(CODESET) != std::string("UTF-8")) - { - errno = ERROR_BAD_ENVIRONMENT; - return -1; - } - struct stat statBuf; int returnCode = lstat(fileName, &statBuf); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a065c66c1d..b0216f88e7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(googletest) add_executable(psnative-test + test-locale.cpp test-getcurrentprocessid.cpp test-getusername.cpp test-getcomputername.cpp diff --git a/tests/test-locale.cpp b/tests/test-locale.cpp new file mode 100644 index 0000000000..8588fb4943 --- /dev/null +++ b/tests/test-locale.cpp @@ -0,0 +1,22 @@ +//! @file test-locale.cpp +//! @author Alex Jordan +//! @brief Unit tests for linux locale + +#include +#include +#include +#include +#include +//! Test fixture for LocaleTest + +class LocaleTest : public ::testing::Test +{ +}; + +TEST_F(LocaleTest, Success) +{ + setlocale (LC_ALL, ""); + ASSERT_FALSE (nl_langinfo(CODESET) == NULL); + ASSERT_TRUE(nl_langinfo(CODESET) == std::string("UTF-8")); + ASSERT_FALSE(nl_langinfo(CODESET) != std::string("UTF-8")); +} From 6fd5d5d40eab24a4b6ad0ed79241c1c796d63a8c Mon Sep 17 00:00:00 2001 From: Alex Jordan Date: Wed, 25 Nov 2015 00:29:57 +0000 Subject: [PATCH 273/298] Removed LANG dependancies from native fns --- native/getcomputername.cpp | 1 - native/getlinkcount.cpp | 1 - native/getusername.cpp | 1 - native/isexecutable.cpp | 1 - native/issymlink.cpp | 1 - tests/test-locale.cpp | 1 - 6 files changed, 6 deletions(-) diff --git a/native/getcomputername.cpp b/native/getcomputername.cpp index 29094e4903..03ec03517f 100644 --- a/native/getcomputername.cpp +++ b/native/getcomputername.cpp @@ -3,7 +3,6 @@ //! @brief Implements GetComputerName Win32 API #include -#include #include #include #include "getcomputername.h" diff --git a/native/getlinkcount.cpp b/native/getlinkcount.cpp index 9a828216b1..aab533640a 100644 --- a/native/getlinkcount.cpp +++ b/native/getlinkcount.cpp @@ -3,7 +3,6 @@ //! @brief Retrieve link count of a file #include -#include #include #include #include diff --git a/native/getusername.cpp b/native/getusername.cpp index ce2b865bd4..923e76e750 100644 --- a/native/getusername.cpp +++ b/native/getusername.cpp @@ -3,7 +3,6 @@ //! @brief Implements GetUserName for Linux #include -#include #include #include #include diff --git a/native/isexecutable.cpp b/native/isexecutable.cpp index 78ffea47b5..a243cbc4da 100644 --- a/native/isexecutable.cpp +++ b/native/isexecutable.cpp @@ -3,7 +3,6 @@ //! @brief returns whether a file is executable #include -#include #include #include #include "isexecutable.h" diff --git a/native/issymlink.cpp b/native/issymlink.cpp index c0787ec6b7..537a4a160a 100644 --- a/native/issymlink.cpp +++ b/native/issymlink.cpp @@ -3,7 +3,6 @@ //! @brief returns whether a path is a symbolic link #include -#include #include #include #include diff --git a/tests/test-locale.cpp b/tests/test-locale.cpp index 8588fb4943..043e98910e 100644 --- a/tests/test-locale.cpp +++ b/tests/test-locale.cpp @@ -18,5 +18,4 @@ TEST_F(LocaleTest, Success) setlocale (LC_ALL, ""); ASSERT_FALSE (nl_langinfo(CODESET) == NULL); ASSERT_TRUE(nl_langinfo(CODESET) == std::string("UTF-8")); - ASSERT_FALSE(nl_langinfo(CODESET) != std::string("UTF-8")); } From 2fd54306f94546385211c7d66ec716132037ac10 Mon Sep 17 00:00:00 2001 From: Alex Jordan Date: Wed, 25 Nov 2015 00:37:45 +0000 Subject: [PATCH 274/298] Removed BAD_ENVIRONMENT from comments and added errno back to several fns --- native/getcomputername.cpp | 2 +- native/getlinkcount.cpp | 1 - native/getusername.cpp | 1 - native/isexecutable.cpp | 1 - native/issymlink.cpp | 3 ++- 5 files changed, 3 insertions(+), 5 deletions(-) diff --git a/native/getcomputername.cpp b/native/getcomputername.cpp index 03ec03517f..0906aa5afd 100644 --- a/native/getcomputername.cpp +++ b/native/getcomputername.cpp @@ -11,7 +11,6 @@ //! the current thread. //! //! @exception errno Passes these errors via errno to GetLastError: -//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 //! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code //! - ERROR_INVALID_ADDRESS: buffer is an invalid address //! - ERROR_GEN_FAILURE: buffer not large enough @@ -20,6 +19,7 @@ char* GetComputerName() { + errno = 0; // Get computername from system, note that gethostname(2) gets the // nodename from uname std::string computername(HOST_NAME_MAX, 0); diff --git a/native/getlinkcount.cpp b/native/getlinkcount.cpp index aab533640a..3d8061876c 100644 --- a/native/getlinkcount.cpp +++ b/native/getlinkcount.cpp @@ -30,7 +30,6 @@ //! //! @exception errno Passes these errors via errno to GetLastError: //! - ERROR_INVALID_PARAMETER: parameter is not valid -//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 //! - ERROR_FILE_NOT_FOUND: file does not exist //! - ERROR_ACCESS_DENIED: access is denied //! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified diff --git a/native/getusername.cpp b/native/getusername.cpp index 923e76e750..505291593f 100644 --- a/native/getusername.cpp +++ b/native/getusername.cpp @@ -15,7 +15,6 @@ //! //! @exception errno Passes these errors via errno to GetLastError: //! - ERROR_INVALID_PARAMETER: parameter is not valid -//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 //! - ERROR_NO_SUCH_USER: there was no corresponding user //! - ERROR_GEN_FAILURE: sysconf() or getpwuid() failed for unknown reasons //! diff --git a/native/isexecutable.cpp b/native/isexecutable.cpp index a243cbc4da..38f6ad1844 100644 --- a/native/isexecutable.cpp +++ b/native/isexecutable.cpp @@ -19,7 +19,6 @@ //! @endparblock //! //! @exception errno Passes these errors via errno to GetLastError: -//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 //! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified //! - ERROR_INVALID_ADDRESS: attempt to access invalid address //! - ERROR_GEN_FAILURE: device attached to the system is not functioning diff --git a/native/issymlink.cpp b/native/issymlink.cpp index 537a4a160a..a48a9935b1 100644 --- a/native/issymlink.cpp +++ b/native/issymlink.cpp @@ -23,7 +23,6 @@ //! //! @exception errno Passes these errors via errno to GetLastError: //! - ERROR_INVALID_PARAMETER: parameter is not valid -//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 //! - ERROR_FILE_NOT_FOUND: file does not exist //! - ERROR_ACCESS_DENIED: access is denied //! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified @@ -44,6 +43,8 @@ int32_t IsSymLink(const char* fileName) { + errno = 0; + // Check parameters if (!fileName) { From d0960b3cf22ccf2aab89ded4d8a40426d0578112 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Mon, 7 Dec 2015 15:59:53 -0800 Subject: [PATCH 275/298] Refactor host for dotnet-cli - Now uses Boost - No longer uses libicu --- host/CMakeLists.txt | 13 ++-- host/coreclrutil.cpp | 162 ++++++------------------------------------- host/coreclrutil.h | 2 +- host/main.cpp | 16 ++--- 4 files changed, 37 insertions(+), 156 deletions(-) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index cdca0049d9..985bc8bb79 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -1,10 +1,11 @@ add_library(pshost STATIC coreclrutil.cpp) -target_link_libraries(pshost dl icuuc) +target_link_libraries(pshost dl ${Boost_LIBRARIES}) +target_include_directories(pshost PRIVATE ${Boost_INCLUDE_DIRS}) target_compile_options(pshost PRIVATE -fPIC) -add_executable(powershell main.cpp) -target_link_libraries(powershell pshost) +set(Boost_USE_STATIC_LIBS ON) +find_package(Boost 1.54.0 REQUIRED COMPONENTS filesystem system) -install(TARGETS powershell pshost - RUNTIME DESTINATION bin - ARCHIVE DESTINATION lib) +# simple native host executable test +add_executable(powershell main.cpp) +target_link_libraries(powershell pshost ${Boost_LIBRARIES}) diff --git a/host/coreclrutil.cpp b/host/coreclrutil.cpp index 0324105f43..daffd4cc0d 100644 --- a/host/coreclrutil.cpp +++ b/host/coreclrutil.cpp @@ -1,14 +1,12 @@ #include "coreclrutil.h" #include #include -#include -#include #include -#include -#include #include #include -#include + +#include +using namespace boost; // The name of the CoreCLR native runtime DLL #if defined(__APPLE__) @@ -18,8 +16,7 @@ constexpr char coreClrDll[] = "libcoreclr.so"; #endif void* coreclrLib; -char exePath[PATH_MAX]; -char pwrshPath[PATH_MAX]; +char coreRoot[PATH_MAX]; // Prototype of the coreclr_initialize function from the libcoreclr.so typedef int (*InitializeCoreCLRFunction)( @@ -41,93 +38,22 @@ ShutdownCoreCLRFunction shutdownCoreCLR; ExecuteAssemblyFunction executeAssembly; CreateDelegateFunction createDelegate; -// -// Below is from unixcoreruncommon/coreruncommon.cpp -// - -bool GetAbsolutePath(const char* path, std::string& absolutePath) -{ - char realPath[PATH_MAX]; - if (realpath(path, realPath) != nullptr && realPath[0] != '\0') - { - absolutePath.assign(realPath); - // realpath should return canonicalized path without the trailing slash - assert(absolutePath.back() != '/'); - return true; - } - - std::cerr << "failed to get absolute path for " << path << std::endl; - return false; -} - -// TODO use dirname -bool GetDirectory(const char* absolutePath, std::string& directory) -{ - directory.assign(absolutePath); - size_t lastSlash = directory.rfind('/'); - if (lastSlash != std::string::npos) - { - directory.erase(lastSlash); - return true; - } - - std::cerr << "failed to get directory for " << absolutePath << std::endl; - return false; -} - // // Get the absolute path given the environment variable. // // Return true in case of a success, false otherwise. // -bool GetEnvAbsolutePath(const char* envVar, std::string& absolutePath) +filesystem::path GetEnvAbsolutePath(const char* env) { - const char* filesPathLocal = std::getenv(envVar);; - if (filesPathLocal == nullptr) - { - return false; - } + const char* local = std::getenv(env); + if (!local) + return nullptr; - return GetAbsolutePath(filesPathLocal, absolutePath); -} - -// -// Get the a root path given an environment variable and default -// relative to exePath -// -bool GetRootPath(const char* envVar, - const char* relativePath, - std::string& absolutePath) -{ - if (!GetEnvAbsolutePath(envVar, absolutePath)) - { - // Default to bin/relativePath - std::string path; - if (!GetDirectory(exePath, path)) - { - return false; - } - path.append("/"); - path.append(relativePath); - return GetAbsolutePath(path.c_str(), absolutePath); - } - - return true; -} - -// Get the PowerShell root path, with sensible default -bool GetPwrshRoot(std::string& absolutePath) -{ - return GetRootPath("PWRSH_ROOT", "../lib/powershell", absolutePath); -} - -// Get the CoreCLR root path, with sensible default -bool GetCoreRoot(std::string& absolutePath) -{ - return GetRootPath("CORE_ROOT", "../lib/coreclr", absolutePath); + return filesystem::canonical(local); } // Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. +// Note: copied from unixcorerun void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) { const char * const tpaExtensions[] = { @@ -229,27 +155,30 @@ int startCoreCLR( void** hostHandle, unsigned int* domainId) { + char exePath[PATH_MAX]; + // get path to current executable readlink("/proc/self/exe", exePath, PATH_MAX); // get the CoreCLR root path - std::string clrAbsolutePath; - if(!GetCoreRoot(clrAbsolutePath)) + auto clrAbsolutePath = GetEnvAbsolutePath("CORE_ROOT"); + if(!clrAbsolutePath.is_absolute()) { + std::cerr << "Failed to get CORE_ROOT path" << std::endl; return -1; } + // copy to shared buffer + clrAbsolutePath.native().copy(coreRoot, clrAbsolutePath.native().size(), 0); // get the CoreCLR shared library path - std::string coreClrDllPath(clrAbsolutePath); - coreClrDllPath.append("/"); - coreClrDllPath.append(coreClrDll); + filesystem::path coreClrDllPath(clrAbsolutePath); + coreClrDllPath /= coreClrDll; // open the shared library coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); if (coreclrLib == nullptr) { - char* error = dlerror(); - std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl; + std::cerr << "dlopen failed to open the CoreCLR library: " << dlerror() << std::endl; return -1; } @@ -286,30 +215,6 @@ int startCoreCLR( // add assemblies in the CoreCLR root path AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(), tpaList); - // get path to PowerShell libraries - std::string psAbsolutePath; - if(!GetPwrshRoot(psAbsolutePath)) - { - return -1; - } - psAbsolutePath.copy(pwrshPath, psAbsolutePath.size(), 0); - - // get path to AssemblyLoadContext.dll - std::string alcAbsolutePath(psAbsolutePath); - alcAbsolutePath.append("/"); - alcAbsolutePath.append("Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"); - - // add AssemblyLoadContext - tpaList.append(alcAbsolutePath); - - // generate the assembly search paths - std::string appPath(psAbsolutePath); - // TODO: add LD_LIBRARY_PATH? - - std::string nativeDllSearchDirs(appPath); - nativeDllSearchDirs.append(":"); - nativeDllSearchDirs.append(clrAbsolutePath); - // create list of properties to initialize CoreCLR const char* propertyKeys[] = { "TRUSTED_PLATFORM_ASSEMBLIES", @@ -321,9 +226,9 @@ int startCoreCLR( const char* propertyValues[] = { tpaList.c_str(), - appPath.c_str(), - appPath.c_str(), - nativeDllSearchDirs.c_str(), + clrAbsolutePath.c_str(), + clrAbsolutePath.c_str(), + clrAbsolutePath.c_str(), "UseLatestBehaviorWhenTFMNotSpecified" }; @@ -343,27 +248,6 @@ int startCoreCLR( return -1; } - // initialize PowerShell's custom assembly load context - typedef void (*LoaderRunHelperFp)(const char16_t* appPath); - LoaderRunHelperFp loaderDelegate = nullptr; - status = createDelegate( - *hostHandle, - *domainId, - "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "System.Management.Automation.PowerShellAssemblyLoadContextInitializer", - "SetPowerShellAssemblyLoadContext", - (void**)&loaderDelegate); - - if (!SUCCEEDED(status)) - { - std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; - return -1; - } - - icu::UnicodeString psUnicodeAbsolutePath = icu::UnicodeString::fromUTF8(psAbsolutePath.c_str()); - - loaderDelegate((const char16_t*)psUnicodeAbsolutePath.getTerminatedBuffer()); - return status; } diff --git a/host/coreclrutil.h b/host/coreclrutil.h index 843a440ad5..8fb99c79fc 100644 --- a/host/coreclrutil.h +++ b/host/coreclrutil.h @@ -48,7 +48,7 @@ extern "C" extern ExecuteAssemblyFunction executeAssembly; extern CreateDelegateFunction createDelegate; - extern char pwrshPath[]; + extern char coreRoot[]; #ifdef __cplusplus } #endif diff --git a/host/main.cpp b/host/main.cpp index 36bee13dae..dcb39be0ea 100644 --- a/host/main.cpp +++ b/host/main.cpp @@ -11,19 +11,15 @@ namespace Cmdline << "Usage: powershell [assembly] [...]" << std::endl << std::endl << "What it does:" << std::endl - << "- the host assumes that CoreCLR is located $CORE_ROOT," << std::endl - << " else in lib/coreclr" - << "- the host assumes that the assembly named" << std::endl - << " Microsoft.PowerShell.CoreCLR.AssemblyLoadContext is " << std::endl - << " located in $PWRSH_ROOT, else in lib/powershell" << std::endl - << "- the host will launch $PWRSH_ROOT/powershell.exe" << std::endl - << " if not given an explicit assembly.exe" << std::endl + << "- the host assumes that PSL has been published to $CORE_ROOT," << std::endl + << "- the host will launch $CORE_ROOT/Microsoft.PowerShell.Linux.Host.dll" << std::endl + << " if not given an explicit assembly" << std::endl << "- all additional parameters at the end of the command line are forwarded" << std::endl << " to the Main function in the assembly" << std::endl << "- the host will execute the Main function in the specified assembly" << std::endl << std::endl << "Example:" << std::endl - << "CORE_ROOT=/test/coreclr PWRSH_ROOT=/test/powershell ./powershell get-process" << std::endl; + << "CORE_ROOT=/test/coreclr ./powershell get-process" << std::endl; } struct Args @@ -90,9 +86,9 @@ int main(int argc, char** argv) // default to powershell.exe if no host specified if (args.assembly.empty()) { - args.assembly.assign(pwrshPath); + args.assembly.append(coreRoot); args.assembly.append("/"); - args.assembly.append("powershell.exe"); + args.assembly.append("Microsoft.PowerShell.Linux.Host.dll"); } // call into Main of assembly From 418b947f38ec5b2b35b3fd4707277e5e2b91aea2 Mon Sep 17 00:00:00 2001 From: Paul Allen Date: Mon, 7 Dec 2015 17:11:05 -0800 Subject: [PATCH 276/298] Null terminate exePath --- host/coreclrutil.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/host/coreclrutil.cpp b/host/coreclrutil.cpp index daffd4cc0d..0ccbb9bd66 100644 --- a/host/coreclrutil.cpp +++ b/host/coreclrutil.cpp @@ -158,7 +158,10 @@ int startCoreCLR( char exePath[PATH_MAX]; // get path to current executable - readlink("/proc/self/exe", exePath, PATH_MAX); + ssize_t len = readlink("/proc/self/exe", exePath, PATH_MAX); + if (len == -1 || len == sizeof(exePath)) + len = 0; + exePath[len] = '\0'; // get the CoreCLR root path auto clrAbsolutePath = GetEnvAbsolutePath("CORE_ROOT"); From a33977edb26b22e0bf8ea9a3bf8f9d9464478fb4 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 9 Dec 2015 09:57:08 -0800 Subject: [PATCH 277/298] Resurrect PowerShell's AssemblyLoadContext --- host/CMakeLists.txt | 2 +- host/coreclrutil.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 985bc8bb79..94b132a3e5 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -1,5 +1,5 @@ add_library(pshost STATIC coreclrutil.cpp) -target_link_libraries(pshost dl ${Boost_LIBRARIES}) +target_link_libraries(pshost dl icuuc ${Boost_LIBRARIES}) target_include_directories(pshost PRIVATE ${Boost_INCLUDE_DIRS}) target_compile_options(pshost PRIVATE -fPIC) diff --git a/host/coreclrutil.cpp b/host/coreclrutil.cpp index 0ccbb9bd66..679cecb157 100644 --- a/host/coreclrutil.cpp +++ b/host/coreclrutil.cpp @@ -5,6 +5,8 @@ #include #include +#include + #include using namespace boost; @@ -251,6 +253,30 @@ int startCoreCLR( return -1; } + // initialize PowerShell's custom assembly load context + filesystem::path alcAbsolutePath(clrAbsolutePath); + alcAbsolutePath /= "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"; + + typedef void (*LoaderRunHelperFp)(const char16_t* appPath); + LoaderRunHelperFp loaderDelegate = nullptr; + status = createDelegate( + *hostHandle, + *domainId, + "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, PublicKeyToken=null", + "System.Management.Automation.PowerShellAssemblyLoadContextInitializer", + "SetPowerShellAssemblyLoadContext", + (void**)&loaderDelegate); + + if (!SUCCEEDED(status)) + { + std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; + return -1; + } + + icu::UnicodeString psUnicodeAbsolutePath = icu::UnicodeString::fromUTF8(clrAbsolutePath.c_str()); + + loaderDelegate((const char16_t*)psUnicodeAbsolutePath.getTerminatedBuffer()); + return status; } From e2b2279fcb8e447926be8d71d747a82aa35a8432 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 15 Dec 2015 14:23:09 -0800 Subject: [PATCH 278/298] Remove icuuc dependency from host Broke this dependency by changing the `SetPowerShellAssemblyLoadContext()` function to expect an LPStr on Linux, instead of an LPWStr, which is easier to deal with because .NET can marshal an LPStr automatically. --- host/CMakeLists.txt | 2 +- host/coreclrutil.cpp | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 94b132a3e5..985bc8bb79 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -1,5 +1,5 @@ add_library(pshost STATIC coreclrutil.cpp) -target_link_libraries(pshost dl icuuc ${Boost_LIBRARIES}) +target_link_libraries(pshost dl ${Boost_LIBRARIES}) target_include_directories(pshost PRIVATE ${Boost_INCLUDE_DIRS}) target_compile_options(pshost PRIVATE -fPIC) diff --git a/host/coreclrutil.cpp b/host/coreclrutil.cpp index 679cecb157..1a27d359fc 100644 --- a/host/coreclrutil.cpp +++ b/host/coreclrutil.cpp @@ -5,8 +5,6 @@ #include #include -#include - #include using namespace boost; @@ -257,7 +255,7 @@ int startCoreCLR( filesystem::path alcAbsolutePath(clrAbsolutePath); alcAbsolutePath /= "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"; - typedef void (*LoaderRunHelperFp)(const char16_t* appPath); + typedef void (*LoaderRunHelperFp)(const char* appPath); LoaderRunHelperFp loaderDelegate = nullptr; status = createDelegate( *hostHandle, @@ -273,9 +271,7 @@ int startCoreCLR( return -1; } - icu::UnicodeString psUnicodeAbsolutePath = icu::UnicodeString::fromUTF8(clrAbsolutePath.c_str()); - - loaderDelegate((const char16_t*)psUnicodeAbsolutePath.getTerminatedBuffer()); + loaderDelegate(clrAbsolutePath.c_str()); return status; } From fc81606886fd659e18218097301a25ca4cd91643 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sat, 19 Dec 2015 11:52:30 -0800 Subject: [PATCH 279/298] Remove icuuc entirely While we no longer used it, we still linked to it and included its header. This is now gone. --- native/CMakeLists.txt | 1 - native/getlinkcount.cpp | 1 - native/getusername.cpp | 1 - native/issymlink.cpp | 1 - tests/test-getusername.cpp | 1 - 5 files changed, 5 deletions(-) diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index e2841943d0..20e8e8b2d3 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -9,7 +9,6 @@ add_library(psnative SHARED setdate.cpp terminal.cpp) -target_link_libraries(psnative icuuc) target_include_directories (psnative PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) install(TARGETS psnative diff --git a/native/getlinkcount.cpp b/native/getlinkcount.cpp index 3d8061876c..e11ba7d208 100644 --- a/native/getlinkcount.cpp +++ b/native/getlinkcount.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include "getlinkcount.h" //! @brief GetLinkCount retrieves the file link count (number of hard links) diff --git a/native/getusername.cpp b/native/getusername.cpp index 505291593f..0efab96688 100644 --- a/native/getusername.cpp +++ b/native/getusername.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "getusername.h" diff --git a/native/issymlink.cpp b/native/issymlink.cpp index a48a9935b1..d4ce011cba 100644 --- a/native/issymlink.cpp +++ b/native/issymlink.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include "issymlink.h" //! @brief IsSymLink determines if path is a symbolic link diff --git a/tests/test-getusername.cpp b/tests/test-getusername.cpp index cab8cb98bf..2ccb29f68a 100644 --- a/tests/test-getusername.cpp +++ b/tests/test-getusername.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "getusername.h" From 262471958f5c89aab30ebaead9da9d3dea1e7f49 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sat, 19 Dec 2015 11:54:01 -0800 Subject: [PATCH 280/298] Fix Boost include dir variable Boost_INCLUDE_DIRS is only used intermittently by CMake, whereas Boost_INCLUDE_DIR (no S) is always populated correctly. --- host/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 985bc8bb79..51e9a0c5ce 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -1,6 +1,6 @@ add_library(pshost STATIC coreclrutil.cpp) target_link_libraries(pshost dl ${Boost_LIBRARIES}) -target_include_directories(pshost PRIVATE ${Boost_INCLUDE_DIRS}) +target_include_directories(pshost PRIVATE ${Boost_INCLUDE_DIR}) target_compile_options(pshost PRIVATE -fPIC) set(Boost_USE_STATIC_LIBS ON) From 129bff77a2cdc4e29e310f28fb15c8deed59ce85 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Sat, 19 Dec 2015 11:58:37 -0800 Subject: [PATCH 281/298] Return 0, not undefined FALSE --- native/getlinkcount.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/getlinkcount.cpp b/native/getlinkcount.cpp index e11ba7d208..9e8db3d652 100644 --- a/native/getlinkcount.cpp +++ b/native/getlinkcount.cpp @@ -55,7 +55,7 @@ int32_t GetLinkCount(const char* fileName, int32_t *count) if (!fileName) { errno = ERROR_INVALID_PARAMETER; - return FALSE; + return 0; } struct stat statBuf; From 5b1bc20618333c0a1509870549f4d7bf30056561 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Mon, 21 Dec 2015 10:15:13 -0800 Subject: [PATCH 282/298] Handle error in GetEnvAbsolutePath Can't return nullptr because its an invalid cast for the return type. --- host/coreclrutil.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/host/coreclrutil.cpp b/host/coreclrutil.cpp index 1a27d359fc..ccf802386b 100644 --- a/host/coreclrutil.cpp +++ b/host/coreclrutil.cpp @@ -47,7 +47,9 @@ filesystem::path GetEnvAbsolutePath(const char* env) { const char* local = std::getenv(env); if (!local) - return nullptr; + { + std::cerr << "Could not read environment variable " << env << std::endl; + } return filesystem::canonical(local); } From 3d52aa35dab5c478c4413b018f2769aee32c9250 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Mon, 21 Dec 2015 10:15:16 -0800 Subject: [PATCH 283/298] Use _POSIX_HOST_NAME_MAX instead of HOST_NAME_MAX For OS X compatibility. --- native/getcomputername.cpp | 2 +- tests/test-getcomputername.cpp | 2 +- tests/test-getfullyqualifiedname.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/native/getcomputername.cpp b/native/getcomputername.cpp index 0906aa5afd..e363cf1678 100644 --- a/native/getcomputername.cpp +++ b/native/getcomputername.cpp @@ -22,7 +22,7 @@ char* GetComputerName() errno = 0; // Get computername from system, note that gethostname(2) gets the // nodename from uname - std::string computername(HOST_NAME_MAX, 0); + std::string computername(_POSIX_HOST_NAME_MAX, 0); int err = gethostname(&computername[0], computername.length()); // Map errno to Win32 Error Codes if (err != 0) diff --git a/tests/test-getcomputername.cpp b/tests/test-getcomputername.cpp index e0e9ca17f5..9c1d676cbd 100644 --- a/tests/test-getcomputername.cpp +++ b/tests/test-getcomputername.cpp @@ -12,7 +12,7 @@ class GetComputerNameTest : public ::testing::Test TEST_F(GetComputerNameTest, Success) { - char expectedComputerName[HOST_NAME_MAX]; + char expectedComputerName[_POSIX_HOST_NAME_MAX]; // the gethostname system call gets the nodename from uname FILE *fPtr = popen("uname -n", "r"); diff --git a/tests/test-getfullyqualifiedname.cpp b/tests/test-getfullyqualifiedname.cpp index c34419ab60..974316562a 100644 --- a/tests/test-getfullyqualifiedname.cpp +++ b/tests/test-getfullyqualifiedname.cpp @@ -12,7 +12,7 @@ class GetFullyQualifiedNameTest : public ::testing::Test TEST_F(GetFullyQualifiedNameTest, ValidateLinuxGetFullyQualifiedDomainName) { - char expectedComputerName[HOST_NAME_MAX]; + char expectedComputerName[_POSIX_HOST_NAME_MAX]; //Get expected result from using linux command From eb6099fb49242f21b01d41bdba1c22ea93898835 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 22 Dec 2015 12:55:46 -0800 Subject: [PATCH 284/298] Clean up native host CLI - Fix launching of specific assembly via --assembly - Fix displaying help via --native-help --- host/main.cpp | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/host/main.cpp b/host/main.cpp index dcb39be0ea..8665c80429 100644 --- a/host/main.cpp +++ b/host/main.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -8,18 +9,18 @@ namespace Cmdline void printHelp() { std::cerr << "PowerShell on Linux native host" << std::endl - << "Usage: powershell [assembly] [...]" << std::endl + << "Usage: powershell [-a assembly] [...]" << std::endl << std::endl << "What it does:" << std::endl << "- the host assumes that PSL has been published to $CORE_ROOT," << std::endl << "- the host will launch $CORE_ROOT/Microsoft.PowerShell.Linux.Host.dll" << std::endl - << " if not given an explicit assembly" << std::endl + << " if not given an explicit assembly via -a (or --assembly)" << std::endl << "- all additional parameters at the end of the command line are forwarded" << std::endl << " to the Main function in the assembly" << std::endl << "- the host will execute the Main function in the specified assembly" << std::endl << std::endl << "Example:" << std::endl - << "CORE_ROOT=/test/coreclr ./powershell get-process" << std::endl; + << "CORE_ROOT=$(pwd)/bin ./powershell get-process" << std::endl; } struct Args @@ -36,14 +37,7 @@ namespace Cmdline std::string assembly; }; - // checks if string ends with ".exe" - bool isExe(std::string arg) - { - std::size_t dot = arg.find_last_of("."); - return dot == std::string::npos ? false : arg.substr(dot) == ".exe"; - } - - // simple extraction of assembly.exe so we can run other hosts + // simple CLI parsing so we can run other hosts void parseCmdline(int argc, char** argv, Args& args) { // index of arguments to forward (skip zeroth) @@ -51,12 +45,21 @@ namespace Cmdline // if we have any arguments if (argc > 1) { - // check if the first is an assembly.exe - const std::string arg = argv[i]; - if (isExe(arg)) + std::string arg(argv[i]); + + // handle help if first argument; note that this can't be --help + // because the managed hosts use it + if (arg == "--native-help") { - args.assembly.assign(arg); - ++i; // don't forward the first argument + printHelp(); + exit(0); + } + + // check if given an explicit assembly to launch + if (argc > 2 && (arg == "-a" || arg == "--assembly")) + { + args.assembly.assign(std::string(argv[i+1])); + i += 2; // don't forward the first two arguments } } // forward arguments From 5bcd7148939db50e586291f874f0002a2dd1886f Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 5 Jan 2016 17:37:03 -0800 Subject: [PATCH 285/298] Remove host code Moved to OMI provider as the local shell no longer depends on a custom native host. --- CMakeLists.txt | 1 - host/CMakeLists.txt | 11 - host/coreclrutil.cpp | 297 ------------------- host/coreclrutil.h | 54 ---- host/main.cpp | 113 -------- host/unixcoreruncommon/.gitmirror | 1 - host/unixcoreruncommon/coreruncommon.cpp | 346 ----------------------- host/unixcoreruncommon/coreruncommon.h | 46 --- 8 files changed, 869 deletions(-) delete mode 100644 host/CMakeLists.txt delete mode 100644 host/coreclrutil.cpp delete mode 100644 host/coreclrutil.h delete mode 100644 host/main.cpp delete mode 100644 host/unixcoreruncommon/.gitmirror delete mode 100644 host/unixcoreruncommon/coreruncommon.cpp delete mode 100644 host/unixcoreruncommon/coreruncommon.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e0e4a7ab90..e665428fd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,4 +7,3 @@ add_compile_options(-std=c++11 -Wall -Werror) enable_testing() add_subdirectory(tests) add_subdirectory(native) -add_subdirectory(host) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt deleted file mode 100644 index 51e9a0c5ce..0000000000 --- a/host/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_library(pshost STATIC coreclrutil.cpp) -target_link_libraries(pshost dl ${Boost_LIBRARIES}) -target_include_directories(pshost PRIVATE ${Boost_INCLUDE_DIR}) -target_compile_options(pshost PRIVATE -fPIC) - -set(Boost_USE_STATIC_LIBS ON) -find_package(Boost 1.54.0 REQUIRED COMPONENTS filesystem system) - -# simple native host executable test -add_executable(powershell main.cpp) -target_link_libraries(powershell pshost ${Boost_LIBRARIES}) diff --git a/host/coreclrutil.cpp b/host/coreclrutil.cpp deleted file mode 100644 index ccf802386b..0000000000 --- a/host/coreclrutil.cpp +++ /dev/null @@ -1,297 +0,0 @@ -#include "coreclrutil.h" -#include -#include -#include -#include -#include - -#include -using namespace boost; - -// The name of the CoreCLR native runtime DLL -#if defined(__APPLE__) -constexpr char coreClrDll[] = "libcoreclr.dylib"; -#else -constexpr char coreClrDll[] = "libcoreclr.so"; -#endif - -void* coreclrLib; -char coreRoot[PATH_MAX]; - -// Prototype of the coreclr_initialize function from the libcoreclr.so -typedef int (*InitializeCoreCLRFunction)( - const char* exePath, - const char* appDomainFriendlyName, - int propertyCount, - const char** propertyKeys, - const char** propertyValues, - void** hostHandle, - unsigned int* domainId); - -// Prototype of the coreclr_shutdown function from the libcoreclr.so -typedef int (*ShutdownCoreCLRFunction)( - void* hostHandle, - unsigned int domainId); - -InitializeCoreCLRFunction initializeCoreCLR; -ShutdownCoreCLRFunction shutdownCoreCLR; -ExecuteAssemblyFunction executeAssembly; -CreateDelegateFunction createDelegate; - -// -// Get the absolute path given the environment variable. -// -// Return true in case of a success, false otherwise. -// -filesystem::path GetEnvAbsolutePath(const char* env) -{ - const char* local = std::getenv(env); - if (!local) - { - std::cerr << "Could not read environment variable " << env << std::endl; - } - - return filesystem::canonical(local); -} - -// Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. -// Note: copied from unixcorerun -void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) -{ - const char * const tpaExtensions[] = { - ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir - ".dll", - ".ni.exe", - ".exe", - }; - - DIR* dir = opendir(directory); - if (dir == nullptr) - { - return; - } - - std::set addedAssemblies; - - // Walk the directory for each extension separately so that we first get files with .ni.dll extension, - // then files with .dll extension, etc. - for (unsigned int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) - { - const char* ext = tpaExtensions[extIndex]; - int extLength = strlen(ext); - - struct dirent* entry; - - // For all entries in the directory - while ((entry = readdir(dir)) != nullptr) - { - // We are interested in files only - switch (entry->d_type) - { - case DT_REG: - break; - - // Handle symlinks and file systems that do not support d_type - case DT_LNK: - case DT_UNKNOWN: - { - std::string fullFilename; - - fullFilename.append(directory); - fullFilename.append("/"); - fullFilename.append(entry->d_name); - - struct stat sb; - if (stat(fullFilename.c_str(), &sb) == -1) - { - continue; - } - - if (!S_ISREG(sb.st_mode)) - { - continue; - } - } - break; - - default: - continue; - } - - std::string filename(entry->d_name); - - // Check if the extension matches the one we are looking for - int extPos = filename.length() - extLength; - if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) - { - continue; - } - - std::string filenameWithoutExt(filename.substr(0, extPos)); - - // Make sure if we have an assembly with multiple extensions present, - // we insert only one version of it. - if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) - { - addedAssemblies.insert(filenameWithoutExt); - - tpaList.append(directory); - tpaList.append("/"); - tpaList.append(filename); - tpaList.append(":"); - } - } - - // Rewind the directory stream to be able to iterate over it for the next extension - rewinddir(dir); - } - - closedir(dir); -} - -// -// Below is our custom start/stop interface -// -int startCoreCLR( - const char* appDomainFriendlyName, - void** hostHandle, - unsigned int* domainId) -{ - char exePath[PATH_MAX]; - - // get path to current executable - ssize_t len = readlink("/proc/self/exe", exePath, PATH_MAX); - if (len == -1 || len == sizeof(exePath)) - len = 0; - exePath[len] = '\0'; - - // get the CoreCLR root path - auto clrAbsolutePath = GetEnvAbsolutePath("CORE_ROOT"); - if(!clrAbsolutePath.is_absolute()) - { - std::cerr << "Failed to get CORE_ROOT path" << std::endl; - return -1; - } - // copy to shared buffer - clrAbsolutePath.native().copy(coreRoot, clrAbsolutePath.native().size(), 0); - - // get the CoreCLR shared library path - filesystem::path coreClrDllPath(clrAbsolutePath); - coreClrDllPath /= coreClrDll; - - // open the shared library - coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL); - if (coreclrLib == nullptr) - { - std::cerr << "dlopen failed to open the CoreCLR library: " << dlerror() << std::endl; - return -1; - } - - // query and verify the function pointers - initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize"); - shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown"); - executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly"); - createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate"); - - if (initializeCoreCLR == nullptr) - { - std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl; - return -1; - } - if (executeAssembly == nullptr) - { - std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl; - return -1; - } - if (shutdownCoreCLR == nullptr) - { - std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl; - return -1; - } - if (createDelegate == nullptr) - { - std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl; - return -1; - } - - // generate the Trusted Platform Assemblies list - std::string tpaList; - - // add assemblies in the CoreCLR root path - AddFilesFromDirectoryToTpaList(clrAbsolutePath.c_str(), tpaList); - - // create list of properties to initialize CoreCLR - const char* propertyKeys[] = { - "TRUSTED_PLATFORM_ASSEMBLIES", - "APP_PATHS", - "APP_NI_PATHS", - "NATIVE_DLL_SEARCH_DIRECTORIES", - "AppDomainCompatSwitch" - }; - - const char* propertyValues[] = { - tpaList.c_str(), - clrAbsolutePath.c_str(), - clrAbsolutePath.c_str(), - clrAbsolutePath.c_str(), - "UseLatestBehaviorWhenTFMNotSpecified" - }; - - // initialize CoreCLR - int status = initializeCoreCLR( - exePath, - appDomainFriendlyName, - sizeof(propertyKeys)/sizeof(propertyKeys[0]), - propertyKeys, - propertyValues, - hostHandle, - domainId); - - if (!SUCCEEDED(status)) - { - std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl; - return -1; - } - - // initialize PowerShell's custom assembly load context - filesystem::path alcAbsolutePath(clrAbsolutePath); - alcAbsolutePath /= "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll"; - - typedef void (*LoaderRunHelperFp)(const char* appPath); - LoaderRunHelperFp loaderDelegate = nullptr; - status = createDelegate( - *hostHandle, - *domainId, - "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=1.0.0.0, PublicKeyToken=null", - "System.Management.Automation.PowerShellAssemblyLoadContextInitializer", - "SetPowerShellAssemblyLoadContext", - (void**)&loaderDelegate); - - if (!SUCCEEDED(status)) - { - std::cerr << "could not create delegate for SetPowerShellAssemblyLoadContext - status: " << std::hex << status << std::endl; - return -1; - } - - loaderDelegate(clrAbsolutePath.c_str()); - - return status; -} - -int stopCoreCLR(void* hostHandle, unsigned int domainId) -{ - // shutdown CoreCLR - int status = shutdownCoreCLR(hostHandle, domainId); - if (!SUCCEEDED(status)) - { - std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl; - } - - // close the dynamic library - if (0 != dlclose(coreclrLib)) - { - std::cerr << "failed to close CoreCLR library" << std::endl; - } - - return status; -} diff --git a/host/coreclrutil.h b/host/coreclrutil.h deleted file mode 100644 index 8fb99c79fc..0000000000 --- a/host/coreclrutil.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#define SUCCEEDED(Status) ((Status) >= 0) - -/* PowerShell on Linux custom host interface - * - * startCoreCLR() takes a friendly name, e.g. "powershell", and a - * writable pointer and identifier - * - * executeAssmbly() will be made available after starting CoreCLR, and - * is used to launch assemblies with a main function - * - * createDelegate() works similarly but provides a reverse P/Invoke - * given an assembly, type, and method; note that on Linux, - * PublicKeyToken must be null - * - * stopCoreCLR() will deinitialize given the handle and identifier - */ - -#ifdef __cplusplus -extern "C" -{ -#endif - int startCoreCLR( - const char* appDomainFriendlyName, - void** hostHandle, - unsigned int* domainId); - - int stopCoreCLR(void* hostHandle, unsigned int domainId); - - /* Prototype of the coreclr_execute_assembly function from the libcoreclr.so */ - typedef int (*ExecuteAssemblyFunction)( - void* hostHandle, - unsigned int domainId, - int argc, - const char** argv, - const char* managedAssemblyPath, - unsigned int* exitCode); - - /* Prototype of coreclr_create_delegate function from the libcoreclr.so */ - typedef int (*CreateDelegateFunction)( - void* hostHandle, - unsigned int domainId, - const char* entryPointAssemblyName, - const char* entryPointTypeName, - const char* entryPointMethodName, - void** delegate); - - extern ExecuteAssemblyFunction executeAssembly; - extern CreateDelegateFunction createDelegate; - extern char coreRoot[]; -#ifdef __cplusplus -} -#endif diff --git a/host/main.cpp b/host/main.cpp deleted file mode 100644 index 8665c80429..0000000000 --- a/host/main.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include -#include -#include -#include -#include "coreclrutil.h" - -namespace Cmdline -{ - void printHelp() - { - std::cerr << "PowerShell on Linux native host" << std::endl - << "Usage: powershell [-a assembly] [...]" << std::endl - << std::endl - << "What it does:" << std::endl - << "- the host assumes that PSL has been published to $CORE_ROOT," << std::endl - << "- the host will launch $CORE_ROOT/Microsoft.PowerShell.Linux.Host.dll" << std::endl - << " if not given an explicit assembly via -a (or --assembly)" << std::endl - << "- all additional parameters at the end of the command line are forwarded" << std::endl - << " to the Main function in the assembly" << std::endl - << "- the host will execute the Main function in the specified assembly" << std::endl - << std::endl - << "Example:" << std::endl - << "CORE_ROOT=$(pwd)/bin ./powershell get-process" << std::endl; - } - - struct Args - { - Args() : - argc(0), - argv(nullptr), - assembly() - { - } - - int argc; - char** argv; - std::string assembly; - }; - - // simple CLI parsing so we can run other hosts - void parseCmdline(int argc, char** argv, Args& args) - { - // index of arguments to forward (skip zeroth) - int i = 1; - // if we have any arguments - if (argc > 1) - { - std::string arg(argv[i]); - - // handle help if first argument; note that this can't be --help - // because the managed hosts use it - if (arg == "--native-help") - { - printHelp(); - exit(0); - } - - // check if given an explicit assembly to launch - if (argc > 2 && (arg == "-a" || arg == "--assembly")) - { - args.assembly.assign(std::string(argv[i+1])); - i += 2; // don't forward the first two arguments - } - } - // forward arguments - args.argc = argc - i; - args.argv = &argv[i]; - } -} - -int main(int argc, char** argv) -{ - Cmdline::Args args; - Cmdline::parseCmdline(argc, argv, args); - - void* hostHandle; - unsigned int domainId; - int status = startCoreCLR( - "psl_cmdline_host", - &hostHandle, - &domainId); - - if (!SUCCEEDED(status)) - { - std::cerr << "could not start CoreCLR" << std::endl; - return -1; - } - - // default to powershell.exe if no host specified - if (args.assembly.empty()) - { - args.assembly.append(coreRoot); - args.assembly.append("/"); - args.assembly.append("Microsoft.PowerShell.Linux.Host.dll"); - } - - // call into Main of assembly - unsigned int exitCode; - executeAssembly( - hostHandle, domainId, args.argc, - (const char**)args.argv, - args.assembly.c_str(), - &exitCode); - - status = stopCoreCLR(hostHandle, domainId); - if (!SUCCEEDED(status)) - { - std::cerr << "could not stop CoreCLR" << std::endl; - return -1; - } - - return exitCode; -} diff --git a/host/unixcoreruncommon/.gitmirror b/host/unixcoreruncommon/.gitmirror deleted file mode 100644 index f507630f94..0000000000 --- a/host/unixcoreruncommon/.gitmirror +++ /dev/null @@ -1 +0,0 @@ -Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror. \ No newline at end of file diff --git a/host/unixcoreruncommon/coreruncommon.cpp b/host/unixcoreruncommon/coreruncommon.cpp deleted file mode 100644 index ecbbf39290..0000000000 --- a/host/unixcoreruncommon/coreruncommon.cpp +++ /dev/null @@ -1,346 +0,0 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -// -// Code that is used by both the Unix corerun and coreconsole. -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// The name of the CoreCLR native runtime DLL -#if defined(__APPLE__) -static const char * const coreClrDll = "libcoreclr.dylib"; -#else -static const char * const coreClrDll = "libcoreclr.so"; -#endif - -#define SUCCEEDED(Status) ((Status) >= 0) - -// Prototype of the coreclr_initialize function from the libcoreclr.so -typedef int (*InitializeCoreCLRFunction)( - const char* exePath, - const char* appDomainFriendlyName, - int propertyCount, - const char** propertyKeys, - const char** propertyValues, - void** hostHandle, - unsigned int* domainId); - -// Prototype of the coreclr_shutdown function from the libcoreclr.so -typedef int (*ShutdownCoreCLRFunction)( - void* hostHandle, - unsigned int domainId); - -// Prototype of the coreclr_execute_assembly function from the libcoreclr.so -typedef int (*ExecuteAssemblyFunction)( - void* hostHandle, - unsigned int domainId, - int argc, - const char** argv, - const char* managedAssemblyPath, - unsigned int* exitCode); - -bool GetAbsolutePath(const char* path, std::string& absolutePath) -{ - bool result = false; - - char realPath[PATH_MAX]; - if (realpath(path, realPath) != nullptr && realPath[0] != '\0') - { - absolutePath.assign(realPath); - // realpath should return canonicalized path without the trailing slash - assert(absolutePath.back() != '/'); - - result = true; - } - - return result; -} - -bool GetDirectory(const char* absolutePath, std::string& directory) -{ - directory.assign(absolutePath); - size_t lastSlash = directory.rfind('/'); - if (lastSlash != std::string::npos) - { - directory.erase(lastSlash); - return true; - } - - return false; -} - -bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath) -{ - std::string clrFilesRelativePath; - const char* clrFilesPathLocal = clrFilesPath; - if (clrFilesPathLocal == nullptr) - { - // There was no CLR files path specified, use the folder of the corerun/coreconsole - if (!GetDirectory(currentExePath, clrFilesRelativePath)) - { - perror("Failed to get directory from argv[0]"); - return false; - } - - clrFilesPathLocal = clrFilesRelativePath.c_str(); - - // TODO: consider using an env variable (if defined) as a fall-back. - // The windows version of the corerun uses core_root env variable - } - - if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath)) - { - perror("Failed to convert CLR files path to absolute path"); - return false; - } - - return true; -} - -void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList) -{ - const char * const tpaExtensions[] = { - ".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir - ".dll", - ".ni.exe", - ".exe", - }; - - DIR* dir = opendir(directory); - if (dir == nullptr) - { - return; - } - - std::set addedAssemblies; - - // Walk the directory for each extension separately so that we first get files with .ni.dll extension, - // then files with .dll extension, etc. - for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++) - { - const char* ext = tpaExtensions[extIndex]; - int extLength = strlen(ext); - - struct dirent* entry; - - // For all entries in the directory - while ((entry = readdir(dir)) != nullptr) - { - // We are interested in files only - switch (entry->d_type) - { - case DT_REG: - break; - - // Handle symlinks and file systems that do not support d_type - case DT_LNK: - case DT_UNKNOWN: - { - std::string fullFilename; - - fullFilename.append(directory); - fullFilename.append("/"); - fullFilename.append(entry->d_name); - - struct stat sb; - if (stat(fullFilename.c_str(), &sb) == -1) - { - continue; - } - - if (!S_ISREG(sb.st_mode)) - { - continue; - } - } - break; - - default: - continue; - } - - std::string filename(entry->d_name); - - // Check if the extension matches the one we are looking for - int extPos = filename.length() - extLength; - if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) - { - continue; - } - - std::string filenameWithoutExt(filename.substr(0, extPos)); - - // Make sure if we have an assembly with multiple extensions present, - // we insert only one version of it. - if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) - { - addedAssemblies.insert(filenameWithoutExt); - - tpaList.append(directory); - tpaList.append("/"); - tpaList.append(filename); - tpaList.append(":"); - } - } - - // Rewind the directory stream to be able to iterate over it for the next extension - rewinddir(dir); - } - - closedir(dir); -} - -int ExecuteManagedAssembly( - const char* currentExeAbsolutePath, - const char* clrFilesAbsolutePath, - const char* managedAssemblyAbsolutePath, - int managedAssemblyArgc, - const char** managedAssemblyArgv) -{ - // Indicates failure - int exitCode = -1; - - std::string coreClrDllPath(clrFilesAbsolutePath); - coreClrDllPath.append("/"); - coreClrDllPath.append(coreClrDll); - - if (coreClrDllPath.length() >= PATH_MAX) - { - fprintf(stderr, "Absolute path to libcoreclr.so too long\n"); - return -1; - } - - // Get just the path component of the managed assembly path - std::string appPath; - GetDirectory(managedAssemblyAbsolutePath, appPath); - - std::string nativeDllSearchDirs(appPath); - nativeDllSearchDirs.append(":"); - nativeDllSearchDirs.append(clrFilesAbsolutePath); - - std::string tpaList; - AddFilesFromDirectoryToTpaList(clrFilesAbsolutePath, tpaList); - - void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW | RTLD_LOCAL); - if (coreclrLib != nullptr) - { - InitializeCoreCLRFunction initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib, "coreclr_initialize"); - ExecuteAssemblyFunction executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib, "coreclr_execute_assembly"); - ShutdownCoreCLRFunction shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib, "coreclr_shutdown"); - - if (initializeCoreCLR == nullptr) - { - fprintf(stderr, "Function coreclr_initialize not found in the libcoreclr.so\n"); - } - else if (executeAssembly == nullptr) - { - fprintf(stderr, "Function coreclr_execute_assembly not found in the libcoreclr.so\n"); - } - else if (shutdownCoreCLR == nullptr) - { - fprintf(stderr, "Function coreclr_shutdown not found in the libcoreclr.so\n"); - } - else - { - // Allowed property names: - // APPBASE - // - The base path of the application from which the exe and other assemblies will be loaded - // - // TRUSTED_PLATFORM_ASSEMBLIES - // - The list of complete paths to each of the fully trusted assemblies - // - // APP_PATHS - // - The list of paths which will be probed by the assembly loader - // - // APP_NI_PATHS - // - The list of additional paths that the assembly loader will probe for ngen images - // - // NATIVE_DLL_SEARCH_DIRECTORIES - // - The list of paths that will be probed for native DLLs called by PInvoke - // - const char *propertyKeys[] = { - "TRUSTED_PLATFORM_ASSEMBLIES", - "APP_PATHS", - "APP_NI_PATHS", - "NATIVE_DLL_SEARCH_DIRECTORIES", - "AppDomainCompatSwitch" - }; - const char *propertyValues[] = { - // TRUSTED_PLATFORM_ASSEMBLIES - tpaList.c_str(), - // APP_PATHS - appPath.c_str(), - // APP_NI_PATHS - appPath.c_str(), - // NATIVE_DLL_SEARCH_DIRECTORIES - nativeDllSearchDirs.c_str(), - // AppDomainCompatSwitch - "UseLatestBehaviorWhenTFMNotSpecified" - }; - - void* hostHandle; - unsigned int domainId; - - int st = initializeCoreCLR( - currentExeAbsolutePath, - "unixcorerun", - sizeof(propertyKeys) / sizeof(propertyKeys[0]), - propertyKeys, - propertyValues, - &hostHandle, - &domainId); - - if (!SUCCEEDED(st)) - { - fprintf(stderr, "coreclr_initialize failed - status: 0x%08x\n", st); - exitCode = -1; - } - else - { - st = executeAssembly( - hostHandle, - domainId, - managedAssemblyArgc, - managedAssemblyArgv, - managedAssemblyAbsolutePath, - (unsigned int*)&exitCode); - - if (!SUCCEEDED(st)) - { - fprintf(stderr, "coreclr_execute_assembly failed - status: 0x%08x\n", st); - exitCode = -1; - } - - st = shutdownCoreCLR(hostHandle, domainId); - if (!SUCCEEDED(st)) - { - fprintf(stderr, "coreclr_shutdown failed - status: 0x%08x\n", st); - exitCode = -1; - } - } - } - - if (dlclose(coreclrLib) != 0) - { - fprintf(stderr, "Warning - dlclose failed\n"); - } - } - else - { - char* error = dlerror(); - fprintf(stderr, "dlopen failed to open the libcoreclr.so with error %s\n", error); - } - - return exitCode; -} diff --git a/host/unixcoreruncommon/coreruncommon.h b/host/unixcoreruncommon/coreruncommon.h deleted file mode 100644 index b587e407fc..0000000000 --- a/host/unixcoreruncommon/coreruncommon.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -#include - -// Get absolute path from the specified path. -// Return true in case of a success, false otherwise. -bool GetAbsolutePath(const char* path, std::string& absolutePath); - -// Get directory of the specified path. -// Return true in case of a success, false otherwise. -bool GetDirectory(const char* absolutePath, std::string& directory); - -// -// Get the absolute path to use to locate libcoreclr.so and the CLR assemblies are stored. If clrFilesPath is provided, -// this function will return the absolute path to it. Otherwise, the directory of the current executable is used. -// -// Return true in case of a success, false otherwise. -// -bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath); - -// Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string. -void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList); - -// -// Execute the specified managed assembly. -// -// Parameters: -// currentExePath - Path to the current executable -// clrFilesAbsolutePath - Absolute path to the folder where the libcoreclr.so and CLR managed assemblies are stored -// managedAssemblyPath - Path to the managed assembly to execute -// managedAssemblyArgc - Number of arguments passed to the executed assembly -// managedAssemblyArgv - Array of arguments passed to the executed assembly -// -// Returns: -// ExitCode of the assembly -// -int ExecuteManagedAssembly( - const char* currentExeAbsolutePath, - const char* clrFilesAbsolutePath, - const char* managedAssemblyAbsolutePath, - int managedAssemblyArgc, - const char** managedAssemblyArgv); - From 6e8ce797fc63e794c4a6934407ada12b7360364a Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 12 Jan 2016 13:52:50 -0800 Subject: [PATCH 286/298] Rename native to src With the removal of the host, this submodule is now just one thing: libpsnative, so it makes sense to have a `src` directory instead of a poorly named `monad-native/native`. --- CMakeLists.txt | 2 +- {native => src}/CMakeLists.txt | 0 {native => src}/getcomputername.cpp | 0 {native => src}/getcomputername.h | 0 {native => src}/getcurrentprocessorid.cpp | 0 {native => src}/getcurrentprocessorid.h | 0 {native => src}/getcurrentthreadid.cpp | 0 {native => src}/getcurrentthreadid.h | 0 {native => src}/getfullyqualifiedname.cpp | 0 {native => src}/getfullyqualifiedname.h | 0 {native => src}/getlinkcount.cpp | 0 {native => src}/getlinkcount.h | 0 {native => src}/getusername.cpp | 0 {native => src}/getusername.h | 0 {native => src}/isexecutable.cpp | 0 {native => src}/isexecutable.h | 0 {native => src}/issymlink.cpp | 0 {native => src}/issymlink.h | 0 {native => src}/pal.h | 0 {native => src}/setdate.cpp | 0 {native => src}/setdate.h | 0 {native => src}/terminal.cpp | 0 {native => src}/terminal.h | 0 23 files changed, 1 insertion(+), 1 deletion(-) rename {native => src}/CMakeLists.txt (100%) rename {native => src}/getcomputername.cpp (100%) rename {native => src}/getcomputername.h (100%) rename {native => src}/getcurrentprocessorid.cpp (100%) rename {native => src}/getcurrentprocessorid.h (100%) rename {native => src}/getcurrentthreadid.cpp (100%) rename {native => src}/getcurrentthreadid.h (100%) rename {native => src}/getfullyqualifiedname.cpp (100%) rename {native => src}/getfullyqualifiedname.h (100%) rename {native => src}/getlinkcount.cpp (100%) rename {native => src}/getlinkcount.h (100%) rename {native => src}/getusername.cpp (100%) rename {native => src}/getusername.h (100%) rename {native => src}/isexecutable.cpp (100%) rename {native => src}/isexecutable.h (100%) rename {native => src}/issymlink.cpp (100%) rename {native => src}/issymlink.h (100%) rename {native => src}/pal.h (100%) rename {native => src}/setdate.cpp (100%) rename {native => src}/setdate.h (100%) rename {native => src}/terminal.cpp (100%) rename {native => src}/terminal.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index e665428fd8..a5ce4f40ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,5 +5,5 @@ add_compile_options(-std=c++11 -Wall -Werror) # test in BUILD_DIR enable_testing() +add_subdirectory(src) add_subdirectory(tests) -add_subdirectory(native) diff --git a/native/CMakeLists.txt b/src/CMakeLists.txt similarity index 100% rename from native/CMakeLists.txt rename to src/CMakeLists.txt diff --git a/native/getcomputername.cpp b/src/getcomputername.cpp similarity index 100% rename from native/getcomputername.cpp rename to src/getcomputername.cpp diff --git a/native/getcomputername.h b/src/getcomputername.h similarity index 100% rename from native/getcomputername.h rename to src/getcomputername.h diff --git a/native/getcurrentprocessorid.cpp b/src/getcurrentprocessorid.cpp similarity index 100% rename from native/getcurrentprocessorid.cpp rename to src/getcurrentprocessorid.cpp diff --git a/native/getcurrentprocessorid.h b/src/getcurrentprocessorid.h similarity index 100% rename from native/getcurrentprocessorid.h rename to src/getcurrentprocessorid.h diff --git a/native/getcurrentthreadid.cpp b/src/getcurrentthreadid.cpp similarity index 100% rename from native/getcurrentthreadid.cpp rename to src/getcurrentthreadid.cpp diff --git a/native/getcurrentthreadid.h b/src/getcurrentthreadid.h similarity index 100% rename from native/getcurrentthreadid.h rename to src/getcurrentthreadid.h diff --git a/native/getfullyqualifiedname.cpp b/src/getfullyqualifiedname.cpp similarity index 100% rename from native/getfullyqualifiedname.cpp rename to src/getfullyqualifiedname.cpp diff --git a/native/getfullyqualifiedname.h b/src/getfullyqualifiedname.h similarity index 100% rename from native/getfullyqualifiedname.h rename to src/getfullyqualifiedname.h diff --git a/native/getlinkcount.cpp b/src/getlinkcount.cpp similarity index 100% rename from native/getlinkcount.cpp rename to src/getlinkcount.cpp diff --git a/native/getlinkcount.h b/src/getlinkcount.h similarity index 100% rename from native/getlinkcount.h rename to src/getlinkcount.h diff --git a/native/getusername.cpp b/src/getusername.cpp similarity index 100% rename from native/getusername.cpp rename to src/getusername.cpp diff --git a/native/getusername.h b/src/getusername.h similarity index 100% rename from native/getusername.h rename to src/getusername.h diff --git a/native/isexecutable.cpp b/src/isexecutable.cpp similarity index 100% rename from native/isexecutable.cpp rename to src/isexecutable.cpp diff --git a/native/isexecutable.h b/src/isexecutable.h similarity index 100% rename from native/isexecutable.h rename to src/isexecutable.h diff --git a/native/issymlink.cpp b/src/issymlink.cpp similarity index 100% rename from native/issymlink.cpp rename to src/issymlink.cpp diff --git a/native/issymlink.h b/src/issymlink.h similarity index 100% rename from native/issymlink.h rename to src/issymlink.h diff --git a/native/pal.h b/src/pal.h similarity index 100% rename from native/pal.h rename to src/pal.h diff --git a/native/setdate.cpp b/src/setdate.cpp similarity index 100% rename from native/setdate.cpp rename to src/setdate.cpp diff --git a/native/setdate.h b/src/setdate.h similarity index 100% rename from native/setdate.h rename to src/setdate.h diff --git a/native/terminal.cpp b/src/terminal.cpp similarity index 100% rename from native/terminal.cpp rename to src/terminal.cpp diff --git a/native/terminal.h b/src/terminal.h similarity index 100% rename from native/terminal.h rename to src/terminal.h From e612ccb1e8b350e34d02805c71a3806e3cac0ef2 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 12 Jan 2016 13:58:25 -0800 Subject: [PATCH 287/298] Rename to psl-native The name `psnative` would have been confusing when this goes cross-platform; instead use the `psl` suffix for PowerShell on Linux. --- .gitignore | 6 ++---- CMakeLists.txt | 2 +- src/CMakeLists.txt | 7 ++----- tests/CMakeLists.txt | 10 +++++----- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 45177e796c..0e33a4cd55 100644 --- a/.gitignore +++ b/.gitignore @@ -6,8 +6,6 @@ cmake_install.cmake install_manifest.txt CTestTestfile.cmake Testing/ -tests/psnative-test -host/powershell -host/libpshost.a -native/libpsnative.so +tests/psl-native-test +src/libpsl-native.so tests/native-tests.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index a5ce4f40ea..1194d4b0ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 2.8.4) -project(MONAD_NATIVE) +project(PSL-NATIVE) add_compile_options(-std=c++11 -Wall -Werror) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 20e8e8b2d3..11b110f449 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(psnative SHARED +add_library(psl-native SHARED getcurrentprocessorid.cpp getusername.cpp getcomputername.cpp @@ -9,7 +9,4 @@ add_library(psnative SHARED setdate.cpp terminal.cpp) -target_include_directories (psnative PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -install(TARGETS psnative - LIBRARY DESTINATION lib) +target_include_directories(psl-native PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b0216f88e7..bcdc0b4594 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,6 @@ add_subdirectory(googletest) -add_executable(psnative-test +add_executable(psl-native-test test-locale.cpp test-getcurrentprocessid.cpp test-getusername.cpp @@ -12,9 +12,9 @@ add_executable(psnative-test main.cpp) # manually include gtest headers -target_include_directories(psnative-test PRIVATE ${gtest_SOURCE_DIR}/include) +target_include_directories(psl-native-test PRIVATE ${gtest_SOURCE_DIR}/include) -target_link_libraries(psnative-test psnative gtest) +target_link_libraries(psl-native-test psl-native gtest) -add_test(NAME psnative-test - COMMAND psnative-test --gtest_output=xml:native-tests.xml) +add_test(NAME psl-native-test + COMMAND psl-native-test --gtest_output=xml:native-tests.xml) From 494f08a16bdd1e0ea965b9595f2473a346712d6a Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 12 Jan 2016 14:00:25 -0800 Subject: [PATCH 288/298] Remove terminal queries Thanks to improvements in System.Console, we no longer rely on these. --- src/CMakeLists.txt | 3 +-- src/terminal.cpp | 21 --------------------- src/terminal.h | 11 ----------- 3 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 src/terminal.cpp delete mode 100644 src/terminal.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 11b110f449..acb732525a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,7 +6,6 @@ add_library(psl-native SHARED getfullyqualifiedname.cpp issymlink.cpp isexecutable.cpp - setdate.cpp - terminal.cpp) + setdate.cpp) target_include_directories(psl-native PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/terminal.cpp b/src/terminal.cpp deleted file mode 100644 index 44fadd0846..0000000000 --- a/src/terminal.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "terminal.h" -#include - -int32_t GetTerminalWidth() -{ - struct winsize ws; - if (-1 == ioctl(0,TIOCGWINSZ,&ws)) - return -1; - - return ws.ws_col; -} - -int32_t GetTerminalHeight() -{ - struct winsize ws; - if (-1 == ioctl(0,TIOCGWINSZ,&ws)) - return -1; - - return ws.ws_row; -} - diff --git a/src/terminal.h b/src/terminal.h deleted file mode 100644 index e036bc8492..0000000000 --- a/src/terminal.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "pal.h" - -PAL_BEGIN_EXTERNC - -int32_t GetTerminalWidth(); -int32_t GetTerminalHeight(); - -PAL_END_EXTERNC - From 6e8565967274f1b2ff6d29246e3aa5356639dd92 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Thu, 14 Jan 2016 10:14:40 -0800 Subject: [PATCH 289/298] Rename tests to test Requires moving a submodule, so its better to do it now when everything is moving. --- .gitignore | 4 ++-- .gitmodules | 4 ++-- CMakeLists.txt | 2 +- {tests => test}/CMakeLists.txt | 0 {tests => test}/googletest | 0 {tests => test}/main.cpp | 0 {tests => test}/test-getcomputername.cpp | 0 {tests => test}/test-getcurrentprocessid.cpp | 0 {tests => test}/test-getcurrentthreadid.cpp | 0 {tests => test}/test-getfullyqualifiedname.cpp | 0 {tests => test}/test-getlinkcount.cpp | 0 {tests => test}/test-getusername.cpp | 0 {tests => test}/test-isexecutable.cpp | 0 {tests => test}/test-issymlink.cpp | 0 {tests => test}/test-locale.cpp | 0 15 files changed, 5 insertions(+), 5 deletions(-) rename {tests => test}/CMakeLists.txt (100%) rename {tests => test}/googletest (100%) rename {tests => test}/main.cpp (100%) rename {tests => test}/test-getcomputername.cpp (100%) rename {tests => test}/test-getcurrentprocessid.cpp (100%) rename {tests => test}/test-getcurrentthreadid.cpp (100%) rename {tests => test}/test-getfullyqualifiedname.cpp (100%) rename {tests => test}/test-getlinkcount.cpp (100%) rename {tests => test}/test-getusername.cpp (100%) rename {tests => test}/test-isexecutable.cpp (100%) rename {tests => test}/test-issymlink.cpp (100%) rename {tests => test}/test-locale.cpp (100%) diff --git a/.gitignore b/.gitignore index 0e33a4cd55..798fa6c008 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,6 @@ cmake_install.cmake install_manifest.txt CTestTestfile.cmake Testing/ -tests/psl-native-test +test/psl-native-test src/libpsl-native.so -tests/native-tests.xml +test/native-tests.xml diff --git a/.gitmodules b/.gitmodules index 44d6d26f4a..7cdedd8478 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ -[submodule "tests/googletest"] - path = tests/googletest +[submodule "test/googletest"] + path = test/googletest url = https://github.com/google/googletest.git ignore = dirty diff --git a/CMakeLists.txt b/CMakeLists.txt index 1194d4b0ea..f5778ed819 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,4 +6,4 @@ add_compile_options(-std=c++11 -Wall -Werror) # test in BUILD_DIR enable_testing() add_subdirectory(src) -add_subdirectory(tests) +add_subdirectory(test) diff --git a/tests/CMakeLists.txt b/test/CMakeLists.txt similarity index 100% rename from tests/CMakeLists.txt rename to test/CMakeLists.txt diff --git a/tests/googletest b/test/googletest similarity index 100% rename from tests/googletest rename to test/googletest diff --git a/tests/main.cpp b/test/main.cpp similarity index 100% rename from tests/main.cpp rename to test/main.cpp diff --git a/tests/test-getcomputername.cpp b/test/test-getcomputername.cpp similarity index 100% rename from tests/test-getcomputername.cpp rename to test/test-getcomputername.cpp diff --git a/tests/test-getcurrentprocessid.cpp b/test/test-getcurrentprocessid.cpp similarity index 100% rename from tests/test-getcurrentprocessid.cpp rename to test/test-getcurrentprocessid.cpp diff --git a/tests/test-getcurrentthreadid.cpp b/test/test-getcurrentthreadid.cpp similarity index 100% rename from tests/test-getcurrentthreadid.cpp rename to test/test-getcurrentthreadid.cpp diff --git a/tests/test-getfullyqualifiedname.cpp b/test/test-getfullyqualifiedname.cpp similarity index 100% rename from tests/test-getfullyqualifiedname.cpp rename to test/test-getfullyqualifiedname.cpp diff --git a/tests/test-getlinkcount.cpp b/test/test-getlinkcount.cpp similarity index 100% rename from tests/test-getlinkcount.cpp rename to test/test-getlinkcount.cpp diff --git a/tests/test-getusername.cpp b/test/test-getusername.cpp similarity index 100% rename from tests/test-getusername.cpp rename to test/test-getusername.cpp diff --git a/tests/test-isexecutable.cpp b/test/test-isexecutable.cpp similarity index 100% rename from tests/test-isexecutable.cpp rename to test/test-isexecutable.cpp diff --git a/tests/test-issymlink.cpp b/test/test-issymlink.cpp similarity index 100% rename from tests/test-issymlink.cpp rename to test/test-issymlink.cpp diff --git a/tests/test-locale.cpp b/test/test-locale.cpp similarity index 100% rename from tests/test-locale.cpp rename to test/test-locale.cpp From 8650c6a6a1f782361d49191e935eef616f190155 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 15 Jan 2016 12:37:03 -0800 Subject: [PATCH 290/298] Add readme --- README.md | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000000..930ea3630d --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# libpsl-native + +This library provides functionality missing from .NET Core via system calls, +that are called from from the `CorePsPlatform.cs` file of PowerShell. The +method to do this is a Platform Invoke, which is C#'s Foreign Function +Interface to C code (and C++ by way of `extern C`). + +## Build + +[CMake][] is used to build the project, which results in a `libpsl-native.so` +library on Linux, and `libpsl-native.dylib` on OS X. + +```sh +cmake -DCMAKE_BUILD_TYPE=Debug . +make -j +``` + +[CMake]: https://cmake.org/cmake/help/v2.8.12/cmake.html + +## Test + +The [Google Test][] framework is used for unit tests. + +Use either `make test` or `ctest --verbose` for more output. + +[Google Test]: https://github.com/google/googletest/tree/release-1.7.0 + +## Notes + +Marshalling data from native to managed code is much easier on Linux than it is +on Windows. For instance, to return a string, you simply return a copy of it on +the heap. Since only one memory allocator is used on Linux, the .NET runtime +has no problem later freeing the buffer. Additionally, .NET presumes that the +codepage "Ansi" on Linux is always UTF-8. So just marshal the string as +`UnmanagedType.LPStr`. + +### C# (Managed) + +```c# +[DllImport("libpsl-native", CharSet = CharSet.Ansi)] +[return: MarshalAs(UnmanagedType.LPStr)] +internal static extern string GetSomeString(); +``` + +### C (Native) + +```c +char *GetSomeString() +{ + return strdup("some string"); +} +``` + +The CoreFX team has an excellent guide for [UNIX Interop][]. + +[UNIX Interop]: https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/interop-guidelines.md#unix-shims From 4bfa1fa23173309168dd674dc05f9f3cd1d0ad8c Mon Sep 17 00:00:00 2001 From: George Fleming Date: Fri, 26 Feb 2016 14:31:17 -0800 Subject: [PATCH 291/298] Add new CreateSymLink function --- src/CMakeLists.txt | 3 +- src/createsymlink.cpp | 108 ++++++++++++++++++++++++++++++++++++++++++ src/createsymlink.h | 9 ++++ src/pal.h | 2 + 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 src/createsymlink.cpp create mode 100644 src/createsymlink.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index acb732525a..b75ba8f160 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,6 +6,7 @@ add_library(psl-native SHARED getfullyqualifiedname.cpp issymlink.cpp isexecutable.cpp - setdate.cpp) + setdate.cpp + createsymlink.cpp) target_include_directories(psl-native PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/createsymlink.cpp b/src/createsymlink.cpp new file mode 100644 index 0000000000..fcff5c25ba --- /dev/null +++ b/src/createsymlink.cpp @@ -0,0 +1,108 @@ +//! @file createsymlink.cpp +//! @author George FLeming +//! @brief create new symbolic link + +#include +//#include +//#include +#include +#include +#include "createsymlink.h" + +//! @brief Createsymlink create new symbolic link +//! +//! Createsymlink +//! +//! @param[in] link +//! @parblock +//! A pointer to the buffer that contains the symbolic link to create +//! +//! char* is marshaled as an LPStr, which on Linux is UTF-8. +//! @endparblock +//! +//! @param[in] target +//! @parblock +//! A pointer to the buffer that contains the existing file +//! +//! char* is marshaled as an LPStr, which on Linux is UTF-8. +//! @endparblock +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_INVALID_PARAMETER: parameter is not valid +//! - ERROR_FILE_NOT_FOUND: file does not exist +//! - ERROR_ACCESS_DENIED: access is denied +//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified +//! - ERROR_INVALID_ADDRESS: attempt to access invalid address +//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link +//! - ERROR_GEN_FAILURE: device attached to the system is not functioning +//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file +//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect +//! - ERROR_BUFFER_OVERFLOW: file name is too long +//! - ERROR_INVALID_FUNCTION: incorrect function +//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters +//! +//! @retval 1 if creation is successful +//! @retval 0 if createion failed +//! + +int32_t CreateSymLink(const char *link, const char *target) +{ + errno = 0; + + // Check parameters + if (!link || !target) + { + errno = ERROR_INVALID_PARAMETER; + return 0; + } + + int returnCode = symlink(target, link); + + if (returnCode == 0) + { + return 1; + } + + switch(errno) + { + case EACCES: + errno = ERROR_ACCESS_DENIED; + break; + case EDQUOT: + errno = ERROR_DISK_FULL; + break; + case EEXIST: + errno = ERROR_FILE_EXISTS; + break; + case EFAULT: + errno = ERROR_INVALID_ADDRESS; + break; + case EIO: + errno = ERROR_GEN_FAILURE; + break; + case ELOOP: + errno = ERROR_STOPPED_ON_SYMLINK; + break; + case ENAMETOOLONG: + errno = ERROR_BAD_PATH_NAME; + break; + case ENOENT: + errno = ERROR_FILE_NOT_FOUND; + break; + case ENOMEM: + errno = ERROR_OUTOFMEMORY; + break; + case ENOTDIR: + errno = ERROR_INVALID_NAME; + break; + case ENOSPC: + errno = ERROR_DISK_FULL; + break; + case EPERM: + errno = ERROR_GEN_FAILURE; + break; + default: + errno = ERROR_INVALID_FUNCTION; + } + return 0; +} diff --git a/src/createsymlink.h b/src/createsymlink.h new file mode 100644 index 0000000000..e47bce3fa1 --- /dev/null +++ b/src/createsymlink.h @@ -0,0 +1,9 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +int32_t CreateSymLink(const char *link, const char *target); + +PAL_END_EXTERNC diff --git a/src/pal.h b/src/pal.h index d47b2845e2..754289776c 100644 --- a/src/pal.h +++ b/src/pal.h @@ -22,6 +22,8 @@ #define ERROR_FILE_NOT_FOUND 0x00000002 #define ERROR_BAD_PATH_NAME 0x000000A1 #define ERROR_BAD_NET_NAME 0x00000043 +#define ERROR_DISK_FULL 0x00000070 +#define ERROR_FILE_EXISTS 0x00000050 /* **============================================================================== From 19dbaaf54cfa47c0673af6a3da2c4dad5fb56e8f Mon Sep 17 00:00:00 2001 From: George Fleming Date: Fri, 26 Feb 2016 15:16:42 -0800 Subject: [PATCH 292/298] Add native test for createSymLink --- src/createsymlink.cpp | 2 - test/CMakeLists.txt | 1 + test/test-createsymlink.cpp | 107 ++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 test/test-createsymlink.cpp diff --git a/src/createsymlink.cpp b/src/createsymlink.cpp index fcff5c25ba..4ea8d6fd9d 100644 --- a/src/createsymlink.cpp +++ b/src/createsymlink.cpp @@ -3,8 +3,6 @@ //! @brief create new symbolic link #include -//#include -//#include #include #include #include "createsymlink.h" diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bcdc0b4594..cd9bf063de 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,6 +9,7 @@ add_executable(psl-native-test test-getfullyqualifiedname.cpp test-issymlink.cpp test-isexecutable.cpp + test-createsymlink.cpp main.cpp) # manually include gtest headers diff --git a/test/test-createsymlink.cpp b/test/test-createsymlink.cpp new file mode 100644 index 0000000000..1100d022cd --- /dev/null +++ b/test/test-createsymlink.cpp @@ -0,0 +1,107 @@ +//! @file test-issymlink.cpp +//! @author George Fleming +//! @brief Implements test for isSymLink() + +#include +#include +#include +#include "issymlink.h" +#include "createsymlink.h" + +using namespace std; + +class CreateSymLinkTest : public ::testing::Test +{ +protected: + + static const int bufSize = 64; + const string fileTemplate = "/tmp/symlinktest.fXXXXXX"; + const string dirTemplate = "/tmp/symlinktest.dXXXXXX"; + const string fileSymLink = "/tmp/symlinktest.flink"; + const string dirSymLink = "/tmp/symlinktest.dlink"; + char *file, *dir; + char fileTemplateBuf[bufSize], dirTemplateBuf[bufSize]; + + CreateSymLinkTest() + { + // since mkstemp and mkdtemp modifies the template string, let's give them writable buffers + strcpy(fileTemplateBuf, fileTemplate.c_str()); + strcpy(dirTemplateBuf, dirTemplate.c_str()); + + // First create a temp file + int fd = mkstemp(fileTemplateBuf); + EXPECT_TRUE(fd != -1); + file = fileTemplateBuf; + + // Create a temp directory + dir = mkdtemp(dirTemplateBuf); + EXPECT_TRUE(dir != NULL); + + // Create symbolic link to file + int ret1 = CreateSymLink(fileSymLink.c_str(), file); + EXPECT_EQ(ret1, 1); + + // Create symbolic link to directory + int ret2 = CreateSymLink(dirSymLink.c_str(), dir); + EXPECT_EQ(ret2, 1); + } + + ~CreateSymLinkTest() + { + int ret; + + ret = unlink(fileSymLink.c_str()); + EXPECT_EQ(0, ret); + + ret = unlink(dirSymLink.c_str()); + EXPECT_EQ(0, ret); + + ret = unlink(file); + EXPECT_EQ(0, ret); + + ret = rmdir(dir); + EXPECT_EQ(0, ret); + } +}; + +TEST_F(CreateSymLinkTest, FilePathNameIsNull) +{ + int retVal = CreateSymLink(NULL, NULL); + EXPECT_EQ(retVal, 0); + EXPECT_EQ(ERROR_INVALID_PARAMETER, errno); +} + +TEST_F(CreateSymLinkTest, FilePathNameDoesNotExist) +{ + std::string invalidFile = "/tmp/symlinktest_invalidFile"; + std::string invalidLink = "/tmp/symlinktest_invalidLink"; + + // make sure neither exists + unlink(invalidFile.c_str()); + unlink(invalidLink.c_str()); + + // Linux allows creation of symbolic link that points to an invalid file + int retVal = CreateSymLink(invalidLink.c_str(), invalidFile.c_str()); + EXPECT_EQ(retVal, 1); + + unlink(invalidLink.c_str()); +} + +TEST_F(CreateSymLinkTest, SymLinkToFile) +{ + int retVal = IsSymLink(fileSymLink.c_str()); + EXPECT_EQ(1, retVal); +} + +TEST_F(CreateSymLinkTest, SymLinkToDirectory) +{ + int retVal = IsSymLink(dirSymLink.c_str()); + EXPECT_EQ(1, retVal); +} + +TEST_F(CreateSymLinkTest, SymLinkAgain) +{ + int retVal = CreateSymLink(fileSymLink.c_str(), file); + EXPECT_EQ(0, retVal); + EXPECT_EQ(ERROR_FILE_EXISTS, errno); +} From 5e0728e48e5c9317f35deeed4ac1493c2cf0639e Mon Sep 17 00:00:00 2001 From: George Fleming Date: Fri, 4 Mar 2016 15:59:32 -0800 Subject: [PATCH 293/298] New native code to support creation of hard links --- src/CMakeLists.txt | 1 + src/createhardlink.cpp | 115 +++++++++++++++++++++++++++++++++++ src/createhardlink.h | 9 +++ src/pal.h | 1 + test/CMakeLists.txt | 1 + test/test-createhardlink.cpp | 91 +++++++++++++++++++++++++++ 6 files changed, 218 insertions(+) create mode 100644 src/createhardlink.cpp create mode 100644 src/createhardlink.h create mode 100644 test/test-createhardlink.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b75ba8f160..cfd91e9fb2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(psl-native SHARED issymlink.cpp isexecutable.cpp setdate.cpp + createhardlink.cpp createsymlink.cpp) target_include_directories(psl-native PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/createhardlink.cpp b/src/createhardlink.cpp new file mode 100644 index 0000000000..2f131efaa5 --- /dev/null +++ b/src/createhardlink.cpp @@ -0,0 +1,115 @@ +//! @file createsymlink.cpp +//! @author George FLeming +//! @brief create new hard link + +#include +#include +#include +#include "createhardlink.h" + +//! @brief Createhardlink create new symbolic link +//! +//! Createhardlink +//! +//! @param[in] link +//! @parblock +//! A pointer to the buffer that contains the symbolic link to create +//! +//! char* is marshaled as an LPStr, which on Linux is UTF-8. +//! @endparblock +//! +//! @param[in] target +//! @parblock +//! A pointer to the buffer that contains the existing file +//! +//! char* is marshaled as an LPStr, which on Linux is UTF-8. +//! @endparblock +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_INVALID_PARAMETER: parameter is not valid +//! - ERROR_FILE_NOT_FOUND: file does not exist +//! - ERROR_ACCESS_DENIED: access is denied +//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified +//! - ERROR_INVALID_ADDRESS: attempt to access invalid address +//! - ERROR_TOO_MANY_LINK: max number of hard links has been exceeded +//! - ERROR_GEN_FAILURE: device attached to the system is not functioning +//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file +//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect +//! - ERROR_BUFFER_OVERFLOW: file name is too long +//! - ERROR_INVALID_FUNCTION: incorrect function +//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters +//! +//! @retval 1 if creation is successful +//! @retval 0 if createion failed +//! + +int32_t CreateHardLink(const char *newlink, const char *target) +{ + errno = 0; + + // Check parameters + if (!newlink || !target) + { + errno = ERROR_INVALID_PARAMETER; + return 0; + } + + int returnCode = link(target, newlink); + + if (returnCode == 0) + { + return 1; + } + + switch(errno) + { + case EACCES: + errno = ERROR_ACCESS_DENIED; + break; + case EDQUOT: + errno = ERROR_DISK_FULL; + break; + case EEXIST: + errno = ERROR_FILE_EXISTS; + break; + case EFAULT: + errno = ERROR_INVALID_ADDRESS; + break; + case EIO: + errno = ERROR_GEN_FAILURE; + break; + case ELOOP: + errno = ERROR_TOO_MANY_LINKS; + break; + case EMLINK: + errno = ERROR_TOO_MANY_LINKS; + break; + case ENAMETOOLONG: + errno = ERROR_BAD_PATH_NAME; + break; + case ENOENT: + errno = ERROR_FILE_NOT_FOUND; + break; + case ENOMEM: + errno = ERROR_OUTOFMEMORY; + break; + case ENOTDIR: + errno = ERROR_INVALID_NAME; + break; + case ENOSPC: + errno = ERROR_DISK_FULL; + break; + case EPERM: + errno = ERROR_ACCESS_DENIED; + break; + case EROFS: + errno = ERROR_ACCESS_DENIED; + break; + case EXDEV: + errno = ERROR_GEN_FAILURE; + break; + default: + errno = ERROR_INVALID_FUNCTION; + } + return 0; +} diff --git a/src/createhardlink.h b/src/createhardlink.h new file mode 100644 index 0000000000..b8e62ddcc2 --- /dev/null +++ b/src/createhardlink.h @@ -0,0 +1,9 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +int32_t CreateHardLink(const char *link, const char *target); + +PAL_END_EXTERNC diff --git a/src/pal.h b/src/pal.h index 754289776c..39fb6db82c 100644 --- a/src/pal.h +++ b/src/pal.h @@ -24,6 +24,7 @@ #define ERROR_BAD_NET_NAME 0x00000043 #define ERROR_DISK_FULL 0x00000070 #define ERROR_FILE_EXISTS 0x00000050 +#define ERROR_TOO_MANY_LINKS 0x00000476 /* **============================================================================== diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cd9bf063de..4ddc538361 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,6 +10,7 @@ add_executable(psl-native-test test-issymlink.cpp test-isexecutable.cpp test-createsymlink.cpp + test-createhardlink.cpp main.cpp) # manually include gtest headers diff --git a/test/test-createhardlink.cpp b/test/test-createhardlink.cpp new file mode 100644 index 0000000000..090864b9f7 --- /dev/null +++ b/test/test-createhardlink.cpp @@ -0,0 +1,91 @@ +//! @file test-createhardlink.cpp +//! @author George Fleming +//! @brief Implements test for CreateHardLink() + +#include +#include +#include +#include "getlinkcount.h" +#include "createhardlink.h" + +using namespace std; + +class CreateHardLinkTest : public ::testing::Test +{ +protected: + + static const int bufSize = 64; + const string fileTemplate = "/tmp/symlinktest.fXXXXXX"; + const string dirTemplate = "/tmp/symlinktest.dXXXXXX"; + const string fileHardLink = "/tmp/symlinktest.flink"; + const string dirHardLink = "/tmp/symlinktest.dlink"; + char *file, *dir; + char fileTemplateBuf[bufSize], dirTemplateBuf[bufSize]; + + CreateHardLinkTest() + { + // since mkstemp and mkdtemp modifies the template string, let's give them writable buffers + strcpy(fileTemplateBuf, fileTemplate.c_str()); + strcpy(dirTemplateBuf, dirTemplate.c_str()); + + // First create a temp file + int fd = mkstemp(fileTemplateBuf); + EXPECT_TRUE(fd != -1); + file = fileTemplateBuf; + + // Create a temp directory + dir = mkdtemp(dirTemplateBuf); + EXPECT_TRUE(dir != NULL); + + // Create hard link to file + int ret1 = CreateHardLink(fileHardLink.c_str(), file); + EXPECT_EQ(ret1, 1); + + // Create hard link to directory - should fail + int ret2 = CreateHardLink(dirHardLink.c_str(), dir); + EXPECT_EQ(ret2, 0); + } + + ~CreateHardLinkTest() + { + int ret; + + ret = unlink(fileHardLink.c_str()); + EXPECT_EQ(0, ret); + + ret = unlink(file); + EXPECT_EQ(0, ret); + + ret = rmdir(dir); + EXPECT_EQ(0, ret); + } +}; + +TEST_F(CreateHardLinkTest, FilePathNameIsNull) +{ + int retVal = CreateHardLink(NULL, NULL); + EXPECT_EQ(retVal, 0); + EXPECT_EQ(ERROR_INVALID_PARAMETER, errno); +} + +TEST_F(CreateHardLinkTest, FilePathNameDoesNotExist) +{ + std::string invalidFile = "/tmp/symlinktest_invalidFile"; + std::string invalidLink = "/tmp/symlinktest_invalidLink"; + + // make sure neither exists + unlink(invalidFile.c_str()); + unlink(invalidLink.c_str()); + + int retVal = CreateHardLink(invalidLink.c_str(), invalidFile.c_str()); + EXPECT_EQ(retVal, 0); +} + +TEST_F(CreateHardLinkTest, VerifyLinkCount) +{ + int count = 0; + int retVal = GetLinkCount(fileHardLink.c_str(), &count); + EXPECT_EQ(1, retVal); + EXPECT_EQ(2, count); +} + From 7146cc0b860aa7c9401eaea8b807a86290c5061a Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 4 Mar 2016 19:52:03 -0800 Subject: [PATCH 294/298] Fix test of FQDN We can't use `hostname --fqdn` or any other shell tool because there is no POSIX compatible way to do this short of system calls. Unfortunately this means the test practically reimplements the original code, but oh well. --- test/test-getfullyqualifiedname.cpp | 36 +++++++++++++++++------------ 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/test/test-getfullyqualifiedname.cpp b/test/test-getfullyqualifiedname.cpp index 974316562a..7c0353cd1d 100644 --- a/test/test-getfullyqualifiedname.cpp +++ b/test/test-getfullyqualifiedname.cpp @@ -4,6 +4,10 @@ #include #include "getfullyqualifiedname.h" +#include +#include +#include +#include //! Test fixture for GetComputerNameTest class GetFullyQualifiedNameTest : public ::testing::Test @@ -12,23 +16,25 @@ class GetFullyQualifiedNameTest : public ::testing::Test TEST_F(GetFullyQualifiedNameTest, ValidateLinuxGetFullyQualifiedDomainName) { - char expectedComputerName[_POSIX_HOST_NAME_MAX]; - - //Get expected result from using linux command + std::string actual(GetFullyQualifiedName()); - FILE *fPtr = popen("hostname --fqdn", "r"); - ASSERT_TRUE(fPtr != NULL); + std::string hostname(_POSIX_HOST_NAME_MAX, 0); + ASSERT_FALSE(gethostname(&hostname[0], hostname.length())); + // trim null characters from string + hostname = std::string(hostname.c_str()); - char *linePtr = fgets(expectedComputerName, sizeof(expectedComputerName), fPtr); - ASSERT_TRUE(linePtr != NULL); + struct addrinfo hints, *info; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + ASSERT_FALSE(getaddrinfo(hostname.c_str(), "http", &hints, &info)); - // There's a tendency to have \n at end of fgets string, so remove it before compare - size_t sz = strlen(expectedComputerName); - if (sz > 0 && expectedComputerName[sz - 1] == '\n') - { - expectedComputerName[sz - 1] = '\0'; - } - pclose(fPtr); + // Compare hostname part of FQDN + ASSERT_EQ(hostname, actual.substr(0, hostname.length())); - ASSERT_STREQ(GetFullyQualifiedName(), expectedComputerName); + // Compare canonical name to FQDN + ASSERT_EQ(info->ai_canonname, actual); + + freeaddrinfo(info); } From 61667a43b58f34b3101bd388b8b822b7db404349 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 4 Mar 2016 19:52:59 -0800 Subject: [PATCH 295/298] Ignore built library on OS X --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 798fa6c008..0dff693725 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ CTestTestfile.cmake Testing/ test/psl-native-test src/libpsl-native.so +src/libpsl-native.dylib test/native-tests.xml From 86801f0457df8bd582cd861d656cb47313c65824 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 4 Mar 2016 19:53:16 -0800 Subject: [PATCH 296/298] Various code cleanups --- src/getcomputername.cpp | 4 +--- src/getcomputername.h | 2 +- src/getfullyqualifiedname.cpp | 21 +++++++++------------ src/getfullyqualifiedname.h | 2 +- src/getlinkcount.cpp | 1 - 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/getcomputername.cpp b/src/getcomputername.cpp index e363cf1678..3e480b9ad4 100644 --- a/src/getcomputername.cpp +++ b/src/getcomputername.cpp @@ -12,7 +12,7 @@ //! //! @exception errno Passes these errors via errno to GetLastError: //! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code -//! - ERROR_INVALID_ADDRESS: buffer is an invalid address +//! - ERROR_INVALID_ADDRESS: buffer is an invalid address //! - ERROR_GEN_FAILURE: buffer not large enough //! //! @retval username as UTF-8 string, or null if unsuccessful @@ -42,6 +42,4 @@ char* GetComputerName() } return strdup(computername.c_str()); - } - diff --git a/src/getcomputername.h b/src/getcomputername.h index 66b0c352b3..363210921b 100644 --- a/src/getcomputername.h +++ b/src/getcomputername.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -char* GetComputerName(); +char *GetComputerName(); PAL_END_EXTERNC diff --git a/src/getfullyqualifiedname.cpp b/src/getfullyqualifiedname.cpp index 5d711c2f39..44178a0a5a 100644 --- a/src/getfullyqualifiedname.cpp +++ b/src/getfullyqualifiedname.cpp @@ -12,7 +12,6 @@ //! @brief GetFullyQualifiedName retrieves the fully qualifed dns name of the host //! //! @exception errno Passes these errors via errno to GetLastError: -//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8 (from GetComputerName) //! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code (from GetComputerName) //! - ERROR_INVALID_ADDRESS: buffer is an invalid address (from GetComputerName) //! - ERROR_GEN_FAILURE: buffer not large enough (from GetComputerName) @@ -21,12 +20,12 @@ //! @retval username as UTF-8 string, or null if unsuccessful //! -char* GetFullyQualifiedName() +char *GetFullyQualifiedName() { errno = 0; - + char *computerName = GetComputerName(); - if (NULL == computerName) + if (computerName == NULL) { return NULL; } @@ -37,7 +36,6 @@ char* GetFullyQualifiedName() } struct addrinfo hints, *info; - int gai_result; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; /*either IPV4 or IPV6*/ @@ -45,12 +43,12 @@ char* GetFullyQualifiedName() hints.ai_flags = AI_CANONNAME; /* There are several ways to get the domain name: - * uname(2), gethostbyname(3), resolver(3), getdomainname(2), - * and getaddrinfo(3). Some of these are not portable, some aren't - * POSIX compliant, and some are being deprecated. Getaddrinfo seems - * to be the best choice right now. + * uname(2), gethostbyname(3), resolver(3), getdomainname(2), + * and getaddrinfo(3). Some of these are not portable, some aren't + * POSIX compliant, and some are being deprecated. getaddrinfo seems + * to be the best choice. */ - if ((gai_result = getaddrinfo(computerName, "http", &hints, &info)) != 0) + if (getaddrinfo(computerName, "http", &hints, &info) != 0) { errno = ERROR_BAD_NET_NAME; return NULL; @@ -58,10 +56,9 @@ char* GetFullyQualifiedName() // info is actually a link-list. We'll just return the first full name - char *fullName = strdup(info->ai_canonname); + char *fullName = strndup(info->ai_canonname, strlen(info->ai_canonname)); freeaddrinfo(info); free(computerName); return fullName; } - diff --git a/src/getfullyqualifiedname.h b/src/getfullyqualifiedname.h index 4db1fd2e76..b44ab68fd5 100644 --- a/src/getfullyqualifiedname.h +++ b/src/getfullyqualifiedname.h @@ -4,6 +4,6 @@ PAL_BEGIN_EXTERNC -char* GetFullyQualifiedName(); +char *GetFullyQualifiedName(); PAL_END_EXTERNC diff --git a/src/getlinkcount.cpp b/src/getlinkcount.cpp index 9e8db3d652..1b97a41671 100644 --- a/src/getlinkcount.cpp +++ b/src/getlinkcount.cpp @@ -101,5 +101,4 @@ int32_t GetLinkCount(const char* fileName, int32_t *count) *count = statBuf.st_nlink; return 1; - } From 454524cf7294021584a3005f2f3243c80b670a89 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Fri, 25 Mar 2016 14:37:16 -0700 Subject: [PATCH 297/298] new native code and test for obtaining target of symlinks --- src/CMakeLists.txt | 3 +- src/followsymlink.cpp | 90 +++++++++++++++++++++++++++++++++++++ src/followsymlink.h | 9 ++++ test/test-createsymlink.cpp | 14 +++++- 4 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 src/followsymlink.cpp create mode 100644 src/followsymlink.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cfd91e9fb2..5b2ec24199 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,6 +8,7 @@ add_library(psl-native SHARED isexecutable.cpp setdate.cpp createhardlink.cpp - createsymlink.cpp) + createsymlink.cpp + followsymlink.cpp) target_include_directories(psl-native PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/followsymlink.cpp b/src/followsymlink.cpp new file mode 100644 index 0000000000..40e12b9b78 --- /dev/null +++ b/src/followsymlink.cpp @@ -0,0 +1,90 @@ +//! @file followSymLink.cpp +//! @author George FLeming +//! @brief returns whether a path is a symbolic link + +#include +#include +#include +#include +#include "followsymlink.h" + +//! @brief Followsymlink determines target path of a sym link +//! +//! Followsymlink +//! +//! @param[in] fileName +//! @parblock +//! A pointer to the buffer that contains the file name +//! +//! char* is marshaled as an LPStr, which on Linux is UTF-8. +//! @endparblock +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_INVALID_PARAMETER: parameter is not valid +//! - ERROR_FILE_NOT_FOUND: file does not exist +//! - ERROR_ACCESS_DENIED: access is denied +//! - ERROR_INVALID_ADDRESS: attempt to access invalid address +//! - ERROR_STOPPED_ON_SYMLINK: too many symbolic links +//! - ERROR_GEN_FAILURE: I/O error occurred +//! - ERROR_INVALID_NAME: file provided is not a symbolic link +//! - ERROR_INVALID_FUNCTION: incorrect function +//! - ERROR_BAD_PATH_NAME: pathname is too long +//! - ERROR_OUTOFMEMORY insufficient kernal memory +//! +//! @retval target path, or NULL if unsuccessful +//! + +char* FollowSymLink(const char* fileName) +{ + errno = 0; + + // Check parameters + if (!fileName) + { + errno = ERROR_INVALID_PARAMETER; + return NULL; + } + + char buffer[PATH_MAX]; + ssize_t sz = readlink(fileName, buffer, PATH_MAX); + + if (sz == -1) + { + switch(errno) + { + case EACCES: + errno = ERROR_ACCESS_DENIED; + break; + case EFAULT: + errno = ERROR_INVALID_ADDRESS; + break; + case EINVAL: + errno = ERROR_INVALID_NAME; + break; + case EIO: + errno = ERROR_GEN_FAILURE; + break; + case ELOOP: + errno = ERROR_STOPPED_ON_SYMLINK; + break; + case ENAMETOOLONG: + errno = ERROR_BAD_PATH_NAME; + break; + case ENOENT: + errno = ERROR_FILE_NOT_FOUND; + break; + case ENOMEM: + errno = ERROR_OUTOFMEMORY; + break; + case ENOTDIR: + errno = ERROR_BAD_PATH_NAME; + break; + default: + errno = ERROR_INVALID_FUNCTION; + } + return NULL; + } + + buffer[sz] = '\0'; + return strndup(buffer, sz + 1); +} diff --git a/src/followsymlink.h b/src/followsymlink.h new file mode 100644 index 0000000000..fac7f5244f --- /dev/null +++ b/src/followsymlink.h @@ -0,0 +1,9 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +char* FollowSymLink(const char* fileName); + +PAL_END_EXTERNC diff --git a/test/test-createsymlink.cpp b/test/test-createsymlink.cpp index 1100d022cd..abc0646c61 100644 --- a/test/test-createsymlink.cpp +++ b/test/test-createsymlink.cpp @@ -1,12 +1,13 @@ -//! @file test-issymlink.cpp +//! @file test-createsymlink.cpp //! @author George Fleming -//! @brief Implements test for isSymLink() +//! @brief Implements test for CreateSymLink() and FollowSymLink() #include #include #include #include "issymlink.h" #include "createsymlink.h" +#include "followsymlink.h" using namespace std; @@ -84,6 +85,9 @@ TEST_F(CreateSymLinkTest, FilePathNameDoesNotExist) int retVal = CreateSymLink(invalidLink.c_str(), invalidFile.c_str()); EXPECT_EQ(retVal, 1); + std::string target = FollowSymLink(invalidLink.c_str()); + EXPECT_EQ(target, invalidFile); + unlink(invalidLink.c_str()); } @@ -91,12 +95,18 @@ TEST_F(CreateSymLinkTest, SymLinkToFile) { int retVal = IsSymLink(fileSymLink.c_str()); EXPECT_EQ(1, retVal); + + std::string target = FollowSymLink(fileSymLink.c_str()); + EXPECT_EQ(target, file); } TEST_F(CreateSymLinkTest, SymLinkToDirectory) { int retVal = IsSymLink(dirSymLink.c_str()); EXPECT_EQ(1, retVal); + + std::string target = FollowSymLink(dirSymLink.c_str()); + EXPECT_EQ(target, dir); } TEST_F(CreateSymLinkTest, SymLinkAgain) From 4bb241ad11c54985617343fbeb8700cfdcdf7ae0 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Mon, 28 Mar 2016 14:04:36 -0700 Subject: [PATCH 298/298] Output libraries to host directory --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f5778ed819..d0e83e6bba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 2.8.4) project(PSL-NATIVE) add_compile_options(-std=c++11 -Wall -Werror) +set(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/../Microsoft.PowerShell.Linux.Host") # test in BUILD_DIR enable_testing()