CreateProcessAsUser生成错误5

CreateProcessAsUser generating error 5

本文关键字:错误 CreateProcessAsUser      更新时间:2023-10-16

我已经尝试混合这里和这里的代码运行一个GUI exe从一个服务,通过QtService初始化,但每当我运行下面的代码,我得到一个错误5从CreateProcessAsUser。

另外,我在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)