在Windows 7 64位上

时间:2018-11-06 18:05:27

标签: c++ winapi windows-7-x64 createprocessasuser

我有一个C#应用程序,它是使用CreateProcessAsUserW api从C ++ DLL启动的。该过程成功启动,但立即终止。它可以在Windows 10 [32位和64位]和Windows 7上的32位上正常工作。我找到了以下链接,

Why is this process crashing as soon as it is launched?

但是,SysInternals的进程监视器没有丢失的dll。 [我可以从ProcMon附加已保存的日志]我还尝试按照其他建议在API的lpCurrentDirectory参数中将路径传递到应用程序文件夹,但这也不起作用。

我按照How to get the active user when multiple users are logged on in Windows?中的指导编写了启动该过程的代码, 然后从Windows服务调用启动该过程的方法。为了从命令行进行仿真,我使用了以下命令 How do you run CMD.exe under the Local System Account? [psexec64 -i -s cmd.exe,然后从cmd.exe启动该过程] 方法如下 // How to get the active user when multiple users are logged on in Windows?

 STDMETHODIMP CProcessManager::LaunchProcessAsActiveUser(BSTR processName, LONG* dwProcessId)
    {

        //char *lpszPath = _com_util::ConvertBSTRToString(processName);
        wchar_t* path = (wchar_t*)processName;//CharToWideChar(lpszPath);

        DWORD session_id = -1;
        DWORD session_count = 0;

        WTS_SESSION_INFOA *pSession = NULL;


        if (WTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count))
        {
            //log success
        }
        else
        {
            //log error
            return S_OK;
        }
        logger->Log(L"Session Count", session_count);
        logger->Log(L"Begin Enumerating Sesions");
        for (int i = 0; i < session_count; i++)
        {
            session_id = pSession[i].SessionId;
            logger->Log(L"SessionId", session_id);

            WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected;
            WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL;

            DWORD bytes_returned = 0;
            if (::WTSQuerySessionInformation(
                WTS_CURRENT_SERVER_HANDLE,
                session_id,
                WTSConnectState,
                reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state),
                &bytes_returned))
            {
                wts_connect_state = *ptr_wts_connect_state;
                ::WTSFreeMemory(ptr_wts_connect_state);
                if (wts_connect_state != WTSActive) continue;
            }
            else
            {
                //log error
                continue;
            }
            logger->Log(L"End Enumerating Sesions");
            logger->Log(L"Selected Session Id", session_id);
            HANDLE hImpersonationToken;

            if (!WTSQueryUserToken(session_id, &hImpersonationToken))
            {
                //log error
                logger->Log(L"Exception in WTSQueryUserToken", GetLastError());
                continue;
            }


            //Get real token from impersonation token
            DWORD neededSize1 = 0;
            HANDLE *realToken = new HANDLE;
            if (GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize1))
            {
                CloseHandle(hImpersonationToken);
                hImpersonationToken = *realToken;
            }
            else
            {
                //log error
                logger->Log(L"Exception in GetTokenInformation", GetLastError());
                continue;
            }


            HANDLE hUserToken;

            if (!DuplicateTokenEx(hImpersonationToken,
                //0,
                //MAXIMUM_ALLOWED,
                TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED,
                NULL,
                SecurityImpersonation,
                TokenPrimary,
                &hUserToken))
            {
                //log error
                logger->Log(L"Exception in DuplicateTokenEx", GetLastError());
                continue;
            }

            // Get user name of this process
            //LPTSTR pUserName = NULL;
            WCHAR* pUserName;
            DWORD user_name_len = 0;

            if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSUserName, &pUserName, &user_name_len))
            {
                //log username contained in pUserName WCHAR string
                // char * lpszUserName = WideCharToChar(pUserName);
                logger->Log(pUserName);
                //LocalFree(lpszUserName);
            }
            else
            {
                logger->Log(L"Exception in WTSQuerySessionInformation", GetLastError());
            }

            //Free memory                         
            if (pUserName) WTSFreeMemory(pUserName);

            ImpersonateLoggedOnUser(hUserToken);

            STARTUPINFOW StartupInfo;

            StartupInfo.cb = sizeof(STARTUPINFOW);




            //GetStartupInfoW(&StartupInfo);
            ZeroMemory(&StartupInfo, sizeof(StartupInfo));
            //Uncommented  by Sagar 20th January 20118 1612
            StartupInfo.lpDesktop = CharToWideChar("winsta0\\default");

            //to Hide Console Process 03-10-2018
            StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
            StartupInfo.wShowWindow = SW_SHOW;//SW_HIDE;



            PROCESS_INFORMATION processInfo;



            SECURITY_ATTRIBUTES Security1;
            ZeroMemory(&Security1, sizeof(Security1));

            Security1.nLength = sizeof SECURITY_ATTRIBUTES;


            SECURITY_ATTRIBUTES Security2;
            ZeroMemory(&Security2, sizeof(Security2));
            Security2.nLength = sizeof SECURITY_ATTRIBUTES;

            void* lpEnvironment = NULL;

            // Get all necessary environment variables of logged in user
            // to pass them to the new process
            BOOL resultEnv = CreateEnvironmentBlock(&lpEnvironment, hUserToken, FALSE);

            if (!resultEnv)
            {
                //log error
                DWORD err = GetLastError();
                logger->Log(L"Exception in CreateEnvironmentBlock", err);

                continue;
            }

            WCHAR PP[1024]; //path and parameters
            ZeroMemory(PP, 1024 * sizeof WCHAR);
            wcscpy_s(PP, path);
            wcscat_s(PP, L" ");
            //wcscat(PP, args);

            // Start the process on behalf of the current user 
            BOOL result = CreateProcessAsUserW(hUserToken,
                PP,
                NULL,
                &Security1,
                &Security2,
                FALSE,
                NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE/*| CREATE_NO_WINDOW*/,//CREATE_NO_WINDOW to Hide Console Process 03-10-2018
                /*lpEnvironment*/NULL,

                //"C:\\ProgramData\\some_dir",
                NULL,
                /*NULL,*/
                &StartupInfo,
                &processInfo);

            if (!result)
            {
                //log error
                //char * lpszPath = WideCharToChar(PP);
                logger->Log(L"Failed to create process", PP);
                //LocalFree(lpszPath);
                DWORD err = GetLastError();
                logger->Log(L"GetLastError returned", err);

            }
            else
            {
                *dwProcessId = processInfo.dwProcessId;
                logger->Log(L"Created Process", *dwProcessId);
                //log success
            }

            DestroyEnvironmentBlock(lpEnvironment);

            CloseHandle(hImpersonationToken);
            CloseHandle(hUserToken);
            CloseHandle(realToken);

            RevertToSelf();
        }

        WTSFreeMemory(pSession);


        return S_OK;
    }

