CreateProcessAsUser调用问题

youxikaifa113 2010-12-01 02:43:52
为了实现远程连接也能和服务程序交互,以下是我实现的代码,但是执行完既没报错也没看到服务程序启动,连任务管理器里面都没有该进程(把显示所有用户的进程勾起来也是一样)。原先直接用CreateProcess创建进程倒是可以,但是就是只能本机本地交互,其它登入用户都没办法交互,我的服务程序本身是可以允许交互的(CreateService参数有设置SERVICE_INTERACTIVE_PROCESS,且在控制面板里面的服务--登入也看过了,是允许交互的)。

代码如下:
BOOL RunProcess(int ProcessIndex)
{
char* pProcessNames;
pProcessNames = ProcessNames[ProcessIndex];
if (pProcessNames[strlen(pProcessNames)-1] == '\\')
return false;

//获取服务进程Token
HANDLE hTokenThis = NULL;
HANDLE hTokenDup = NULL;
BOOL bResult = GetTokenByName(hTokenThis, "EXPLORER.EXE");
if (!bResult)
{
WriteLog(pLogFile, "Failed to GetTokenByName!");
return FALSE;
}
//复制服务进程的Token然后修改其中的SessionId,用于在用户桌面上创建一个具有SYSTEM权限的新进程
bResult = DuplicateTokenEx(hTokenThis, MAXIMUM_ALLOWED,NULL, SecurityIdentification, TokenPrimary, &hTokenDup);
if (!bResult)
{
CloseHandle(hTokenThis);
WriteLog(pLogFile, "Failed to DuplicateTokenEx!");
return FALSE;
}

//遍历出活动SessionId
DWORD dwSessionId = 0;
WTS_SESSION_INFO* sessionInfo = NULL;
DWORD ndSessionInfoCount;
bResult = WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessionInfo, &ndSessionInfoCount);
if (!bResult)
{
CloseHandle(hTokenDup);
CloseHandle(hTokenThis);
WriteLog(pLogFile, "Failed to WTSEnumerateSessions!");
return FALSE;
}
for(unsigned int i=0; i<ndSessionInfoCount; i++)
{
if( (sessionInfo[i].State == WTSActive) || (sessionInfo[i].State == WTSDisconnected) )
{
//修改Token中的SessionId
dwSessionId = sessionInfo[i].SessionId;
bResult = SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(DWORD));
if (!bResult)
{
CloseHandle(hTokenDup);
CloseHandle(hTokenThis);
WriteLog(pLogFile, "Failed to SetTokenInformation!");
return FALSE;
}

//创建进程
STARTUPINFO startUpInfo;
ZeroMemory(&startUpInfo, sizeof(STARTUPINFO));
startUpInfo.cb = sizeof(STARTUPINFO);
startUpInfo.lpDesktop = "WinSta0\\Default";
LPVOID pEnv = NULL;
bResult = CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE); //创建进程环境块
if (!bResult)
{
CloseHandle(hTokenDup);
CloseHandle(hTokenThis);
WriteLog(pLogFile, "Failed to CreateEnvironmentBlock!");
return FALSE;
}
bResult = CreateProcessAsUser(
hTokenDup,
NULL,
ProcessNames[ProcessIndex],
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
pEnv,
NULL,
&startUpInfo,
&pProcInfo[ProcessIndex]);
if (!bResult)
{
CloseHandle(hTokenDup);
CloseHandle(hTokenThis);
DestroyEnvironmentBlock(&pEnv);
WriteLog(pLogFile, "Failed to CreateProcessAsUser!");
return FALSE;
}
}
}

//关闭句柄
CloseHandle(hTokenDup);
CloseHandle(hTokenThis);
return TRUE;
}

照理来说这样处理后应该是在活动Session中创建进程了,但是事实上却是没有,不知道谁可以帮我看下是不是参数或则哪里不对,感激不尽。。
...全文
972 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
sexinshanghai 2013-03-18
  • 打赏
  • 举报
回复
这个问题我也在研究,而且也没有搞清楚。帮你顶顶吧
youxikaifa113 2010-12-03
  • 打赏
  • 举报
