Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Windows:Have native CommandLine in Process
Signed-off-by: John Howard <[email protected]> This adds a new field `CommandLine` in the `Process` structure for use on Windows. A Windows runtime will check this first and use it as-is when launching WCOW processes in a container. If omitted, the Windows runtime will fall back to the previous behaviour of escaping (eg Windows.EscapeArg in golang) each of the `args` array elements, and space-concatenating them. The reason for this change is to avoid loss of fidelity for launching processes. One such example is the following: `cmd /S /C mkdir "c:/foo"` When parsed into a JSON array such as `Args`, it becomes 5 elements - cmd - /S - /C - mkdir - c:/foo Here, note the lost information being the double-quotes around `c:/foo`. When using the required contenation, space separation required on Windows, (https://github.com/golang/sys/blob/c4afb3effaa53fd9a06ca61262dc7ce8df4c081b/windows/exec_windows.go#L9-L18), this becomes the following command line: `cmd /S /C mkdir c:/foo` When the double-quotes are missing, mkdir would fail, but with the double-quotes, it succeeds as expected: ``` C:\>cmd /s /c mkdir c:/foo The syntax of the command is incorrect. C:\>cmd /s /c mkdir "c:/foo" C:\> ``` The addition of a full `commandLine` in Process for use on Windows alleviates issues where fidelity can be lost. Some further background: For historical reasons, Windows only has native support for launching processes using a command line. It does not support an argument array as per Linux. See the `CreateProcess` API documentation on MSDN. What happens under the covers is that prior to invoking a programs main, the language runtime will convert the command line to a set of argv[] suach as in the C-style `int main(int argc, char* argv), or the golang `os.Args` prior to the programs `main` being invoked, using Windows- specific rules. In go, that's the `commandLineToArgv` function which is called in the init() function of the os package https://github.com/golang/go/blob/ff7b245a31394b700a252fd547cf16ad0ad838b6/src/os/exec_windows.go#L100, In the Microsoft C++ startup code, it does exactly the same processing as documented here prior to invoking main itself: https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments?view=vs-2017. The processing it describes is documented at https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156(v=vs.85).aspx and https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-commandlinetoargvw Some related links which provide a lot more information about the very specific (and unique to Windows) command line escaping rules, and handling of them are below: https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ https://stackoverflow.com/questions/31838469/how-do-i-convert-argv-to-lpcommandline-parameter-of-createprocess https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments?view=vs-2017
- Loading branch information