c++ - CreateProcessAsUser 生成错误 5

标签 c++ windows winapi

我试过混合代码 herehere从通过 QtService 初始化的服务运行 GUI exe,但每当我运行下面的代码时,我都会从 CreateProcessAsUser 收到错误 5。

另外,我看到了类似问题的答案here on StackOverflow但无法弄清楚 DACL 与问题的关系,并且无法使用 Harry Johnson 的答案,因为我不会获得用户的登录信息。

那么,有人可以帮助我理解为什么我会从下面的代码中收到错误 5(访问被拒绝)吗?

if(initUiWin())
    log->write("InitUiWin executed.");
else {
    QString errorNumber = QString::number(GetLastError());
    log->write("InitUiWin error: " + errorNumber);
}

-

bool initUiWin()
{
    // obtain the currently active session id; every logged on
    // User in the system has a unique session id
    uint dwSessionId = WTSGetActiveConsoleSessionId();

    // obtain the process id of the winlogon process that
    // is running within the currently active session
    QString processName("winlogon.exe");
    DWORD winlogonPID = FindProcessId(processName.toStdWString(),dwSessionId);
    if( winlogonPID != 0 ) {
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, winlogonPID);
    HANDLE hToken;
    OpenProcessToken(hProcess,TOKEN_READ,&hToken);

    // Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser
    SECURITY_ATTRIBUTES sa;
    sa.nLength = static_cast<DWORD>(sizeof(SECURITY_ATTRIBUTES));

    // copy the access token of the winlogon process;
    // the newly created token will be a primary token
    HANDLE hUserTokenDup;
    if (!DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,&sa,
                            SecurityIdentification,TokenPrimary,&hUserTokenDup)) {
        CloseHandle(hProcess);
        CloseHandle(hToken);
        return false;
    }

    // Get Handle to the interactive window station
    HWINSTA hwinsta = NULL;
    hwinsta = OpenWindowStation(
           _T(L"winsta0"),                   // the interactive window station
           FALSE,                       // handle is not inheritable
           READ_CONTROL | WRITE_DAC);   // rights to read/write the DACL
    if(hwinsta == NULL)
        return false;

    // To get the correct default desktop, set the caller's
    // window station to the interactive window station.
    if (!SetProcessWindowStation(hwinsta))
        return false;

    // Get a handle to the interactive desktop.
    HDESK hdesk = NULL;
    hdesk = OpenDesktop(
          _T(L"default"),     // the interactive window station
          0,             // no interaction with other desktop processes
          FALSE,         // handle is not inheritable
          READ_CONTROL | // request the rights to read and write the DACL
          WRITE_DAC |
          DESKTOP_WRITEOBJECTS |
          DESKTOP_READOBJECTS);
    if(hdesk == NULL)
        return false;

    // Get the SID for the client's logon session.
    PSID pSid = NULL;
    if (!GetLogonSID(hUserTokenDup, &pSid))
          return false;

    // Allow logon SID full access to interactive window station.
    if (!AddAceToWindowStation(hwinsta, pSid) )
          return false;

    // Allow logon SID full access to interactive desktop.
    if (!AddAceToDesktop(hdesk, pSid) )
          return false;

    // Impersonate client to ensure access to executable file.
    if (!ImpersonateLoggedOnUser(hUserTokenDup) )
          return false;

    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = static_cast<DWORD>(sizeof(STARTUPINFO));

    // interactive window station parameter; basically this indicates
    // that the process created can display a GUI on the desktop
    wchar_t auxBuffer[16] = L"winsta0\\default";
    si.lpDesktop = auxBuffer;

    // flags that specify the priority and creation method of the process
    int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_BREAKAWAY_FROM_JOB;

    // create a new process in the current User's logon session
    bool result = CreateProcessAsUser(hUserTokenDup,  // client's access token
                                    L"test-ui-systray.exe",             // file to execute
                                    NULL,  // command line
                                    &sa,           // pointer to process SECURITY_ATTRIBUTES
                                    &sa,           // pointer to thread SECURITY_ATTRIBUTES
                                    false,            // handles are not inheritable
                                    dwCreationFlags,  // creation flags
                                    NULL,      // pointer to new environment block
                                    NULL,             // name of current directory
                                    &si,           // pointer to STARTUPINFO structure
                                    &pi      // receives information about new process
                                    );

    if (pSid)
          FreeLogonSID(&pSid);
    if (hdesk)
          CloseDesktop(hdesk);
    if (hwinsta)
          CloseWindowStation(hwinsta);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    return result;
}

return false;

}

最佳答案

为了可见性,把它放在这里。 HarryJohnston 在评论中回答。问题是 OpenProcessToken 中的标志,我只是更改了

OpenProcessToken(hProcess,TOKEN_READ,&hToken)

OpenProcessToken(hProcess,TOKEN_READ|TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY,&hToken)

关于c++ - CreateProcessAsUser 生成错误 5,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32638655/

相关文章:

c++ - 如何设置项目属性以删除警告 MSB8004 : Intermediate Directory does not end with a trailing slash.

c++ - 是否存在任何情况下有效的 C 代码无法使用 g++ 正确编译

c++ - Shell 扩展 : Static-Linking vs. C/C++ 运行时 DLL 的动态链接

python - 如何在后台修复窗口?

c++ - CreateHwndRenderTarget引发异常:读取访问冲突。 **这**是nullptr

c++ - 在 std::map 中的给定迭代器位置之后继续循环

C++11 在 constexpr 函数中使用统一值初始化数组

c# - 将 OpenGL 用于桌面应用程序是否合理?

windows - 如何以编程方式检查远程主机的操作系统?

android - 如何在 cordova 中禁用 gradle?