回复
等待回答中。。。
rendao0563 2010-12-02
  • 打赏
  • 举报
回复

BOOL ProcessIdToSessionId(
DWORD dwProcessId,
DWORD* pSessionId
);
youxikaifa113 2010-12-02
  • 打赏
  • 举报
回复
沉了。。。。
youxikaifa113 2010-12-02
  • 打赏
  • 举报
回复
ProcessIdToSessionId参数咋弄,该通过什么进程来查找呢?"winlogon.exe"不行,这个每个登入用户都有一个的,我想要查找我自己的用户。其他人的不管
youxikaifa113 2010-12-01
  • 打赏
  • 举报
回复
我输出看了下theApp.m_csIniFile = run\ISMyTest.ini,这个貌似没错吧
youxikaifa113 2010-12-01
  • 打赏
  • 举报
回复
是不是因为远程登入的账号路径有什么猫腻呢?
youxikaifa113 2010-12-01
  • 打赏
  • 举报
回复
额,实在是不好意思,不太常发帖。
谢谢rendao0563,但是还有个问题就是我发现程序读取配置文件的时候出错了
BOOL CMyTestWinApp::InitInstance()
{
...
// 分析标准外壳命令、DDE、打开文件操作的命令行
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (cmdInfo.m_strFileName.GetLength()>0)
{
strcpy(m_csIniFile,(LPCSTR)cmdInfo.m_strFileName);
}
...
}


bool CMyTestWinDlg::CheckConfigFile(const char *filename)
{
FILE *fp = 0;
fp = _tfopen(filename, _T("rt"));
if (fp)
{
...
}
else
{
LOG((CLOG_DEBUG "could not _tfopen!"));
}

}

BOOL CMyTestWinDlg::OnInitDialog()
{
...
if(!CheckConfigFile(theApp.m_csIniFile))
{
...
}
...
}

输出了:could not _tfopen!

是不是这个filename的问题?
前面CreateProcessAsUser传入的参数3:
E:\Test\MyTest.exe run\ISMyTest.ini
rendao0563 2010-12-01
  • 打赏
  • 举报
回复

DWORD
CMSWindowsRelauncher::getSessionId()
{
return WTSGetActiveConsoleSessionId();
}

BOOL
CMSWindowsRelauncher::winlogonInSession(DWORD sessionId, PHANDLE process)
{
// first we need to take a snapshot of the running processes
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE) {
LOG((CLOG_ERR "could not get process snapshot (error: %i)",
GetLastError()));
return 0;
}

PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);

// get the first process, and if we can't do that then it's
// unlikely we can go any further
BOOL gotEntry = Process32First(snapshot, &entry);
if (!gotEntry) {
LOG((CLOG_ERR "could not get first process entry (error: %i)",
GetLastError()));
return 0;
}

// used to record process names for debug info
std::list<std::string> nameList;

// now just iterate until we can find winlogon.exe pid
DWORD pid = 0;
while(gotEntry) {

// make sure we're not checking the system process
if (entry.th32ProcessID != 0) {

DWORD processSessionId;
BOOL pidToSidRet = ProcessIdToSessionId(
entry.th32ProcessID, &processSessionId);

if (!pidToSidRet) {
LOG((CLOG_ERR "could not get session id for process id %i (error: %i)",
entry.th32ProcessID, GetLastError()));
return 0;
}

// only pay attention to processes in the active session
if (processSessionId == sessionId) {

// store the names so we can record them for debug
nameList.push_back(entry.szExeFile);

if (_stricmp(entry.szExeFile, "winlogon.exe") == 0) {
pid = entry.th32ProcessID;
break;
}
}
}

// now move on to the next entry (if we're not at the end)
gotEntry = Process32Next(snapshot, &entry);
if (!gotEntry) {

DWORD err = GetLastError();
if (err != ERROR_NO_MORE_FILES) {

// only worry about error if it's not the end of the snapshot
LOG((CLOG_ERR "could not get subsiquent process entry (error: %i)",
GetLastError()));
return 0;
}
}
}

std::string nameListJoin;
for(std::list<std::string>::iterator it = nameList.begin();
it != nameList.end(); it++) {
nameListJoin.append(*it);
nameListJoin.append(", ");
}

