zoukankan      html  css  js  c++  java
  • 转: 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. }  
  • 相关阅读:
    文件操作小练习
    阶段练习1
    copy小练习
    小练习
    str 小列题
    条款50:使用自定义的new以及delete的时机会
    条款49:了解new-handle行为
    简单的说一下:tarits技法就是一种模板元编程,起可以将本来处于运行期的事拉到编译期来做,增加了运行效率。 看以非模板元编程的例子,就是前面的那个例子:
    条款47:请使用traits class表示类型信息
    条款46:需要类型转换的时候请为模板定义非成员函数
  • 原文地址:https://www.cnblogs.com/studyskill/p/7650833.html
Copyright © 2011-2022 走看看