Bug 1567614: Part 2 - Add ShellExecuteByExplorer overload to handle absolute PIDL lists; r=jmathies
authorAaron Klotz <aklotz@mozilla.com>
Tue, 23 Jul 2019 20:18:07 +0000
changeset 483901 cae98337ddda1b78db120235072ef5154cdf65f5
parent 483900 e8bf96e8321a7966be57bf567ce5aad7688f1e2e
child 483902 e7d500f650ccfe119d46a36392fa641b47c142a2
push id36336
push usermalexandru@mozilla.com
push dateWed, 24 Jul 2019 09:54:28 +0000
treeherdermozilla-central@5585edba8fdb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmathies
bugs1567614
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1567614: Part 2 - Add ShellExecuteByExplorer overload to handle absolute PIDL lists; r=jmathies For the URI handling case, we still want to parse the URI to look for any malformation. OTOH, IShellDispatch2::ShellExecute does not accept PIDLs as arguments, we we need an overload that converts the absolute PIDL back to a path for the purposes of passing on to that interface. Differential Revision: https://phabricator.services.mozilla.com/D38944
widget/windows/ShellHeaderOnlyUtils.h
widget/windows/WinHeaderOnlyUtils.h
--- a/widget/windows/ShellHeaderOnlyUtils.h
+++ b/widget/windows/ShellHeaderOnlyUtils.h
@@ -142,11 +142,67 @@ inline LauncherVoidResult ShellExecuteBy
 #    define ShellExecute ShellExecuteA
 #  endif
 #  undef MOZ_REDEFINE_SHELLEXECUTE
 #endif  // defined(MOZ_REDEFINE_SHELLEXECUTE)
 
   return Ok();
 }
 
+using UniqueAbsolutePidl =
+    UniquePtr<RemovePointer<PIDLIST_ABSOLUTE>::Type, CoTaskMemFreeDeleter>;
+
+inline UniqueAbsolutePidl ShellParseDisplayName(const wchar_t* aPath) {
+  PIDLIST_ABSOLUTE rawAbsPidl = nullptr;
+  SFGAOF sfgao;
+  HRESULT hr = ::SHParseDisplayName(aPath, nullptr, &rawAbsPidl, 0, &sfgao);
+  if (FAILED(hr)) {
+    return nullptr;
+  }
+
+  return UniqueAbsolutePidl(rawAbsPidl);
+}
+
+/**
+ * Since IShellDispatch2::ShellExecute does not accept a PIDL as one of its
+ * parameters, we need to convert a PIDL back to a path. This overload handles
+ * that conversion and then proceeds with the ShellExecuteByExplorer call.
+ */
+inline LauncherVoidResult ShellExecuteByExplorer(
+    const UniqueAbsolutePidl& aPath, const _variant_t& aArgs,
+    const _variant_t& aVerb, const _variant_t& aWorkingDir,
+    const _variant_t& aShowCmd) {
+  // |aPath| is an absolute path. IShellFolder::GetDisplayNameOf requires a
+  // valid child ID, so the first thing we need to resolve is the IShellFolder
+  // for |aPath|'s parent, as well as the childId that represents |aPath|.
+  // Fortunately SHBindToParent does exactly that!
+  PCUITEMID_CHILD childId = nullptr;
+  RefPtr<IShellFolder> parentFolder;
+  HRESULT hr = ::SHBindToParent(aPath.get(), IID_IShellFolder,
+                                getter_AddRefs(parentFolder), &childId);
+  if (FAILED(hr)) {
+    return LAUNCHER_ERROR_FROM_HRESULT(hr);
+  }
+
+  // Now we retrieve the display name of |childId|, telling the shell that we
+  // plan to have the string parsed.
+  STRRET strret;
+  hr = parentFolder->GetDisplayNameOf(childId, SHGDN_FORPARSING, &strret);
+  if (FAILED(hr)) {
+    return LAUNCHER_ERROR_FROM_HRESULT(hr);
+  }
+
+  // Since ShellExecuteByExplorer wants a BSTR, we convert |strret|. Calling
+  // StrRetToBSTR is advantageous since it automatically takes care of
+  // freeing any dynamically allocated memory in |strret|.
+  _bstr_t bstrPath;
+  hr = ::StrRetToBSTR(&strret, nullptr, bstrPath.GetAddress());
+  if (FAILED(hr)) {
+    return LAUNCHER_ERROR_FROM_HRESULT(hr);
+  }
+
+  // Now we have a bstr_t so we can invoke the overload.
+  return ShellExecuteByExplorer(bstrPath, aArgs, aVerb, aWorkingDir, aShowCmd);
+}
+
 }  // namespace mozilla
 
 #endif  // mozilla_ShellHeaderOnlyUtils_h
--- a/widget/windows/WinHeaderOnlyUtils.h
+++ b/widget/windows/WinHeaderOnlyUtils.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_WinHeaderOnlyUtils_h
 #define mozilla_WinHeaderOnlyUtils_h
 
 #include <windows.h>
 #include <winerror.h>
 #include <winnt.h>
 #include <winternl.h>
+#include <objbase.h>
 
 #include <stdlib.h>
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DynamicallyLinkedFunctionPtr.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/Result.h"
@@ -527,11 +528,15 @@ inline WindowsErrorResult<ModuleVersion>
   if (NS_FAILED(rv)) {
     return Err(WindowsError::CreateGeneric());
   }
 
   return GetModuleVersion(fullPath.get());
 }
 #endif  // defined(MOZILLA_INTERNAL_API)
 
+struct CoTaskMemFreeDeleter {
+  void operator()(void* aPtr) { ::CoTaskMemFree(aPtr); }
+};
+
 }  // namespace mozilla
 
 #endif  // mozilla_WinHeaderOnlyUtils_h