LOG((CLOG_DEBUG "checked processes while looking for winlogon.exe: %s",
nameListJoin.c_str()));

CloseHandle(snapshot);

if (pid) {
// now get the process so we can get the process, with which
// we'll use to get the process token.
*process = OpenProcess(MAXIMUM_ALLOWED, FALSE, pid);
return true;
}
else {
LOG((CLOG_DEBUG "could not find winlogon.exe in session %i", sessionId));
return false;
}
}
rendao0563 2010-12-01
  • 打赏
  • 举报
回复

// gets the current user (so we can launch under their session)
HANDLE
CMSWindowsRelauncher::getCurrentUserToken(DWORD sessionId, LPSECURITY_ATTRIBUTES security)
{
HANDLE currentToken;
HANDLE winlogonProcess;

if (winlogonInSession(sessionId, &winlogonProcess)) {

LOG((CLOG_DEBUG "session %i has winlogon.exe", sessionId));

// get the token, so we can re-launch with this token
// -- do we really need all these access bits?
BOOL tokenRet = OpenProcessToken(
winlogonProcess,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY |
TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY |
TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE,
¤tToken);
}
else {

LOG((CLOG_ERR "session %i does not have winlogon.exe "
"which is needed for re-launch", sessionId));
return 0;
}

HANDLE primaryToken;
BOOL duplicateRet = DuplicateTokenEx(
currentToken, MAXIMUM_ALLOWED, security,
SecurityImpersonation, TokenPrimary, &primaryToken);

if (!duplicateRet) {
LOG((CLOG_ERR "could not duplicate token %i (error: %i)",
currentToken, GetLastError()));
return 0;
}

return primaryToken;
}

int
CMSWindowsRelauncher::relaunchLoop()
{
// start with invalid id (gets re-assigned on first loop)
DWORD sessionId = -1;

// keep here so we can check if proc running -- huh?
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

int returnCode = kExitSuccess;
bool launched = false;

// TODO: fix this hack BEFORE release; we need to exit gracefully instead
// of being force killed!
bool loopRunning = true;
while (loopRunning) {

DWORD newSessionId = getSessionId();

// only enter here when id changes, and the session isn't -1, which
// may mean that there is no active session.
if ((newSessionId != sessionId) && (newSessionId != -1)) {

// HACK: doesn't close process in a nice way
// TODO: use CloseMainWindow instead
if (launched) {
TerminateProcess(pi.hProcess, kExitSuccess);
LOG((CLOG_DEBUG "terminated existing process to make way for new one"));
launched = false;
}

// ok, this is now the active session (forget the old one if any)
sessionId = newSessionId;

SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));

// get the token for the user in active session, which is the
// one receiving input from mouse and keyboard.
HANDLE userToken = getCurrentUserToken(sessionId, &sa);

if (userToken != 0) {
LOG((CLOG_DEBUG "got user token to launch new process"));

std::string cmd = getCommand();

// in case reusing process info struct
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = "winsta0\\default";

LPVOID environment;
BOOL blockRet = CreateEnvironmentBlock(&environment, userToken, FALSE);
if (!blockRet) {
LOG((CLOG_ERR "could not create environment block (error: %i)",
GetLastError()));

returnCode = kExitFailed;
loopRunning = false; // stop loop
}
else {

DWORD creationFlags =
NORMAL_PRIORITY_CLASS |
CREATE_NO_WINDOW |
CREATE_UNICODE_ENVIRONMENT;

// re-launch in current active user session
BOOL createRet = CreateProcessAsUser(
userToken, NULL, LPSTR(cmd.c_str()),
&sa, NULL, TRUE, creationFlags,
environment, NULL, &si, &pi);

DestroyEnvironmentBlock(environment);
CloseHandle(userToken);

if (!createRet) {
LOG((CLOG_ERR "could not launch (error: %i)", GetLastError()));
returnCode = kExitFailed;
loopRunning = false;
}
else {
LOG((CLOG_DEBUG "launched in session %i (cmd: %s)",
sessionId, cmd.c_str()));
launched = true;
}
}
}
}

// check for session change every second
ARCH->sleep(1);
}

