头文件
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <tchar.h>
#include <Tlhelp32.h>
#include <UserEnv.h>
#include <io.h>
日志
void writefile(TCHAR* szBuf)
{
static FILE* fp = NULL;
if (NULL == fp)
{
fp = fopen(".\\tmp.log", "w+b");
}
if (NULL == fp)
{
system("echo open voi.log fialed >> .\\tmp2.log");
return;
}
fseek(fp, 0, FILE_END);
fwrite(szBuf, 1, _tcslen(szBuf) * sizeof(TCHAR), fp);
fflush(fp);
//fclose(fp);
//_tprintf(_T("write %s "), szBuf);
}
#define CURRENT_LOG_LEVEL 1
#define LOG_DEBUG 1
#define LOG_ERROR 2
void Log(int logLevel, TCHAR* format, ...)
{
TCHAR tszLogInfo[1024], szBuf[512];
va_list arglist;
szBuf[0] = 0;
// 获取参数列表
va_start(arglist, format);
// 格式化缓冲区
_vstprintf_s(szBuf, sizeof(szBuf), format, arglist);
//if (CURRENT_LOG_LEVEL > logLevel)
//{
// return;
//}
if (LOG_DEBUG == logLevel)
{
_stprintf_s(tszLogInfo, sizeof(tszLogInfo), _T("debug : %s"), szBuf);
}
else
{
_stprintf_s(tszLogInfo, sizeof(tszLogInfo), _T("error : %s"), szBuf);
}
if (CURRENT_LOG_LEVEL <= logLevel)
{
_tprintf(tszLogInfo);
}
writefile(tszLogInfo);
}
获取桌面进程
BOOL GetExplorerProcessToken(DWORD* dwProcessId)
{
HANDLE hThisProcess = NULL;
PROCESSENTRY32 pe;
BOOL bMore;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
{
return FALSE;
}
pe.dwSize = sizeof(PROCESSENTRY32);
bMore = Process32First(hSnapshot, &pe);
while (bMore)
{
if (0 == _tcsicmp(pe.szExeFile, _T("explorer.exe")))
{
hThisProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pe.th32ProcessID);
*dwProcessId = pe.th32ProcessID;
return true;
}
bMore = Process32Next(hSnapshot, &pe);
}
return false;
}
根据桌面进程创建新的用户进程
//ptszParameter的第一个字符要为空格,不然会报错,参数错误87
//注意ptszParameter的第一个字符要为空格
//ptszParameter的第一个字符要为空格
//重要的事情说三遍
BOOL RunProcess(const TCHAR* ptszProcessPath, const TCHAR* ptszParameter, LONG* plExitCode, BOOL bBlock)
{
DWORD dwSessionId;
DWORD dwProcessId;
HANDLE hTokenThis = NULL;
HANDLE hThisProcess = NULL;
HANDLE hTokenDup = NULL;
STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD dwCreationFlag = CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS;//NORMAL_PRIORITY_CLASS| CREATE_NEW_CONSOLE;
LPVOID pEnv = NULL;
TCHAR tszDeskTop[20];
Log(LOG_DEBUG, _T("RunProcessAsUser %s %s \r\n"), ptszProcessPath, ptszParameter);
if (!ptszProcessPath)
{
Log(LOG_ERROR, _T("RunProcess pwProcessPath is NULL\n"));
return FALSE;
}
if (ptszProcessPath[0] == '\0')
{
return FALSE;
}
//if (!CheckFileIsExist(pwProcessPath))
//{
// return EXE_NOT_EXIT;
//}
//HANDLE hThisProcess = GetCurrentProcess();
if (!GetExplorerProcessToken(&dwProcessId))//获取桌面进程的id。
{
Log(LOG_ERROR, _T("Get explorer.exe processId faild... \r\n"));
return FALSE;
}
hThisProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessId);
//获取桌面进程的回话id,不然在远程桌面的情况下,消息框显示不出来。
ProcessIdToSessionId(dwProcessId, &dwSessionId);
if (!hThisProcess)
{
Log(LOG_ERROR, _T("RunProcess GetProcessToken is NULL\n"));
return FALSE;
}
OpenProcessToken(hThisProcess, TOKEN_ALL_ACCESS, &hTokenThis);
// 复制一个进程令牌,目的是为了修改session id属性,以便在其它session中创建进程
if (!DuplicateTokenEx(hTokenThis, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokenDup))
{
Log(LOG_ERROR, _T("RunProcess DuplicateTokenEx faild,error code is: %d\n"), GetLastError());
return FALSE;
}
SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(DWORD)); // 把session id设置到备份的令牌中
ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
_tcscpy_s(tszDeskTop, sizeof(tszDeskTop) / sizeof(tszDeskTop[0]), _T("WinSta0\\Default"));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = tszDeskTop;
si.wShowWindow = SW_SHOW;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE); // 创建环境块
if (!CreateProcessAsUser(hTokenDup, ptszProcessPath, ptszParameter, NULL, NULL, FALSE, dwCreationFlag, pEnv, NULL, &si, &pi))
{
Log(LOG_ERROR, _T("CreateProcessAsUser faild, error code: %d\n"), GetLastError());
return FALSE;
}
//bBlok表示是否 阻塞,也可以传入timeout=dwMilliseconds
//if (dwMilliseconds > 0)
//{
// if (WaitForSingleObject(pi.hProcess, dwMilliseconds))
// {
// TerminateProcess(pi.hProcess, 0);
// }
//}
if (bBlock)
{
WaitForSingleObject(pi.hProcess, INFINITE);
}
GetExitCodeProcess(pi.hProcess, (DWORD*)plExitCode);
Log(LOG_DEBUG, _T("run %s %s return 0x%x\r\n"), ptszProcessPath, ptszParameter, *plExitCode);
if (hTokenDup)
{
CloseHandle(hTokenDup);
}
if (hTokenThis)
{
CloseHandle(hTokenThis);
}
if (pi.hThread != INVALID_HANDLE_VALUE)
{
CloseHandle(pi.hThread);
}
if (pi.hProcess != INVALID_HANDLE_VALUE)
{
CloseHandle(pi.hProcess);
}
return TRUE;
}