windows: add command line escaping wrappers around EscapeArg and CommandLineToArgv

DecomposeCommandLine makes CommandLineToArgv usable in an ordinary way.
There's actually a pure-Go version of this available as the private
os.commandLineToArgv function, which we could copy, but given this is
x/sys/windows, it seems best to stick to the actual Windows primitives
which will always remain current. Then, ComposeCommandLine is just a
simple wrapper around EscapeArg (which has no native win32 substitute).

Change-Id: Ia2c7ca2ded9e5713b281dade34639dfeacf1171c
Reviewed-on: https://go-review.googlesource.com/c/sys/+/319229
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
Jason A. Donenfeld
2021-05-14 08:44:01 +00:00
parent b0526f3d87
commit e8d321eab0
2 changed files with 93 additions and 0 deletions
+34
View File
@@ -78,6 +78,40 @@ func EscapeArg(s string) string {
return string(qs[:j])
}
// ComposeCommandLine escapes and joins the given arguments suitable for use as a Windows command line,
// in CreateProcess's CommandLine argument, CreateService/ChangeServiceConfig's BinaryPathName argument,
// or any program that uses CommandLineToArgv.
func ComposeCommandLine(args []string) string {
var commandLine string
for i := range args {
if i > 0 {
commandLine += " "
}
commandLine += EscapeArg(args[i])
}
return commandLine
}
// DecomposeCommandLine breaks apart its argument command line into unescaped parts using CommandLineToArgv,
// as gathered from GetCommandLine, QUERY_SERVICE_CONFIG's BinaryPathName argument, or elsewhere that
// command lines are passed around.
func DecomposeCommandLine(commandLine string) ([]string, error) {
if len(commandLine) == 0 {
return []string{}, nil
}
var argc int32
argv, err := CommandLineToArgv(StringToUTF16Ptr(commandLine), &argc)
if err != nil {
return nil, err
}
defer LocalFree(Handle(unsafe.Pointer(argv)))
var args []string
for _, v := range (*argv)[:argc] {
args = append(args, UTF16ToString((*v)[:]))
}
return args, nil
}
func CloseOnExec(fd Handle) {
SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
}