if (launched) {
// HACK: kill just in case process it has survived somehow
TerminateProcess(pi.hProcess, kExitSuccess);
}

return kExitSuccess;
}
youxikaifa113 2010-12-01
  • 打赏
  • 举报
回复
用WTSEnumerateSessions枚举Session时,当有1个以上的Session.State == WTSActive时,该怎么得到当前正在操作的SessionID。

原先我是使用WTSGetActiveConsoleSessionId,但是这个貌似有问题,我在2003上登入了账户administration,然后又在XP上登入了账户administration,我查看了下任务管理器,发现XP上的账户标识是1,2003上的是0。
然后,我在XP上运行服务进程的时候,我发现log上输出的WTSGetActiveConsoleSessionId得到的SessionId竟然是0,而不是1。。。。
谁可以告诉我下,这个要该怎么弄。如何才能得到正确的SessionId
rendao0563 2010-12-01
  • 打赏
  • 举报
回复
//获取服务进程Token

"EXPLORER.EXE"好像不是服务

你的说明乱七八糟. 代码发不发是一回事. 至少你把上下文环境 以及 希望输入什么 输出什么结果 说清楚了.
youxikaifa113 2010-12-01
  • 打赏
  • 举报
回复
额,米办法,工作需求。俺也是想睡觉的说
youxikaifa113 2010-12-01
  • 打赏
  • 举报
回复
18楼的兄弟,你是说我8楼那个问题吧,恩,那个没错,是要绝对路径
safeildw 2010-12-01
  • 打赏
  • 举报
回复
童鞋这么晚了还在钻研C++,俺很汗颜~~等待学习
yiruirui0507 2010-12-01
  • 打赏
  • 举报
回复
使用绝对路径 回避相对路径被修改问题.
youxikaifa113 2010-12-01
  • 打赏
  • 举报
回复
WTSGetActiveConsoleSessionId这个函数当我有1个以上用户时,即时是断开的,它也只会返回第一个??奇怪
youxikaifa113 2010-12-01
  • 打赏
  • 举报
回复
自己顶。。。
youxikaifa113 2010-12-01
  • 打赏
  • 举报
回复
用WTSEnumerateSessions枚举Session时,当有1个以上的Session.State == WTSActive时,该怎么得到当前的正常操作的Session。

原先我是使用WTSGetActiveConsoleSessionId,但是这个貌似有问题,我在2003上登入了账户administration,然后又在XP上登入了账户administration,我查看了下任务管理器,发现XP上的账户标识是1,2003上的是0。
然后,我在XP上运行服务进程的时候,我发现log上输出的WTSGetActiveConsoleSessionId得到的SessionId竟然是0,而不是1。。。。
谁可以告诉我下,这个要该怎么弄。如何才能得到正确的SessionId
rendao0563 2010-12-01
  • 打赏
  • 举报
回复
我只随便copy了个代码过来. 具体你要做什么需要你自己去判断.

