1
2
3
4
5
6
7 package windows
8
9 import (
10 errorspkg "errors"
11 "unsafe"
12 )
13
14
15
16
17
18
19
20
21
22
23 func EscapeArg(s string) string {
24 if len(s) == 0 {
25 return `""`
26 }
27 n := len(s)
28 hasSpace := false
29 for i := 0; i < len(s); i++ {
30 switch s[i] {
31 case '"', '\\':
32 n++
33 case ' ', '\t':
34 hasSpace = true
35 }
36 }
37 if hasSpace {
38 n += 2
39 }
40 if n == len(s) {
41 return s
42 }
43
44 qs := make([]byte, n)
45 j := 0
46 if hasSpace {
47 qs[j] = '"'
48 j++
49 }
50 slashes := 0
51 for i := 0; i < len(s); i++ {
52 switch s[i] {
53 default:
54 slashes = 0
55 qs[j] = s[i]
56 case '\\':
57 slashes++
58 qs[j] = s[i]
59 case '"':
60 for ; slashes > 0; slashes-- {
61 qs[j] = '\\'
62 j++
63 }
64 qs[j] = '\\'
65 j++
66 qs[j] = s[i]
67 }
68 j++
69 }
70 if hasSpace {
71 for ; slashes > 0; slashes-- {
72 qs[j] = '\\'
73 j++
74 }
75 qs[j] = '"'
76 j++
77 }
78 return string(qs[:j])
79 }
80
81
82
83
84 func ComposeCommandLine(args []string) string {
85 if len(args) == 0 {
86 return ""
87 }
88
89
90
91
92
93
94
95 prog := args[0]
96 mustQuote := len(prog) == 0
97 for i := 0; i < len(prog); i++ {
98 c := prog[i]
99 if c <= ' ' || (c == '"' && i == 0) {
100
101
102
103
104
105 mustQuote = true
106 break
107 }
108 }
109 var commandLine []byte
110 if mustQuote {
111 commandLine = make([]byte, 0, len(prog)+2)
112 commandLine = append(commandLine, '"')
113 for i := 0; i < len(prog); i++ {
114 c := prog[i]
115 if c == '"' {
116
117
118
119 continue
120 }
121 commandLine = append(commandLine, c)
122 }
123 commandLine = append(commandLine, '"')
124 } else {
125 if len(args) == 1 {
126
127
128 return prog
129 }
130 commandLine = []byte(prog)
131 }
132
133 for _, arg := range args[1:] {
134 commandLine = append(commandLine, ' ')
135
136
137
138 commandLine = append(commandLine, EscapeArg(arg)...)
139 }
140 return string(commandLine)
141 }
142
143
144
145
146
147 func DecomposeCommandLine(commandLine string) ([]string, error) {
148 if len(commandLine) == 0 {
149 return []string{}, nil
150 }
151 utf16CommandLine, err := UTF16FromString(commandLine)
152 if err != nil {
153 return nil, errorspkg.New("string with NUL passed to DecomposeCommandLine")
154 }
155 var argc int32
156 argv, err := commandLineToArgv(&utf16CommandLine[0], &argc)
157 if err != nil {
158 return nil, err
159 }
160 defer LocalFree(Handle(unsafe.Pointer(argv)))
161
162 var args []string
163 for _, p := range unsafe.Slice(argv, argc) {
164 args = append(args, UTF16PtrToString(p))
165 }
166 return args, nil
167 }
168
169
170
171
172
173
174
175
176
177
178
179 func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) {
180 argp, err := commandLineToArgv(cmd, argc)
181 argv = (*[8192]*[8192]uint16)(unsafe.Pointer(argp))
182 return argv, err
183 }
184
185 func CloseOnExec(fd Handle) {
186 SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
187 }
188
189
190 func FullPath(name string) (path string, err error) {
191 p, err := UTF16PtrFromString(name)
192 if err != nil {
193 return "", err
194 }
195 n := uint32(100)
196 for {
197 buf := make([]uint16, n)
198 n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
199 if err != nil {
200 return "", err
201 }
202 if n <= uint32(len(buf)) {
203 return UTF16ToString(buf[:n]), nil
204 }
205 }
206 }
207
208
209 func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeListContainer, error) {
210 var size uintptr
211 err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size)
212 if err != ERROR_INSUFFICIENT_BUFFER {
213 if err == nil {
214 return nil, errorspkg.New("unable to query buffer size from InitializeProcThreadAttributeList")
215 }
216 return nil, err
217 }
218 alloc, err := LocalAlloc(LMEM_FIXED, uint32(size))
219 if err != nil {
220 return nil, err
221 }
222
223 al := &ProcThreadAttributeListContainer{data: (*ProcThreadAttributeList)(unsafe.Pointer(alloc))}
224 err = initializeProcThreadAttributeList(al.data, maxAttrCount, 0, &size)
225 if err != nil {
226 return nil, err
227 }
228 return al, err
229 }
230
231
232 func (al *ProcThreadAttributeListContainer) Update(attribute uintptr, value unsafe.Pointer, size uintptr) error {
233 al.pointers = append(al.pointers, value)
234 return updateProcThreadAttribute(al.data, 0, attribute, value, size, nil, nil)
235 }
236
237
238 func (al *ProcThreadAttributeListContainer) Delete() {
239 deleteProcThreadAttributeList(al.data)
240 LocalFree(Handle(unsafe.Pointer(al.data)))
241 al.data = nil
242 al.pointers = nil
243 }
244
245
246 func (al *ProcThreadAttributeListContainer) List() *ProcThreadAttributeList {
247 return al.data
248 }
249
View as plain text