转: CreateProcessAsUser 0xC0000005访问冲突问题

转:http://blog.csdn.net/glc22/article/details/77227367
 
在使用CreateProcessAsUser时出现了 0xC0000005访问冲突问题,百思不得其解。终于在子航的博客http://www.cnblogs.com/hezihang/p/3387283.html找到问题根源
 
错误代码:
  1. #include <WtsApi32.h>  
  2. #pragma comment(lib, "WtsApi32.lib")  
  3.   
  4. bool MyImpersonateLoggedOnUser()  
  5. {  
  6.     HANDLE hToken = NULL;  
  7.     DWORD dwConsoleSessionId = WTSGetActiveConsoleSessionId();  
  8.     if (WTSQueryUserToken(dwConsoleSessionId, &hToken))  
  9.     {  
  10.         if (ImpersonateLoggedOnUser(hToken))  
  11.         {  
  12.             // 保存Token  
  13.             WCHAR *szCmdLine = L"c:\notepad.exe";  //错误在这里  
  14.   
  15.             STARTUPINFO si;  
  16.             ZeroMemory(&si, sizeof(STARTUPINFO));  
  17.             si.cb = sizeof(STARTUPINFO);  
  18.             si.lpDesktop = L"winsta0\default";  
  19.   
  20.             PROCESS_INFORMATION pi;  
  21.             ZeroMemory(&pi, sizeof(pi));  
  22.             // hToken为当前登陆用户的令牌  
  23.             LPVOID lpEnvBlock = NULL;  
  24.             BOOL bEnv = false;// CreateEnvironmentBlock(&lpEnvBlock, hToken, FALSE);  
  25.             DWORD dwFlags = CREATE_NEW_CONSOLE;  
  26.             if (bEnv)  
  27.             {  
  28.                 dwFlags |= CREATE_UNICODE_ENVIRONMENT;  
  29.             }  
  30.             // 环境变量创建失败仍然可以创建进程,但会影响到后面的进程获取环境变量内容  
  31.             bool bRet = CreateProcessAsUser(  
  32.                 hToken,  
  33.                 NULL,  
  34.                 szCmdLine,  
  35.                 NULL,  
  36.                 NULL,  
  37.                 FALSE,  
  38.                 dwFlags,  
  39.                 bEnv ? lpEnvBlock : NULL,  
  40.                 NULL,  
  41.                 &si,  
  42.                 &pi);  
  43.             int a = GetLastError();  
  44.             // 使用完毕需要释放环境变量的空间  
  45.             if (bEnv)  
  46.             {  
  47.                 DestroyEnvironmentBlock(lpEnvBlock);  
  48.             }  
  49.             WaitForSingleObject(pi.hProcess, INFINITE);  
  50.            return true;  
  51.         }  
  52.     }  
  53.     return false;  
  54. }   

szCmdLine指针是保存在堆上,但字符串“c:\notepad.exe”是一个常量,它是保存在常量区的,被写保护了CreateProcessAsUser 访问堆上的地址出了问题
如果把“c:\notepad.exe"定义到栈或者全局变量就不存在此问题了。
修改后的代码:      
  1. #include <WtsApi32.h>  
  2. #pragma comment(lib, "WtsApi32.lib")  
  3. bool MyImpersonateLoggedOnUser()  
  4. {  
  5.     HANDLE hToken = NULL;  
  6.     DWORD dwConsoleSessionId = WTSGetActiveConsoleSessionId();  
  7.     if (WTSQueryUserToken(dwConsoleSessionId, &hToken))  
  8.     {  
  9.         if (ImpersonateLoggedOnUser(hToken))  
  10.         {  
  11.             // 保存Token  
  12.             WCHAR szCmdLine[] = L"c:\notepad.exe";   //改变了szCmdLine的地址空间  
  13.             STARTUPINFO si;  
  14.             ZeroMemory(&si, sizeof(STARTUPINFO));  
  15. si.cb = sizeof(STARTUPINFO);  
  16. si.lpDesktop = L"winsta0\default";  
  17.             PROCESS_INFORMATION pi;  
  18.             ZeroMemory(&pi, sizeof(pi));  
  19.             // hToken为当前登陆用户的令牌  
  20.             LPVOID lpEnvBlock = NULL;  
  21.             BOOL bEnv = false;// CreateEnvironmentBlock(&lpEnvBlock, hToken, FALSE);  
  22.             DWORD dwFlags = CREATE_NEW_CONSOLE;  
  23.             if (bEnv)  
  24.             {  
  25.                 dwFlags |= CREATE_UNICODE_ENVIRONMENT;  
  26.             }  
  27.             // 环境变量创建失败仍然可以创建进程,但会影响到后面的进程获取环境变量内容  
  28.             bool bRet = CreateProcessAsUser(  
  29.                 hToken,  
  30.                 NULL,  
  31.                 szCmdLine,  
  32.                 NULL,  
  33.                 NULL,  
  34.                 FALSE,  
  35.                 dwFlags,  
  36.                 bEnv ? lpEnvBlock : NULL,  
  37.                 NULL,  
  38.                 &si,  
  39.                 &pi);  
  40.             int a = GetLastError();  
  41.             // 使用完毕需要释放环境变量的空间  
  42.             if (bEnv)  
  43.             {  
  44.                 DestroyEnvironmentBlock(lpEnvBlock);  
  45.             }  
  46.                         WaitForSingleObject(pi.hProcess, INFINITE);  
  47.             return true;  
  48.         }  
  49.     }  
  50.     return false;  
  51. }  
原文地址:https://www.cnblogs.com/studyskill/p/7650833.html