diff --git a/impl/getusername.cpp b/impl/getusername.cpp index 0ca96e5a9..5d0bec036 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 d00acdf30..e27aeef28 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(); }