/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifdefined(LIBXUL) && !defined(UNICODE) # error \ "UNICODE not set - must be set to prevent compile failure in `comdef.h` due to us deleting `FormatMessage` when absent." #endif
#include"mozilla/WinHeaderOnlyUtils.h"
#include <objbase.h>
#include <exdisp.h> #include <shldisp.h> #include <shlobj.h> #include <shlwapi.h> #include <shobjidl.h> #include <shtypes.h> // NB: include this after shldisp.h so its macros do not conflict with COM // interfaces defined by shldisp.h #include <shellapi.h> #include <type_traits>
/** * Ask the current user's Desktop to ShellExecute on our behalf, thus causing * the resulting launched process to inherit its security priviliges from * Explorer instead of our process. * * This is useful in two scenarios, in particular: * * We are running as an elevated user and we want to start something as the * "normal" user; * * We are starting a process that is incompatible with our process's * process mitigation policies. By delegating to Explorer, the child process * will not be affected by our process mitigations. * * Since this communication happens over DCOM, Explorer's COM DACL governs * whether or not we can execute against it, thus avoiding privilege escalation.
*/ inline LauncherVoidResult ShellExecuteByExplorer(const _bstr_t& aPath, const _variant_t& aArgs, const _variant_t& aVerb, const _variant_t& aWorkingDir, const _variant_t& aShowCmd) { // NB: Explorer may be a local server, not an inproc server
RefPtr<IShellWindows> shellWindows;
HRESULT hr = ::CoCreateInstance(
CLSID_ShellWindows, nullptr, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
IID_IShellWindows, getter_AddRefs(shellWindows)); if (FAILED(hr)) { return LAUNCHER_ERROR_FROM_HRESULT(hr);
}
// 1. Find the shell view for the desktop.
_variant_t loc(int(CSIDL_DESKTOP));
_variant_t empty; long hwnd;
RefPtr<IDispatch> dispDesktop;
hr = shellWindows->FindWindowSW(&loc, &empty, SWC_DESKTOP, &hwnd,
SWFO_NEEDDISPATCH,
getter_AddRefs(dispDesktop)); if (FAILED(hr)) { return LAUNCHER_ERROR_FROM_HRESULT(hr);
}
if (hr == S_FALSE) { // The call succeeded but the window was not found. return LAUNCHER_ERROR_FROM_WIN32(ERROR_NOT_FOUND);
}
// 2. Get the automation object for the desktop.
RefPtr<IDispatch> dispView;
hr = activeShellView->GetItemObject(SVGIO_BACKGROUND, IID_IDispatch,
getter_AddRefs(dispView)); if (FAILED(hr)) { return LAUNCHER_ERROR_FROM_HRESULT(hr);
}
// 3. Get the interface to IShellDispatch2
RefPtr<IDispatch> dispShell;
hr = folderView->get_Application(getter_AddRefs(dispShell)); if (FAILED(hr)) { return LAUNCHER_ERROR_FROM_HRESULT(hr);
}
// Passing the foreground privilege so that the shell can launch an // application in the foreground. This fails with E_ACCESSDENIED if the // current window is shown in the background. We keep a soft assert for // the other failures to investigate how it happened.
hr = ::CoAllowSetForegroundWindow(shellDisp, nullptr);
MOZ_ASSERT(SUCCEEDED(hr) || hr == E_ACCESSDENIED);
// shellapi.h macros interfere with the correct naming of the method being // called on IShellDispatch2. Temporarily remove that definition. #ifdefined(ShellExecute) # define MOZ_REDEFINE_SHELLEXECUTE # undef ShellExecute #endif// defined(ShellExecute)
// 4. Now call IShellDispatch2::ShellExecute to ask Explorer to execute.
hr = shellDisp->ShellExecute(aPath, aArgs, aWorkingDir, aVerb, aShowCmd); if (FAILED(hr)) { return LAUNCHER_ERROR_FROM_HRESULT(hr);
}
// Restore the macro that was removed prior to IShellDispatch2::ShellExecute #ifdefined(MOZ_REDEFINE_SHELLEXECUTE) # ifdefined(UNICODE) # define ShellExecute ShellExecuteW # else # define ShellExecute ShellExecuteA # endif # undef MOZ_REDEFINE_SHELLEXECUTE #endif// defined(MOZ_REDEFINE_SHELLEXECUTE)
return Ok();
}
using UniqueAbsolutePidl =
UniquePtr<std::remove_pointer_t<PIDLIST_ABSOLUTE>, CoTaskMemFreeDeleter>;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.