system进程启动普通用户进程

关键函数是CreateProcessAsUser

主要思路是先取得目的用户的token,然后用上面的函数启动

1、从explorer中取token

BOOL GetTokenByName(HANDLE &hToken,LPSTR lpName)
{
if(!lpName)
{
return FALSE;
}
HANDLE hProcessSnap = NULL;
BOOL bRet = FALSE;
PROCESSENTRY32 pe32 = {0}; hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
return (FALSE); pe32.dwSize = sizeof(PROCESSENTRY32); if (Process32First(hProcessSnap, &pe32))
{
do
{
if(!strcmp(_strupr(pe32.szExeFile),_strupr(lpName)))
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,
FALSE,pe32.th32ProcessID);
bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken);
CloseHandle (hProcessSnap);
return (bRet);
}
}
while (Process32Next(hProcessSnap, &pe32));
bRet = TRUE;
}
else
bRet = FALSE; CloseHandle (hProcessSnap);
return (bRet);
} BOOL RunProcess(LPCSTR lpImage)
{
if(!lpImage)
{
return FALSE;
}
HANDLE hToken;
if(!GetTokenByName(hToken,"EXPLORER.EXE"))
{
return FALSE;
}
STARTUPINFO si;
PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = TEXT("winsta0\\default"); BOOL bResult = CreateProcessAsUser(hToken,lpImage,NULL,NULL,NULL,
FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);
CloseHandle(hToken);
if(bResult)
{
OutputDebugString("CreateProcessAsUser ok!\r\n");
}
else
{
OutputDebugString("CreateProcessAsUser false!\r\n");
}
return bResult;
}

这种方式的缺点是,如果当前有多个用户登陆,则进程中会有多个explorer进程,需额外控制从哪个explorer中取token

2、从当前活动的session中查询token,再启动

BOOL RunProcess1(LPCSTR lpImage, LPSTR lpCmd = "")
{
if(!lpImage)
{
return FALSE;
} DWORD dwSID = WTSGetActiveConsoleSessionId();
HANDLE hToken;
WTSQueryUserToken(dwSID, &hToken); STARTUPINFO si;
PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = TEXT("winsta0\\default");
//si.dwFlags = STARTF_USESHOWWINDOW;
//si.wShowWindow = SW_HIDE; BOOL bResult = CreateProcessAsUser(hToken,lpImage,lpCmd,NULL,NULL,
FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);
CloseHandle(hToken);
if(bResult)
{
OutputDebugString("CreateProcessAsUser ok!\r\n");
}
else
{
OutputDebugString("CreateProcessAsUser false!\r\n");
}
return bResult;
}

这种方式相对于上一种就是可以创建一个当前活动用户的进程,但在使用过程中发现,如果以非system用户调用WTSQueryUserToken,可能会失败

3、CreateProcessAsUser的命令行参数问题

在实际使用中,想给新进程传递参数,一直没传对,后来才发现,CreateProcessCreateProcessAsUser中,cmdline参数的使用比较特别,要注意

比较保险的两种用法是

  • appname参数置空,cmdline参数为完整命令行,这种用法的限制在于,cmdline长度最大为MAX_PATH
  • appname参数为要启动的程序的完整路径,cmdline参数为完整命令行,这种用法的好处是,长度可以达到32K(MSDN中写的,未试验),限制在于,一定要使用完整命令行,包括要启动的程序的路径。因为该函数不会将appname和cmdline拼在一起

另外需注意的一点是,cmdline在函数调用期间,值会被修改,不能使用常量

最新文章

  1. AE开发中栅格图层实现分级渲染
  2. Apache虚拟主机配置,实现多域名访问本地项目PHP空间,以及配置403Forbidden等错误的解决办法
  3. NGUI 按钮点击音效统一管理开启与关闭
  4. 随笔分类 - 无废话ExtJs系列教程
  5. 基于 Equinox 的 OSGi Console 的研究和探索
  6. SQL Server查看表信息
  7. CentOS6.3系统安装SCP命令
  8. @Autowired与@Resource用法
  9. git svn 简易同时使用
  10. MAC安装XAMPP的出现无法打开Apache server
  11. Android学习笔记(二)Manifest文件节点详解
  12. gc overhead limit exceeded eclipse错误解决方式
  13. 摆弄【Nhibernate 协会制图--导乐陪伴分娩】
  14. 数据的压缩存储与解压缩算法实现(C语言)
  15. Cobbler安装CentOS7系统时报错 What do you want do now?
  16. 【.NET开发之美】使用ComponentOne提高.NET DataMap中的加载速度
  17. oracle 问题
  18. c++ Pthread创建线程后必须使用join或detach释放线程资源
  19. 类里的通用成员函数应声明为static
  20. Tomcat 安装为服务后台自动启用

热门文章

  1. [每日一题] OCP1z0-047 :2013-07-25 权限――角色与对象权限
  2. 转载:[Java]读取文件方法大全
  3. ./configure 时候报错c++ 编译器不能执行
  4. Membership修改密码
  5. AES CBC 128的实现
  6. 后台获取HTMLTABLE的innerHtml
  7. pod应用--备用
  8. node实现创建服务器获取wx jssdk签名
  9. 使用Query 进行空值(empty)校验
  10. quote, quasiquote, unquote和unquote-splicing