Send command line arguments through to the Flutter Engine on Windows (#68931)

diff --git a/packages/flutter_tools/templates/app/windows.tmpl/runner/main.cpp.tmpl b/packages/flutter_tools/templates/app/windows.tmpl/runner/main.cpp.tmpl
index 6d2c86b..b3f8777 100644
--- a/packages/flutter_tools/templates/app/windows.tmpl/runner/main.cpp.tmpl
+++ b/packages/flutter_tools/templates/app/windows.tmpl/runner/main.cpp.tmpl
@@ -21,6 +21,12 @@
   RunLoop run_loop;
 
   flutter::DartProject project(L"data");
+
+  std::vector<std::string> command_line_arguments =
+      GetCommandLineArguments();
+
+  project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
+
   FlutterWindow window(&run_loop, project);
   Win32Window::Point origin(10, 10);
   Win32Window::Size size(1280, 720);
diff --git a/packages/flutter_tools/templates/app/windows.tmpl/runner/utils.cpp b/packages/flutter_tools/templates/app/windows.tmpl/runner/utils.cpp
index 37501e5..d19bdbb 100644
--- a/packages/flutter_tools/templates/app/windows.tmpl/runner/utils.cpp
+++ b/packages/flutter_tools/templates/app/windows.tmpl/runner/utils.cpp
@@ -20,3 +20,45 @@
     FlutterDesktopResyncOutputStreams();
   }
 }
+
+std::vector<std::string> GetCommandLineArguments() {
+  // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
+  int argc;
+  wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
+  if (argv == nullptr) {
+    return std::vector<std::string>();
+  }
+
+  std::vector<std::string> command_line_arguments;
+
+  // Skip the first argument as it's the binary name.
+  for (int i = 1; i < argc; i++) {
+    command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
+  }
+
+  ::LocalFree(argv);
+
+  return command_line_arguments;
+}
+
+std::string Utf8FromUtf16(const wchar_t* utf16_string) {
+  if (utf16_string == nullptr) {
+    return std::string();
+  }
+  int target_length = ::WideCharToMultiByte(
+      CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
+      -1, nullptr, 0, nullptr, nullptr);
+  if (target_length == 0) {
+    return std::string();
+  }
+  std::string utf8_string;
+  utf8_string.resize(target_length);
+  int converted_length = ::WideCharToMultiByte(
+      CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
+      -1, utf8_string.data(),
+      target_length, nullptr, nullptr);
+  if (converted_length == 0) {
+    return std::string();
+  }
+  return utf8_string;
+}
diff --git a/packages/flutter_tools/templates/app/windows.tmpl/runner/utils.h b/packages/flutter_tools/templates/app/windows.tmpl/runner/utils.h
index d792603..3879d54 100644
--- a/packages/flutter_tools/templates/app/windows.tmpl/runner/utils.h
+++ b/packages/flutter_tools/templates/app/windows.tmpl/runner/utils.h
@@ -1,8 +1,19 @@
 #ifndef RUNNER_UTILS_H_
 #define RUNNER_UTILS_H_
 
+#include <string>
+#include <vector>
+
 // Creates a console for the process, and redirects stdout and stderr to
 // it for both the runner and the Flutter library.
 void CreateAndAttachConsole();
 
+// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
+// encoded in UTF-8. Returns an empty std::string on failure.
+std::string Utf8FromUtf16(const wchar_t* utf16_string);
+
+// Gets the command line arguments passed in as a std::vector<std::string>,
+// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
+std::vector<std::string> GetCommandLineArguments();
+
 #endif  // RUNNER_UTILS_H_