Win32相当于getuid()

时间:2009-10-20 13:47:56

标签: c++ windows

我正在将C ++库从Linux移植到Windows,并且遇到了getuid()的问题,这在Windows中是不受支持的。

我可以使用哪些想法?

7 个答案:

答案 0 :(得分:4)

您可以使用GetUserName检索与当前主题相关联的用户的名称:

// ANSI version    
string GetWindowsUserNameA()
    {
        char buffer[UNLEN + 1] = {0};
        DWORD buffer_len = UNLEN + 1;
        if (!::GetUserNameA(buffer, & buffer_len))
        {
            // error handling
        }

        return string(buffer);
    }

答案 1 :(得分:4)

Windows equivilent实际上是用户的SID。您可以使用“GetTokenInformation”调用并查询TokenUser信息类来获取此信息。

要调用GetTokenInformation,您需要一个用户令牌的句柄,您可以通过调用OpenProcessToken(或者如果您冒充某人)来获取OpenThreadToken。

答案 2 :(得分:2)

Windows最接近的UID等价物(可能)是SID。 GetUserName后跟LookupAccountName可以获得用户的SID。

答案 3 :(得分:1)

查看Microsoft关于移植Interix (also known as Services for UNIX 3.0)库的建议。虽然你想要的东西太过分了。

答案 4 :(得分:0)

在DotNet中 - Environment.UserName

答案 5 :(得分:0)

正确的api是SHGetUID(),从Shell导出

答案 6 :(得分:0)

这就是我想出来的。

#include <stdint.h>
#include <stdlib.h>
#include <Windows.h>
#include <sddl.h>

#include <iostream>
#include <iomanip>
#include <memory>

struct heap_delete
{
    typedef LPVOID pointer;
    void operator()(LPVOID p)
    {
        ::HeapFree(::GetProcessHeap(), 0, p);
    }
};
typedef std::unique_ptr<LPVOID, heap_delete> heap_unique_ptr;

struct handle_delete
{
    typedef HANDLE pointer;
    void operator()(HANDLE p)
    {
        ::CloseHandle(p);
    }
};
typedef std::unique_ptr<HANDLE, handle_delete> handle_unique_ptr;

typedef uint32_t uid_t;

BOOL GetUserSID(HANDLE token, PSID* sid)
{
    if (
        token == nullptr || token == INVALID_HANDLE_VALUE
        || sid == nullptr
        )
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
    DWORD tokenInformationLength = 0;
    ::GetTokenInformation(
        token, TokenUser, nullptr, 0, &tokenInformationLength);
    if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
    {
        return FALSE;
    }
    heap_unique_ptr data(
        ::HeapAlloc(
            ::GetProcessHeap(), HEAP_ZERO_MEMORY,     
            tokenInformationLength));
    if (data.get() == nullptr)
    {
        return FALSE;
    }
    BOOL getTokenInfo = ::GetTokenInformation(
        token, TokenUser, data.get(),
        tokenInformationLength, &tokenInformationLength);
    if (! getTokenInfo)
    {
        return FALSE;
    }
    PTOKEN_USER pTokenUser = (PTOKEN_USER)(data.get());
    DWORD sidLength = ::GetLengthSid(pTokenUser->User.Sid);
    heap_unique_ptr sidPtr(
        ::HeapAlloc(
            GetProcessHeap(), HEAP_ZERO_MEMORY, sidLength));
    PSID sidL = (PSID)(sidPtr.get());
    if (sidL == nullptr)
    {
        return FALSE;
    }
    BOOL copySid = ::CopySid(sidLength, sidL, pTokenUser->User.Sid);
    if (! copySid)
    {
        return FALSE;
    }
    if (!IsValidSid(sidL))
    {
        return FALSE;
    }
    *sid = sidL;
    sidPtr.release();
    return TRUE;
}

uid_t GetUID(HANDLE token)
{
    PSID sid = nullptr;
    BOOL getSID = GetUserSID(token, &sid);
    if (! getSID || ! sid)
    {
        return -1;
    }
    heap_unique_ptr sidPtr((LPVOID)(sid));
    LPWSTR stringSid = nullptr;
    BOOL convertSid = ::ConvertSidToStringSidW(
        sid, &stringSid);
    if (! convertSid)
    {
        return -1;
    }
    uid_t ret = -1;
    LPCWSTR p = ::wcsrchr(stringSid, L'-');
    if (p && ::iswdigit(p[1]))
    {
        ++p;
        ret = ::_wtoi(p);
    }
    ::LocalFree(stringSid);
    return ret;
}

uid_t getuid()
{
    HANDLE process = ::GetCurrentProcess();
    handle_unique_ptr processPtr(process);
    HANDLE token = nullptr;
    BOOL openToken = ::OpenProcessToken(
        process, TOKEN_READ|TOKEN_QUERY_SOURCE, &token);
    if (! openToken)
    {
        return -1;
    }
    handle_unique_ptr tokenPtr(token);
    uid_t ret = GetUID(token);
    return ret;
}

uid_t geteuid()
{
    HANDLE process = ::GetCurrentProcess();
    HANDLE thread = ::GetCurrentThread();
    HANDLE token = nullptr;
    BOOL openToken = ::OpenThreadToken(
        thread, TOKEN_READ|TOKEN_QUERY_SOURCE, FALSE, &token);
    if (! openToken && ::GetLastError() == ERROR_NO_TOKEN)
    {
        openToken = ::OpenThreadToken(
            thread, TOKEN_READ|TOKEN_QUERY_SOURCE, TRUE, &token);
        if (! openToken && ::GetLastError() == ERROR_NO_TOKEN)
        {
            openToken = ::OpenProcessToken(
                process, TOKEN_READ|TOKEN_QUERY_SOURCE, &token);
        }
    }
    if (! openToken)
    {
        return -1;
    }
    handle_unique_ptr tokenPtr(token);
    uid_t ret = GetUID(token);
    return ret;
}

int main()
{
    uid_t uid = getuid();
    uid_t euid = geteuid();
    std::cout
        << "uid: "  << std::setbase(10) << uid  << std::endl
        << "euid: " << std::setbase(10) << euid << std::endl
        << std::endl;
    return EXIT_SUCCESS;
}

请注意Larry Osterman给出的答案非常有用。它让我开始朝着正确的方向前进。