我尝试将代码here和here混合使用,以从通过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;
}
最佳答案
将其放在此处以提高知名度。哈里·约翰斯顿在评论中回答。问题是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/