windows Win32 等价于 getuid()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1594746/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 13:18:47  来源:igfitidea点击:

Win32 equivalent of getuid()

c++windows

提问by StevieG

I'm in the process of porting a C++ library from Linux to Windows, and am having problems with getuid(), which is not supported in Windows.

我正在将 C++ 库从 Linux 移植到 Windows,并且在使用 Windows 不支持的 getuid() 时遇到问题。

Any ideas what I can use in its place?

我可以用什么来代替它的任何想法?

回答by KeatsPeeks

You can retrieves the name of the user associated with the current thread with GetUserName:

您可以使用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);
    }

回答by ReinstateMonica Larry Osterman

The Windows equivilent is actually the user's SID. You can get this by using the "GetTokenInformation" call and querying for the TokenUser information class.

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

To call GetTokenInformation, you need a handle to the users token, which you can get by calling OpenProcessToken (or OpenThreadToken if you're impersonating someone).

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

回答by Jerry Coffin

Windows' closest equivalent of a UID is (probably) a SID. GetUserNamefollowed by LookupAccountNameshould get you the user's SID.

Windows 最接近的 UID 等价物(可能)是 SID。GetUserName其次LookupAccountName应该为您提供用户的 SID。

回答by Ben Key

This is what I came up with.

这就是我想出的。

#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;
}

Note that the answer given by Larry Ostermanwas very helpful. It got me started in the correct direction.

请注意,拉里·奥斯特曼( Larry Osterman)给出的答案非常有帮助。它让我朝着正确的方向开始。

回答by Epsilon Prime

Check out Microsoft's recommendations on porting with the Interix (also known as Services for UNIX 3.0)library. Overkill for what you want though.

查看 Microsoft 关于移植Interix(也称为 UNIX 3.0 服务)库的建议。不过,你想要的东西太过分了。

回答by Dani

in DotNet - Environment.UserName

在 DotNet 中 - Environment.UserName

回答by marcus

The right api is SHGetUID(), exported from Shell

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