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 487145 6006b0096da29528c0870bc4dfa2a4ccf046daa9
parent 487144 4fb20c215e9c3ea771d8709c5912610d626edb3e
child 487146 b8d8c53289150332f491df758566cf6832f2f400
push id246
push userfmarier@mozilla.com
push dateSat, 13 Oct 2018 00:15:40 +0000
reviewersagashlin
bugs1494900
milestone64.0a1
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