From 70645d5bc1f8d039a240f3753b656a1cdfc7ca70 Mon Sep 17 00:00:00 2001 From: Peter Honeder Date: Fri, 3 Apr 2015 10:22:05 -0700 Subject: [PATCH 01/17] 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 4355f98d0..868a006fa 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 000000000..f67adab0b --- /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 000000000..a1d6cefe2 --- /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 000000000..c2c152ed5 --- /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 ea7b78ef1c00106b03a1cfd2bf4b4aa049415e27 Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Mon, 6 Apr 2015 09:57:16 -0700 Subject: [PATCH 02/17] 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 f67adab0b..66a34e67e 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 a1d6cefe2..7f8dd8eb5 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 659afd4f6..defde3b1f 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 c2c152ed5..f4ce811fc 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 299e362d112d6c6a403e91e44754c21ec04e3591 Mon Sep 17 00:00:00 2001 From: Aaron Katz Date: Thu, 9 Apr 2015 15:16:37 -0700 Subject: [PATCH 03/17] 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 66a34e67e..1ec69110c 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 f4ce811fc..8b0f19f5d 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 84f5b079ec6fefcf0c8c14310b42d80053c68e46 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 30 Jul 2015 12:44:48 -0700 Subject: [PATCH 04/17] Added ERROR_BUFFER_OVERFLOW --- impl/pal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/impl/pal.h b/impl/pal.h index defde3b1f..d693f778c 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 8797ebb127f42163df06786d40842f46a7edcdd0 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 30 Jul 2015 12:46:28 -0700 Subject: [PATCH 05/17] 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 1ec69110c..6b3d348ae 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 b8ae6d13a9eff0c7ff6acdf1e9a2d99292ae07c7 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 30 Jul 2015 12:47:10 -0700 Subject: [PATCH 06/17] 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 8b0f19f5d..207f96421 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 4661081c7dc1c0d7849bb5cbe869ee8d96e9935b Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 30 Jul 2015 13:47:31 -0700 Subject: [PATCH 07/17] 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 6b3d348ae..c8a7c9719 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 207f96421..ffce53881 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 7a85d035c071f09882275499aa17ed0bce9f1ab4 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 3 Aug 2015 10:48:46 -0700 Subject: [PATCH 08/17] 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 05be91e26..97b14a942 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 c8a7c9719..5946851b2 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 7f8dd8eb5..3c83030df 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 645974e33..196e0314a 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 ffce53881..e76e88df4 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 c97988180434ec0fc59d12b188fe96f19b6149f3 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 3 Aug 2015 13:54:07 -0700 Subject: [PATCH 09/17] 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 97b14a942..e25d43a83 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 5946851b2..1d9894014 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 196e0314a..38ff35934 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 e76e88df4..0ca76c2c1 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 54618f1750a4567b5c66a23cfedaf76070b51dd4 Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 4 Aug 2015 14:38:53 -0700 Subject: [PATCH 10/17] 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 e25d43a83..755b5c1db 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 1d9894014..c403cfe6d 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 3c83030df..5e0d5be2b 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 38ff35934..1692f15df 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 0ca76c2c1..b91730553 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 f2ce0d713d8fd529d0e18b04c69cc97ec087c347 Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 12 Aug 2015 13:56:55 -0700 Subject: [PATCH 11/17] 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 1692f15df..a6034f0eb 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 f496f91af09c421926163a682e20834906f7ddf7 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 13 Aug 2015 09:47:10 -0700 Subject: [PATCH 12/17] 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 c403cfe6d..801c4000b 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 5e0d5be2b..8d39d3f9f 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 a6034f0eb..17e58d409 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 b91730553..93cbfe71d 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 72ea5abd0b724d0ed8743de190e29823d8bffd03 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 13 Aug 2015 10:53:09 -0700 Subject: [PATCH 13/17] 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 801c4000b..f930dc890 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 93cbfe71d..a566d83cc 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 1a796b59244b2681965ad5e22586ac3ec3f136bf Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 14 Aug 2015 10:51:25 -0700 Subject: [PATCH 14/17] 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 f930dc890..03a8cda0e 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 a566d83cc..612655c22 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 2241d63a28e7813e210bab4884f05a14b66c3b6a Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 14 Aug 2015 11:27:22 -0700 Subject: [PATCH 15/17] No longer defining LPSTR --- impl/pal.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/impl/pal.h b/impl/pal.h index 17e58d409..f30903a2f 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 e4fd76b7398ec4657ea014ac7f28a19dbb0077c7 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 17 Aug 2015 17:02:40 -0700 Subject: [PATCH 16/17] 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 5ee935bc3..d799e590b 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 03a8cda0e..364179aa1 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 f30903a2f..3ef233fd6 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 612655c22..21e8c5382 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 23ad440cfc5d6cd6f7bce5b93bed616d16ba1854 Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 21 Aug 2015 09:55:39 -0700 Subject: [PATCH 17/17] 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 364179aa1..818623ddf 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 3ef233fd6..8bf54dbce 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 21e8c5382..51ebd0ccc 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); }