Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么LoadUserProfile()失败并出现错误5“;拒绝访问”;在系统服务中运行的代码中?_C++_Windows_Visual Studio_Winapi - Fatal编程技术网

C++ 为什么LoadUserProfile()失败并出现错误5“;拒绝访问”;在系统服务中运行的代码中?

C++ 为什么LoadUserProfile()失败并出现错误5“;拒绝访问”;在系统服务中运行的代码中?,c++,windows,visual-studio,winapi,C++,Windows,Visual Studio,Winapi,我的系统级Windows服务中运行了一段代码,如下所示。如果我将CreateEnvironmentBlock()和CreateProcessAsUser()添加到代码中,就可以了。但是我使用了“LoadUserProfile()”,它失败了,出现错误5,这意味着“访问被拒绝”。请帮助检查缺少的内容。我想要的是从这个系统服务中检索一个用户级注册表值。代码中的注释是另一种方式,但也无法检索用户级注册表值 void GetUserRegistry() { #ifdef Q_OS_WIN DW

我的系统级Windows服务中运行了一段代码,如下所示。如果我将CreateEnvironmentBlock()和CreateProcessAsUser()添加到代码中,就可以了。但是我使用了“LoadUserProfile()”,它失败了,出现错误5,这意味着“访问被拒绝”。请帮助检查缺少的内容。我想要的是从这个系统服务中检索一个用户级注册表值。代码中的注释是另一种方式,但也无法检索用户级注册表值

void GetUserRegistry()
{
#ifdef Q_OS_WIN

    DWORD lastError = 0;

    DWORD sessionId = WTSGetActiveConsoleSessionId();
    qInfo() << "Session ID = " << sessionId;

    wchar_t* ppUserName[100];
    DWORD sizeOfUserName;
    WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, ppUserName, &sizeOfUserName);
    qInfo() << "Windows User Name = " << QString::fromWCharArray(*ppUserName);

    std::wstring strValueOfBinDir = L"Unknown Value";
    // LONG regOpenResult = ERROR_SUCCESS;

    HANDLE hUserToken = NULL;
    HANDLE hFakeToken = NULL;

    if (WTSQueryUserToken(sessionId, &hUserToken))
    {
         if (DuplicateTokenEx(hUserToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &hFakeToken) == TRUE)
         {
            qInfo() << "Before ImpersonateLoggedOnUser()......";
            if (ImpersonateLoggedOnUser(hFakeToken))
            {
                HKEY hKey;

                // regOpenResult = RegOpenCurrentUser(KEY_READ, &hKey);

                PROFILEINFO profileInfo;
                ZeroMemory( &profileInfo, sizeof( PROFILEINFO ) );
                profileInfo.dwSize = sizeof( PROFILEINFO );
                profileInfo.lpUserName = *ppUserName;
                // wchar_t roamingPath[] = L"C:\\Users\\Finix";  // L"C:\\Users\\Finix\\AppData\\Roaming";
                // profileInfo.lpProfilePath = roamingPath;

                if (LoadUserProfile(hFakeToken, &profileInfo))
                {
                    HANDLE hProfile = profileInfo.hProfile;

                    RegOpenKeyEx(HKEY_CURRENT_USER,
                                 TEXT("Software\\Baidu\\BaiduYunGuanjia"),
                                 0,
                                 KEY_READ,
                                 &hKey);

                    GetStringRegKey(hKey, TEXT("installDir"), strValueOfBinDir, TEXT("Unknown"));

                    UnloadUserProfile(hFakeToken, hProfile);
                }
                else
                {
                    lastError = GetLastError();
                }

                RevertToSelf();

            }
            else
            {
                qCritical() << "Failed to ImpersonateLoggedOnUser...";
            }

            CloseHandle(hFakeToken);
        }
        else
        {
            qCritical() << "Failed to call DuplicateTokenEx...";
        }

        CloseHandle(hUserToken);
    }
    else
    {
        qCritical() << "Failed to get the user token of session " << sessionId;
    }

    if (lastError)
    {
        qCritical() << "Failed to LoadUserProfile(), The ERROR is " << lastError;
    }

//    if (regOpenResult != ERROR_SUCCESS)
//    {
//        qCritical() << "Failed to call RegOpenCurrentUser(), Error is " << regOpenResult;
//    }

    qInfo() << "The value of Registry is " << QString::fromWCharArray( strValueOfBinDir.c_str() );

#endif
}
void GetUserRegistry()
{
#如果你赢了
DWORD lastError=0;
DWORD sessionId=WTSGetActiveConsoleSessionId();
()您不能调用
LoadUserProfile
的原因是您正在模拟用户。
LoadUserProfile
需要管理员权限,即您应该在自己的上下文中调用它,而不是在模拟的上下文中调用它。这不是用户加载自己的配置文件的功能,通常系统代表用户调用它

您不应该调用
LoadUserProfile
的原因是用户已登录,因此配置文件将已加载。我们知道相关用户已登录,因为
WTSQueryUserToken
不能用于为未登录的用户获取令牌

(可能存在用户当前正在登录或注销的边缘情况。但是在登录/注销期间调用
LoadUserProfile
函数在任何情况下都可能是不明智的。)

如果您只想打开已登录用户的注册表配置单元,请使用。(请注意,您确实希望将模拟与此函数一起使用,如文档所述。)您不能调用
LoadUserProfile
的原因是您正在模拟用户。
LoadUserProfile
需要管理员权限,即您应该在您自己的上下文中调用它,而不是在模拟的上下文中调用它。这不是用户加载自己的配置文件的函数,通常系统代表用户调用它

您不应该调用
LoadUserProfile
的原因是用户已登录,因此配置文件将已加载。我们知道相关用户已登录,因为
WTSQueryUserToken
不能用于为未登录的用户获取令牌

(可能存在用户当前正在登录或注销的边缘情况。但是在登录/注销期间调用
LoadUserProfile
函数在任何情况下都可能是不明智的。)


如果您只想打开已登录用户的注册表配置单元,请使用。(注意,您确实希望使用此函数的模拟,如文档所述。)

简单来说,调用是:WTSGetActiveConsoleSessionId()+WTSQueryUserToken()+DuplicateTokenEx()+ImpersonateLoggedOnUser()+LoadUserProfile()。为什么是LoadUserProfile())失败,出现错误5?在调用LoadUserProfile()之前,应该做什么?我已经做了如上所示的代码。我是否遗漏了什么?您正在声明一个指向字符数组的指针
wchar\t*ppUserName[100]
。您必须将其更改为
wchar\t ppUserName[100]
但是可能还有其他错误。@BarmakShemirani上面的代码是正确的。WTSQuerySessionInformation()的第四个参数是“LPWSTR*”,因此它是指向指针的指针。正如我提到的,如果将LoadUserProfile()更改为“CreateEnvironmentBlock()+CreateProcessAsUser(),这个程序就会工作。这意味着除了对LoadUserProfile()的调用之外,其余部分都很好失败。然后将其声明为
wchar\u t*pUsername;
并将
&pUsername
传递给该函数。完成后将其释放。您现在设置它的方式没有意义。如果您只使用
RegOpenCurrentUser
本身,它不工作吗?简单地说,调用是:WTSGetActiveConsoleSessionId()+WTSQueryUserToken()+DuplicateTokenEx()+ImpersonateLoggedOnUser()+LoadUserProfile()。为什么LoadUserProfile()失败并出现错误5?在调用LoadUserProfile()之前,应该做什么?我做了如上所示的代码。是否遗漏了什么?您正在声明指向字符数组的指针
。您必须将其更改为
wchar_t ppUserName[100];
,但可能还有其他错误。@BarmakShemirani上面的代码是正确的。WTSQuerySessionInformation()的第四个参数是“LPWSTR*”,因此它是指向指针的指针。正如我提到的,如果将LoadUserProfile()更改为“CreateEnvironmentBlock(),则该程序可以工作+CreateProcessAsUser()”。这意味着除了对LoadUserProfile()的调用之外,其余部分都很好失败。然后将其声明为
wchar\u t*pUsername;
并将
&pUsername
传递给该函数。完成后将其释放。您现在设置它的方式没有意义。如果您仅使用
RegOpenCurrentUser
本身,它不起作用吗?我注意到您说您尝试了
RegOpenCurrentUser
,但它不起作用。我知道建议您发布一个单独的问题,包括代码和失败原因的详细描述。另请参阅@HarryJohnston,谢谢您的建议。在我调整RegOpenKeyEx()的某些参数后,它会起作用。对于您附加的博客,我也做了一个测试。看起来博客所说的不正确。在中断后,我可以获得活动用户的一个特殊用户注册表配置单元;然后,在模拟结束后,我再次调用代码,它无法再获得相同的配置单元。您是指使用HKEY_CURRENT_user还是使用RegOpenCurrentUser返回的键?根据你的最新问题,使用HKEY_CURRENT_用户不起作用,这就是博客文章所说的。使用RegOpenCurrentUser返回的密钥(如你最新问题的公认答案所示)如果你在模拟,应该总是有效的。啊,是的,@HarryJohnston,我认为你是对的。我使用了RegOpenCurrentUser返回的密钥。我注意到你说你尝试了
RegOpenCurrentUser
,但它不起作用。我建议你单独发布一篇文章