andre
andre

Reputation: 7249

LogonUser: The program has unexpectedly finished

The following use of LogonUser will crash my application.

inline std::string w_to_string(std::wstring wstr) {
    typedef std::codecvt_utf8<wchar_t> convert_type;
    std::wstring_convert<convert_type, wchar_t> converter;
    return converter.to_bytes(wstr);
}

inline const std::wstring to_wstring(const std::string& str) {
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
    return converter.from_bytes(str);
}

inline bool verify(const std::string username,
        const std::string password, const std::string domain) {
    auto user = to_wstring(username);
    auto pass = to_wstring(password);
    auto dom  = to_wstring(domain);
    PHANDLE hToken;
    //UNICODE is set
    return LogonUser(user.c_str(), dom.c_str(), pass.c_str(), LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, hToken);
}

However if I replace auto pass = to_wstring(password); with auto pass = to_wstring("test"); everything works fine.

Can someone explain why this is the case and how to avoid it?

Upvotes: 0

Views: 209

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596497

The problem is not with your strings, it is with your hToken variable. You are passing an uninitialized pointer to LogonUser(), so it writes the user's token to random memory, which is undefined behavior so anything can happen.

You need to pass a pointer to a valid HANDLE variable, and then call CloseHandle() when you are done using it, eg:

inline bool verify(const std::string username, const std::string password, const std::string domain)
{
    auto user = to_wstring(username);
    auto pass = to_wstring(password);
    auto dom  = to_wstring(domain);
    HANDLE hToken;
    bool success = LogonUserW(user.c_str(), dom.c_str(), pass.c_str(), LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken);
    if (success)
        CloseHandle(hToken);
    return success;
}

Which can be simplified to this:

inline bool verify(const std::string username, const std::string password, const std::string domain)
{
    HANDLE hToken;
    bool success = LogonUserW(to_wstring(username).c_str(), to_wstring(domain).c_str(), to_wstring(password).c_str(), LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken);
    if (success)
        CloseHandle(hToken);
    return success;
}

Upvotes: 2

Related Questions