cubefs

Форк
0
/x
/
exec_windows.go 
178 строк · 4.6 Кб
1
// Copyright 2009 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4

5
// Fork, exec, wait, etc.
6

7
package windows
8

9
import (
10
	errorspkg "errors"
11
	"unsafe"
12
)
13

14
// EscapeArg rewrites command line argument s as prescribed
15
// in http://msdn.microsoft.com/en-us/library/ms880421.
16
// This function returns "" (2 double quotes) if s is empty.
17
// Alternatively, these transformations are done:
18
//   - every back slash (\) is doubled, but only if immediately
19
//     followed by double quote (");
20
//   - every double quote (") is escaped by back slash (\);
21
//   - finally, s is wrapped with double quotes (arg -> "arg"),
22
//     but only if there is space or tab inside s.
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
// ComposeCommandLine escapes and joins the given arguments suitable for use as a Windows command line,
82
// in CreateProcess's CommandLine argument, CreateService/ChangeServiceConfig's BinaryPathName argument,
83
// or any program that uses CommandLineToArgv.
84
func ComposeCommandLine(args []string) string {
85
	var commandLine string
86
	for i := range args {
87
		if i > 0 {
88
			commandLine += " "
89
		}
90
		commandLine += EscapeArg(args[i])
91
	}
92
	return commandLine
93
}
94

95
// DecomposeCommandLine breaks apart its argument command line into unescaped parts using CommandLineToArgv,
96
// as gathered from GetCommandLine, QUERY_SERVICE_CONFIG's BinaryPathName argument, or elsewhere that
97
// command lines are passed around.
98
func DecomposeCommandLine(commandLine string) ([]string, error) {
99
	if len(commandLine) == 0 {
100
		return []string{}, nil
101
	}
102
	var argc int32
103
	argv, err := CommandLineToArgv(StringToUTF16Ptr(commandLine), &argc)
104
	if err != nil {
105
		return nil, err
106
	}
107
	defer LocalFree(Handle(unsafe.Pointer(argv)))
108
	var args []string
109
	for _, v := range (*argv)[:argc] {
110
		args = append(args, UTF16ToString((*v)[:]))
111
	}
112
	return args, nil
113
}
114

115
func CloseOnExec(fd Handle) {
116
	SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
117
}
118

119
// FullPath retrieves the full path of the specified file.
120
func FullPath(name string) (path string, err error) {
121
	p, err := UTF16PtrFromString(name)
122
	if err != nil {
123
		return "", err
124
	}
125
	n := uint32(100)
126
	for {
127
		buf := make([]uint16, n)
128
		n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
129
		if err != nil {
130
			return "", err
131
		}
132
		if n <= uint32(len(buf)) {
133
			return UTF16ToString(buf[:n]), nil
134
		}
135
	}
136
}
137

138
// NewProcThreadAttributeList allocates a new ProcThreadAttributeListContainer, with the requested maximum number of attributes.
139
func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeListContainer, error) {
140
	var size uintptr
141
	err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size)
142
	if err != ERROR_INSUFFICIENT_BUFFER {
143
		if err == nil {
144
			return nil, errorspkg.New("unable to query buffer size from InitializeProcThreadAttributeList")
145
		}
146
		return nil, err
147
	}
148
	alloc, err := LocalAlloc(LMEM_FIXED, uint32(size))
149
	if err != nil {
150
		return nil, err
151
	}
152
	// size is guaranteed to be ≥1 by InitializeProcThreadAttributeList.
153
	al := &ProcThreadAttributeListContainer{data: (*ProcThreadAttributeList)(unsafe.Pointer(alloc))}
154
	err = initializeProcThreadAttributeList(al.data, maxAttrCount, 0, &size)
155
	if err != nil {
156
		return nil, err
157
	}
158
	return al, err
159
}
160

161
// Update modifies the ProcThreadAttributeList using UpdateProcThreadAttribute.
162
func (al *ProcThreadAttributeListContainer) Update(attribute uintptr, value unsafe.Pointer, size uintptr) error {
163
	al.pointers = append(al.pointers, value)
164
	return updateProcThreadAttribute(al.data, 0, attribute, value, size, nil, nil)
165
}
166

167
// Delete frees ProcThreadAttributeList's resources.
168
func (al *ProcThreadAttributeListContainer) Delete() {
169
	deleteProcThreadAttributeList(al.data)
170
	LocalFree(Handle(unsafe.Pointer(al.data)))
171
	al.data = nil
172
	al.pointers = nil
173
}
174

175
// List returns the actual ProcThreadAttributeList to be passed to StartupInfoEx.
176
func (al *ProcThreadAttributeListContainer) List() *ProcThreadAttributeList {
177
	return al.data
178
}
179

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.