关于API的使用建议你直接用分类法看MSDN肯定能找到你需要的API.
加载更多回复(4)
program Project1; //{$APPTYPE CONSOLE} uses windows, SysUtils, tlhelp32, accctrl, aclapi; procedure SetPrivilege; var OldTokenPrivileges, TokenPrivileges: TTokenPrivileges; ReturnLength: dword; hToken: THandle; Luid: int64; begin OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken); LookupPrivilegeValue(nil, 'SeDebugPrivilege', Luid); TokenPrivileges.Privileges[0].luid := Luid; TokenPrivileges.PrivilegeCount := 1; TokenPrivileges.Privileges[0].Attributes := 0; AdjustTokenPrivileges(hToken, False, TokenPrivileges, SizeOf(TTokenPrivileges), OldTokenPrivileges, ReturnLength); OldTokenPrivileges.Privileges[0].luid := Luid; OldTokenPrivileges.PrivilegeCount := 1; OldTokenPrivileges.Privileges[0].Attributes := TokenPrivileges.Privileges[0].Attributes or SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, False, OldTokenPrivileges, ReturnLength, PTokenPrivileges(nil)^, ReturnLength); end; function GetProcessID(EXE_Name: PChar): THandle; var s: string; ok: Bool; ProcessListHandle: THandle; ProcessStruct: TProcessEntry32; begin Result := 0; //获得进程列表句柄 ProcessListHandle := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0); try ProcessStruct.dwSize := SizeOf(ProcessStruct); //获得第一个进程句柄 ok := Process32First(ProcessListHandle, ProcessStruct); while ok do begin s := ExtractFileName(ProcessStruct.szExeFile);//获取进程的可执行文件名称 if AnsiCompareText(Trim(s), EXE_Name)=0 then//如果是HL程序名,表示找到游戏进程。 begin Result := ProcessStruct.th32ProcessID;//保留游戏进程句柄 break; end; ok := Process32Next(ProcessListHandle, ProcessStruct);//获取下一个进程信息。 end; finally CloseHandle(ProcessListHandle);//关闭进程列表句柄 end; end; ///////////////////////////////////////////////////////////////// Function CreateSystemProcess(szProcessName: LPTSTR): BOOL; Var hProcess: THANDLE; hToken, hNewToken: THANDLE; dwPid: DWORD; pOldDAcl: PACL; pNewDAcl: PACL; bDAcl: BOOL; bDefDAcl: BOOL; dwRet: DWORD; pSacl: PACL; pSidOwner: PSID; pSidPrimary: PSID; dwAclSize: DWORD; dwSaclSize: DWORD; dwSidOwnLen: DWORD; dwSidPrimLen: DWORD; dwSDLen: DWORD; ea: EXPLICIT_ACCESS; pOrigSd: PSECURITY_DESCRIPTOR; pNewSd: PSECURITY_DESCRIPTOR; si: STARTUPINFO; pi: PROCESS_INFORMATION; bError: BOOL; Label Cleanup; begin pOldDAcl:= nil; pNewDAcl:= nil; pSacl:= nil; pSidOwner:= nil; pSidPrimary:= nil; dwAclSize:= 0; dwSaclSize:= 0; dwSidOwnLen:= 0; dwSidPrimLen:= 0; pOrigSd:= nil; pNewSd:= nil; SetPrivilege; // 选择 WINLOGON 进程 dwPid := GetProcessId('WINLOGON.EXE'); If dwPid = High(Cardinal) Then begin bError := TRUE; Goto Cleanup; end; hProcess := OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,dwPid); If hProcess = 0 Then begin bError := TRUE; Goto Cleanup; end; If not OpenProcessToken(hProcess,READ_CONTROL or WRITE_DAC,hToken) Then begin bError := TRUE; Goto Cleanup; end; // 设置 ACE 具有所有访问权限 ZeroMemory(@ea, Sizeof(EXPLICIT_ACCESS)); BuildExplicitAccessWithName(@ea, 'Everyone', TOKEN_ALL_ACCESS, GRANT_ACCESS, 0); If not GetKernelObjectSecurity(hToken, DACL_SECURITY_INFORMATION, pOrigSd, 0, dwSDLen) Then begin {第一次调用给出的参数肯定返回这个错误,这样做的目的是 为了得到原安全描述符 pOrigSd 的长度} // HEAP_ZERO_MEMORY = 8;HEAP_GENERATE_EXCEPTIONS = &H4 If GetLastError = ERROR_INSUFFICIENT_BUFFER Then begin pOrigSd := HeapAlloc(GetProcessHeap(), $00000008, dwSDLen); If pOrigSd = nil Then begin bError := TRUE; Goto Cleanup; end; // 再次调用才正确得到安全描述符 pOrigSd If not GetKernelObjectSecurity(hToken, DACL_SECURITY_INFORMATION, pOrigSd, dwSDLen, dwSDLen) Then begin bError := TRUE; Goto Cleanup; end; end Else begin bError := TRUE; Goto Cleanup; end; end;//GetKernelObjectSecurity() // 得到原安全描述符的访问控制列表 ACL If not GetSecurityDescriptorDacl(pOrigSd,bDAcl,pOldDAcl,bDefDAcl) Then begin bError := TRUE; goto Cleanup; end; // 生成新 ACE 权限的访问控制列表 ACL dwRet := SetEntriesInAcl(1,@ea,pOldDAcl,pNewDAcl); If dwRet ERROR_SUCCESS Then begin pNewDAcl := nil; bError := TRUE; goto Cleanup; end; If not MakeAbsoluteSD(pOrigSd, pNewSd, dwSDLen, pOldDAcl^, dwAclSize, pSacl^, dwSaclSize, pSidOwner, dwSidOwnLen, pSidPrimary, dwSidPrimLen) Then begin {第一次调用给出的参数肯定返回这个错误,这样做的目的是 为了创建新的安全描述符 pNewSd 而得到各项的长度} If GetLastError = ERROR_INSUFFICIENT_BUFFER Then begin pOldDAcl := HeapAlloc(GetProcessHeap(), $00000008, dwAclSize); pSacl := HeapAlloc(GetProcessHeap(), $00000008, dwSaclSize); pSidOwner := HeapAlloc(GetProcessHeap(), $00000008, dwSidOwnLen); pSidPrimary := HeapAlloc(GetProcessHeap(), $00000008, dwSidPrimLen); pNewSd := HeapAlloc(GetProcessHeap(), $00000008, dwSDLen); If (pOldDAcl = nil) or (pSacl = nil) or (pSidOwner = nil) or (pSidPrimary = nil) or (pNewSd = nil) Then begin bError := TRUE; goto Cleanup; end; {再次调用才可以成功创建新的安全描述符 pNewSd 但新的安全描述符仍然是原访问控制列表 ACL} If not MakeAbsoluteSD(pOrigSd, pNewSd, dwSDLen, pOldDAcl^, dwAclSize, pSacl^, dwSaclSize, pSidOwner, dwSidOwnLen, pSidPrimary, dwSidPrimLen) Then begin bError := TRUE; goto Cleanup; end; end Else begin bError := TRUE; goto Cleanup; end; end; {将具有所有访问权限的访问控制列表 pNewDAcl 加入到新的 安全描述符 pNewSd 中} If not SetSecurityDescriptorDacl(pNewSd,bDAcl,pNewDAcl,bDefDAcl) Then begin bError := TRUE; goto Cleanup; end; // 将新的安全描述符加到 TOKEN 中 If not SetKernelObjectSecurity(hToken,DACL_SECURITY_INFORMATION,pNewSd) Then begin bError := TRUE; goto Cleanup; end; // 再次打开 WINLOGON 进程的 TOKEN,这时已经具有所有访问权限 If not OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,hToken) Then begin bError := TRUE; goto Cleanup; end; // 复制一份具有相同访问权限的 TOKEN If not DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, nil, SecurityImpersonation, TokenPrimary, hNewToken) Then begin bError := TRUE; goto Cleanup; end; ZeroMemory(@si,Sizeof(STARTUPINFO)); si.cb := Sizeof(STARTUPINFO); {不虚拟登陆用户的话,创建新进程会提示 1314 客户没有所需的特权错误} ImpersonateLoggedOnUser(hNewToken); {我们仅仅是需要建立高权限进程,不用切换用户 所以也无需设置相关桌面,有了新 TOKEN 足够} // 利用具有所有权限的 TOKEN,创建高权限进程 If not CreateProcessAsUser(hNewToken, nil, szProcessName, nil, nil, FALSE, 0, nil, nil, si, pi) Then begin bError := TRUE; goto Cleanup; end; bError := FALSE; Cleanup: If pOrigSd = nil Then HeapFree(GetProcessHeap(),0,pOrigSd); If pNewSd = nil Then HeapFree(GetProcessHeap(),0,pNewSd); If pSidPrimary = nil Then HeapFree(GetProcessHeap(),0,pSidPrimary); If pSidOwner = nil Then HeapFree(GetProcessHeap(),0,pSidOwner); If pSacl = nil Then HeapFree(GetProcessHeap(),0,pSacl); If pOldDAcl = nil Then HeapFree(GetProcessHeap(),0,pOldDAcl); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); CloseHandle(hToken); CloseHandle(hNewToken); //CloseHandle(hProcess); If bError Then Result := FALSE Else Result := True; end; begin CreateSystemProcess('test.exe'); { TODO -oUser -cConsole Main : Insert code here } end.

64,439

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