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
This commit is contained in:
Andrew Schwartzmeyer 2015-08-06 17:06:04 -07:00 committed by Andrew Schwartzmeyer
parent 1b18bfd5e1
commit 062eb5a7b4
No known key found for this signature in database
GPG key ID: D50036A9A84A216F
3 changed files with 119 additions and 96 deletions

View file

@ -1,4 +1,7 @@
#include "getusername.h"
//! @file getusername.cpp
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
//! @brief Implements GetUserName Win32 API
#include <errno.h>
#include <langinfo.h>
#include <locale.h>
@ -8,66 +11,62 @@
#include <unicode/ucnv.h>
#include <unicode/ustring.h>
#include <unicode/uchar.h>
#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<char16_t> username16(LOGIN_NAME_MAX+1, 0);
icu::UnicodeString username8(username.c_str(), "UTF-8");
int32_t targetSize = username8.extract(0, username8.length(),
reinterpret_cast<char *>(&username16[0]),
reinterpret_cast<char*>(&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;
}

View file

@ -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

View file

@ -1,3 +1,7 @@
//! @file test-getusername.cpp
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
//! @brief Unit tests for GetUserName
#include <string>
#include <vector>
#include <unistd.h>
@ -8,7 +12,9 @@
#include <unicode/uchar.h>
#include "getusername.h"
class GetUserNameTest : public ::testing::Test {
//! Test fixture for GetUserNameW
class GetUserNameTest : public ::testing::Test
{
protected:
DWORD lpnSize;
std::vector<WCHAR_T> 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<char *>(&lpBuffer[0]);
const char* begin = reinterpret_cast<char*>(&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<char *>(&username[0]), "UTF-8");
username16.extract(0, username.length(),
reinterpret_cast<char*>(&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();
}