Bug 1494900 Part 1 - Support optional command line arguments in the ExecInExplorer plugin. r=agashlin
authorMatt Howell <mhowell@mozilla.com>
Fri, 28 Sep 2018 08:43:17 -0700
changeset 494572 6006b0096da29528c0870bc4dfa2a4ccf046daa9
parent 494571 4fb20c215e9c3ea771d8709c5912610d626edb3e
child 494573 b8d8c53289150332f491df758566cf6832f2f400
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersagashlin
bugs1494900
milestone64.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 1494900 Part 1 - Support optional command line arguments in the ExecInExplorer plugin. r=agashlin
other-licenses/nsis/Contrib/ExecInExplorer/ExecInExplorer.cpp
other-licenses/nsis/Plugins/ExecInExplorer.dll
--- a/other-licenses/nsis/Contrib/ExecInExplorer/ExecInExplorer.cpp
+++ b/other-licenses/nsis/Contrib/ExecInExplorer/ExecInExplorer.cpp
@@ -1,11 +1,11 @@
 /* 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 http://mozilla.org/MPL/2.0/. */
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // This file is an NSIS plugin which exports a function that starts a process
 // from a provided path by using the shell automation API to have explorer.exe
 // invoke ShellExecute. This roundabout method of starting a process is useful
 // because it means the new process will use the integrity level and security
 // token of the shell, so it allows starting an unelevated process from inside
 // an elevated one. The method is based on
 // https://blogs.msdn.microsoft.com/oldnewthing/20131118-00/?p=2643
@@ -84,51 +84,57 @@ GetApplicationFromShellView(IShellView* 
       shellViewFolder->Release();
     }
     viewDisp->Release();
   }
   return shellDispatch;
 }
 
 static bool
-ShellExecInExplorerProcess(wchar_t* path)
+ShellExecInExplorerProcess(wchar_t* path, wchar_t* args = nullptr)
 {
   bool rv = false;
   if (SUCCEEDED(CoInitialize(nullptr))) {
     IShellView *desktopView = GetDesktopWindowShellView();
     if (desktopView) {
       IShellDispatch2 *shellDispatch = GetApplicationFromShellView(desktopView);
       if (shellDispatch) {
         BSTR bstrPath = SysAllocString(path);
-        rv = SUCCEEDED(shellDispatch->ShellExecuteW(bstrPath,
-                                                    VARIANT{}, VARIANT{},
+        VARIANT vArgs;
+        VariantInit(&vArgs);
+        if (args) {
+          vArgs.vt = VT_BSTR;
+          vArgs.bstrVal = SysAllocString(args);
+        }
+        rv = SUCCEEDED(shellDispatch->ShellExecuteW(bstrPath, vArgs, VARIANT{},
                                                     VARIANT{}, VARIANT{}));
+        VariantClear(&vArgs);
         SysFreeString(bstrPath);
         shellDispatch->Release();
       }
       desktopView->Release();
     }
     CoUninitialize();
   }
   return rv;
 }
 
 struct stack_t {
   stack_t* next;
   TCHAR text[MAX_PATH];
 };
 
 /**
-* Removes an element from the top of the NSIS stack
-*
-* @param  stacktop A pointer to the top of the stack
-* @param  str      The string to pop to
-* @param  len      The max length
-* @return 0 on success
-*/
+ * Removes an element from the top of the NSIS stack
+ *
+ * @param  stacktop A pointer to the top of the stack
+ * @param  str      The string to pop to
+ * @param  len      The max length
+ * @return 0 on success
+ */
 int
 popstring(stack_t **stacktop, TCHAR *str, int len)
 {
   // Removes the element from the top of the stack and puts it in the buffer
   stack_t *th;
   if (!stacktop || !*stacktop) {
     return 1;
   }
@@ -136,23 +142,23 @@ popstring(stack_t **stacktop, TCHAR *str
   th = (*stacktop);
   lstrcpyn(str, th->text, len);
   *stacktop = th->next;
   HeapFree(GetProcessHeap(), 0, th);
   return 0;
 }
 
 /**
-* Adds an element to the top of the NSIS stack
-*
-* @param  stacktop A pointer to the top of the stack
-* @param  str      The string to push on the stack
-* @param  len      The length of the string to push on the stack
-* @return 0 on success
-*/
+ * Adds an element to the top of the NSIS stack
+ *
+ * @param  stacktop A pointer to the top of the stack
+ * @param  str      The string to push on the stack
+ * @param  len      The length of the string to push on the stack
+ * @return 0 on success
+ */
 void
 pushstring(stack_t **stacktop, const TCHAR *str, int len)
 {
   stack_t *th;
   if (!stacktop) {
     return;
   }
   th = (stack_t*)HeapAlloc(GetProcessHeap(), 0, sizeof(stack_t) + len);
@@ -167,21 +173,41 @@ pushstring(stack_t **stacktop, const TCH
 * @param  stacktop  Pointer to the top of the stack, AKA the first parameter to
                     the plugin call. Should contain the file or URL to execute.
 * @return 1 if the file/URL was executed successfully, 0 if it was not
 */
 extern "C" void __declspec(dllexport)
 Exec(HWND, int, TCHAR *, stack_t **stacktop, void *)
 {
   wchar_t path[MAX_PATH + 1];
+  wchar_t args[MAX_PATH + 1];
+  bool rv = false;
+  bool restoreArgString = false;
   // We're skipping building the C runtime to keep the file size low, so we
   // can't use a normal string initialization because that would call memset.
   path[0] = L'\0';
+  args[0] = L'\0';
   popstring(stacktop, path, MAX_PATH);
-  bool rv = ShellExecInExplorerProcess(path);
+  if (!stacktop || !*stacktop) {
+    popstring(stacktop, args, MAX_PATH);
+    // This stack item may not be for us, but we don't know yet.
+    restoreArgString = true;
+  }
+
+  if (lstrcmpW(args, L"/cmdargs") == 0) {
+    popstring(stacktop, args, MAX_PATH);
+    rv = ShellExecInExplorerProcess(path, args);
+  } else {
+    // If the stack wasn't empty, then we popped something that wasn't for us.
+    if (restoreArgString) {
+      pushstring(stacktop, args, lstrlenW(args));
+    }
+    rv = ShellExecInExplorerProcess(path);
+  }
+
   pushstring(stacktop, rv ? L"1" : L"0", 2);
 }
 
 BOOL APIENTRY
 DllMain(HMODULE, DWORD, LPVOID)
 {
   return TRUE;
 }
index 7f37d8aa46b29923ad95af149c8151ec6165a4c0..e05eda1961a290669a578c0ab64251000a97e6ad
GIT binary patch
literal 4096
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
Y8ySmyJ@R7Y)yQPzqu1QW^#7!P0pi(0b^rhX