annotate vendor/golang.org/x/sys/windows/exec_windows.go @ 68:4b79810863f6 draft

Ready to release 0.6.0 Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>
author yakumo.izuru
date Wed, 13 Sep 2023 10:49:50 +0000
parents 787b5ee0289d
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
66
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1 // Copyright 2009 The Go Authors. All rights reserved.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2 // Use of this source code is governed by a BSD-style
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
3 // license that can be found in the LICENSE file.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
4
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
5 // Fork, exec, wait, etc.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
6
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
7 package windows
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
8
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
9 import (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
10 errorspkg "errors"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
11 "unsafe"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
12 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
13
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
14 // EscapeArg rewrites command line argument s as prescribed
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
15 // in http://msdn.microsoft.com/en-us/library/ms880421.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
16 // This function returns "" (2 double quotes) if s is empty.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
17 // Alternatively, these transformations are done:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
18 // - every back slash (\) is doubled, but only if immediately
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
19 // followed by double quote (");
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
20 // - every double quote (") is escaped by back slash (\);
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
21 // - finally, s is wrapped with double quotes (arg -> "arg"),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
22 // but only if there is space or tab inside s.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
23 func EscapeArg(s string) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
24 if len(s) == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
25 return "\"\""
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
26 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
27 n := len(s)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
28 hasSpace := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
29 for i := 0; i < len(s); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
30 switch s[i] {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
31 case '"', '\\':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
32 n++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
33 case ' ', '\t':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
34 hasSpace = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
35 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
36 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
37 if hasSpace {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
38 n += 2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
39 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
40 if n == len(s) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
41 return s
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
42 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
43
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
44 qs := make([]byte, n)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
45 j := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
46 if hasSpace {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
47 qs[j] = '"'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
48 j++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
49 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
50 slashes := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
51 for i := 0; i < len(s); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
52 switch s[i] {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
53 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
54 slashes = 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
55 qs[j] = s[i]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
56 case '\\':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
57 slashes++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
58 qs[j] = s[i]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
59 case '"':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
60 for ; slashes > 0; slashes-- {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
61 qs[j] = '\\'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
62 j++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
63 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
64 qs[j] = '\\'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
65 j++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
66 qs[j] = s[i]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
67 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
68 j++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
69 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
70 if hasSpace {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
71 for ; slashes > 0; slashes-- {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
72 qs[j] = '\\'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
73 j++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
74 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
75 qs[j] = '"'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
76 j++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
77 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
78 return string(qs[:j])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
79 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
80
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
81 // ComposeCommandLine escapes and joins the given arguments suitable for use as a Windows command line,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
82 // in CreateProcess's CommandLine argument, CreateService/ChangeServiceConfig's BinaryPathName argument,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
83 // or any program that uses CommandLineToArgv.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
84 func ComposeCommandLine(args []string) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
85 var commandLine string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
86 for i := range args {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
87 if i > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
88 commandLine += " "
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
89 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
90 commandLine += EscapeArg(args[i])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
91 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
92 return commandLine
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
93 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
94
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
95 // DecomposeCommandLine breaks apart its argument command line into unescaped parts using CommandLineToArgv,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
96 // as gathered from GetCommandLine, QUERY_SERVICE_CONFIG's BinaryPathName argument, or elsewhere that
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
97 // command lines are passed around.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
98 func DecomposeCommandLine(commandLine string) ([]string, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
99 if len(commandLine) == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
100 return []string{}, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
101 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
102 var argc int32
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
103 argv, err := CommandLineToArgv(StringToUTF16Ptr(commandLine), &argc)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
104 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
105 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
106 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
107 defer LocalFree(Handle(unsafe.Pointer(argv)))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
108 var args []string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
109 for _, v := range (*argv)[:argc] {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
110 args = append(args, UTF16ToString((*v)[:]))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
111 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
112 return args, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
113 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
114
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
115 func CloseOnExec(fd Handle) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
116 SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
117 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
118
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
119 // FullPath retrieves the full path of the specified file.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
120 func FullPath(name string) (path string, err error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
121 p, err := UTF16PtrFromString(name)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
122 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
123 return "", err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
124 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
125 n := uint32(100)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
126 for {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
127 buf := make([]uint16, n)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
128 n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
129 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
130 return "", err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
131 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
132 if n <= uint32(len(buf)) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
133 return UTF16ToString(buf[:n]), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
134 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
135 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
136 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
137
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
138 // NewProcThreadAttributeList allocates a new ProcThreadAttributeListContainer, with the requested maximum number of attributes.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
139 func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeListContainer, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
140 var size uintptr
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
141 err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
142 if err != ERROR_INSUFFICIENT_BUFFER {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
143 if err == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
144 return nil, errorspkg.New("unable to query buffer size from InitializeProcThreadAttributeList")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
145 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
146 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
147 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
148 alloc, err := LocalAlloc(LMEM_FIXED, uint32(size))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
149 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
150 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
151 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
152 // size is guaranteed to be ≥1 by InitializeProcThreadAttributeList.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
153 al := &ProcThreadAttributeListContainer{data: (*ProcThreadAttributeList)(unsafe.Pointer(alloc))}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
154 err = initializeProcThreadAttributeList(al.data, maxAttrCount, 0, &size)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
155 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
156 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
157 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
158 return al, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
159 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
160
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
161 // Update modifies the ProcThreadAttributeList using UpdateProcThreadAttribute.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
162 func (al *ProcThreadAttributeListContainer) Update(attribute uintptr, value unsafe.Pointer, size uintptr) error {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
163 al.pointers = append(al.pointers, value)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
164 return updateProcThreadAttribute(al.data, 0, attribute, value, size, nil, nil)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
165 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
166
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
167 // Delete frees ProcThreadAttributeList's resources.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
168 func (al *ProcThreadAttributeListContainer) Delete() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
169 deleteProcThreadAttributeList(al.data)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
170 LocalFree(Handle(unsafe.Pointer(al.data)))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
171 al.data = nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
172 al.pointers = nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
173 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
174
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
175 // List returns the actual ProcThreadAttributeList to be passed to StartupInfoEx.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
176 func (al *ProcThreadAttributeListContainer) List() *ProcThreadAttributeList {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
177 return al.data
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
178 }