0

Trying to follow this sample: https://devblogs.microsoft.com/oldnewthing/20040520-00/?p=39243

void ShellExecuteFromExplorer(PCWSTR pszFile,    PCWSTR pszParameters = nullptr,    PCWSTR pszDirectory  = nullptr,    PCWSTR pszOperation  = nullptr,    int nShowCmd         = SW_SHOWNORMAL)
{
    CComPtr<IShellFolderViewDual> spFolderView;
    GetDesktopAutomationObject(IID_PPV_ARGS(&spFolderView));
    CComPtr<IDispatch> spdispShell;
    spFolderView->get_Application(&spdispShell);
    CComQIPtr<IShellDispatch2>(spdispShell)
       ->ShellExecute(CComBSTR(pszFile),
                      CComVariant(pszParameters ? pszParameters : L""),
                      CComVariant(pszDirectory ? pszDirectory : L""),
                      CComVariant(pszOperation ? pszOperation : L""),
                      CComVariant(nShowCmd));
}

In this case, how do i retrieve the pid from the process being launch from the ShellExecute?

  • [c++ - Get PID from ShellExecute - Stack Overflow](https://stackoverflow.com/questions/7620322/get-pid-from-shellexecute) ? – user202729 Sep 30 '21 at 01:18
  • Is this ATL? -- -- – user202729 Sep 30 '21 at 01:20
  • for what you need exec process from explorer ? for what need it pid ? what is your real target ? – RbMm Sep 30 '21 at 01:34
  • @RbMm "*for what you need exec process from explorer?*" - `IShellDispatch2::ShellExecute()` can be used to [launch an unelevated process from an elevated process](https://devblogs.microsoft.com/oldnewthing/20131118-00/?p=2643) (which I know you already knew) – Remy Lebeau Sep 30 '21 at 01:38
  • Yes, this is the point @RemyLebeau –  Sep 30 '21 at 01:40
  • @RemyLebeau - in this case you can open explorer handle and use it as parent for new process. also can and use explorer token in call CreateProcessAsUser ( elevated process can got `SeAssignPrimaryTokenPrivilege` ) – RbMm Sep 30 '21 at 01:46
  • @RbMm Yes, I'm aware, you already explained that in [Wait for the process started by IShellDispatch2.ShellExecute](https://stackoverflow.com/questions/55050455/wait-for-the-process-started-by-ishelldispatch2-shellexecute) – Remy Lebeau Sep 30 '21 at 01:47

2 Answers2

2

not need use this way for create unelevated process. for instance we can use shell process (explorer) as parent for new process with help PROC_THREAD_ATTRIBUTE_PARENT_PROCESS. example of code

ULONG ExecFromShell(_In_opt_ PCWSTR lpApplicationName,
                    _Inout_opt_ PWSTR lpCommandLine)
{
    if (HWND hwnd = GetShellWindow())
    {
        ULONG dwProcessId, dwThreadId;
        if (dwThreadId = GetWindowThreadProcessId(hwnd, &dwProcessId))
        {
            if (HANDLE hProcess = OpenProcess(PROCESS_CREATE_PROCESS|READ_CONTROL, 
                    FALSE, dwProcessId))
            {
                PROCESS_INFORMATION pi;
                STARTUPINFOEXW si { sizeof(si)};
                SIZE_T s = 0;
                ULONG dwError;

__0:
                switch (dwError = InitializeProcThreadAttributeList(
                    si.lpAttributeList, 1, 0, &s) ? NOERROR : GetLastError())
                {
                case ERROR_INSUFFICIENT_BUFFER:
                    if (!si.lpAttributeList)
                    {
                        si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)alloca(s);
                        goto __0;
                    }
                    break;
                case NOERROR:
                    if (UpdateProcThreadAttribute(si.lpAttributeList, 0, 
                        PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
                        &hProcess, sizeof(hProcess), 0, 0))
                    {
                        ULONG cb = 0;
                        SECURITY_ATTRIBUTES sa = { sizeof(sa) };

__1:
                        switch (GetKernelObjectSecurity(hProcess, 
                            DACL_SECURITY_INFORMATION|LABEL_SECURITY_INFORMATION, 
                            sa.lpSecurityDescriptor, cb, &cb) ? NOERROR : GetLastError())
                        {
                        case ERROR_INSUFFICIENT_BUFFER:
                            if (!sa.lpSecurityDescriptor)
                            {
                                sa.lpSecurityDescriptor = alloca(cb);
                                goto __1;
                            }
                            break;
                        case NOERROR:
                            if (CreateProcessW(lpApplicationName, lpCommandLine, &sa, &sa, 
                                FALSE, EXTENDED_STARTUPINFO_PRESENT, 0, 0, &si.StartupInfo, &pi))
                            {
                                CloseHandle(pi.hThread);
                                CloseHandle(pi.hProcess);
                            }
                            else
                            {
                                dwError = GetLastError();
                            }
                            break;
                        }                       

                    }
                    else
                    {
                        dwError = GetLastError();
                    }

                    DeleteProcThreadAttributeList(si.lpAttributeList);
                    break;
                }
                
                CloseHandle(hProcess);

                return dwError;
            }

            return GetLastError();
        }
    }

    return ERROR_NOT_FOUND;
}
RbMm
  • 31,280
  • 3
  • 35
  • 56
  • @BarmakShemirani - this is not endless loop. this is my technique – RbMm Oct 01 '21 at 20:18
  • Oh, I see what you are doing. It would be less code if you just called `InitializeProcThreadAttributeList` twice. – Barmak Shemirani Oct 01 '21 at 20:24
  • @BarmakShemirani - twice in src code :) and this will be not less code - try it. i prefer such style. this also will be called twice in runtime, but only once in src – RbMm Oct 01 '21 at 20:25
1

In this case, how do i retrieve the pid from the process being launch from the ShellExecute?

You can't. just like ::ShellExecute(), IShellDispatch2::ShellExecute() simply does not provide any information about the new process.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770