Added support for running crashpad that is embedded inside a dll

This code was merged from chromium commit:
6a2d5519c69e195e584055b186789b7f760c9703

Implement crashpad support for GCPW

- Implements crashpad support for GCPW installer
- Implements crashpad support for the actual credential provider dll
and runs the crashpad handler directly in the dll as an entry point

Bug: 890348
Change-Id: I5b256b4d6ad8ee7153fd22e4d13f1a1791fa6d65
Reviewed-on: https://chromium-review.googlesource.com/c/1344210
Commit-Queue: Tien Mai <tienmai@chromium.org>
Reviewed-by: Greg Thompson <grt@chromium.org>
Reviewed-by: Roger Tawa <rogerta@chromium.org>
Reviewed-by: Scott Graham <scottmg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611187}
Message-Id: Merged from chromium 6a2d5519c69e195e584055b186789b7f760c9703
Reviewed-on: https://chromium-review.googlesource.com/c/1358731
Commit-Queue: Scott Graham <scottmg@chromium.org>
diff --git a/client/crashpad_client_win.cc b/client/crashpad_client_win.cc
index 8ceded3..0037c1f 100644
--- a/client/crashpad_client_win.cc
+++ b/client/crashpad_client_win.cc
@@ -15,6 +15,7 @@
 #include "client/crashpad_client.h"
 
 #include <windows.h>
+
 #include <signal.h>
 #include <stdint.h>
 #include <string.h>
@@ -73,10 +74,10 @@
 ExceptionInformation g_non_crash_exception_information;
 
 enum class StartupState : int {
-  kNotReady = 0,   // This must be value 0 because it is the initial value of a
-                   // global AtomicWord.
+  kNotReady = 0,  // This must be value 0 because it is the initial value of a
+                  // global AtomicWord.
   kSucceeded = 1,  // The CreateProcess() for the handler succeeded.
-  kFailed = 2,     // The handler failed to start.
+  kFailed = 2,  // The handler failed to start.
 };
 
 // This is a tri-state of type StartupState. It starts at 0 == kNotReady, and
@@ -93,8 +94,7 @@
 CRITICAL_SECTION g_critical_section_with_debug_info;
 
 void SetHandlerStartupState(StartupState state) {
-  DCHECK(state == StartupState::kSucceeded ||
-         state == StartupState::kFailed);
+  DCHECK(state == StartupState::kSucceeded || state == StartupState::kFailed);
   base::subtle::Acquire_Store(&g_handler_startup_state,
                               static_cast<base::subtle::AtomicWord>(state));
 }
@@ -476,17 +476,34 @@
     }
   }
 
+  // If the embedded crashpad handler is being started via an entry point in a
+  // DLL (the handler executable is rundll32.exe), then don't pass
+  // the application name to CreateProcess as this appears to generate an
+  // invalid command line where the first argument needed by rundll32 is not in
+  // the correct format as required in:
+  // https://support.microsoft.com/en-ca/help/164787/info-windows-rundll-and-rundll32-interface
+  const base::StringPiece16 kRunDll32Exe(L"rundll32.exe");
+  bool is_embedded_in_dll = false;
+  if (data->handler.value().size() >= kRunDll32Exe.size() &&
+      _wcsicmp(data->handler.value()
+                   .substr(data->handler.value().size() - kRunDll32Exe.size())
+                   .c_str(),
+               kRunDll32Exe.data()) == 0) {
+    is_embedded_in_dll = true;
+  }
+
   PROCESS_INFORMATION process_info;
-  rv = CreateProcess(data->handler.value().c_str(),
-                     &command_line[0],
-                     nullptr,
-                     nullptr,
-                     true,
-                     creation_flags,
-                     nullptr,
-                     nullptr,
-                     &startup_info.StartupInfo,
-                     &process_info);
+  rv = CreateProcess(
+      is_embedded_in_dll ? nullptr : data->handler.value().c_str(),
+      &command_line[0],
+      nullptr,
+      nullptr,
+      true,
+      creation_flags,
+      nullptr,
+      nullptr,
+      &startup_info.StartupInfo,
+      &process_info);
   if (!rv) {
     PLOG(ERROR) << "CreateProcess";
     return false;