在使用CreateProcessAsUser时出现了 0xC0000005访问冲突问题,百思不得其解。终于在
子航的博客http://www.cnblogs.com/hezihang/p/3387283.html找到问题根源
错误代码:
#include <WtsApi32.h>
#pragma comment(lib, "WtsApi32.lib")
bool MyImpersonateLoggedOnUser()
{
HANDLE hToken = NULL;
DWORD dwConsoleSessionId = WTSGetActiveConsoleSessionId();
if (WTSQueryUserToken(dwConsoleSessionId, &hToken))
{
if (ImpersonateLoggedOnUser(hToken))
{
// 保存Token
WCHAR *szCmdLine = L"c:\\notepad.exe"; //错误在这里
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = L"winsta0\\default";
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
// hToken为当前登陆用户的令牌
LPVOID lpEnvBlock = NULL;
BOOL bEnv = false;// CreateEnvironmentBlock(&lpEnvBlock, hToken, FALSE);
DWORD dwFlags = CREATE_NEW_CONSOLE;
if (bEnv)
{
dwFlags |= CREATE_UNICODE_ENVIRONMENT;
}
// 环境变量创建失败仍然可以创建进程,但会影响到后面的进程获取环境变量内容
bool bRet = CreateProcessAsUser(
hToken,
NULL,
szCmdLine,
NULL,
NULL,
FALSE,
dwFlags,
bEnv ? lpEnvBlock : NULL,
NULL,
&si,
&pi);
int a = GetLastError();
// 使用完毕需要释放环境变量的空间
if (bEnv)
{
DestroyEnvironmentBlock(lpEnvBlock);
}
WaitForSingleObject(pi.hProcess, INFINITE);
return true;
}
}
return false;
}
szCmdLine指针是保存在堆上,但字符串“c:\\notepad.exe”是一个常量,它是保存在常量区的,被写保护了,CreateProcessAsUser 访问堆上的地址出了问题
如果把“c:\\notepad.exe"定义到栈或者全局变量就不存在此问题了。
修改后的代码:
#include <WtsApi32.h>
#pragma comment(lib, "WtsApi32.lib")
bool MyImpersonateLoggedOnUser()
{
HANDLE hToken = NULL;
DWORD dwConsoleSessionId = WTSGetActiveConsoleSessionId();
if (WTSQueryUserToken(dwConsoleSessionId, &hToken))
{
if (ImpersonateLoggedOnUser(hToken))
{
// 保存Token
WCHAR szCmdLine[] = L"c:\\notepad.exe"; //改变了szCmdLine的地址空间
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = L"winsta0\\default";
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
// hToken为当前登陆用户的令牌
LPVOID lpEnvBlock = NULL;
BOOL bEnv = false;// CreateEnvironmentBlock(&lpEnvBlock, hToken, FALSE);
DWORD dwFlags = CREATE_NEW_CONSOLE;
if (bEnv)
{
dwFlags |= CREATE_UNICODE_ENVIRONMENT;
}
// 环境变量创建失败仍然可以创建进程,但会影响到后面的进程获取环境变量内容
bool bRet = CreateProcessAsUser(
hToken,
NULL,
szCmdLine,
NULL,
NULL,
FALSE,
dwFlags,
bEnv ? lpEnvBlock : NULL,
NULL,
&si,
&pi);
int a = GetLastError();
// 使用完毕需要释放环境变量的空间
if (bEnv)
{
DestroyEnvironmentBlock(lpEnvBlock);
}
WaitForSingleObject(pi.hProcess, INFINITE);
return true;
}
}
return false;
}