下面附有说明屏幕截图 请帮忙。 谢谢, 萨加尔

[![Pg 1](https://i.stack.imgur.com/CJCrG.png)
[![Pg 2](https://i.stack.imgur.com/uo8Uw.png)
[![Pg 3](https://i.stack.imgur.com/G7g12.png)
[![Pg 4](https://i.stack.imgur.com/6e5w4.png)
[![Pg 5](https://i.stack.imgur.com/8k2b0.png)

我尝试了以下排列

Target Process : ATL DLL : Launcher:Result
 64 bit      64 bit     64 bit      Crashes
 64 bit      32 bit     64 bit      Crashes
 32 bit      32 bit     64 bit      Crashes
 32 bit      64 bit     64 bit      Crashes
 32 bit      32 bit     32 bit      OK
 64 bit      32 bit     32 bit      OK
 64 bit      64 bit     32 bit      OK
 32 bit      64 bit     32 bit      OK

因此,如果启动器进程是64位,则似乎总是崩溃,如果启动器是32位,则总是成功。 64位和32位启动器进程有什么区别?

1 个答案:

答案 0 :(得分:0)

我在https://social.msdn.microsoft.com/Forums/vstudio/en-US/fb9d15fb-dc9f-488e-92c4-e0bb438442e1/64-bit-dot-net-process-created-with-createprocessasuserw-exits-immediately-with-exception-code?forum=vcgeneral上得到了答案[RLWA32回答了] 启动过程的方式存在问题。他启动该过程的代码如下,并且工作正常。

UINT __stdcall RunProgram(LPVOID pv)
{
    WCHAR szTarg32[MAX_PATH] = TARGET32_PATH, szTarg64[MAX_PATH] = TARGET64_PATH;
    LPWSTR pszProcess = nullptr;
    PWTS_SESSION_INFOW pwsi = NULL;
    DWORD dwSession = -1, dwCount = 0;
    HANDLE hToken = NULL;
    LPVOID lpEnvironment = nullptr;
    LPWSTR pszPath = nullptr;
    UINT ret = 1;


    DWORD dwOpcode = reinterpret_cast<DWORD>(pv);

    if (dwOpcode == LAUNCH_X86PROCESS)
        pszProcess = szTarg32;
    else
        pszProcess = szTarg64;

    if (!WTSEnumerateSessionsW(WTS_CURRENT_SERVER, 0, 1, &pwsi, &dwCount))
    {
        Report(L"WTSEnumerateSessions failed with %d\n", GetLastError());
        return ret;
    }

    for (DWORD i = 0; i < dwCount; i++)
    {
        if (pwsi[i].State == WTSActive)
        {
            dwSession = pwsi[i].SessionId;
            break;
        }
    }

    if (dwSession != -1)
    {
        if (WTSQueryUserToken(dwSession, &hToken))
        {
            if (CreateEnvironmentBlock(&lpEnvironment, hToken, FALSE))
            {
                HRESULT hr;
                if (SUCCEEDED((hr = SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, hToken, &pszPath))))
                {
                    if (ImpersonateLoggedOnUser(hToken))
                    {
                        STARTUPINFOW si = { sizeof si };
                        PROCESS_INFORMATION pi = {};

                        if (CreateProcessAsUserW(hToken, pszProcess, nullptr, nullptr, nullptr, FALSE, CREATE_UNICODE_ENVIRONMENT, lpEnvironment, pszPath, &si, &pi))
                        {
                            CloseHandle(pi.hThread);
                            CloseHandle(pi.hProcess);
                            Report(L"CreateProcessAsUser started %s, pid is %d\n", pszProcess, pi.dwProcessId);
                            ret = 0;
                        }
                        else
                            Report(L"CreateProcessAsUser failed with %d\n", GetLastError());

                        RevertToSelf();
                    }
                    else
                        Report(L"ImpersonateLoggedOnUser failed with %d\n", GetLastError());
                }
                else
                    Report(L"SHGetKnownFolderPath failed with 0x%X\n", hr);
            }
            else
                Report(L"CreateEnvironmentBlock failed with %d\n", GetLastError());
        }
        else
            Report(L"WTSQueryUserToken failed with %d\n", GetLastError());
    }
    else
        Report(L"WTSEnumerateSessions reported no active session\n");

    if (pwsi)
        WTSFreeMemory(pwsi);

    if (hToken)
        CloseHandle(hToken);

    if (lpEnvironment)
        DestroyEnvironmentBlock(lpEnvironment);

    if (pszPath)
        CoTaskMemFree(pszPath);

    return ret;
}