This update changes the way hcsshim invokes Windows DLLs to avoid races
with the garbage collector. It also now uses go-winio to access the
pipes used for communication with processes running in the container;
this reduces the number of threads used by docker.exe, improving
scalability.
Signed-off-by: John Starks <jostarks@microsoft.com>
| ... | ... |
@@ -7,6 +7,7 @@ source 'hack/.vendor-helpers.sh' |
| 7 | 7 |
|
| 8 | 8 |
# the following lines are in sorted order, FYI |
| 9 | 9 |
clone git github.com/Azure/go-ansiterm 70b2c90b260171e829f1ebd7c17f600c11858dbe |
| 10 |
+clone git github.com/Microsoft/go-winio 2b085935f02c272e7a1855df6f8fe03029ffcadd |
|
| 10 | 11 |
clone git github.com/Sirupsen/logrus v0.8.7 # logrus is a common dependency among multiple deps |
| 11 | 12 |
clone git github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a |
| 12 | 13 |
clone git github.com/go-check/check 11d3bc7aa68e238947792f30573146a3231fc0f1 |
| ... | ... |
@@ -15,7 +16,7 @@ clone git github.com/gorilla/mux e444e69cbd |
| 15 | 15 |
clone git github.com/kr/pty 5cf931ef8f |
| 16 | 16 |
clone git github.com/mattn/go-shellwords v1.0.0 |
| 17 | 17 |
clone git github.com/mattn/go-sqlite3 v1.1.0 |
| 18 |
-clone git github.com/microsoft/hcsshim de43b42b5ce14dfdcbeedb0628b0032174d89caa |
|
| 18 |
+clone git github.com/microsoft/hcsshim 35ad4d808a97203cb1748d7c43167e91f51e7f86 |
|
| 19 | 19 |
clone git github.com/mistifyio/go-zfs v2.1.1 |
| 20 | 20 |
clone git github.com/tchap/go-patricia v2.1.0 |
| 21 | 21 |
clone git github.com/vdemeester/shakers 3c10293ce22b900c27acad7b28656196fcc2f73b |
| 22 | 22 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,22 @@ |
| 0 |
+The MIT License (MIT) |
|
| 1 |
+ |
|
| 2 |
+Copyright (c) 2015 Microsoft |
|
| 3 |
+ |
|
| 4 |
+Permission is hereby granted, free of charge, to any person obtaining a copy |
|
| 5 |
+of this software and associated documentation files (the "Software"), to deal |
|
| 6 |
+in the Software without restriction, including without limitation the rights |
|
| 7 |
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
| 8 |
+copies of the Software, and to permit persons to whom the Software is |
|
| 9 |
+furnished to do so, subject to the following conditions: |
|
| 10 |
+ |
|
| 11 |
+The above copyright notice and this permission notice shall be included in all |
|
| 12 |
+copies or substantial portions of the Software. |
|
| 13 |
+ |
|
| 14 |
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
| 15 |
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
| 16 |
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
| 17 |
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
| 18 |
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
| 19 |
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
| 20 |
+SOFTWARE. |
|
| 21 |
+ |
| 0 | 22 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,15 @@ |
| 0 |
+# go-winio |
|
| 1 |
+ |
|
| 2 |
+This repository contains utilities for efficiently performing Win32 IO operations in |
|
| 3 |
+Go. Currently, this is focused on accessing named pipes and other file handles, and |
|
| 4 |
+for using named pipes as a net transport. |
|
| 5 |
+ |
|
| 6 |
+This code relies on IO completion ports to avoid blocking IO on system threads, allowing Go |
|
| 7 |
+to reuse the thread to schedule another goroutine. This limits support to Windows Vista and |
|
| 8 |
+newer operating systems. This is similar to the implementation of network sockets in Go's net |
|
| 9 |
+package. |
|
| 10 |
+ |
|
| 11 |
+Please see the LICENSE file for licensing information. |
|
| 12 |
+ |
|
| 13 |
+Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe |
|
| 14 |
+for another named pipe implementation. |
| 0 | 15 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,216 @@ |
| 0 |
+package winio |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "errors" |
|
| 4 |
+ "io" |
|
| 5 |
+ "runtime" |
|
| 6 |
+ "sync" |
|
| 7 |
+ "syscall" |
|
| 8 |
+ "time" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx |
|
| 12 |
+//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort |
|
| 13 |
+//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus |
|
| 14 |
+//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes |
|
| 15 |
+ |
|
| 16 |
+const ( |
|
| 17 |
+ cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1 |
|
| 18 |
+ cFILE_SKIP_SET_EVENT_ON_HANDLE = 2 |
|
| 19 |
+) |
|
| 20 |
+ |
|
| 21 |
+var ( |
|
| 22 |
+ ErrFileClosed = errors.New("file has already been closed")
|
|
| 23 |
+ ErrTimeout = &timeoutError{}
|
|
| 24 |
+) |
|
| 25 |
+ |
|
| 26 |
+type timeoutError struct{}
|
|
| 27 |
+ |
|
| 28 |
+func (e *timeoutError) Error() string { return "i/o timeout" }
|
|
| 29 |
+func (e *timeoutError) Timeout() bool { return true }
|
|
| 30 |
+func (e *timeoutError) Temporary() bool { return true }
|
|
| 31 |
+ |
|
| 32 |
+var ioInitOnce sync.Once |
|
| 33 |
+var ioCompletionPort syscall.Handle |
|
| 34 |
+ |
|
| 35 |
+// ioResult contains the result of an asynchronous IO operation |
|
| 36 |
+type ioResult struct {
|
|
| 37 |
+ bytes uint32 |
|
| 38 |
+ err error |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+// ioOperation represents an outstanding asynchronous Win32 IO |
|
| 42 |
+type ioOperation struct {
|
|
| 43 |
+ o syscall.Overlapped |
|
| 44 |
+ ch chan ioResult |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 47 |
+func initIo() {
|
|
| 48 |
+ h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff) |
|
| 49 |
+ if err != nil {
|
|
| 50 |
+ panic(err) |
|
| 51 |
+ } |
|
| 52 |
+ ioCompletionPort = h |
|
| 53 |
+ go ioCompletionProcessor(h) |
|
| 54 |
+} |
|
| 55 |
+ |
|
| 56 |
+// win32File implements Reader, Writer, and Closer on a Win32 handle without blocking in a syscall. |
|
| 57 |
+// It takes ownership of this handle and will close it if it is garbage collected. |
|
| 58 |
+type win32File struct {
|
|
| 59 |
+ handle syscall.Handle |
|
| 60 |
+ wg sync.WaitGroup |
|
| 61 |
+ closing bool |
|
| 62 |
+ readDeadline time.Time |
|
| 63 |
+ writeDeadline time.Time |
|
| 64 |
+} |
|
| 65 |
+ |
|
| 66 |
+// makeWin32File makes a new win32File from an existing file handle |
|
| 67 |
+func makeWin32File(h syscall.Handle) (*win32File, error) {
|
|
| 68 |
+ f := &win32File{handle: h}
|
|
| 69 |
+ ioInitOnce.Do(initIo) |
|
| 70 |
+ _, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff) |
|
| 71 |
+ if err != nil {
|
|
| 72 |
+ return nil, err |
|
| 73 |
+ } |
|
| 74 |
+ err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE) |
|
| 75 |
+ if err != nil {
|
|
| 76 |
+ return nil, err |
|
| 77 |
+ } |
|
| 78 |
+ runtime.SetFinalizer(f, (*win32File).closeHandle) |
|
| 79 |
+ return f, nil |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
|
|
| 83 |
+ return makeWin32File(h) |
|
| 84 |
+} |
|
| 85 |
+ |
|
| 86 |
+// closeHandle closes the resources associated with a Win32 handle |
|
| 87 |
+func (f *win32File) closeHandle() {
|
|
| 88 |
+ if !f.closing {
|
|
| 89 |
+ // cancel all IO and wait for it to complete |
|
| 90 |
+ f.closing = true |
|
| 91 |
+ cancelIoEx(f.handle, nil) |
|
| 92 |
+ f.wg.Wait() |
|
| 93 |
+ // at this point, no new IO can start |
|
| 94 |
+ syscall.Close(f.handle) |
|
| 95 |
+ f.handle = 0 |
|
| 96 |
+ } |
|
| 97 |
+} |
|
| 98 |
+ |
|
| 99 |
+// Close closes a win32File. |
|
| 100 |
+func (f *win32File) Close() error {
|
|
| 101 |
+ f.closeHandle() |
|
| 102 |
+ runtime.SetFinalizer(f, nil) |
|
| 103 |
+ return nil |
|
| 104 |
+} |
|
| 105 |
+ |
|
| 106 |
+// prepareIo prepares for a new IO operation |
|
| 107 |
+func (f *win32File) prepareIo() (*ioOperation, error) {
|
|
| 108 |
+ f.wg.Add(1) |
|
| 109 |
+ if f.closing {
|
|
| 110 |
+ return nil, ErrFileClosed |
|
| 111 |
+ } |
|
| 112 |
+ c := &ioOperation{}
|
|
| 113 |
+ c.ch = make(chan ioResult) |
|
| 114 |
+ return c, nil |
|
| 115 |
+} |
|
| 116 |
+ |
|
| 117 |
+// ioCompletionProcessor processes completed async IOs forever |
|
| 118 |
+func ioCompletionProcessor(h syscall.Handle) {
|
|
| 119 |
+ for {
|
|
| 120 |
+ var bytes uint32 |
|
| 121 |
+ var key uintptr |
|
| 122 |
+ var op *ioOperation |
|
| 123 |
+ err := getQueuedCompletionStatus(h, &bytes, &key, &op, syscall.INFINITE) |
|
| 124 |
+ if op == nil {
|
|
| 125 |
+ panic(err) |
|
| 126 |
+ } |
|
| 127 |
+ op.ch <- ioResult{bytes, err}
|
|
| 128 |
+ } |
|
| 129 |
+} |
|
| 130 |
+ |
|
| 131 |
+// asyncIo processes the return value from ReadFile or WriteFile, blocking until |
|
| 132 |
+// the operation has actually completed. |
|
| 133 |
+func (f *win32File) asyncIo(c *ioOperation, deadline time.Time, bytes uint32, err error) (int, error) {
|
|
| 134 |
+ if err != syscall.ERROR_IO_PENDING {
|
|
| 135 |
+ f.wg.Done() |
|
| 136 |
+ return int(bytes), err |
|
| 137 |
+ } else {
|
|
| 138 |
+ var r ioResult |
|
| 139 |
+ wait := true |
|
| 140 |
+ timedout := false |
|
| 141 |
+ if f.closing {
|
|
| 142 |
+ cancelIoEx(f.handle, &c.o) |
|
| 143 |
+ } else if !deadline.IsZero() {
|
|
| 144 |
+ now := time.Now() |
|
| 145 |
+ if !deadline.After(now) {
|
|
| 146 |
+ timedout = true |
|
| 147 |
+ } else {
|
|
| 148 |
+ timeout := time.After(deadline.Sub(now)) |
|
| 149 |
+ select {
|
|
| 150 |
+ case r = <-c.ch: |
|
| 151 |
+ wait = false |
|
| 152 |
+ case <-timeout: |
|
| 153 |
+ timedout = true |
|
| 154 |
+ } |
|
| 155 |
+ } |
|
| 156 |
+ } |
|
| 157 |
+ if timedout {
|
|
| 158 |
+ cancelIoEx(f.handle, &c.o) |
|
| 159 |
+ } |
|
| 160 |
+ if wait {
|
|
| 161 |
+ r = <-c.ch |
|
| 162 |
+ } |
|
| 163 |
+ err = r.err |
|
| 164 |
+ if err == syscall.ERROR_OPERATION_ABORTED {
|
|
| 165 |
+ if f.closing {
|
|
| 166 |
+ err = ErrFileClosed |
|
| 167 |
+ } else if timedout {
|
|
| 168 |
+ err = ErrTimeout |
|
| 169 |
+ } |
|
| 170 |
+ } |
|
| 171 |
+ f.wg.Done() |
|
| 172 |
+ return int(r.bytes), err |
|
| 173 |
+ } |
|
| 174 |
+} |
|
| 175 |
+ |
|
| 176 |
+// Read reads from a file handle. |
|
| 177 |
+func (f *win32File) Read(b []byte) (int, error) {
|
|
| 178 |
+ c, err := f.prepareIo() |
|
| 179 |
+ if err != nil {
|
|
| 180 |
+ return 0, err |
|
| 181 |
+ } |
|
| 182 |
+ var bytes uint32 |
|
| 183 |
+ err = syscall.ReadFile(f.handle, b, &bytes, &c.o) |
|
| 184 |
+ n, err := f.asyncIo(c, f.readDeadline, bytes, err) |
|
| 185 |
+ |
|
| 186 |
+ // Handle EOF conditions. |
|
| 187 |
+ if err == nil && n == 0 && len(b) != 0 {
|
|
| 188 |
+ return 0, io.EOF |
|
| 189 |
+ } else if err == syscall.ERROR_BROKEN_PIPE {
|
|
| 190 |
+ return 0, io.EOF |
|
| 191 |
+ } else {
|
|
| 192 |
+ return n, err |
|
| 193 |
+ } |
|
| 194 |
+} |
|
| 195 |
+ |
|
| 196 |
+// Write writes to a file handle. |
|
| 197 |
+func (f *win32File) Write(b []byte) (int, error) {
|
|
| 198 |
+ c, err := f.prepareIo() |
|
| 199 |
+ if err != nil {
|
|
| 200 |
+ return 0, err |
|
| 201 |
+ } |
|
| 202 |
+ var bytes uint32 |
|
| 203 |
+ err = syscall.WriteFile(f.handle, b, &bytes, &c.o) |
|
| 204 |
+ return f.asyncIo(c, f.writeDeadline, bytes, err) |
|
| 205 |
+} |
|
| 206 |
+ |
|
| 207 |
+func (f *win32File) SetReadDeadline(t time.Time) error {
|
|
| 208 |
+ f.readDeadline = t |
|
| 209 |
+ return nil |
|
| 210 |
+} |
|
| 211 |
+ |
|
| 212 |
+func (f *win32File) SetWriteDeadline(t time.Time) error {
|
|
| 213 |
+ f.writeDeadline = t |
|
| 214 |
+ return nil |
|
| 215 |
+} |
| 0 | 216 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,797 @@ |
| 0 |
+// Copyright 2013 The Go Authors. All rights reserved. |
|
| 1 |
+// Use of this source code is governed by a BSD-style |
|
| 2 |
+// license that can be found in the LICENSE file. |
|
| 3 |
+ |
|
| 4 |
+// +build ignore |
|
| 5 |
+ |
|
| 6 |
+/* |
|
| 7 |
+mksyscall_windows generates windows system call bodies |
|
| 8 |
+ |
|
| 9 |
+It parses all files specified on command line containing function |
|
| 10 |
+prototypes (like syscall_windows.go) and prints system call bodies |
|
| 11 |
+to standard output. |
|
| 12 |
+ |
|
| 13 |
+The prototypes are marked by lines beginning with "//sys" and read |
|
| 14 |
+like func declarations if //sys is replaced by func, but: |
|
| 15 |
+ |
|
| 16 |
+* The parameter lists must give a name for each argument. This |
|
| 17 |
+ includes return parameters. |
|
| 18 |
+ |
|
| 19 |
+* The parameter lists must give a type for each argument: |
|
| 20 |
+ the (x, y, z int) shorthand is not allowed. |
|
| 21 |
+ |
|
| 22 |
+* If the return parameter is an error number, it must be named err. |
|
| 23 |
+ |
|
| 24 |
+* If go func name needs to be different from it's winapi dll name, |
|
| 25 |
+ the winapi name could be specified at the end, after "=" sign, like |
|
| 26 |
+ //sys LoadLibrary(libname string) (handle uint32, err error) = LoadLibraryA |
|
| 27 |
+ |
|
| 28 |
+* Each function that returns err needs to supply a condition, that |
|
| 29 |
+ return value of winapi will be tested against to detect failure. |
|
| 30 |
+ This would set err to windows "last-error", otherwise it will be nil. |
|
| 31 |
+ The value can be provided at end of //sys declaration, like |
|
| 32 |
+ //sys LoadLibrary(libname string) (handle uint32, err error) [failretval==-1] = LoadLibraryA |
|
| 33 |
+ and is [failretval==0] by default. |
|
| 34 |
+ |
|
| 35 |
+Usage: |
|
| 36 |
+ mksyscall_windows [flags] [path ...] |
|
| 37 |
+ |
|
| 38 |
+The flags are: |
|
| 39 |
+ -output |
|
| 40 |
+ Specify output file name (outputs to console if blank). |
|
| 41 |
+ -trace |
|
| 42 |
+ Generate print statement after every syscall. |
|
| 43 |
+*/ |
|
| 44 |
+package main |
|
| 45 |
+ |
|
| 46 |
+import ( |
|
| 47 |
+ "bufio" |
|
| 48 |
+ "bytes" |
|
| 49 |
+ "errors" |
|
| 50 |
+ "flag" |
|
| 51 |
+ "fmt" |
|
| 52 |
+ "go/format" |
|
| 53 |
+ "go/parser" |
|
| 54 |
+ "go/token" |
|
| 55 |
+ "io" |
|
| 56 |
+ "io/ioutil" |
|
| 57 |
+ "log" |
|
| 58 |
+ "os" |
|
| 59 |
+ "strconv" |
|
| 60 |
+ "strings" |
|
| 61 |
+ "text/template" |
|
| 62 |
+) |
|
| 63 |
+ |
|
| 64 |
+var ( |
|
| 65 |
+ filename = flag.String("output", "", "output file name (standard output if omitted)")
|
|
| 66 |
+ printTraceFlag = flag.Bool("trace", false, "generate print statement after every syscall")
|
|
| 67 |
+) |
|
| 68 |
+ |
|
| 69 |
+func trim(s string) string {
|
|
| 70 |
+ return strings.Trim(s, " \t") |
|
| 71 |
+} |
|
| 72 |
+ |
|
| 73 |
+var packageName string |
|
| 74 |
+ |
|
| 75 |
+func packagename() string {
|
|
| 76 |
+ return packageName |
|
| 77 |
+} |
|
| 78 |
+ |
|
| 79 |
+func syscalldot() string {
|
|
| 80 |
+ if packageName == "syscall" {
|
|
| 81 |
+ return "" |
|
| 82 |
+ } |
|
| 83 |
+ return "syscall." |
|
| 84 |
+} |
|
| 85 |
+ |
|
| 86 |
+// Param is function parameter |
|
| 87 |
+type Param struct {
|
|
| 88 |
+ Name string |
|
| 89 |
+ Type string |
|
| 90 |
+ fn *Fn |
|
| 91 |
+ tmpVarIdx int |
|
| 92 |
+} |
|
| 93 |
+ |
|
| 94 |
+// tmpVar returns temp variable name that will be used to represent p during syscall. |
|
| 95 |
+func (p *Param) tmpVar() string {
|
|
| 96 |
+ if p.tmpVarIdx < 0 {
|
|
| 97 |
+ p.tmpVarIdx = p.fn.curTmpVarIdx |
|
| 98 |
+ p.fn.curTmpVarIdx++ |
|
| 99 |
+ } |
|
| 100 |
+ return fmt.Sprintf("_p%d", p.tmpVarIdx)
|
|
| 101 |
+} |
|
| 102 |
+ |
|
| 103 |
+// BoolTmpVarCode returns source code for bool temp variable. |
|
| 104 |
+func (p *Param) BoolTmpVarCode() string {
|
|
| 105 |
+ const code = `var %s uint32 |
|
| 106 |
+ if %s {
|
|
| 107 |
+ %s = 1 |
|
| 108 |
+ } else {
|
|
| 109 |
+ %s = 0 |
|
| 110 |
+ }` |
|
| 111 |
+ tmp := p.tmpVar() |
|
| 112 |
+ return fmt.Sprintf(code, tmp, p.Name, tmp, tmp) |
|
| 113 |
+} |
|
| 114 |
+ |
|
| 115 |
+// SliceTmpVarCode returns source code for slice temp variable. |
|
| 116 |
+func (p *Param) SliceTmpVarCode() string {
|
|
| 117 |
+ const code = `var %s *%s |
|
| 118 |
+ if len(%s) > 0 {
|
|
| 119 |
+ %s = &%s[0] |
|
| 120 |
+ }` |
|
| 121 |
+ tmp := p.tmpVar() |
|
| 122 |
+ return fmt.Sprintf(code, tmp, p.Type[2:], p.Name, tmp, p.Name) |
|
| 123 |
+} |
|
| 124 |
+ |
|
| 125 |
+// StringTmpVarCode returns source code for string temp variable. |
|
| 126 |
+func (p *Param) StringTmpVarCode() string {
|
|
| 127 |
+ errvar := p.fn.Rets.ErrorVarName() |
|
| 128 |
+ if errvar == "" {
|
|
| 129 |
+ errvar = "_" |
|
| 130 |
+ } |
|
| 131 |
+ tmp := p.tmpVar() |
|
| 132 |
+ const code = `var %s %s |
|
| 133 |
+ %s, %s = %s(%s)` |
|
| 134 |
+ s := fmt.Sprintf(code, tmp, p.fn.StrconvType(), tmp, errvar, p.fn.StrconvFunc(), p.Name) |
|
| 135 |
+ if errvar == "-" {
|
|
| 136 |
+ return s |
|
| 137 |
+ } |
|
| 138 |
+ const morecode = ` |
|
| 139 |
+ if %s != nil {
|
|
| 140 |
+ return |
|
| 141 |
+ }` |
|
| 142 |
+ return s + fmt.Sprintf(morecode, errvar) |
|
| 143 |
+} |
|
| 144 |
+ |
|
| 145 |
+// TmpVarCode returns source code for temp variable. |
|
| 146 |
+func (p *Param) TmpVarCode() string {
|
|
| 147 |
+ switch {
|
|
| 148 |
+ case p.Type == "bool": |
|
| 149 |
+ return p.BoolTmpVarCode() |
|
| 150 |
+ case strings.HasPrefix(p.Type, "[]"): |
|
| 151 |
+ return p.SliceTmpVarCode() |
|
| 152 |
+ default: |
|
| 153 |
+ return "" |
|
| 154 |
+ } |
|
| 155 |
+} |
|
| 156 |
+ |
|
| 157 |
+// TmpVarHelperCode returns source code for helper's temp variable. |
|
| 158 |
+func (p *Param) TmpVarHelperCode() string {
|
|
| 159 |
+ if p.Type != "string" {
|
|
| 160 |
+ return "" |
|
| 161 |
+ } |
|
| 162 |
+ return p.StringTmpVarCode() |
|
| 163 |
+} |
|
| 164 |
+ |
|
| 165 |
+// SyscallArgList returns source code fragments representing p parameter |
|
| 166 |
+// in syscall. Slices are translated into 2 syscall parameters: pointer to |
|
| 167 |
+// the first element and length. |
|
| 168 |
+func (p *Param) SyscallArgList() []string {
|
|
| 169 |
+ t := p.HelperType() |
|
| 170 |
+ var s string |
|
| 171 |
+ switch {
|
|
| 172 |
+ case t[0] == '*': |
|
| 173 |
+ s = fmt.Sprintf("unsafe.Pointer(%s)", p.Name)
|
|
| 174 |
+ case t == "bool": |
|
| 175 |
+ s = p.tmpVar() |
|
| 176 |
+ case strings.HasPrefix(t, "[]"): |
|
| 177 |
+ return []string{
|
|
| 178 |
+ fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.tmpVar()),
|
|
| 179 |
+ fmt.Sprintf("uintptr(len(%s))", p.Name),
|
|
| 180 |
+ } |
|
| 181 |
+ default: |
|
| 182 |
+ s = p.Name |
|
| 183 |
+ } |
|
| 184 |
+ return []string{fmt.Sprintf("uintptr(%s)", s)}
|
|
| 185 |
+} |
|
| 186 |
+ |
|
| 187 |
+// IsError determines if p parameter is used to return error. |
|
| 188 |
+func (p *Param) IsError() bool {
|
|
| 189 |
+ return p.Name == "err" && p.Type == "error" |
|
| 190 |
+} |
|
| 191 |
+ |
|
| 192 |
+// HelperType returns type of parameter p used in helper function. |
|
| 193 |
+func (p *Param) HelperType() string {
|
|
| 194 |
+ if p.Type == "string" {
|
|
| 195 |
+ return p.fn.StrconvType() |
|
| 196 |
+ } |
|
| 197 |
+ return p.Type |
|
| 198 |
+} |
|
| 199 |
+ |
|
| 200 |
+// join concatenates parameters ps into a string with sep separator. |
|
| 201 |
+// Each parameter is converted into string by applying fn to it |
|
| 202 |
+// before conversion. |
|
| 203 |
+func join(ps []*Param, fn func(*Param) string, sep string) string {
|
|
| 204 |
+ if len(ps) == 0 {
|
|
| 205 |
+ return "" |
|
| 206 |
+ } |
|
| 207 |
+ a := make([]string, 0) |
|
| 208 |
+ for _, p := range ps {
|
|
| 209 |
+ a = append(a, fn(p)) |
|
| 210 |
+ } |
|
| 211 |
+ return strings.Join(a, sep) |
|
| 212 |
+} |
|
| 213 |
+ |
|
| 214 |
+// Rets describes function return parameters. |
|
| 215 |
+type Rets struct {
|
|
| 216 |
+ Name string |
|
| 217 |
+ Type string |
|
| 218 |
+ ReturnsError bool |
|
| 219 |
+ FailCond string |
|
| 220 |
+} |
|
| 221 |
+ |
|
| 222 |
+// ErrorVarName returns error variable name for r. |
|
| 223 |
+func (r *Rets) ErrorVarName() string {
|
|
| 224 |
+ if r.ReturnsError {
|
|
| 225 |
+ return "err" |
|
| 226 |
+ } |
|
| 227 |
+ if r.Type == "error" {
|
|
| 228 |
+ return r.Name |
|
| 229 |
+ } |
|
| 230 |
+ return "" |
|
| 231 |
+} |
|
| 232 |
+ |
|
| 233 |
+// ToParams converts r into slice of *Param. |
|
| 234 |
+func (r *Rets) ToParams() []*Param {
|
|
| 235 |
+ ps := make([]*Param, 0) |
|
| 236 |
+ if len(r.Name) > 0 {
|
|
| 237 |
+ ps = append(ps, &Param{Name: r.Name, Type: r.Type})
|
|
| 238 |
+ } |
|
| 239 |
+ if r.ReturnsError {
|
|
| 240 |
+ ps = append(ps, &Param{Name: "err", Type: "error"})
|
|
| 241 |
+ } |
|
| 242 |
+ return ps |
|
| 243 |
+} |
|
| 244 |
+ |
|
| 245 |
+// List returns source code of syscall return parameters. |
|
| 246 |
+func (r *Rets) List() string {
|
|
| 247 |
+ s := join(r.ToParams(), func(p *Param) string { return p.Name + " " + p.Type }, ", ")
|
|
| 248 |
+ if len(s) > 0 {
|
|
| 249 |
+ s = "(" + s + ")"
|
|
| 250 |
+ } |
|
| 251 |
+ return s |
|
| 252 |
+} |
|
| 253 |
+ |
|
| 254 |
+// PrintList returns source code of trace printing part correspondent |
|
| 255 |
+// to syscall return values. |
|
| 256 |
+func (r *Rets) PrintList() string {
|
|
| 257 |
+ return join(r.ToParams(), func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `)
|
|
| 258 |
+} |
|
| 259 |
+ |
|
| 260 |
+// SetReturnValuesCode returns source code that accepts syscall return values. |
|
| 261 |
+func (r *Rets) SetReturnValuesCode() string {
|
|
| 262 |
+ if r.Name == "" && !r.ReturnsError {
|
|
| 263 |
+ return "" |
|
| 264 |
+ } |
|
| 265 |
+ retvar := "r0" |
|
| 266 |
+ if r.Name == "" {
|
|
| 267 |
+ retvar = "r1" |
|
| 268 |
+ } |
|
| 269 |
+ errvar := "_" |
|
| 270 |
+ if r.ReturnsError {
|
|
| 271 |
+ errvar = "e1" |
|
| 272 |
+ } |
|
| 273 |
+ return fmt.Sprintf("%s, _, %s := ", retvar, errvar)
|
|
| 274 |
+} |
|
| 275 |
+ |
|
| 276 |
+func (r *Rets) useLongHandleErrorCode(retvar string) string {
|
|
| 277 |
+ const code = `if %s {
|
|
| 278 |
+ if e1 != 0 {
|
|
| 279 |
+ err = error(e1) |
|
| 280 |
+ } else {
|
|
| 281 |
+ err = %sEINVAL |
|
| 282 |
+ } |
|
| 283 |
+ }` |
|
| 284 |
+ cond := retvar + " == 0" |
|
| 285 |
+ if r.FailCond != "" {
|
|
| 286 |
+ cond = strings.Replace(r.FailCond, "failretval", retvar, 1) |
|
| 287 |
+ } |
|
| 288 |
+ return fmt.Sprintf(code, cond, syscalldot()) |
|
| 289 |
+} |
|
| 290 |
+ |
|
| 291 |
+// SetErrorCode returns source code that sets return parameters. |
|
| 292 |
+func (r *Rets) SetErrorCode() string {
|
|
| 293 |
+ const code = `if r0 != 0 {
|
|
| 294 |
+ %s = %sErrno(r0) |
|
| 295 |
+ }` |
|
| 296 |
+ if r.Name == "" && !r.ReturnsError {
|
|
| 297 |
+ return "" |
|
| 298 |
+ } |
|
| 299 |
+ if r.Name == "" {
|
|
| 300 |
+ return r.useLongHandleErrorCode("r1")
|
|
| 301 |
+ } |
|
| 302 |
+ if r.Type == "error" {
|
|
| 303 |
+ return fmt.Sprintf(code, r.Name, syscalldot()) |
|
| 304 |
+ } |
|
| 305 |
+ s := "" |
|
| 306 |
+ switch {
|
|
| 307 |
+ case r.Type[0] == '*': |
|
| 308 |
+ s = fmt.Sprintf("%s = (%s)(unsafe.Pointer(r0))", r.Name, r.Type)
|
|
| 309 |
+ case r.Type == "bool": |
|
| 310 |
+ s = fmt.Sprintf("%s = r0 != 0", r.Name)
|
|
| 311 |
+ default: |
|
| 312 |
+ s = fmt.Sprintf("%s = %s(r0)", r.Name, r.Type)
|
|
| 313 |
+ } |
|
| 314 |
+ if !r.ReturnsError {
|
|
| 315 |
+ return s |
|
| 316 |
+ } |
|
| 317 |
+ return s + "\n\t" + r.useLongHandleErrorCode(r.Name) |
|
| 318 |
+} |
|
| 319 |
+ |
|
| 320 |
+// Fn describes syscall function. |
|
| 321 |
+type Fn struct {
|
|
| 322 |
+ Name string |
|
| 323 |
+ Params []*Param |
|
| 324 |
+ Rets *Rets |
|
| 325 |
+ PrintTrace bool |
|
| 326 |
+ confirmproc bool |
|
| 327 |
+ dllname string |
|
| 328 |
+ dllfuncname string |
|
| 329 |
+ src string |
|
| 330 |
+ // TODO: get rid of this field and just use parameter index instead |
|
| 331 |
+ curTmpVarIdx int // insure tmp variables have uniq names |
|
| 332 |
+} |
|
| 333 |
+ |
|
| 334 |
+// extractParams parses s to extract function parameters. |
|
| 335 |
+func extractParams(s string, f *Fn) ([]*Param, error) {
|
|
| 336 |
+ s = trim(s) |
|
| 337 |
+ if s == "" {
|
|
| 338 |
+ return nil, nil |
|
| 339 |
+ } |
|
| 340 |
+ a := strings.Split(s, ",") |
|
| 341 |
+ ps := make([]*Param, len(a)) |
|
| 342 |
+ for i := range ps {
|
|
| 343 |
+ s2 := trim(a[i]) |
|
| 344 |
+ b := strings.Split(s2, " ") |
|
| 345 |
+ if len(b) != 2 {
|
|
| 346 |
+ b = strings.Split(s2, "\t") |
|
| 347 |
+ if len(b) != 2 {
|
|
| 348 |
+ return nil, errors.New("Could not extract function parameter from \"" + s2 + "\"")
|
|
| 349 |
+ } |
|
| 350 |
+ } |
|
| 351 |
+ ps[i] = &Param{
|
|
| 352 |
+ Name: trim(b[0]), |
|
| 353 |
+ Type: trim(b[1]), |
|
| 354 |
+ fn: f, |
|
| 355 |
+ tmpVarIdx: -1, |
|
| 356 |
+ } |
|
| 357 |
+ } |
|
| 358 |
+ return ps, nil |
|
| 359 |
+} |
|
| 360 |
+ |
|
| 361 |
+// extractSection extracts text out of string s starting after start |
|
| 362 |
+// and ending just before end. found return value will indicate success, |
|
| 363 |
+// and prefix, body and suffix will contain correspondent parts of string s. |
|
| 364 |
+func extractSection(s string, start, end rune) (prefix, body, suffix string, found bool) {
|
|
| 365 |
+ s = trim(s) |
|
| 366 |
+ if strings.HasPrefix(s, string(start)) {
|
|
| 367 |
+ // no prefix |
|
| 368 |
+ body = s[1:] |
|
| 369 |
+ } else {
|
|
| 370 |
+ a := strings.SplitN(s, string(start), 2) |
|
| 371 |
+ if len(a) != 2 {
|
|
| 372 |
+ return "", "", s, false |
|
| 373 |
+ } |
|
| 374 |
+ prefix = a[0] |
|
| 375 |
+ body = a[1] |
|
| 376 |
+ } |
|
| 377 |
+ a := strings.SplitN(body, string(end), 2) |
|
| 378 |
+ if len(a) != 2 {
|
|
| 379 |
+ return "", "", "", false |
|
| 380 |
+ } |
|
| 381 |
+ return prefix, a[0], a[1], true |
|
| 382 |
+} |
|
| 383 |
+ |
|
| 384 |
+// newFn parses string s and return created function Fn. |
|
| 385 |
+func newFn(s string) (*Fn, error) {
|
|
| 386 |
+ s = trim(s) |
|
| 387 |
+ f := &Fn{
|
|
| 388 |
+ Rets: &Rets{},
|
|
| 389 |
+ src: s, |
|
| 390 |
+ PrintTrace: *printTraceFlag, |
|
| 391 |
+ } |
|
| 392 |
+ // function name and args |
|
| 393 |
+ prefix, body, s, found := extractSection(s, '(', ')')
|
|
| 394 |
+ if !found || prefix == "" {
|
|
| 395 |
+ return nil, errors.New("Could not extract function name and parameters from \"" + f.src + "\"")
|
|
| 396 |
+ } |
|
| 397 |
+ f.Name = prefix |
|
| 398 |
+ var err error |
|
| 399 |
+ f.Params, err = extractParams(body, f) |
|
| 400 |
+ if err != nil {
|
|
| 401 |
+ return nil, err |
|
| 402 |
+ } |
|
| 403 |
+ // return values |
|
| 404 |
+ _, body, s, found = extractSection(s, '(', ')')
|
|
| 405 |
+ if found {
|
|
| 406 |
+ r, err := extractParams(body, f) |
|
| 407 |
+ if err != nil {
|
|
| 408 |
+ return nil, err |
|
| 409 |
+ } |
|
| 410 |
+ switch len(r) {
|
|
| 411 |
+ case 0: |
|
| 412 |
+ case 1: |
|
| 413 |
+ if r[0].IsError() {
|
|
| 414 |
+ f.Rets.ReturnsError = true |
|
| 415 |
+ } else {
|
|
| 416 |
+ f.Rets.Name = r[0].Name |
|
| 417 |
+ f.Rets.Type = r[0].Type |
|
| 418 |
+ } |
|
| 419 |
+ case 2: |
|
| 420 |
+ if !r[1].IsError() {
|
|
| 421 |
+ return nil, errors.New("Only last windows error is allowed as second return value in \"" + f.src + "\"")
|
|
| 422 |
+ } |
|
| 423 |
+ f.Rets.ReturnsError = true |
|
| 424 |
+ f.Rets.Name = r[0].Name |
|
| 425 |
+ f.Rets.Type = r[0].Type |
|
| 426 |
+ default: |
|
| 427 |
+ return nil, errors.New("Too many return values in \"" + f.src + "\"")
|
|
| 428 |
+ } |
|
| 429 |
+ } |
|
| 430 |
+ // fail condition |
|
| 431 |
+ _, body, s, found = extractSection(s, '[', ']') |
|
| 432 |
+ if found {
|
|
| 433 |
+ f.Rets.FailCond = body |
|
| 434 |
+ } |
|
| 435 |
+ // dll and dll function names |
|
| 436 |
+ s = trim(s) |
|
| 437 |
+ if s == "" {
|
|
| 438 |
+ return f, nil |
|
| 439 |
+ } |
|
| 440 |
+ if !strings.HasPrefix(s, "=") {
|
|
| 441 |
+ return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
|
|
| 442 |
+ } |
|
| 443 |
+ s = trim(s[1:]) |
|
| 444 |
+ a := strings.Split(s, ".") |
|
| 445 |
+ switch len(a) {
|
|
| 446 |
+ case 1: |
|
| 447 |
+ f.dllfuncname = a[0] |
|
| 448 |
+ case 2: |
|
| 449 |
+ f.dllname = a[0] |
|
| 450 |
+ f.dllfuncname = a[1] |
|
| 451 |
+ default: |
|
| 452 |
+ return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
|
|
| 453 |
+ } |
|
| 454 |
+ if f.dllfuncname[len(f.dllfuncname)-1] == '?' {
|
|
| 455 |
+ f.confirmproc = true |
|
| 456 |
+ f.dllfuncname = f.dllfuncname[0 : len(f.dllfuncname)-1] |
|
| 457 |
+ } |
|
| 458 |
+ return f, nil |
|
| 459 |
+} |
|
| 460 |
+ |
|
| 461 |
+// DLLName returns DLL name for function f. |
|
| 462 |
+func (f *Fn) DLLName() string {
|
|
| 463 |
+ if f.dllname == "" {
|
|
| 464 |
+ return "kernel32" |
|
| 465 |
+ } |
|
| 466 |
+ return f.dllname |
|
| 467 |
+} |
|
| 468 |
+ |
|
| 469 |
+// DLLName returns DLL function name for function f. |
|
| 470 |
+func (f *Fn) DLLFuncName() string {
|
|
| 471 |
+ if f.dllfuncname == "" {
|
|
| 472 |
+ return f.Name |
|
| 473 |
+ } |
|
| 474 |
+ return f.dllfuncname |
|
| 475 |
+} |
|
| 476 |
+ |
|
| 477 |
+func (f *Fn) ConfirmProc() bool {
|
|
| 478 |
+ return f.confirmproc |
|
| 479 |
+} |
|
| 480 |
+ |
|
| 481 |
+// ParamList returns source code for function f parameters. |
|
| 482 |
+func (f *Fn) ParamList() string {
|
|
| 483 |
+ return join(f.Params, func(p *Param) string { return p.Name + " " + p.Type }, ", ")
|
|
| 484 |
+} |
|
| 485 |
+ |
|
| 486 |
+// HelperParamList returns source code for helper function f parameters. |
|
| 487 |
+func (f *Fn) HelperParamList() string {
|
|
| 488 |
+ return join(f.Params, func(p *Param) string { return p.Name + " " + p.HelperType() }, ", ")
|
|
| 489 |
+} |
|
| 490 |
+ |
|
| 491 |
+// ParamPrintList returns source code of trace printing part correspondent |
|
| 492 |
+// to syscall input parameters. |
|
| 493 |
+func (f *Fn) ParamPrintList() string {
|
|
| 494 |
+ return join(f.Params, func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `)
|
|
| 495 |
+} |
|
| 496 |
+ |
|
| 497 |
+// ParamCount return number of syscall parameters for function f. |
|
| 498 |
+func (f *Fn) ParamCount() int {
|
|
| 499 |
+ n := 0 |
|
| 500 |
+ for _, p := range f.Params {
|
|
| 501 |
+ n += len(p.SyscallArgList()) |
|
| 502 |
+ } |
|
| 503 |
+ return n |
|
| 504 |
+} |
|
| 505 |
+ |
|
| 506 |
+// SyscallParamCount determines which version of Syscall/Syscall6/Syscall9/... |
|
| 507 |
+// to use. It returns parameter count for correspondent SyscallX function. |
|
| 508 |
+func (f *Fn) SyscallParamCount() int {
|
|
| 509 |
+ n := f.ParamCount() |
|
| 510 |
+ switch {
|
|
| 511 |
+ case n <= 3: |
|
| 512 |
+ return 3 |
|
| 513 |
+ case n <= 6: |
|
| 514 |
+ return 6 |
|
| 515 |
+ case n <= 9: |
|
| 516 |
+ return 9 |
|
| 517 |
+ case n <= 12: |
|
| 518 |
+ return 12 |
|
| 519 |
+ case n <= 15: |
|
| 520 |
+ return 15 |
|
| 521 |
+ default: |
|
| 522 |
+ panic("too many arguments to system call")
|
|
| 523 |
+ } |
|
| 524 |
+} |
|
| 525 |
+ |
|
| 526 |
+// Syscall determines which SyscallX function to use for function f. |
|
| 527 |
+func (f *Fn) Syscall() string {
|
|
| 528 |
+ c := f.SyscallParamCount() |
|
| 529 |
+ if c == 3 {
|
|
| 530 |
+ return syscalldot() + "Syscall" |
|
| 531 |
+ } |
|
| 532 |
+ return syscalldot() + "Syscall" + strconv.Itoa(c) |
|
| 533 |
+} |
|
| 534 |
+ |
|
| 535 |
+// SyscallParamList returns source code for SyscallX parameters for function f. |
|
| 536 |
+func (f *Fn) SyscallParamList() string {
|
|
| 537 |
+ a := make([]string, 0) |
|
| 538 |
+ for _, p := range f.Params {
|
|
| 539 |
+ a = append(a, p.SyscallArgList()...) |
|
| 540 |
+ } |
|
| 541 |
+ for len(a) < f.SyscallParamCount() {
|
|
| 542 |
+ a = append(a, "0") |
|
| 543 |
+ } |
|
| 544 |
+ return strings.Join(a, ", ") |
|
| 545 |
+} |
|
| 546 |
+ |
|
| 547 |
+// HelperCallParamList returns source code of call into function f helper. |
|
| 548 |
+func (f *Fn) HelperCallParamList() string {
|
|
| 549 |
+ a := make([]string, 0, len(f.Params)) |
|
| 550 |
+ for _, p := range f.Params {
|
|
| 551 |
+ s := p.Name |
|
| 552 |
+ if p.Type == "string" {
|
|
| 553 |
+ s = p.tmpVar() |
|
| 554 |
+ } |
|
| 555 |
+ a = append(a, s) |
|
| 556 |
+ } |
|
| 557 |
+ return strings.Join(a, ", ") |
|
| 558 |
+} |
|
| 559 |
+ |
|
| 560 |
+// IsUTF16 is true, if f is W (utf16) function. It is false |
|
| 561 |
+// for all A (ascii) functions. |
|
| 562 |
+func (_ *Fn) IsUTF16() bool {
|
|
| 563 |
+ return true |
|
| 564 |
+} |
|
| 565 |
+ |
|
| 566 |
+// StrconvFunc returns name of Go string to OS string function for f. |
|
| 567 |
+func (f *Fn) StrconvFunc() string {
|
|
| 568 |
+ if f.IsUTF16() {
|
|
| 569 |
+ return syscalldot() + "UTF16PtrFromString" |
|
| 570 |
+ } |
|
| 571 |
+ return syscalldot() + "BytePtrFromString" |
|
| 572 |
+} |
|
| 573 |
+ |
|
| 574 |
+// StrconvType returns Go type name used for OS string for f. |
|
| 575 |
+func (f *Fn) StrconvType() string {
|
|
| 576 |
+ if f.IsUTF16() {
|
|
| 577 |
+ return "*uint16" |
|
| 578 |
+ } |
|
| 579 |
+ return "*byte" |
|
| 580 |
+} |
|
| 581 |
+ |
|
| 582 |
+// HasStringParam is true, if f has at least one string parameter. |
|
| 583 |
+// Otherwise it is false. |
|
| 584 |
+func (f *Fn) HasStringParam() bool {
|
|
| 585 |
+ for _, p := range f.Params {
|
|
| 586 |
+ if p.Type == "string" {
|
|
| 587 |
+ return true |
|
| 588 |
+ } |
|
| 589 |
+ } |
|
| 590 |
+ return false |
|
| 591 |
+} |
|
| 592 |
+ |
|
| 593 |
+// HelperName returns name of function f helper. |
|
| 594 |
+func (f *Fn) HelperName() string {
|
|
| 595 |
+ if !f.HasStringParam() {
|
|
| 596 |
+ return f.Name |
|
| 597 |
+ } |
|
| 598 |
+ return "_" + f.Name |
|
| 599 |
+} |
|
| 600 |
+ |
|
| 601 |
+// Source files and functions. |
|
| 602 |
+type Source struct {
|
|
| 603 |
+ Funcs []*Fn |
|
| 604 |
+ Files []string |
|
| 605 |
+} |
|
| 606 |
+ |
|
| 607 |
+// ParseFiles parses files listed in fs and extracts all syscall |
|
| 608 |
+// functions listed in sys comments. It returns source files |
|
| 609 |
+// and functions collection *Source if successful. |
|
| 610 |
+func ParseFiles(fs []string) (*Source, error) {
|
|
| 611 |
+ src := &Source{
|
|
| 612 |
+ Funcs: make([]*Fn, 0), |
|
| 613 |
+ Files: make([]string, 0), |
|
| 614 |
+ } |
|
| 615 |
+ for _, file := range fs {
|
|
| 616 |
+ if err := src.ParseFile(file); err != nil {
|
|
| 617 |
+ return nil, err |
|
| 618 |
+ } |
|
| 619 |
+ } |
|
| 620 |
+ return src, nil |
|
| 621 |
+} |
|
| 622 |
+ |
|
| 623 |
+// DLLs return dll names for a source set src. |
|
| 624 |
+func (src *Source) DLLs() []string {
|
|
| 625 |
+ uniq := make(map[string]bool) |
|
| 626 |
+ r := make([]string, 0) |
|
| 627 |
+ for _, f := range src.Funcs {
|
|
| 628 |
+ name := f.DLLName() |
|
| 629 |
+ if _, found := uniq[name]; !found {
|
|
| 630 |
+ uniq[name] = true |
|
| 631 |
+ r = append(r, name) |
|
| 632 |
+ } |
|
| 633 |
+ } |
|
| 634 |
+ return r |
|
| 635 |
+} |
|
| 636 |
+ |
|
| 637 |
+// ParseFile adds additional file path to a source set src. |
|
| 638 |
+func (src *Source) ParseFile(path string) error {
|
|
| 639 |
+ file, err := os.Open(path) |
|
| 640 |
+ if err != nil {
|
|
| 641 |
+ return err |
|
| 642 |
+ } |
|
| 643 |
+ defer file.Close() |
|
| 644 |
+ |
|
| 645 |
+ s := bufio.NewScanner(file) |
|
| 646 |
+ for s.Scan() {
|
|
| 647 |
+ t := trim(s.Text()) |
|
| 648 |
+ if len(t) < 7 {
|
|
| 649 |
+ continue |
|
| 650 |
+ } |
|
| 651 |
+ if !strings.HasPrefix(t, "//sys") {
|
|
| 652 |
+ continue |
|
| 653 |
+ } |
|
| 654 |
+ t = t[5:] |
|
| 655 |
+ if !(t[0] == ' ' || t[0] == '\t') {
|
|
| 656 |
+ continue |
|
| 657 |
+ } |
|
| 658 |
+ f, err := newFn(t[1:]) |
|
| 659 |
+ if err != nil {
|
|
| 660 |
+ return err |
|
| 661 |
+ } |
|
| 662 |
+ src.Funcs = append(src.Funcs, f) |
|
| 663 |
+ } |
|
| 664 |
+ if err := s.Err(); err != nil {
|
|
| 665 |
+ return err |
|
| 666 |
+ } |
|
| 667 |
+ src.Files = append(src.Files, path) |
|
| 668 |
+ |
|
| 669 |
+ // get package name |
|
| 670 |
+ fset := token.NewFileSet() |
|
| 671 |
+ _, err = file.Seek(0, 0) |
|
| 672 |
+ if err != nil {
|
|
| 673 |
+ return err |
|
| 674 |
+ } |
|
| 675 |
+ pkg, err := parser.ParseFile(fset, "", file, parser.PackageClauseOnly) |
|
| 676 |
+ if err != nil {
|
|
| 677 |
+ return err |
|
| 678 |
+ } |
|
| 679 |
+ packageName = pkg.Name.Name |
|
| 680 |
+ |
|
| 681 |
+ return nil |
|
| 682 |
+} |
|
| 683 |
+ |
|
| 684 |
+// Generate output source file from a source set src. |
|
| 685 |
+func (src *Source) Generate(w io.Writer) error {
|
|
| 686 |
+ funcMap := template.FuncMap{
|
|
| 687 |
+ "packagename": packagename, |
|
| 688 |
+ "syscalldot": syscalldot, |
|
| 689 |
+ } |
|
| 690 |
+ t := template.Must(template.New("main").Funcs(funcMap).Parse(srcTemplate))
|
|
| 691 |
+ err := t.Execute(w, src) |
|
| 692 |
+ if err != nil {
|
|
| 693 |
+ return errors.New("Failed to execute template: " + err.Error())
|
|
| 694 |
+ } |
|
| 695 |
+ return nil |
|
| 696 |
+} |
|
| 697 |
+ |
|
| 698 |
+func usage() {
|
|
| 699 |
+ fmt.Fprintf(os.Stderr, "usage: mksyscall_windows [flags] [path ...]\n") |
|
| 700 |
+ flag.PrintDefaults() |
|
| 701 |
+ os.Exit(1) |
|
| 702 |
+} |
|
| 703 |
+ |
|
| 704 |
+func main() {
|
|
| 705 |
+ flag.Usage = usage |
|
| 706 |
+ flag.Parse() |
|
| 707 |
+ if len(flag.Args()) <= 0 {
|
|
| 708 |
+ fmt.Fprintf(os.Stderr, "no files to parse provided\n") |
|
| 709 |
+ usage() |
|
| 710 |
+ } |
|
| 711 |
+ |
|
| 712 |
+ src, err := ParseFiles(flag.Args()) |
|
| 713 |
+ if err != nil {
|
|
| 714 |
+ log.Fatal(err) |
|
| 715 |
+ } |
|
| 716 |
+ |
|
| 717 |
+ var buf bytes.Buffer |
|
| 718 |
+ if err := src.Generate(&buf); err != nil {
|
|
| 719 |
+ log.Fatal(err) |
|
| 720 |
+ } |
|
| 721 |
+ |
|
| 722 |
+ data, err := format.Source(buf.Bytes()) |
|
| 723 |
+ if err != nil {
|
|
| 724 |
+ log.Fatal(err) |
|
| 725 |
+ } |
|
| 726 |
+ if *filename == "" {
|
|
| 727 |
+ _, err = os.Stdout.Write(data) |
|
| 728 |
+ } else {
|
|
| 729 |
+ err = ioutil.WriteFile(*filename, data, 0644) |
|
| 730 |
+ } |
|
| 731 |
+ if err != nil {
|
|
| 732 |
+ log.Fatal(err) |
|
| 733 |
+ } |
|
| 734 |
+} |
|
| 735 |
+ |
|
| 736 |
+// TODO: use println instead to print in the following template |
|
| 737 |
+const srcTemplate = ` |
|
| 738 |
+ |
|
| 739 |
+{{define "main"}}// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
|
|
| 740 |
+ |
|
| 741 |
+package {{packagename}}
|
|
| 742 |
+ |
|
| 743 |
+import "unsafe"{{if syscalldot}}
|
|
| 744 |
+import "syscall"{{end}}
|
|
| 745 |
+ |
|
| 746 |
+var _ unsafe.Pointer |
|
| 747 |
+ |
|
| 748 |
+var ( |
|
| 749 |
+{{template "dlls" .}}
|
|
| 750 |
+{{template "funcnames" .}})
|
|
| 751 |
+{{range .Funcs}}{{if .HasStringParam}}{{template "helperbody" .}}{{end}}{{template "funcbody" .}}{{end}}
|
|
| 752 |
+{{end}}
|
|
| 753 |
+ |
|
| 754 |
+{{/* help functions */}}
|
|
| 755 |
+ |
|
| 756 |
+{{define "dlls"}}{{range .DLLs}} mod{{.}} = {{syscalldot}}NewLazyDLL("{{.}}.dll")
|
|
| 757 |
+{{end}}{{end}}
|
|
| 758 |
+ |
|
| 759 |
+{{define "funcnames"}}{{range .Funcs}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}")
|
|
| 760 |
+{{end}}{{end}}
|
|
| 761 |
+ |
|
| 762 |
+{{define "helperbody"}}
|
|
| 763 |
+func {{.Name}}({{.ParamList}}) {{template "results" .}}{
|
|
| 764 |
+{{template "helpertmpvars" .}} return {{.HelperName}}({{.HelperCallParamList}})
|
|
| 765 |
+} |
|
| 766 |
+{{end}}
|
|
| 767 |
+ |
|
| 768 |
+{{define "funcbody"}}
|
|
| 769 |
+func {{.HelperName}}({{.HelperParamList}}) {{template "results" .}}{
|
|
| 770 |
+{{template "tmpvars" .}} {{template "syscallcheck" .}}{{template "syscall" .}}
|
|
| 771 |
+{{template "seterror" .}}{{template "printtrace" .}} return
|
|
| 772 |
+} |
|
| 773 |
+{{end}}
|
|
| 774 |
+ |
|
| 775 |
+{{define "helpertmpvars"}}{{range .Params}}{{if .TmpVarHelperCode}} {{.TmpVarHelperCode}}
|
|
| 776 |
+{{end}}{{end}}{{end}}
|
|
| 777 |
+ |
|
| 778 |
+{{define "tmpvars"}}{{range .Params}}{{if .TmpVarCode}} {{.TmpVarCode}}
|
|
| 779 |
+{{end}}{{end}}{{end}}
|
|
| 780 |
+ |
|
| 781 |
+{{define "results"}}{{if .Rets.List}}{{.Rets.List}} {{end}}{{end}}
|
|
| 782 |
+ |
|
| 783 |
+{{define "syscallcheck"}}{{if .ConfirmProc}}if {{.Rets.ErrorVarName}} = proc{{.DLLFuncName}}.Find(); {{.Rets.ErrorVarName}} != nil {
|
|
| 784 |
+ return |
|
| 785 |
+} |
|
| 786 |
+{{end}}{{end}}
|
|
| 787 |
+ |
|
| 788 |
+{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(), {{.ParamCount}}, {{.SyscallParamList}}){{end}}
|
|
| 789 |
+ |
|
| 790 |
+{{define "seterror"}}{{if .Rets.SetErrorCode}} {{.Rets.SetErrorCode}}
|
|
| 791 |
+{{end}}{{end}}
|
|
| 792 |
+ |
|
| 793 |
+{{define "printtrace"}}{{if .PrintTrace}} print("SYSCALL: {{.Name}}(", {{.ParamPrintList}}") (", {{.Rets.PrintList}}")\n")
|
|
| 794 |
+{{end}}{{end}}
|
|
| 795 |
+ |
|
| 796 |
+` |
| 0 | 797 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,280 @@ |
| 0 |
+package winio |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "errors" |
|
| 4 |
+ "net" |
|
| 5 |
+ "os" |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "time" |
|
| 8 |
+ "unsafe" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe |
|
| 12 |
+//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *securityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW |
|
| 13 |
+//sys createFile(name string, access uint32, mode uint32, sa *securityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW |
|
| 14 |
+//sys waitNamedPipe(name string, timeout uint32) (err error) = WaitNamedPipeW |
|
| 15 |
+ |
|
| 16 |
+type securityAttributes struct {
|
|
| 17 |
+ Length uint32 |
|
| 18 |
+ SecurityDescriptor *byte |
|
| 19 |
+ InheritHandle uint32 |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+const ( |
|
| 23 |
+ cERROR_PIPE_BUSY = syscall.Errno(231) |
|
| 24 |
+ cERROR_PIPE_CONNECTED = syscall.Errno(535) |
|
| 25 |
+ cERROR_SEM_TIMEOUT = syscall.Errno(121) |
|
| 26 |
+ |
|
| 27 |
+ cPIPE_ACCESS_DUPLEX = 0x3 |
|
| 28 |
+ cFILE_FLAG_FIRST_PIPE_INSTANCE = 0x80000 |
|
| 29 |
+ cSECURITY_SQOS_PRESENT = 0x100000 |
|
| 30 |
+ cSECURITY_ANONYMOUS = 0 |
|
| 31 |
+ |
|
| 32 |
+ cPIPE_REJECT_REMOTE_CLIENTS = 0x8 |
|
| 33 |
+ |
|
| 34 |
+ cPIPE_UNLIMITED_INSTANCES = 255 |
|
| 35 |
+ |
|
| 36 |
+ cNMPWAIT_USE_DEFAULT_WAIT = 0 |
|
| 37 |
+ cNMPWAIT_NOWAIT = 1 |
|
| 38 |
+) |
|
| 39 |
+ |
|
| 40 |
+var ( |
|
| 41 |
+ // This error should match net.errClosing since docker takes a dependency on its text |
|
| 42 |
+ ErrPipeListenerClosed = errors.New("use of closed network connection")
|
|
| 43 |
+) |
|
| 44 |
+ |
|
| 45 |
+type win32Pipe struct {
|
|
| 46 |
+ *win32File |
|
| 47 |
+ path string |
|
| 48 |
+} |
|
| 49 |
+ |
|
| 50 |
+type pipeAddress string |
|
| 51 |
+ |
|
| 52 |
+func (f *win32Pipe) LocalAddr() net.Addr {
|
|
| 53 |
+ return pipeAddress(f.path) |
|
| 54 |
+} |
|
| 55 |
+ |
|
| 56 |
+func (f *win32Pipe) RemoteAddr() net.Addr {
|
|
| 57 |
+ return pipeAddress(f.path) |
|
| 58 |
+} |
|
| 59 |
+ |
|
| 60 |
+func (f *win32Pipe) SetDeadline(t time.Time) error {
|
|
| 61 |
+ f.SetReadDeadline(t) |
|
| 62 |
+ f.SetWriteDeadline(t) |
|
| 63 |
+ return nil |
|
| 64 |
+} |
|
| 65 |
+ |
|
| 66 |
+func (s pipeAddress) Network() string {
|
|
| 67 |
+ return "pipe" |
|
| 68 |
+} |
|
| 69 |
+ |
|
| 70 |
+func (s pipeAddress) String() string {
|
|
| 71 |
+ return string(s) |
|
| 72 |
+} |
|
| 73 |
+ |
|
| 74 |
+func makeWin32Pipe(h syscall.Handle, path string) (*win32Pipe, error) {
|
|
| 75 |
+ f, err := makeWin32File(h) |
|
| 76 |
+ if err != nil {
|
|
| 77 |
+ return nil, err |
|
| 78 |
+ } |
|
| 79 |
+ return &win32Pipe{f, path}, nil
|
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+// DialPipe connects to a named pipe by path, timing out if the connection |
|
| 83 |
+// takes longer than the specified duration. If timeout is nil, then the timeout |
|
| 84 |
+// is the default timeout established by the pipe server. |
|
| 85 |
+func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
|
|
| 86 |
+ var absTimeout time.Time |
|
| 87 |
+ if timeout != nil {
|
|
| 88 |
+ absTimeout = time.Now().Add(*timeout) |
|
| 89 |
+ } |
|
| 90 |
+ var err error |
|
| 91 |
+ var h syscall.Handle |
|
| 92 |
+ for {
|
|
| 93 |
+ h, err = createFile(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0) |
|
| 94 |
+ if err != cERROR_PIPE_BUSY {
|
|
| 95 |
+ break |
|
| 96 |
+ } |
|
| 97 |
+ now := time.Now() |
|
| 98 |
+ var ms uint32 |
|
| 99 |
+ if absTimeout.IsZero() {
|
|
| 100 |
+ ms = cNMPWAIT_USE_DEFAULT_WAIT |
|
| 101 |
+ } else if now.After(absTimeout) {
|
|
| 102 |
+ ms = cNMPWAIT_NOWAIT |
|
| 103 |
+ } else {
|
|
| 104 |
+ ms = uint32(absTimeout.Sub(now).Nanoseconds() / 1000 / 1000) |
|
| 105 |
+ } |
|
| 106 |
+ err = waitNamedPipe(path, ms) |
|
| 107 |
+ if err != nil {
|
|
| 108 |
+ if err == cERROR_SEM_TIMEOUT {
|
|
| 109 |
+ return nil, ErrTimeout |
|
| 110 |
+ } |
|
| 111 |
+ break |
|
| 112 |
+ } |
|
| 113 |
+ } |
|
| 114 |
+ if err != nil {
|
|
| 115 |
+ return nil, &os.PathError{"open", path, err}
|
|
| 116 |
+ } |
|
| 117 |
+ p, err := makeWin32Pipe(h, path) |
|
| 118 |
+ if err != nil {
|
|
| 119 |
+ syscall.Close(h) |
|
| 120 |
+ return nil, err |
|
| 121 |
+ } |
|
| 122 |
+ return p, nil |
|
| 123 |
+} |
|
| 124 |
+ |
|
| 125 |
+type acceptResponse struct {
|
|
| 126 |
+ p *win32Pipe |
|
| 127 |
+ err error |
|
| 128 |
+} |
|
| 129 |
+ |
|
| 130 |
+type win32PipeListener struct {
|
|
| 131 |
+ firstHandle syscall.Handle |
|
| 132 |
+ path string |
|
| 133 |
+ securityDescriptor []byte |
|
| 134 |
+ acceptCh chan (chan acceptResponse) |
|
| 135 |
+ closeCh chan int |
|
| 136 |
+ doneCh chan int |
|
| 137 |
+} |
|
| 138 |
+ |
|
| 139 |
+func makeServerPipeHandle(path string, securityDescriptor []byte, first bool) (syscall.Handle, error) {
|
|
| 140 |
+ var flags uint32 = cPIPE_ACCESS_DUPLEX | syscall.FILE_FLAG_OVERLAPPED |
|
| 141 |
+ if first {
|
|
| 142 |
+ flags |= cFILE_FLAG_FIRST_PIPE_INSTANCE |
|
| 143 |
+ } |
|
| 144 |
+ var sa securityAttributes |
|
| 145 |
+ sa.Length = uint32(unsafe.Sizeof(sa)) |
|
| 146 |
+ if securityDescriptor != nil {
|
|
| 147 |
+ sa.SecurityDescriptor = &securityDescriptor[0] |
|
| 148 |
+ } |
|
| 149 |
+ h, err := createNamedPipe(path, flags, cPIPE_REJECT_REMOTE_CLIENTS, cPIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, &sa) |
|
| 150 |
+ if err != nil {
|
|
| 151 |
+ return 0, &os.PathError{"open", path, err}
|
|
| 152 |
+ } |
|
| 153 |
+ return h, nil |
|
| 154 |
+} |
|
| 155 |
+ |
|
| 156 |
+func (l *win32PipeListener) makeServerPipe() (*win32Pipe, error) {
|
|
| 157 |
+ h, err := makeServerPipeHandle(l.path, l.securityDescriptor, false) |
|
| 158 |
+ if err != nil {
|
|
| 159 |
+ return nil, err |
|
| 160 |
+ } |
|
| 161 |
+ p, err := makeWin32Pipe(h, l.path) |
|
| 162 |
+ if err != nil {
|
|
| 163 |
+ syscall.Close(h) |
|
| 164 |
+ return nil, err |
|
| 165 |
+ } |
|
| 166 |
+ return p, nil |
|
| 167 |
+} |
|
| 168 |
+ |
|
| 169 |
+func (l *win32PipeListener) listenerRoutine() {
|
|
| 170 |
+ closed := false |
|
| 171 |
+ for !closed {
|
|
| 172 |
+ select {
|
|
| 173 |
+ case <-l.closeCh: |
|
| 174 |
+ closed = true |
|
| 175 |
+ case responseCh := <-l.acceptCh: |
|
| 176 |
+ p, err := l.makeServerPipe() |
|
| 177 |
+ if err == nil {
|
|
| 178 |
+ // Wait for the client to connect. |
|
| 179 |
+ ch := make(chan error) |
|
| 180 |
+ go func() {
|
|
| 181 |
+ ch <- connectPipe(p) |
|
| 182 |
+ }() |
|
| 183 |
+ select {
|
|
| 184 |
+ case err = <-ch: |
|
| 185 |
+ if err != nil {
|
|
| 186 |
+ p.Close() |
|
| 187 |
+ p = nil |
|
| 188 |
+ } |
|
| 189 |
+ case <-l.closeCh: |
|
| 190 |
+ // Abort the connect request by closing the handle. |
|
| 191 |
+ p.Close() |
|
| 192 |
+ p = nil |
|
| 193 |
+ err = <-ch |
|
| 194 |
+ if err == nil || err == ErrFileClosed {
|
|
| 195 |
+ err = ErrPipeListenerClosed |
|
| 196 |
+ } |
|
| 197 |
+ closed = true |
|
| 198 |
+ } |
|
| 199 |
+ } |
|
| 200 |
+ responseCh <- acceptResponse{p, err}
|
|
| 201 |
+ } |
|
| 202 |
+ } |
|
| 203 |
+ syscall.Close(l.firstHandle) |
|
| 204 |
+ l.firstHandle = 0 |
|
| 205 |
+ // Notify Close() and Accept() callers that the handle has been closed. |
|
| 206 |
+ close(l.doneCh) |
|
| 207 |
+} |
|
| 208 |
+ |
|
| 209 |
+func ListenPipe(path, sddl string) (net.Listener, error) {
|
|
| 210 |
+ var ( |
|
| 211 |
+ sd []byte |
|
| 212 |
+ err error |
|
| 213 |
+ ) |
|
| 214 |
+ if sddl != "" {
|
|
| 215 |
+ sd, err = sddlToSecurityDescriptor(sddl) |
|
| 216 |
+ if err != nil {
|
|
| 217 |
+ return nil, err |
|
| 218 |
+ } |
|
| 219 |
+ } |
|
| 220 |
+ h, err := makeServerPipeHandle(path, sd, true) |
|
| 221 |
+ if err != nil {
|
|
| 222 |
+ return nil, err |
|
| 223 |
+ } |
|
| 224 |
+ // Immediately open and then close a client handle so that the named pipe is |
|
| 225 |
+ // created but not currently accepting connections. |
|
| 226 |
+ h2, err := createFile(path, 0, 0, nil, syscall.OPEN_EXISTING, cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0) |
|
| 227 |
+ if err != nil {
|
|
| 228 |
+ syscall.Close(h) |
|
| 229 |
+ return nil, err |
|
| 230 |
+ } |
|
| 231 |
+ syscall.Close(h2) |
|
| 232 |
+ l := &win32PipeListener{
|
|
| 233 |
+ firstHandle: h, |
|
| 234 |
+ path: path, |
|
| 235 |
+ securityDescriptor: sd, |
|
| 236 |
+ acceptCh: make(chan (chan acceptResponse)), |
|
| 237 |
+ closeCh: make(chan int), |
|
| 238 |
+ doneCh: make(chan int), |
|
| 239 |
+ } |
|
| 240 |
+ go l.listenerRoutine() |
|
| 241 |
+ return l, nil |
|
| 242 |
+} |
|
| 243 |
+ |
|
| 244 |
+func connectPipe(p *win32Pipe) error {
|
|
| 245 |
+ c, err := p.prepareIo() |
|
| 246 |
+ if err != nil {
|
|
| 247 |
+ return err |
|
| 248 |
+ } |
|
| 249 |
+ err = connectNamedPipe(p.handle, &c.o) |
|
| 250 |
+ _, err = p.asyncIo(c, time.Time{}, 0, err)
|
|
| 251 |
+ if err != nil && err != cERROR_PIPE_CONNECTED {
|
|
| 252 |
+ return err |
|
| 253 |
+ } |
|
| 254 |
+ return nil |
|
| 255 |
+} |
|
| 256 |
+ |
|
| 257 |
+func (l *win32PipeListener) Accept() (net.Conn, error) {
|
|
| 258 |
+ ch := make(chan acceptResponse) |
|
| 259 |
+ select {
|
|
| 260 |
+ case l.acceptCh <- ch: |
|
| 261 |
+ response := <-ch |
|
| 262 |
+ return response.p, response.err |
|
| 263 |
+ case <-l.doneCh: |
|
| 264 |
+ return nil, ErrPipeListenerClosed |
|
| 265 |
+ } |
|
| 266 |
+} |
|
| 267 |
+ |
|
| 268 |
+func (l *win32PipeListener) Close() error {
|
|
| 269 |
+ select {
|
|
| 270 |
+ case l.closeCh <- 1: |
|
| 271 |
+ <-l.doneCh |
|
| 272 |
+ case <-l.doneCh: |
|
| 273 |
+ } |
|
| 274 |
+ return nil |
|
| 275 |
+} |
|
| 276 |
+ |
|
| 277 |
+func (l *win32PipeListener) Addr() net.Addr {
|
|
| 278 |
+ return pipeAddress(l.path) |
|
| 279 |
+} |
| 0 | 280 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,83 @@ |
| 0 |
+package winio |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "syscall" |
|
| 4 |
+ "unsafe" |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW |
|
| 8 |
+//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW |
|
| 9 |
+//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW |
|
| 10 |
+//sys localFree(mem uintptr) = LocalFree |
|
| 11 |
+//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength |
|
| 12 |
+ |
|
| 13 |
+const ( |
|
| 14 |
+ cERROR_NONE_MAPPED = syscall.Errno(1332) |
|
| 15 |
+) |
|
| 16 |
+ |
|
| 17 |
+type AccountLookupError struct {
|
|
| 18 |
+ Name string |
|
| 19 |
+ Err error |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+func (e *AccountLookupError) Error() string {
|
|
| 23 |
+ if e.Name == "" {
|
|
| 24 |
+ return "lookup account: empty account name specified" |
|
| 25 |
+ } |
|
| 26 |
+ var s string |
|
| 27 |
+ switch e.Err {
|
|
| 28 |
+ case cERROR_NONE_MAPPED: |
|
| 29 |
+ s = "not found" |
|
| 30 |
+ default: |
|
| 31 |
+ s = e.Err.Error() |
|
| 32 |
+ } |
|
| 33 |
+ return "lookup account " + e.Name + ": " + s |
|
| 34 |
+} |
|
| 35 |
+ |
|
| 36 |
+type SddlConversionError struct {
|
|
| 37 |
+ Sddl string |
|
| 38 |
+ Err error |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+func (e *SddlConversionError) Error() string {
|
|
| 42 |
+ return "convert " + e.Sddl + ": " + e.Err.Error() |
|
| 43 |
+} |
|
| 44 |
+ |
|
| 45 |
+// LookupSidByName looks up the SID of an account by name |
|
| 46 |
+func LookupSidByName(name string) (sid string, err error) {
|
|
| 47 |
+ if name == "" {
|
|
| 48 |
+ return "", &AccountLookupError{name, cERROR_NONE_MAPPED}
|
|
| 49 |
+ } |
|
| 50 |
+ |
|
| 51 |
+ var sidSize, sidNameUse, refDomainSize uint32 |
|
| 52 |
+ err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse) |
|
| 53 |
+ if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER {
|
|
| 54 |
+ return "", &AccountLookupError{name, err}
|
|
| 55 |
+ } |
|
| 56 |
+ sidBuffer := make([]byte, sidSize) |
|
| 57 |
+ refDomainBuffer := make([]uint16, refDomainSize) |
|
| 58 |
+ err = lookupAccountName(nil, name, &sidBuffer[0], &sidSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse) |
|
| 59 |
+ if err != nil {
|
|
| 60 |
+ return "", &AccountLookupError{name, err}
|
|
| 61 |
+ } |
|
| 62 |
+ var strBuffer *uint16 |
|
| 63 |
+ err = convertSidToStringSid(&sidBuffer[0], &strBuffer) |
|
| 64 |
+ if err != nil {
|
|
| 65 |
+ return "", &AccountLookupError{name, err}
|
|
| 66 |
+ } |
|
| 67 |
+ sid = syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(strBuffer))[:]) |
|
| 68 |
+ localFree(uintptr(unsafe.Pointer(strBuffer))) |
|
| 69 |
+ return sid, nil |
|
| 70 |
+} |
|
| 71 |
+ |
|
| 72 |
+func sddlToSecurityDescriptor(sddl string) ([]byte, error) {
|
|
| 73 |
+ var sdBuffer uintptr |
|
| 74 |
+ err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil) |
|
| 75 |
+ if err != nil {
|
|
| 76 |
+ return nil, &SddlConversionError{sddl, err}
|
|
| 77 |
+ } |
|
| 78 |
+ defer localFree(sdBuffer) |
|
| 79 |
+ sd := make([]byte, getSecurityDescriptorLength(sdBuffer)) |
|
| 80 |
+ copy(sd, (*[1 << 30]byte)(unsafe.Pointer(sdBuffer))[:len(sd)]) |
|
| 81 |
+ return sd, nil |
|
| 82 |
+} |
| 0 | 3 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,218 @@ |
| 0 |
+// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT |
|
| 1 |
+ |
|
| 2 |
+package winio |
|
| 3 |
+ |
|
| 4 |
+import "unsafe" |
|
| 5 |
+import "syscall" |
|
| 6 |
+ |
|
| 7 |
+var _ unsafe.Pointer |
|
| 8 |
+ |
|
| 9 |
+var ( |
|
| 10 |
+ modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
| 11 |
+ modadvapi32 = syscall.NewLazyDLL("advapi32.dll")
|
|
| 12 |
+ |
|
| 13 |
+ procCancelIoEx = modkernel32.NewProc("CancelIoEx")
|
|
| 14 |
+ procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
|
| 15 |
+ procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
|
|
| 16 |
+ procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
|
|
| 17 |
+ procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
|
|
| 18 |
+ procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
|
| 19 |
+ procCreateFileW = modkernel32.NewProc("CreateFileW")
|
|
| 20 |
+ procWaitNamedPipeW = modkernel32.NewProc("WaitNamedPipeW")
|
|
| 21 |
+ procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
|
|
| 22 |
+ procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW")
|
|
| 23 |
+ procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
|
|
| 24 |
+ procLocalFree = modkernel32.NewProc("LocalFree")
|
|
| 25 |
+ procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength")
|
|
| 26 |
+) |
|
| 27 |
+ |
|
| 28 |
+func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
|
|
| 29 |
+ r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0) |
|
| 30 |
+ if r1 == 0 {
|
|
| 31 |
+ if e1 != 0 {
|
|
| 32 |
+ err = error(e1) |
|
| 33 |
+ } else {
|
|
| 34 |
+ err = syscall.EINVAL |
|
| 35 |
+ } |
|
| 36 |
+ } |
|
| 37 |
+ return |
|
| 38 |
+} |
|
| 39 |
+ |
|
| 40 |
+func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) {
|
|
| 41 |
+ r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0) |
|
| 42 |
+ newport = syscall.Handle(r0) |
|
| 43 |
+ if newport == 0 {
|
|
| 44 |
+ if e1 != 0 {
|
|
| 45 |
+ err = error(e1) |
|
| 46 |
+ } else {
|
|
| 47 |
+ err = syscall.EINVAL |
|
| 48 |
+ } |
|
| 49 |
+ } |
|
| 50 |
+ return |
|
| 51 |
+} |
|
| 52 |
+ |
|
| 53 |
+func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) {
|
|
| 54 |
+ r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0) |
|
| 55 |
+ if r1 == 0 {
|
|
| 56 |
+ if e1 != 0 {
|
|
| 57 |
+ err = error(e1) |
|
| 58 |
+ } else {
|
|
| 59 |
+ err = syscall.EINVAL |
|
| 60 |
+ } |
|
| 61 |
+ } |
|
| 62 |
+ return |
|
| 63 |
+} |
|
| 64 |
+ |
|
| 65 |
+func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) {
|
|
| 66 |
+ r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0) |
|
| 67 |
+ if r1 == 0 {
|
|
| 68 |
+ if e1 != 0 {
|
|
| 69 |
+ err = error(e1) |
|
| 70 |
+ } else {
|
|
| 71 |
+ err = syscall.EINVAL |
|
| 72 |
+ } |
|
| 73 |
+ } |
|
| 74 |
+ return |
|
| 75 |
+} |
|
| 76 |
+ |
|
| 77 |
+func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
|
|
| 78 |
+ r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0) |
|
| 79 |
+ if r1 == 0 {
|
|
| 80 |
+ if e1 != 0 {
|
|
| 81 |
+ err = error(e1) |
|
| 82 |
+ } else {
|
|
| 83 |
+ err = syscall.EINVAL |
|
| 84 |
+ } |
|
| 85 |
+ } |
|
| 86 |
+ return |
|
| 87 |
+} |
|
| 88 |
+ |
|
| 89 |
+func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *securityAttributes) (handle syscall.Handle, err error) {
|
|
| 90 |
+ var _p0 *uint16 |
|
| 91 |
+ _p0, err = syscall.UTF16PtrFromString(name) |
|
| 92 |
+ if err != nil {
|
|
| 93 |
+ return |
|
| 94 |
+ } |
|
| 95 |
+ return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa) |
|
| 96 |
+} |
|
| 97 |
+ |
|
| 98 |
+func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *securityAttributes) (handle syscall.Handle, err error) {
|
|
| 99 |
+ r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0) |
|
| 100 |
+ handle = syscall.Handle(r0) |
|
| 101 |
+ if handle == syscall.InvalidHandle {
|
|
| 102 |
+ if e1 != 0 {
|
|
| 103 |
+ err = error(e1) |
|
| 104 |
+ } else {
|
|
| 105 |
+ err = syscall.EINVAL |
|
| 106 |
+ } |
|
| 107 |
+ } |
|
| 108 |
+ return |
|
| 109 |
+} |
|
| 110 |
+ |
|
| 111 |
+func createFile(name string, access uint32, mode uint32, sa *securityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
|
| 112 |
+ var _p0 *uint16 |
|
| 113 |
+ _p0, err = syscall.UTF16PtrFromString(name) |
|
| 114 |
+ if err != nil {
|
|
| 115 |
+ return |
|
| 116 |
+ } |
|
| 117 |
+ return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile) |
|
| 118 |
+} |
|
| 119 |
+ |
|
| 120 |
+func _createFile(name *uint16, access uint32, mode uint32, sa *securityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
|
| 121 |
+ r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) |
|
| 122 |
+ handle = syscall.Handle(r0) |
|
| 123 |
+ if handle == syscall.InvalidHandle {
|
|
| 124 |
+ if e1 != 0 {
|
|
| 125 |
+ err = error(e1) |
|
| 126 |
+ } else {
|
|
| 127 |
+ err = syscall.EINVAL |
|
| 128 |
+ } |
|
| 129 |
+ } |
|
| 130 |
+ return |
|
| 131 |
+} |
|
| 132 |
+ |
|
| 133 |
+func waitNamedPipe(name string, timeout uint32) (err error) {
|
|
| 134 |
+ var _p0 *uint16 |
|
| 135 |
+ _p0, err = syscall.UTF16PtrFromString(name) |
|
| 136 |
+ if err != nil {
|
|
| 137 |
+ return |
|
| 138 |
+ } |
|
| 139 |
+ return _waitNamedPipe(_p0, timeout) |
|
| 140 |
+} |
|
| 141 |
+ |
|
| 142 |
+func _waitNamedPipe(name *uint16, timeout uint32) (err error) {
|
|
| 143 |
+ r1, _, e1 := syscall.Syscall(procWaitNamedPipeW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(timeout), 0) |
|
| 144 |
+ if r1 == 0 {
|
|
| 145 |
+ if e1 != 0 {
|
|
| 146 |
+ err = error(e1) |
|
| 147 |
+ } else {
|
|
| 148 |
+ err = syscall.EINVAL |
|
| 149 |
+ } |
|
| 150 |
+ } |
|
| 151 |
+ return |
|
| 152 |
+} |
|
| 153 |
+ |
|
| 154 |
+func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
|
| 155 |
+ var _p0 *uint16 |
|
| 156 |
+ _p0, err = syscall.UTF16PtrFromString(accountName) |
|
| 157 |
+ if err != nil {
|
|
| 158 |
+ return |
|
| 159 |
+ } |
|
| 160 |
+ return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse) |
|
| 161 |
+} |
|
| 162 |
+ |
|
| 163 |
+func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
|
| 164 |
+ r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0) |
|
| 165 |
+ if r1 == 0 {
|
|
| 166 |
+ if e1 != 0 {
|
|
| 167 |
+ err = error(e1) |
|
| 168 |
+ } else {
|
|
| 169 |
+ err = syscall.EINVAL |
|
| 170 |
+ } |
|
| 171 |
+ } |
|
| 172 |
+ return |
|
| 173 |
+} |
|
| 174 |
+ |
|
| 175 |
+func convertSidToStringSid(sid *byte, str **uint16) (err error) {
|
|
| 176 |
+ r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0) |
|
| 177 |
+ if r1 == 0 {
|
|
| 178 |
+ if e1 != 0 {
|
|
| 179 |
+ err = error(e1) |
|
| 180 |
+ } else {
|
|
| 181 |
+ err = syscall.EINVAL |
|
| 182 |
+ } |
|
| 183 |
+ } |
|
| 184 |
+ return |
|
| 185 |
+} |
|
| 186 |
+ |
|
| 187 |
+func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) {
|
|
| 188 |
+ var _p0 *uint16 |
|
| 189 |
+ _p0, err = syscall.UTF16PtrFromString(str) |
|
| 190 |
+ if err != nil {
|
|
| 191 |
+ return |
|
| 192 |
+ } |
|
| 193 |
+ return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size) |
|
| 194 |
+} |
|
| 195 |
+ |
|
| 196 |
+func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) {
|
|
| 197 |
+ r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) |
|
| 198 |
+ if r1 == 0 {
|
|
| 199 |
+ if e1 != 0 {
|
|
| 200 |
+ err = error(e1) |
|
| 201 |
+ } else {
|
|
| 202 |
+ err = syscall.EINVAL |
|
| 203 |
+ } |
|
| 204 |
+ } |
|
| 205 |
+ return |
|
| 206 |
+} |
|
| 207 |
+ |
|
| 208 |
+func localFree(mem uintptr) {
|
|
| 209 |
+ syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0) |
|
| 210 |
+ return |
|
| 211 |
+} |
|
| 212 |
+ |
|
| 213 |
+func getSecurityDescriptorLength(sd uintptr) (len uint32) {
|
|
| 214 |
+ r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0) |
|
| 215 |
+ len = uint32(r0) |
|
| 216 |
+ return |
|
| 217 |
+} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// ActivateLayer will find the layer with the given id and mount it's filesystem. |
| 12 | 6 |
// For a read/write layer, the mounted filesystem will appear as a volume on the |
| ... | ... |
@@ -16,42 +10,15 @@ func ActivateLayer(info DriverInfo, id string) error {
|
| 16 | 16 |
title := "hcsshim::ActivateLayer " |
| 17 | 17 |
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) |
| 18 | 18 |
|
| 19 |
- // Load the DLL and get a handle to the procedure we need |
|
| 20 |
- dll, proc, err := loadAndFind(procActivateLayer) |
|
| 21 |
- if dll != nil {
|
|
| 22 |
- defer dll.Release() |
|
| 23 |
- } |
|
| 24 |
- if err != nil {
|
|
| 25 |
- return err |
|
| 26 |
- } |
|
| 27 |
- |
|
| 28 |
- // Convert id to uint16 pointer for calling the procedure |
|
| 29 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 30 |
- if err != nil {
|
|
| 31 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 32 |
- logrus.Error(err) |
|
| 33 |
- return err |
|
| 34 |
- } |
|
| 35 |
- |
|
| 36 |
- // Convert info to API calling convention |
|
| 37 | 19 |
infop, err := convertDriverInfo(info) |
| 38 | 20 |
if err != nil {
|
| 39 |
- err = fmt.Errorf(title+" - Failed conversion info struct %s", err) |
|
| 40 | 21 |
logrus.Error(err) |
| 41 | 22 |
return err |
| 42 | 23 |
} |
| 43 | 24 |
|
| 44 |
- // Call the procedure itself. |
|
| 45 |
- r1, _, _ := proc.Call( |
|
| 46 |
- uintptr(unsafe.Pointer(&infop)), |
|
| 47 |
- uintptr(unsafe.Pointer(idp))) |
|
| 48 |
- |
|
| 49 |
- use(unsafe.Pointer(&infop)) |
|
| 50 |
- use(unsafe.Pointer(idp)) |
|
| 51 |
- |
|
| 52 |
- if r1 != 0 {
|
|
| 53 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s flavour=%d", |
|
| 54 |
- r1, syscall.Errno(r1), id, info.Flavour) |
|
| 25 |
+ err = activateLayer(&infop, id) |
|
| 26 |
+ if err != nil {
|
|
| 27 |
+ err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) |
|
| 55 | 28 |
logrus.Error(err) |
| 56 | 29 |
return err |
| 57 | 30 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// CopyLayer performs a commit of the srcId (which is expected to be a read-write |
| 12 | 6 |
// layer) into a new read-only layer at dstId. This requires the full list of |
| ... | ... |
@@ -16,70 +10,21 @@ func CopyLayer(info DriverInfo, srcId, dstId string, parentLayerPaths []string) |
| 16 | 16 |
title := "hcsshim::CopyLayer " |
| 17 | 17 |
logrus.Debugf(title+"srcId %s dstId", srcId, dstId) |
| 18 | 18 |
|
| 19 |
- // Load the DLL and get a handle to the procedure we need |
|
| 20 |
- dll, proc, err := loadAndFind(procCopyLayer) |
|
| 21 |
- if dll != nil {
|
|
| 22 |
- defer dll.Release() |
|
| 23 |
- } |
|
| 24 |
- if err != nil {
|
|
| 25 |
- return err |
|
| 26 |
- } |
|
| 27 |
- |
|
| 28 |
- // Convert srcId to uint16 pointer for calling the procedure |
|
| 29 |
- srcIdp, err := syscall.UTF16PtrFromString(srcId) |
|
| 30 |
- if err != nil {
|
|
| 31 |
- err = fmt.Errorf(title+" - Failed conversion of srcId %s to pointer %s", srcId, err) |
|
| 32 |
- logrus.Error(err) |
|
| 33 |
- return err |
|
| 34 |
- } |
|
| 35 |
- |
|
| 36 |
- // Convert dstId to uint16 pointer for calling the procedure |
|
| 37 |
- dstIdp, err := syscall.UTF16PtrFromString(dstId) |
|
| 38 |
- if err != nil {
|
|
| 39 |
- err = fmt.Errorf(title+" - Failed conversion of dstId %s to pointer %s", dstId, err) |
|
| 40 |
- logrus.Error(err) |
|
| 41 |
- return err |
|
| 42 |
- } |
|
| 43 |
- |
|
| 44 | 19 |
// Generate layer descriptors |
| 45 | 20 |
layers, err := layerPathsToDescriptors(parentLayerPaths) |
| 46 | 21 |
if err != nil {
|
| 47 |
- err = fmt.Errorf(title+" - Failed to generate layer descriptors %s", err) |
|
| 48 |
- logrus.Error(err) |
|
| 49 | 22 |
return err |
| 50 | 23 |
} |
| 51 | 24 |
|
| 52 | 25 |
// Convert info to API calling convention |
| 53 | 26 |
infop, err := convertDriverInfo(info) |
| 54 | 27 |
if err != nil {
|
| 55 |
- err = fmt.Errorf(title+" - Failed conversion info struct %s", err) |
|
| 56 |
- logrus.Error(err) |
|
| 57 | 28 |
return err |
| 58 | 29 |
} |
| 59 | 30 |
|
| 60 |
- var layerDescriptorsp *WC_LAYER_DESCRIPTOR |
|
| 61 |
- if len(layers) > 0 {
|
|
| 62 |
- layerDescriptorsp = &(layers[0]) |
|
| 63 |
- } else {
|
|
| 64 |
- layerDescriptorsp = nil |
|
| 65 |
- } |
|
| 66 |
- |
|
| 67 |
- // Call the procedure itself. |
|
| 68 |
- r1, _, _ := proc.Call( |
|
| 69 |
- uintptr(unsafe.Pointer(&infop)), |
|
| 70 |
- uintptr(unsafe.Pointer(srcIdp)), |
|
| 71 |
- uintptr(unsafe.Pointer(dstIdp)), |
|
| 72 |
- uintptr(unsafe.Pointer(layerDescriptorsp)), |
|
| 73 |
- uintptr(len(layers))) |
|
| 74 |
- |
|
| 75 |
- use(unsafe.Pointer(&infop)) |
|
| 76 |
- use(unsafe.Pointer(srcIdp)) |
|
| 77 |
- use(unsafe.Pointer(dstIdp)) |
|
| 78 |
- use(unsafe.Pointer(layerDescriptorsp)) |
|
| 79 |
- |
|
| 80 |
- if r1 != 0 {
|
|
| 81 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s srcId=%s dstId=%d", |
|
| 82 |
- r1, syscall.Errno(r1), srcId, dstId) |
|
| 31 |
+ err = copyLayer(&infop, srcId, dstId, layers) |
|
| 32 |
+ if err != nil {
|
|
| 33 |
+ err = makeErrorf(err, title, "srcId=%s dstId=%d", srcId, dstId) |
|
| 83 | 34 |
logrus.Error(err) |
| 84 | 35 |
return err |
| 85 | 36 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// CreateComputeSystem creates a container, initializing its configuration in |
| 12 | 6 |
// the Host Compute Service such that it can be started by a call to the |
| ... | ... |
@@ -16,40 +10,9 @@ func CreateComputeSystem(id string, configuration string) error {
|
| 16 | 16 |
title := "HCSShim::CreateComputeSystem" |
| 17 | 17 |
logrus.Debugln(title+" id=%s, configuration=%s", id, configuration) |
| 18 | 18 |
|
| 19 |
- // Load the DLL and get a handle to the procedure we need |
|
| 20 |
- dll, proc, err := loadAndFind(procCreateComputeSystem) |
|
| 21 |
- if dll != nil {
|
|
| 22 |
- defer dll.Release() |
|
| 23 |
- } |
|
| 19 |
+ err := createComputeSystem(id, configuration) |
|
| 24 | 20 |
if err != nil {
|
| 25 |
- return err |
|
| 26 |
- } |
|
| 27 |
- |
|
| 28 |
- // Convert id to uint16 pointers for calling the procedure |
|
| 29 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 30 |
- if err != nil {
|
|
| 31 |
- err = fmt.Errorf(title+"- Failed conversion of id %s to pointer %s", id, err) |
|
| 32 |
- logrus.Error(err) |
|
| 33 |
- return err |
|
| 34 |
- } |
|
| 35 |
- |
|
| 36 |
- // Convert configuration to uint16 pointers for calling the procedure |
|
| 37 |
- configurationp, err := syscall.UTF16PtrFromString(configuration) |
|
| 38 |
- if err != nil {
|
|
| 39 |
- err = fmt.Errorf(title+" - Failed conversion of configuration %s to pointer %s", configuration, err) |
|
| 40 |
- logrus.Error(err) |
|
| 41 |
- return err |
|
| 42 |
- } |
|
| 43 |
- |
|
| 44 |
- // Call the procedure itself. |
|
| 45 |
- r1, _, _ := proc.Call( |
|
| 46 |
- uintptr(unsafe.Pointer(idp)), uintptr(unsafe.Pointer(configurationp))) |
|
| 47 |
- |
|
| 48 |
- use(unsafe.Pointer(idp)) |
|
| 49 |
- use(unsafe.Pointer(configurationp)) |
|
| 50 |
- |
|
| 51 |
- if r1 != 0 {
|
|
| 52 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s configuration=%s", r1, syscall.Errno(r1), id, configuration) |
|
| 21 |
+ err = makeErrorf(err, title, "id=%s configuration=%s", id, configuration) |
|
| 53 | 22 |
logrus.Error(err) |
| 54 | 23 |
return err |
| 55 | 24 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// CreateLayer creates a new, empty, read-only layer on the filesystem based on |
| 12 | 6 |
// the parent layer provided. |
| ... | ... |
@@ -14,52 +8,16 @@ func CreateLayer(info DriverInfo, id, parent string) error {
|
| 14 | 14 |
title := "hcsshim::CreateLayer " |
| 15 | 15 |
logrus.Debugf(title+"Flavour %d ID %s parent %s", info.Flavour, id, parent) |
| 16 | 16 |
|
| 17 |
- // Load the DLL and get a handle to the procedure we need |
|
| 18 |
- dll, proc, err := loadAndFind(procCreateLayer) |
|
| 19 |
- if dll != nil {
|
|
| 20 |
- defer dll.Release() |
|
| 21 |
- } |
|
| 22 |
- if err != nil {
|
|
| 23 |
- return err |
|
| 24 |
- } |
|
| 25 |
- |
|
| 26 |
- // Convert id to uint16 pointer for calling the procedure |
|
| 27 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 28 |
- if err != nil {
|
|
| 29 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 30 |
- logrus.Error(err) |
|
| 31 |
- return err |
|
| 32 |
- } |
|
| 33 |
- |
|
| 34 |
- // Convert parent to uint16 pointer for calling the procedure |
|
| 35 |
- parentp, err := syscall.UTF16PtrFromString(parent) |
|
| 36 |
- if err != nil {
|
|
| 37 |
- err = fmt.Errorf(title+" - Failed conversion of parent %s to pointer %s", parent, err) |
|
| 38 |
- logrus.Error(err) |
|
| 39 |
- return err |
|
| 40 |
- } |
|
| 41 |
- |
|
| 42 | 17 |
// Convert info to API calling convention |
| 43 | 18 |
infop, err := convertDriverInfo(info) |
| 44 | 19 |
if err != nil {
|
| 45 |
- err = fmt.Errorf(title+" - Failed conversion info struct %s", parent, err) |
|
| 46 | 20 |
logrus.Error(err) |
| 47 | 21 |
return err |
| 48 | 22 |
} |
| 49 | 23 |
|
| 50 |
- // Call the procedure itself. |
|
| 51 |
- r1, _, _ := proc.Call( |
|
| 52 |
- uintptr(unsafe.Pointer(&infop)), |
|
| 53 |
- uintptr(unsafe.Pointer(idp)), |
|
| 54 |
- uintptr(unsafe.Pointer(parentp))) |
|
| 55 |
- |
|
| 56 |
- use(unsafe.Pointer(&infop)) |
|
| 57 |
- use(unsafe.Pointer(idp)) |
|
| 58 |
- use(unsafe.Pointer(parentp)) |
|
| 59 |
- |
|
| 60 |
- if r1 != 0 {
|
|
| 61 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s parent=%s flavour=%d", |
|
| 62 |
- r1, syscall.Errno(r1), id, parent, info.Flavour) |
|
| 24 |
+ err = createLayer(&infop, id, parent) |
|
| 25 |
+ if err != nil {
|
|
| 26 |
+ err = makeErrorf(err, title, "id=%s parent=%s flavour=%d", id, parent, info.Flavour) |
|
| 63 | 27 |
logrus.Error(err) |
| 64 | 28 |
return err |
| 65 | 29 |
} |
| ... | ... |
@@ -2,12 +2,10 @@ package hcsshim |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"encoding/json" |
| 5 |
- "fmt" |
|
| 6 | 5 |
"io" |
| 7 |
- "runtime" |
|
| 8 | 6 |
"syscall" |
| 9 |
- "unsafe" |
|
| 10 | 7 |
|
| 8 |
+ "github.com/Microsoft/go-winio" |
|
| 11 | 9 |
"github.com/Sirupsen/logrus" |
| 12 | 10 |
) |
| 13 | 11 |
|
| ... | ... |
@@ -22,77 +20,38 @@ type CreateProcessParams struct {
|
| 22 | 22 |
ConsoleSize [2]int |
| 23 | 23 |
} |
| 24 | 24 |
|
| 25 |
-// pipe struct used for the stdin/stdout/stderr pipes |
|
| 26 |
-type pipe struct {
|
|
| 27 |
- handle syscall.Handle |
|
| 28 |
-} |
|
| 29 |
- |
|
| 30 |
-func makePipe(h syscall.Handle) *pipe {
|
|
| 31 |
- p := &pipe{h}
|
|
| 32 |
- runtime.SetFinalizer(p, (*pipe).closeHandle) |
|
| 33 |
- return p |
|
| 34 |
-} |
|
| 35 |
- |
|
| 36 |
-func (p *pipe) closeHandle() {
|
|
| 37 |
- if p.handle != 0 {
|
|
| 38 |
- syscall.CloseHandle(p.handle) |
|
| 39 |
- p.handle = 0 |
|
| 25 |
+// makeOpenFiles calls winio.MakeOpenFile for each handle in a slice but closes all the handles |
|
| 26 |
+// if there is an error. |
|
| 27 |
+func makeOpenFiles(hs []syscall.Handle) (_ []io.ReadWriteCloser, err error) {
|
|
| 28 |
+ fs := make([]io.ReadWriteCloser, len(hs)) |
|
| 29 |
+ for i, h := range hs {
|
|
| 30 |
+ if h != syscall.Handle(0) {
|
|
| 31 |
+ if err == nil {
|
|
| 32 |
+ fs[i], err = winio.MakeOpenFile(h) |
|
| 33 |
+ } |
|
| 34 |
+ if err != nil {
|
|
| 35 |
+ syscall.Close(h) |
|
| 36 |
+ } |
|
| 37 |
+ } |
|
| 40 | 38 |
} |
| 41 |
-} |
|
| 42 |
- |
|
| 43 |
-func (p *pipe) Close() error {
|
|
| 44 |
- p.closeHandle() |
|
| 45 |
- runtime.SetFinalizer(p, nil) |
|
| 46 |
- return nil |
|
| 47 |
-} |
|
| 48 |
- |
|
| 49 |
-func (p *pipe) Read(b []byte) (int, error) {
|
|
| 50 |
- // syscall.Read returns 0, nil on ERROR_BROKEN_PIPE, but for |
|
| 51 |
- // our purposes this should indicate EOF. This may be a go bug. |
|
| 52 |
- var read uint32 |
|
| 53 |
- err := syscall.ReadFile(p.handle, b, &read, nil) |
|
| 54 | 39 |
if err != nil {
|
| 55 |
- if err == syscall.ERROR_BROKEN_PIPE {
|
|
| 56 |
- return 0, io.EOF |
|
| 40 |
+ for _, f := range fs {
|
|
| 41 |
+ if f != nil {
|
|
| 42 |
+ f.Close() |
|
| 43 |
+ } |
|
| 57 | 44 |
} |
| 58 |
- return 0, err |
|
| 45 |
+ return nil, err |
|
| 59 | 46 |
} |
| 60 |
- return int(read), nil |
|
| 61 |
-} |
|
| 62 |
- |
|
| 63 |
-func (p *pipe) Write(b []byte) (int, error) {
|
|
| 64 |
- return syscall.Write(p.handle, b) |
|
| 47 |
+ return fs, nil |
|
| 65 | 48 |
} |
| 66 | 49 |
|
| 67 | 50 |
// CreateProcessInComputeSystem starts a process in a container. This is invoked, for example, |
| 68 | 51 |
// as a result of docker run, docker exec, or RUN in Dockerfile. If successful, |
| 69 | 52 |
// it returns the PID of the process. |
| 70 |
-func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useStderr bool, params CreateProcessParams) (uint32, io.WriteCloser, io.ReadCloser, io.ReadCloser, uint32, error) {
|
|
| 71 |
- |
|
| 72 |
- var ( |
|
| 73 |
- stdin io.WriteCloser |
|
| 74 |
- stdout, stderr io.ReadCloser |
|
| 75 |
- ) |
|
| 76 |
- |
|
| 53 |
+func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useStderr bool, params CreateProcessParams) (_ uint32, _ io.WriteCloser, _ io.ReadCloser, _ io.ReadCloser, hr uint32, err error) {
|
|
| 77 | 54 |
title := "HCSShim::CreateProcessInComputeSystem" |
| 78 | 55 |
logrus.Debugf(title+" id=%s", id) |
| 79 |
- |
|
| 80 |
- // Load the DLL and get a handle to the procedure we need |
|
| 81 |
- dll, proc, err := loadAndFind(procCreateProcessWithStdHandlesInComputeSystem) |
|
| 82 |
- if dll != nil {
|
|
| 83 |
- defer dll.Release() |
|
| 84 |
- } |
|
| 85 |
- if err != nil {
|
|
| 86 |
- return 0, nil, nil, nil, 0xFFFFFFFF, err |
|
| 87 |
- } |
|
| 88 |
- |
|
| 89 |
- // Convert id to uint16 pointer for calling the procedure |
|
| 90 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 91 |
- if err != nil {
|
|
| 92 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 93 |
- logrus.Error(err) |
|
| 94 |
- return 0, nil, nil, nil, 0xFFFFFFFF, err |
|
| 95 |
- } |
|
| 56 |
+ hr = 0xFFFFFFFF |
|
| 96 | 57 |
|
| 97 | 58 |
// If we are not emulating a console, ignore any console size passed to us |
| 98 | 59 |
if !params.EmulateConsole {
|
| ... | ... |
@@ -102,65 +61,43 @@ func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useS |
| 102 | 102 |
|
| 103 | 103 |
paramsJson, err := json.Marshal(params) |
| 104 | 104 |
if err != nil {
|
| 105 |
- err = fmt.Errorf(title+" - Failed to marshall params %v %s", params, err) |
|
| 106 |
- return 0, nil, nil, nil, 0xFFFFFFFF, err |
|
| 105 |
+ return |
|
| 107 | 106 |
} |
| 108 | 107 |
|
| 109 |
- // Convert paramsJson to uint16 pointer for calling the procedure |
|
| 110 |
- paramsJsonp, err := syscall.UTF16PtrFromString(string(paramsJson)) |
|
| 111 |
- if err != nil {
|
|
| 112 |
- return 0, nil, nil, nil, 0xFFFFFFFF, err |
|
| 113 |
- } |
|
| 114 |
- |
|
| 115 |
- // Get a POINTER to variable to take the pid outparm |
|
| 116 |
- pid := new(uint32) |
|
| 117 |
- |
|
| 118 | 108 |
logrus.Debugf(title+" - Calling Win32 %s %s", id, paramsJson) |
| 119 | 109 |
|
| 120 |
- var stdinHandle, stdoutHandle, stderrHandle syscall.Handle |
|
| 121 |
- var stdinParam, stdoutParam, stderrParam uintptr |
|
| 110 |
+ var pid uint32 |
|
| 111 |
+ |
|
| 112 |
+ handles := make([]syscall.Handle, 3) |
|
| 113 |
+ var stdinParam, stdoutParam, stderrParam *syscall.Handle |
|
| 122 | 114 |
if useStdin {
|
| 123 |
- stdinParam = uintptr(unsafe.Pointer(&stdinHandle)) |
|
| 115 |
+ stdinParam = &handles[0] |
|
| 124 | 116 |
} |
| 125 | 117 |
if useStdout {
|
| 126 |
- stdoutParam = uintptr(unsafe.Pointer(&stdoutHandle)) |
|
| 118 |
+ stdoutParam = &handles[1] |
|
| 127 | 119 |
} |
| 128 | 120 |
if useStderr {
|
| 129 |
- stderrParam = uintptr(unsafe.Pointer(&stderrHandle)) |
|
| 121 |
+ stderrParam = &handles[2] |
|
| 130 | 122 |
} |
| 131 | 123 |
|
| 132 |
- // Call the procedure itself. |
|
| 133 |
- r1, _, _ := proc.Call( |
|
| 134 |
- uintptr(unsafe.Pointer(idp)), |
|
| 135 |
- uintptr(unsafe.Pointer(paramsJsonp)), |
|
| 136 |
- uintptr(unsafe.Pointer(pid)), |
|
| 137 |
- stdinParam, |
|
| 138 |
- stdoutParam, |
|
| 139 |
- stderrParam) |
|
| 140 |
- |
|
| 141 |
- use(unsafe.Pointer(idp)) |
|
| 142 |
- use(unsafe.Pointer(paramsJsonp)) |
|
| 143 |
- |
|
| 144 |
- if r1 != 0 {
|
|
| 145 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s params=%v", r1, syscall.Errno(r1), id, params) |
|
| 124 |
+ err = createProcessWithStdHandlesInComputeSystem(id, string(paramsJson), &pid, stdinParam, stdoutParam, stderrParam) |
|
| 125 |
+ if err != nil {
|
|
| 126 |
+ winerr := makeErrorf(err, title, "id=%s params=%v", id, params) |
|
| 127 |
+ hr = winerr.HResult() |
|
| 146 | 128 |
// Windows TP4: Hyper-V Containers may return this error with more than one |
| 147 | 129 |
// concurrent exec. Do not log it as an error |
| 148 |
- if uint32(r1) != Win32InvalidArgument {
|
|
| 149 |
- logrus.Error(err) |
|
| 130 |
+ if hr != Win32InvalidArgument {
|
|
| 131 |
+ logrus.Error(winerr) |
|
| 150 | 132 |
} |
| 151 |
- return 0, nil, nil, nil, uint32(r1), err |
|
| 133 |
+ err = winerr |
|
| 134 |
+ return |
|
| 152 | 135 |
} |
| 153 | 136 |
|
| 154 |
- if useStdin {
|
|
| 155 |
- stdin = makePipe(stdinHandle) |
|
| 156 |
- } |
|
| 157 |
- if useStdout {
|
|
| 158 |
- stdout = makePipe(stdoutHandle) |
|
| 159 |
- } |
|
| 160 |
- if useStderr {
|
|
| 161 |
- stderr = makePipe(stderrHandle) |
|
| 137 |
+ pipes, err := makeOpenFiles(handles) |
|
| 138 |
+ if err != nil {
|
|
| 139 |
+ return |
|
| 162 | 140 |
} |
| 163 | 141 |
|
| 164 |
- logrus.Debugf(title+" - succeeded id=%s params=%s pid=%d", id, paramsJson, *pid) |
|
| 165 |
- return *pid, stdin, stdout, stderr, 0, nil |
|
| 142 |
+ logrus.Debugf(title+" - succeeded id=%s params=%s pid=%d", id, paramsJson, pid) |
|
| 143 |
+ return pid, pipes[0], pipes[1], pipes[2], 0, nil |
|
| 166 | 144 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// CreateSandboxLayer creates and populates new read-write layer for use by a container. |
| 12 | 6 |
// This requires both the id of the direct parent layer, as well as the full list |
| ... | ... |
@@ -16,69 +10,22 @@ func CreateSandboxLayer(info DriverInfo, layerId, parentId string, parentLayerPa |
| 16 | 16 |
title := "hcsshim::CreateSandboxLayer " |
| 17 | 17 |
logrus.Debugf(title+"layerId %s parentId %s", layerId, parentId) |
| 18 | 18 |
|
| 19 |
- // Load the DLL and get a handle to the procedure we need |
|
| 20 |
- dll, proc, err := loadAndFind(procCreateSandboxLayer) |
|
| 21 |
- if dll != nil {
|
|
| 22 |
- defer dll.Release() |
|
| 23 |
- } |
|
| 24 |
- if err != nil {
|
|
| 25 |
- return err |
|
| 26 |
- } |
|
| 27 |
- |
|
| 28 | 19 |
// Generate layer descriptors |
| 29 | 20 |
layers, err := layerPathsToDescriptors(parentLayerPaths) |
| 30 | 21 |
if err != nil {
|
| 31 |
- err = fmt.Errorf(title+"- Failed to generate layer descriptors ", err) |
|
| 32 |
- return err |
|
| 33 |
- } |
|
| 34 |
- |
|
| 35 |
- // Convert layerId to uint16 pointer for calling the procedure |
|
| 36 |
- layerIdp, err := syscall.UTF16PtrFromString(layerId) |
|
| 37 |
- if err != nil {
|
|
| 38 |
- err = fmt.Errorf(title+"- Failed conversion of layerId %s to pointer %s", layerId, err) |
|
| 39 |
- logrus.Error(err) |
|
| 40 |
- return err |
|
| 41 |
- } |
|
| 42 |
- |
|
| 43 |
- // Convert parentId to uint16 pointer for calling the procedure |
|
| 44 |
- parentIdp, err := syscall.UTF16PtrFromString(parentId) |
|
| 45 |
- if err != nil {
|
|
| 46 |
- err = fmt.Errorf(title+"- Failed conversion of parentId %s to pointer %s", parentId, err) |
|
| 47 |
- logrus.Error(err) |
|
| 48 | 22 |
return err |
| 49 | 23 |
} |
| 50 | 24 |
|
| 51 | 25 |
// Convert info to API calling convention |
| 52 | 26 |
infop, err := convertDriverInfo(info) |
| 53 | 27 |
if err != nil {
|
| 54 |
- err = fmt.Errorf(title+"- Failed conversion info struct %s", err) |
|
| 55 | 28 |
logrus.Error(err) |
| 56 | 29 |
return err |
| 57 | 30 |
} |
| 58 | 31 |
|
| 59 |
- var layerDescriptorsp *WC_LAYER_DESCRIPTOR |
|
| 60 |
- if len(layers) > 0 {
|
|
| 61 |
- layerDescriptorsp = &(layers[0]) |
|
| 62 |
- } else {
|
|
| 63 |
- layerDescriptorsp = nil |
|
| 64 |
- } |
|
| 65 |
- |
|
| 66 |
- // Call the procedure itself. |
|
| 67 |
- r1, _, _ := proc.Call( |
|
| 68 |
- uintptr(unsafe.Pointer(&infop)), |
|
| 69 |
- uintptr(unsafe.Pointer(layerIdp)), |
|
| 70 |
- uintptr(unsafe.Pointer(parentIdp)), |
|
| 71 |
- uintptr(unsafe.Pointer(layerDescriptorsp)), |
|
| 72 |
- uintptr(len(layers))) |
|
| 73 |
- |
|
| 74 |
- use(unsafe.Pointer(&infop)) |
|
| 75 |
- use(unsafe.Pointer(layerIdp)) |
|
| 76 |
- use(unsafe.Pointer(parentIdp)) |
|
| 77 |
- use(unsafe.Pointer(layerDescriptorsp)) |
|
| 78 |
- |
|
| 79 |
- if r1 != 0 {
|
|
| 80 |
- err = fmt.Errorf(title+"- Win32 API call returned error r1=%d err=%s layerId=%s parentId=%s", |
|
| 81 |
- r1, syscall.Errno(r1), layerId, parentId) |
|
| 32 |
+ err = createSandboxLayer(&infop, layerId, parentId, layers) |
|
| 33 |
+ if err != nil {
|
|
| 34 |
+ err = makeErrorf(err, title, "layerId=%s parentId=%s", layerId, parentId) |
|
| 82 | 35 |
logrus.Error(err) |
| 83 | 36 |
return err |
| 84 | 37 |
} |
| ... | ... |
@@ -1,54 +1,22 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// DeactivateLayer will dismount a layer that was mounted via ActivateLayer. |
| 12 | 6 |
func DeactivateLayer(info DriverInfo, id string) error {
|
| 13 | 7 |
title := "hcsshim::DeactivateLayer " |
| 14 | 8 |
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) |
| 15 | 9 |
|
| 16 |
- // Load the DLL and get a handle to the procedure we need |
|
| 17 |
- dll, proc, err := loadAndFind(procDeactivateLayer) |
|
| 18 |
- if dll != nil {
|
|
| 19 |
- defer dll.Release() |
|
| 20 |
- } |
|
| 21 |
- if err != nil {
|
|
| 22 |
- return err |
|
| 23 |
- } |
|
| 24 |
- |
|
| 25 |
- // Convert id to uint16 pointer for calling the procedure |
|
| 26 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 27 |
- if err != nil {
|
|
| 28 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 29 |
- logrus.Error(err) |
|
| 30 |
- return err |
|
| 31 |
- } |
|
| 32 |
- |
|
| 33 | 10 |
// Convert info to API calling convention |
| 34 | 11 |
infop, err := convertDriverInfo(info) |
| 35 | 12 |
if err != nil {
|
| 36 |
- err = fmt.Errorf(title+" - Failed conversion info struct %s", err) |
|
| 37 | 13 |
logrus.Error(err) |
| 38 | 14 |
return err |
| 39 | 15 |
} |
| 40 | 16 |
|
| 41 |
- // Call the procedure itself. |
|
| 42 |
- r1, _, _ := proc.Call( |
|
| 43 |
- uintptr(unsafe.Pointer(&infop)), |
|
| 44 |
- uintptr(unsafe.Pointer(idp))) |
|
| 45 |
- |
|
| 46 |
- use(unsafe.Pointer(&infop)) |
|
| 47 |
- use(unsafe.Pointer(idp)) |
|
| 48 |
- |
|
| 49 |
- if r1 != 0 {
|
|
| 50 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s flavour=%d", |
|
| 51 |
- r1, syscall.Errno(r1), id, info.Flavour) |
|
| 17 |
+ err = deactivateLayer(&infop, id) |
|
| 18 |
+ if err != nil {
|
|
| 19 |
+ err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) |
|
| 52 | 20 |
logrus.Error(err) |
| 53 | 21 |
return err |
| 54 | 22 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// DestroyLayer will remove the on-disk files representing the layer with the given |
| 12 | 6 |
// id, including that layer's containing folder, if any. |
| ... | ... |
@@ -14,42 +8,16 @@ func DestroyLayer(info DriverInfo, id string) error {
|
| 14 | 14 |
title := "hcsshim::DestroyLayer " |
| 15 | 15 |
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) |
| 16 | 16 |
|
| 17 |
- // Load the DLL and get a handle to the procedure we need |
|
| 18 |
- dll, proc, err := loadAndFind(procDestroyLayer) |
|
| 19 |
- if dll != nil {
|
|
| 20 |
- defer dll.Release() |
|
| 21 |
- } |
|
| 22 |
- if err != nil {
|
|
| 23 |
- return err |
|
| 24 |
- } |
|
| 25 |
- |
|
| 26 |
- // Convert id to uint16 pointer for calling the procedure |
|
| 27 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 28 |
- if err != nil {
|
|
| 29 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 30 |
- logrus.Error(err) |
|
| 31 |
- return err |
|
| 32 |
- } |
|
| 33 |
- |
|
| 34 | 17 |
// Convert info to API calling convention |
| 35 | 18 |
infop, err := convertDriverInfo(info) |
| 36 | 19 |
if err != nil {
|
| 37 |
- err = fmt.Errorf(title+" - Failed conversion info struct %s", err) |
|
| 38 | 20 |
logrus.Error(err) |
| 39 | 21 |
return err |
| 40 | 22 |
} |
| 41 | 23 |
|
| 42 |
- // Call the procedure itself. |
|
| 43 |
- r1, _, _ := proc.Call( |
|
| 44 |
- uintptr(unsafe.Pointer(&infop)), |
|
| 45 |
- uintptr(unsafe.Pointer(idp))) |
|
| 46 |
- |
|
| 47 |
- use(unsafe.Pointer(&infop)) |
|
| 48 |
- use(unsafe.Pointer(idp)) |
|
| 49 |
- |
|
| 50 |
- if r1 != 0 {
|
|
| 51 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s flavour=%d", |
|
| 52 |
- r1, syscall.Errno(r1), id, info.Flavour) |
|
| 24 |
+ err = destroyLayer(&infop, id) |
|
| 25 |
+ if err != nil {
|
|
| 26 |
+ err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) |
|
| 53 | 27 |
logrus.Error(err) |
| 54 | 28 |
return err |
| 55 | 29 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// ExportLayer will create a folder at exportFolderPath and fill that folder with |
| 12 | 6 |
// the transport format version of the layer identified by layerId. This transport |
| ... | ... |
@@ -17,68 +11,22 @@ func ExportLayer(info DriverInfo, layerId string, exportFolderPath string, paren |
| 17 | 17 |
title := "hcsshim::ExportLayer " |
| 18 | 18 |
logrus.Debugf(title+"flavour %d layerId %s folder %s", info.Flavour, layerId, exportFolderPath) |
| 19 | 19 |
|
| 20 |
- // Load the DLL and get a handle to the procedure we need |
|
| 21 |
- dll, proc, err := loadAndFind(procExportLayer) |
|
| 22 |
- if dll != nil {
|
|
| 23 |
- defer dll.Release() |
|
| 24 |
- } |
|
| 25 |
- if err != nil {
|
|
| 26 |
- return err |
|
| 27 |
- } |
|
| 28 |
- |
|
| 29 | 20 |
// Generate layer descriptors |
| 30 | 21 |
layers, err := layerPathsToDescriptors(parentLayerPaths) |
| 31 | 22 |
if err != nil {
|
| 32 |
- err = fmt.Errorf(title+"- Failed to generate layer descriptors ", err) |
|
| 33 |
- return err |
|
| 34 |
- } |
|
| 35 |
- |
|
| 36 |
- // Convert layerId to uint16 pointer for calling the procedure |
|
| 37 |
- layerIdp, err := syscall.UTF16PtrFromString(layerId) |
|
| 38 |
- if err != nil {
|
|
| 39 |
- err = fmt.Errorf(title+"- Failed conversion of layerId %s to pointer %s", layerId, err) |
|
| 40 |
- logrus.Error(err) |
|
| 41 |
- return err |
|
| 42 |
- } |
|
| 43 |
- |
|
| 44 |
- // Convert exportFolderPath to uint16 pointer for calling the procedure |
|
| 45 |
- exportFolderPathp, err := syscall.UTF16PtrFromString(exportFolderPath) |
|
| 46 |
- if err != nil {
|
|
| 47 |
- err = fmt.Errorf(title+"- Failed conversion of exportFolderPath %s to pointer %s", exportFolderPath, err) |
|
| 48 |
- logrus.Error(err) |
|
| 49 | 23 |
return err |
| 50 | 24 |
} |
| 51 | 25 |
|
| 52 | 26 |
// Convert info to API calling convention |
| 53 | 27 |
infop, err := convertDriverInfo(info) |
| 54 | 28 |
if err != nil {
|
| 55 |
- err = fmt.Errorf(title+"- Failed conversion info struct %s", err) |
|
| 56 | 29 |
logrus.Error(err) |
| 57 | 30 |
return err |
| 58 | 31 |
} |
| 59 | 32 |
|
| 60 |
- var layerDescriptorsp *WC_LAYER_DESCRIPTOR |
|
| 61 |
- if len(layers) > 0 {
|
|
| 62 |
- layerDescriptorsp = &(layers[0]) |
|
| 63 |
- } else {
|
|
| 64 |
- layerDescriptorsp = nil |
|
| 65 |
- } |
|
| 66 |
- |
|
| 67 |
- // Call the procedure itself. |
|
| 68 |
- r1, _, _ := proc.Call( |
|
| 69 |
- uintptr(unsafe.Pointer(&infop)), |
|
| 70 |
- uintptr(unsafe.Pointer(layerIdp)), |
|
| 71 |
- uintptr(unsafe.Pointer(exportFolderPathp)), |
|
| 72 |
- uintptr(unsafe.Pointer(layerDescriptorsp)), |
|
| 73 |
- uintptr(len(layers))) |
|
| 74 |
- use(unsafe.Pointer(&infop)) |
|
| 75 |
- use(unsafe.Pointer(layerIdp)) |
|
| 76 |
- use(unsafe.Pointer(exportFolderPathp)) |
|
| 77 |
- use(unsafe.Pointer(layerDescriptorsp)) |
|
| 78 |
- |
|
| 79 |
- if r1 != 0 {
|
|
| 80 |
- err = fmt.Errorf(title+"- Win32 API call returned error r1=%d err=%s layerId=%s flavour=%d folder=%s", |
|
| 81 |
- r1, syscall.Errno(r1), layerId, info.Flavour, exportFolderPath) |
|
| 33 |
+ err = exportLayer(&infop, layerId, exportFolderPath, layers) |
|
| 34 |
+ if err != nil {
|
|
| 35 |
+ err = makeErrorf(err, title, "layerId=%s flavour=%d folder=%s", layerId, info.Flavour, exportFolderPath) |
|
| 82 | 36 |
logrus.Error(err) |
| 83 | 37 |
return err |
| 84 | 38 |
} |
| ... | ... |
@@ -1,9 +1,7 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "fmt" |
|
| 5 | 4 |
"syscall" |
| 6 |
- "unsafe" |
|
| 7 | 5 |
|
| 8 | 6 |
"github.com/Sirupsen/logrus" |
| 9 | 7 |
) |
| ... | ... |
@@ -16,45 +14,21 @@ func GetLayerMountPath(info DriverInfo, id string) (string, error) {
|
| 16 | 16 |
title := "hcsshim::GetLayerMountPath " |
| 17 | 17 |
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) |
| 18 | 18 |
|
| 19 |
- // Load the DLL and get a handle to the procedure we need |
|
| 20 |
- dll, proc, err := loadAndFind(procGetLayerMountPath) |
|
| 21 |
- if dll != nil {
|
|
| 22 |
- defer dll.Release() |
|
| 23 |
- } |
|
| 24 |
- if err != nil {
|
|
| 25 |
- return "", err |
|
| 26 |
- } |
|
| 27 |
- |
|
| 28 |
- // Convert id to uint16 pointer for calling the procedure |
|
| 29 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 30 |
- if err != nil {
|
|
| 31 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 32 |
- logrus.Error(err) |
|
| 33 |
- return "", err |
|
| 34 |
- } |
|
| 35 |
- |
|
| 36 | 19 |
// Convert info to API calling convention |
| 37 | 20 |
infop, err := convertDriverInfo(info) |
| 38 | 21 |
if err != nil {
|
| 39 |
- err = fmt.Errorf(title+" - Failed conversion info struct %s", err) |
|
| 40 | 22 |
logrus.Error(err) |
| 41 | 23 |
return "", err |
| 42 | 24 |
} |
| 43 | 25 |
|
| 44 |
- var mountPathLength uint64 |
|
| 26 |
+ var mountPathLength uintptr |
|
| 45 | 27 |
mountPathLength = 0 |
| 46 | 28 |
|
| 47 | 29 |
// Call the procedure itself. |
| 48 | 30 |
logrus.Debugf("Calling proc (1)")
|
| 49 |
- r1, _, _ := proc.Call( |
|
| 50 |
- uintptr(unsafe.Pointer(&infop)), |
|
| 51 |
- uintptr(unsafe.Pointer(idp)), |
|
| 52 |
- uintptr(unsafe.Pointer(&mountPathLength)), |
|
| 53 |
- uintptr(unsafe.Pointer(nil))) |
|
| 54 |
- |
|
| 55 |
- if r1 != 0 {
|
|
| 56 |
- err = fmt.Errorf(title+" - First Win32 API call returned error r1=%d err=%s id=%s flavour=%d", |
|
| 57 |
- r1, syscall.Errno(r1), id, info.Flavour) |
|
| 31 |
+ err = getLayerMountPath(&infop, id, &mountPathLength, nil) |
|
| 32 |
+ if err != nil {
|
|
| 33 |
+ err = makeErrorf(err, title, "(first call) id=%s flavour=%d", id, info.Flavour) |
|
| 58 | 34 |
logrus.Error(err) |
| 59 | 35 |
return "", err |
| 60 | 36 |
} |
| ... | ... |
@@ -68,19 +42,9 @@ func GetLayerMountPath(info DriverInfo, id string) (string, error) {
|
| 68 | 68 |
|
| 69 | 69 |
// Call the procedure again |
| 70 | 70 |
logrus.Debugf("Calling proc (2)")
|
| 71 |
- r1, _, _ = proc.Call( |
|
| 72 |
- uintptr(unsafe.Pointer(&infop)), |
|
| 73 |
- uintptr(unsafe.Pointer(idp)), |
|
| 74 |
- uintptr(unsafe.Pointer(&mountPathLength)), |
|
| 75 |
- uintptr(unsafe.Pointer(&mountPathp[0]))) |
|
| 76 |
- |
|
| 77 |
- use(unsafe.Pointer(&mountPathLength)) |
|
| 78 |
- use(unsafe.Pointer(&infop)) |
|
| 79 |
- use(unsafe.Pointer(idp)) |
|
| 80 |
- |
|
| 81 |
- if r1 != 0 {
|
|
| 82 |
- err = fmt.Errorf(title+" - Second Win32 API call returned error r1=%d err=%s id=%s flavour=%d", |
|
| 83 |
- r1, syscall.Errno(r1), id, info.Flavour) |
|
| 71 |
+ err = getLayerMountPath(&infop, id, &mountPathLength, &mountPathp[0]) |
|
| 72 |
+ if err != nil {
|
|
| 73 |
+ err = makeErrorf(err, title, "(second call) id=%s flavour=%d", id, info.Flavour) |
|
| 84 | 74 |
logrus.Error(err) |
| 85 | 75 |
return "", err |
| 86 | 76 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// GetSharedBaseImages will enumerate the images stored in the common central |
| 12 | 6 |
// image store and return descriptive info about those images for the purpose |
| ... | ... |
@@ -14,43 +8,15 @@ import ( |
| 14 | 14 |
func GetSharedBaseImages() (imageData string, err error) {
|
| 15 | 15 |
title := "hcsshim::GetSharedBaseImages " |
| 16 | 16 |
|
| 17 |
- // Load the DLL and get a handle to the procedure we need |
|
| 18 |
- dll, proc, err := loadAndFind(procGetSharedBaseImages) |
|
| 19 |
- if dll != nil {
|
|
| 20 |
- defer dll.Release() |
|
| 21 |
- } |
|
| 22 |
- if err != nil {
|
|
| 23 |
- return |
|
| 24 |
- } |
|
| 25 |
- |
|
| 26 |
- // Load the OLE DLL and get a handle to the CoTaskMemFree procedure |
|
| 27 |
- dll2, proc2, err := loadAndFindFromDll(oleDLLName, procCoTaskMemFree) |
|
| 28 |
- if dll2 != nil {
|
|
| 29 |
- defer dll2.Release() |
|
| 30 |
- } |
|
| 31 |
- if err != nil {
|
|
| 32 |
- return |
|
| 33 |
- } |
|
| 34 |
- |
|
| 35 |
- var output uintptr |
|
| 36 |
- |
|
| 37 |
- // Call the procedure again |
|
| 38 | 17 |
logrus.Debugf("Calling proc")
|
| 39 |
- r1, _, _ := proc.Call( |
|
| 40 |
- uintptr(unsafe.Pointer(&output))) |
|
| 41 |
- |
|
| 42 |
- if r1 != 0 {
|
|
| 43 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d errno=%s", |
|
| 44 |
- r1, syscall.Errno(r1)) |
|
| 18 |
+ var buffer *uint16 |
|
| 19 |
+ err = getBaseImages(&buffer) |
|
| 20 |
+ if err != nil {
|
|
| 21 |
+ err = makeError(err, title, "") |
|
| 45 | 22 |
logrus.Error(err) |
| 46 | 23 |
return |
| 47 | 24 |
} |
| 48 |
- |
|
| 49 |
- // Defer the cleanup of the memory using CoTaskMemFree |
|
| 50 |
- defer proc2.Call(output) |
|
| 51 |
- |
|
| 52 |
- imageData = syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(output))[:]) |
|
| 25 |
+ imageData = convertAndFreeCoTaskMemString(buffer) |
|
| 53 | 26 |
logrus.Debugf(title+" - succeeded output=%s", imageData) |
| 54 |
- |
|
| 55 | 27 |
return |
| 56 | 28 |
} |
| ... | ... |
@@ -7,46 +7,39 @@ import ( |
| 7 | 7 |
"fmt" |
| 8 | 8 |
"syscall" |
| 9 | 9 |
"unsafe" |
| 10 |
- |
|
| 11 |
- "github.com/Sirupsen/logrus" |
|
| 12 | 10 |
) |
| 13 | 11 |
|
| 14 |
-const ( |
|
| 15 |
- // Name of the shim DLL for access to the HCS |
|
| 16 |
- shimDLLName = "vmcompute.dll" |
|
| 17 |
- |
|
| 18 |
- // Container related functions in the shim DLL |
|
| 19 |
- procCreateComputeSystem = "CreateComputeSystem" |
|
| 20 |
- procStartComputeSystem = "StartComputeSystem" |
|
| 21 |
- procCreateProcessWithStdHandlesInComputeSystem = "CreateProcessWithStdHandlesInComputeSystem" |
|
| 22 |
- procWaitForProcessInComputeSystem = "WaitForProcessInComputeSystem" |
|
| 23 |
- procShutdownComputeSystem = "ShutdownComputeSystem" |
|
| 24 |
- procTerminateComputeSystem = "TerminateComputeSystem" |
|
| 25 |
- procTerminateProcessInComputeSystem = "TerminateProcessInComputeSystem" |
|
| 26 |
- procResizeConsoleInComputeSystem = "ResizeConsoleInComputeSystem" |
|
| 27 |
- |
|
| 28 |
- // Storage related functions in the shim DLL |
|
| 29 |
- procLayerExists = "LayerExists" |
|
| 30 |
- procCreateLayer = "CreateLayer" |
|
| 31 |
- procDestroyLayer = "DestroyLayer" |
|
| 32 |
- procActivateLayer = "ActivateLayer" |
|
| 33 |
- procDeactivateLayer = "DeactivateLayer" |
|
| 34 |
- procGetLayerMountPath = "GetLayerMountPath" |
|
| 35 |
- procCopyLayer = "CopyLayer" |
|
| 36 |
- procCreateSandboxLayer = "CreateSandboxLayer" |
|
| 37 |
- procPrepareLayer = "PrepareLayer" |
|
| 38 |
- procUnprepareLayer = "UnprepareLayer" |
|
| 39 |
- procExportLayer = "ExportLayer" |
|
| 40 |
- procImportLayer = "ImportLayer" |
|
| 41 |
- procGetSharedBaseImages = "GetBaseImages" |
|
| 42 |
- procNameToGuid = "NameToGuid" |
|
| 43 |
- |
|
| 44 |
- // Name of the standard OLE dll |
|
| 45 |
- oleDLLName = "Ole32.dll" |
|
| 46 |
- |
|
| 47 |
- // Utility functions |
|
| 48 |
- procCoTaskMemFree = "CoTaskMemFree" |
|
| 12 |
+//go:generate go run mksyscall_windows.go -output zhcsshim.go hcsshim.go |
|
| 13 |
+ |
|
| 14 |
+//sys coTaskMemFree(buffer unsafe.Pointer) = ole32.CoTaskMemFree |
|
| 15 |
+ |
|
| 16 |
+//sys activateLayer(info *driverInfo, id string) (hr error) = vmcompute.ActivateLayer? |
|
| 17 |
+//sys copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CopyLayer? |
|
| 18 |
+//sys createLayer(info *driverInfo, id string, parent string) (hr error) = vmcompute.CreateLayer? |
|
| 19 |
+//sys createSandboxLayer(info *driverInfo, id string, parent string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CreateSandboxLayer? |
|
| 20 |
+//sys deactivateLayer(info *driverInfo, id string) (hr error) = vmcompute.DeactivateLayer? |
|
| 21 |
+//sys destroyLayer(info *driverInfo, id string) (hr error) = vmcompute.DestroyLayer? |
|
| 22 |
+//sys exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ExportLayer? |
|
| 23 |
+//sys getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) = vmcompute.GetLayerMountPath? |
|
| 24 |
+//sys getBaseImages(buffer **uint16) (hr error) = vmcompute.GetBaseImages? |
|
| 25 |
+//sys importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ImportLayer? |
|
| 26 |
+//sys layerExists(info *driverInfo, id string, exists *uint32) (hr error) = vmcompute.LayerExists? |
|
| 27 |
+//sys nameToGuid(name string, guid *GUID) (hr error) = vmcompute.NameToGuid? |
|
| 28 |
+//sys prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.PrepareLayer? |
|
| 29 |
+//sys unprepareLayer(info *driverInfo, id string) (hr error) = vmcompute.UnprepareLayer? |
|
| 30 |
+ |
|
| 31 |
+//sys createComputeSystem(id string, configuration string) (hr error) = vmcompute.CreateComputeSystem? |
|
| 32 |
+//sys createProcessWithStdHandlesInComputeSystem(id string, paramsJson string, pid *uint32, stdin *syscall.Handle, stdout *syscall.Handle, stderr *syscall.Handle) (hr error) = vmcompute.CreateProcessWithStdHandlesInComputeSystem? |
|
| 33 |
+//sys resizeConsoleInComputeSystem(id string, pid uint32, height uint16, width uint16, flags uint32) (hr error) = vmcompute.ResizeConsoleInComputeSystem? |
|
| 34 |
+//sys shutdownComputeSystem(id string, timeout uint32) (hr error) = vmcompute.ShutdownComputeSystem? |
|
| 35 |
+//sys startComputeSystem(id string) (hr error) = vmcompute.StartComputeSystem? |
|
| 36 |
+//sys terminateComputeSystem(id string) (hr error) = vmcompute.TerminateComputeSystem? |
|
| 37 |
+//sys terminateProcessInComputeSystem(id string, pid uint32) (hr error) = vmcompute.TerminateProcessInComputeSystem? |
|
| 38 |
+//sys waitForProcessInComputeSystem(id string, pid uint32, timeout uint32, exitCode *uint32) (hr error) = vmcompute.WaitForProcessInComputeSystem? |
|
| 39 |
+ |
|
| 40 |
+//sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall? |
|
| 49 | 41 |
|
| 42 |
+const ( |
|
| 50 | 43 |
// Specific user-visible exit codes |
| 51 | 44 |
WaitErrExecFailed = 32767 |
| 52 | 45 |
|
| ... | ... |
@@ -56,49 +49,45 @@ const ( |
| 56 | 56 |
Win32SpecifiedPathInvalid = 0x800700A1 // ShutdownComputeSystem: The specified path is invalid |
| 57 | 57 |
Win32SystemCannotFindThePathSpecified = 0x80070003 // ShutdownComputeSystem: The system cannot find the path specified |
| 58 | 58 |
Win32InvalidArgument = 0x80072726 // CreateProcessInComputeSystem: An invalid argument was supplied |
| 59 |
+ EFail = 0x80004005 |
|
| 59 | 60 |
|
| 60 | 61 |
// Timeout on wait calls |
| 61 | 62 |
TimeoutInfinite = 0xFFFFFFFF |
| 62 | 63 |
) |
| 63 | 64 |
|
| 64 |
-// loadAndFindFromDll finds a procedure in the given DLL. Note we do NOT do lazy loading as |
|
| 65 |
-// go is particularly unfriendly in the case of a mismatch. By that - it panics |
|
| 66 |
-// if a function can't be found. By explicitly loading, we can control error |
|
| 67 |
-// handling gracefully without the daemon terminating. |
|
| 68 |
-func loadAndFindFromDll(dllName, procedure string) (dll *syscall.DLL, proc *syscall.Proc, err error) {
|
|
| 69 |
- dll, err = syscall.LoadDLL(dllName) |
|
| 70 |
- if err != nil {
|
|
| 71 |
- err = fmt.Errorf("Failed to load %s - error %s", dllName, err)
|
|
| 72 |
- logrus.Error(err) |
|
| 73 |
- return |
|
| 74 |
- } |
|
| 75 |
- |
|
| 76 |
- proc, err = dll.FindProc(procedure) |
|
| 77 |
- if err != nil {
|
|
| 78 |
- err = fmt.Errorf("Failed to find %s in %s", procedure, dllName)
|
|
| 79 |
- logrus.Error(err) |
|
| 80 |
- return |
|
| 81 |
- } |
|
| 65 |
+type hcsError struct {
|
|
| 66 |
+ title string |
|
| 67 |
+ rest string |
|
| 68 |
+ err error |
|
| 69 |
+} |
|
| 82 | 70 |
|
| 83 |
- return |
|
| 71 |
+type Win32Error interface {
|
|
| 72 |
+ error |
|
| 73 |
+ HResult() uint32 |
|
| 84 | 74 |
} |
| 85 | 75 |
|
| 86 |
-// loadAndFind finds a procedure in the shim DLL. |
|
| 87 |
-func loadAndFind(procedure string) (*syscall.DLL, *syscall.Proc, error) {
|
|
| 76 |
+func makeError(err error, title, rest string) Win32Error {
|
|
| 77 |
+ return &hcsError{title, rest, err}
|
|
| 78 |
+} |
|
| 88 | 79 |
|
| 89 |
- return loadAndFindFromDll(shimDLLName, procedure) |
|
| 80 |
+func makeErrorf(err error, title, format string, a ...interface{}) Win32Error {
|
|
| 81 |
+ return makeError(err, title, fmt.Sprintf(format, a...)) |
|
| 90 | 82 |
} |
| 91 | 83 |
|
| 92 |
-// use is a no-op, but the compiler cannot see that it is. |
|
| 93 |
-// Calling use(p) ensures that p is kept live until that point. |
|
| 94 |
-/* |
|
| 95 |
-//go:noescape |
|
| 96 |
-func use(p unsafe.Pointer) |
|
| 97 |
-*/ |
|
| 84 |
+func (e *hcsError) HResult() uint32 {
|
|
| 85 |
+ if hr, ok := e.err.(syscall.Errno); ok {
|
|
| 86 |
+ return uint32(hr) |
|
| 87 |
+ } else {
|
|
| 88 |
+ return EFail |
|
| 89 |
+ } |
|
| 90 |
+} |
|
| 98 | 91 |
|
| 99 |
-// Alternate without using //go:noescape and asm.s |
|
| 100 |
-var temp unsafe.Pointer |
|
| 92 |
+func (e *hcsError) Error() string {
|
|
| 93 |
+ return fmt.Sprintf("%s- Win32 API call returned error r1=0x%x err=%s%s", e.title, e.HResult(), e.err, e.rest)
|
|
| 94 |
+} |
|
| 101 | 95 |
|
| 102 |
-func use(p unsafe.Pointer) {
|
|
| 103 |
- temp = p |
|
| 96 |
+func convertAndFreeCoTaskMemString(buffer *uint16) string {
|
|
| 97 |
+ str := syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(buffer))[:]) |
|
| 98 |
+ coTaskMemFree(unsafe.Pointer(buffer)) |
|
| 99 |
+ return str |
|
| 104 | 100 |
} |
| 105 | 101 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,131 @@ |
| 0 |
+package hcsshim |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/json" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "net" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/Sirupsen/logrus" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+type NatPolicy struct {
|
|
| 11 |
+ Type string |
|
| 12 |
+ Protocol string |
|
| 13 |
+ InternalPort uint16 |
|
| 14 |
+ ExternalPort uint16 |
|
| 15 |
+} |
|
| 16 |
+ |
|
| 17 |
+type QosPolicy struct {
|
|
| 18 |
+ Type string |
|
| 19 |
+ MaximumOutgoingBandwidthInBytes uint64 |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+// Subnet is assoicated with a network and represents a list |
|
| 23 |
+// of subnets available to the network |
|
| 24 |
+type Subnet struct {
|
|
| 25 |
+ AddressPrefix string `json:",omitempty"` |
|
| 26 |
+ GatewayAddress string `json:",omitempty"` |
|
| 27 |
+} |
|
| 28 |
+ |
|
| 29 |
+// MacPool is assoicated with a network and represents a list |
|
| 30 |
+// of macaddresses available to the network |
|
| 31 |
+type MacPool struct {
|
|
| 32 |
+ StartMacAddress string `json:",omitempty"` |
|
| 33 |
+ EndMacAddress string `json:",omitempty"` |
|
| 34 |
+} |
|
| 35 |
+ |
|
| 36 |
+// HNSNetwork represents a network in HNS |
|
| 37 |
+type HNSNetwork struct {
|
|
| 38 |
+ Id string `json:",omitempty"` |
|
| 39 |
+ Name string `json:",omitempty"` |
|
| 40 |
+ Type string `json:",omitempty"` |
|
| 41 |
+ Policies []json.RawMessage `json:",omitempty"` |
|
| 42 |
+ MacPools []MacPool `json:",omitempty"` |
|
| 43 |
+ Subnets []Subnet `json:",omitempty"` |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+// HNSEndpoint represents a network endpoint in HNS |
|
| 47 |
+type HNSEndpoint struct {
|
|
| 48 |
+ Id string `json:",omitempty"` |
|
| 49 |
+ Name string `json:",omitempty"` |
|
| 50 |
+ VirtualNetwork string `json:",omitempty"` |
|
| 51 |
+ VirtualNetworkName string `json:",omitempty"` |
|
| 52 |
+ Policies []json.RawMessage `json:",omitempty"` |
|
| 53 |
+ MacAddress string `json:",omitempty"` |
|
| 54 |
+ IPAddress net.IP `json:",omitempty"` |
|
| 55 |
+} |
|
| 56 |
+ |
|
| 57 |
+type hnsNetworkResponse struct {
|
|
| 58 |
+ Success bool |
|
| 59 |
+ Error string |
|
| 60 |
+ Output HNSNetwork |
|
| 61 |
+} |
|
| 62 |
+ |
|
| 63 |
+type hnsResponse struct {
|
|
| 64 |
+ Success bool |
|
| 65 |
+ Error string |
|
| 66 |
+ Output json.RawMessage |
|
| 67 |
+} |
|
| 68 |
+ |
|
| 69 |
+func hnsCall(method, path, request string, returnResponse interface{}) error {
|
|
| 70 |
+ var responseBuffer *uint16 |
|
| 71 |
+ err := _hnsCall(method, path, request, &responseBuffer) |
|
| 72 |
+ if err != nil {
|
|
| 73 |
+ return makeError(err, "hnsCall ", "") |
|
| 74 |
+ } |
|
| 75 |
+ response := convertAndFreeCoTaskMemString(responseBuffer) |
|
| 76 |
+ |
|
| 77 |
+ hnsresponse := &hnsResponse{}
|
|
| 78 |
+ if err = json.Unmarshal([]byte(response), &hnsresponse); err != nil {
|
|
| 79 |
+ return err |
|
| 80 |
+ } |
|
| 81 |
+ |
|
| 82 |
+ if !hnsresponse.Success {
|
|
| 83 |
+ return fmt.Errorf("HNS failed with error : %s", hnsresponse.Error)
|
|
| 84 |
+ } |
|
| 85 |
+ |
|
| 86 |
+ if len(hnsresponse.Output) == 0 {
|
|
| 87 |
+ return nil |
|
| 88 |
+ } |
|
| 89 |
+ |
|
| 90 |
+ logrus.Debugf("Network Response : %s", hnsresponse.Output)
|
|
| 91 |
+ err = json.Unmarshal(hnsresponse.Output, returnResponse) |
|
| 92 |
+ if err != nil {
|
|
| 93 |
+ return err |
|
| 94 |
+ } |
|
| 95 |
+ |
|
| 96 |
+ return nil |
|
| 97 |
+} |
|
| 98 |
+ |
|
| 99 |
+// HNSNetworkRequest makes a call into HNS to update/query a single network |
|
| 100 |
+func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) {
|
|
| 101 |
+ var network HNSNetwork |
|
| 102 |
+ err := hnsCall(method, "/networks/"+path, request, &network) |
|
| 103 |
+ if err != nil {
|
|
| 104 |
+ return nil, err |
|
| 105 |
+ } |
|
| 106 |
+ |
|
| 107 |
+ return &network, nil |
|
| 108 |
+} |
|
| 109 |
+ |
|
| 110 |
+// HNSListNetworkRequest makes a HNS call to query the list of available networks |
|
| 111 |
+func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) {
|
|
| 112 |
+ var network []HNSNetwork |
|
| 113 |
+ err := hnsCall(method, "/networks/"+path, request, &network) |
|
| 114 |
+ if err != nil {
|
|
| 115 |
+ return nil, err |
|
| 116 |
+ } |
|
| 117 |
+ |
|
| 118 |
+ return network, nil |
|
| 119 |
+} |
|
| 120 |
+ |
|
| 121 |
+// HNSEndpointRequest makes a HNS call to modify/query a network endpoint |
|
| 122 |
+func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) {
|
|
| 123 |
+ endpoint := &HNSEndpoint{}
|
|
| 124 |
+ err := hnsCall(method, "/endpoints/"+path, request, &endpoint) |
|
| 125 |
+ if err != nil {
|
|
| 126 |
+ return nil, err |
|
| 127 |
+ } |
|
| 128 |
+ |
|
| 129 |
+ return endpoint, nil |
|
| 130 |
+} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// ImportLayer will take the contents of the folder at importFolderPath and import |
| 12 | 6 |
// that into a layer with the id layerId. Note that in order to correctly populate |
| ... | ... |
@@ -16,68 +10,22 @@ func ImportLayer(info DriverInfo, layerId string, importFolderPath string, paren |
| 16 | 16 |
title := "hcsshim::ImportLayer " |
| 17 | 17 |
logrus.Debugf(title+"flavour %d layerId %s folder %s", info.Flavour, layerId, importFolderPath) |
| 18 | 18 |
|
| 19 |
- // Load the DLL and get a handle to the procedure we need |
|
| 20 |
- dll, proc, err := loadAndFind(procImportLayer) |
|
| 21 |
- if dll != nil {
|
|
| 22 |
- defer dll.Release() |
|
| 23 |
- } |
|
| 24 |
- if err != nil {
|
|
| 25 |
- return err |
|
| 26 |
- } |
|
| 27 |
- |
|
| 28 | 19 |
// Generate layer descriptors |
| 29 | 20 |
layers, err := layerPathsToDescriptors(parentLayerPaths) |
| 30 | 21 |
if err != nil {
|
| 31 |
- err = fmt.Errorf(title+"- Failed to generate layer descriptors ", err) |
|
| 32 |
- return err |
|
| 33 |
- } |
|
| 34 |
- |
|
| 35 |
- // Convert layerId to uint16 pointer for calling the procedure |
|
| 36 |
- layerIdp, err := syscall.UTF16PtrFromString(layerId) |
|
| 37 |
- if err != nil {
|
|
| 38 |
- err = fmt.Errorf(title+"- Failed conversion of layerId %s to pointer %s", layerId, err) |
|
| 39 |
- logrus.Error(err) |
|
| 40 |
- return err |
|
| 41 |
- } |
|
| 42 |
- |
|
| 43 |
- // Convert importFolderPath to uint16 pointer for calling the procedure |
|
| 44 |
- importFolderPathp, err := syscall.UTF16PtrFromString(importFolderPath) |
|
| 45 |
- if err != nil {
|
|
| 46 |
- err = fmt.Errorf(title+"- Failed conversion of importFolderPath %s to pointer %s", importFolderPath, err) |
|
| 47 |
- logrus.Error(err) |
|
| 48 | 22 |
return err |
| 49 | 23 |
} |
| 50 | 24 |
|
| 51 | 25 |
// Convert info to API calling convention |
| 52 | 26 |
infop, err := convertDriverInfo(info) |
| 53 | 27 |
if err != nil {
|
| 54 |
- err = fmt.Errorf(title+"- Failed conversion info struct %s", err) |
|
| 55 | 28 |
logrus.Error(err) |
| 56 | 29 |
return err |
| 57 | 30 |
} |
| 58 | 31 |
|
| 59 |
- var layerDescriptorsp *WC_LAYER_DESCRIPTOR |
|
| 60 |
- if len(layers) > 0 {
|
|
| 61 |
- layerDescriptorsp = &(layers[0]) |
|
| 62 |
- } else {
|
|
| 63 |
- layerDescriptorsp = nil |
|
| 64 |
- } |
|
| 65 |
- |
|
| 66 |
- // Call the procedure itself. |
|
| 67 |
- r1, _, _ := proc.Call( |
|
| 68 |
- uintptr(unsafe.Pointer(&infop)), |
|
| 69 |
- uintptr(unsafe.Pointer(layerIdp)), |
|
| 70 |
- uintptr(unsafe.Pointer(importFolderPathp)), |
|
| 71 |
- uintptr(unsafe.Pointer(layerDescriptorsp)), |
|
| 72 |
- uintptr(len(layers))) |
|
| 73 |
- use(unsafe.Pointer(&infop)) |
|
| 74 |
- use(unsafe.Pointer(layerIdp)) |
|
| 75 |
- use(unsafe.Pointer(importFolderPathp)) |
|
| 76 |
- use(unsafe.Pointer(layerDescriptorsp)) |
|
| 77 |
- |
|
| 78 |
- if r1 != 0 {
|
|
| 79 |
- err = fmt.Errorf(title+"- Win32 API call returned error r1=%d err=%s layerId=%s flavour=%d folder=%s", |
|
| 80 |
- r1, syscall.Errno(r1), layerId, info.Flavour, importFolderPath) |
|
| 32 |
+ err = importLayer(&infop, layerId, importFolderPath, layers) |
|
| 33 |
+ if err != nil {
|
|
| 34 |
+ err = makeErrorf(err, title, "layerId=%s flavour=%d folder=%s", layerId, info.Flavour, importFolderPath) |
|
| 81 | 35 |
logrus.Error(err) |
| 82 | 36 |
return err |
| 83 | 37 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// LayerExists will return true if a layer with the given id exists and is known |
| 12 | 6 |
// to the system. |
| ... | ... |
@@ -14,49 +8,23 @@ func LayerExists(info DriverInfo, id string) (bool, error) {
|
| 14 | 14 |
title := "hcsshim::LayerExists " |
| 15 | 15 |
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) |
| 16 | 16 |
|
| 17 |
- // Load the DLL and get a handle to the procedure we need |
|
| 18 |
- dll, proc, err := loadAndFind(procLayerExists) |
|
| 19 |
- if dll != nil {
|
|
| 20 |
- defer dll.Release() |
|
| 21 |
- } |
|
| 22 |
- if err != nil {
|
|
| 23 |
- return false, err |
|
| 24 |
- } |
|
| 25 |
- |
|
| 26 |
- // Convert id to uint16 pointer for calling the procedure |
|
| 27 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 28 |
- if err != nil {
|
|
| 29 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 30 |
- logrus.Error(err) |
|
| 31 |
- return false, err |
|
| 32 |
- } |
|
| 33 |
- |
|
| 34 | 17 |
// Convert info to API calling convention |
| 35 | 18 |
infop, err := convertDriverInfo(info) |
| 36 | 19 |
if err != nil {
|
| 37 |
- err = fmt.Errorf(title+" - Failed conversion info struct %s", err) |
|
| 38 | 20 |
logrus.Error(err) |
| 39 | 21 |
return false, err |
| 40 | 22 |
} |
| 41 | 23 |
|
| 42 | 24 |
// Call the procedure itself. |
| 43 |
- var exists bool // Outparam from Win32 |
|
| 25 |
+ var exists uint32 |
|
| 44 | 26 |
|
| 45 |
- r1, _, _ := proc.Call( |
|
| 46 |
- uintptr(unsafe.Pointer(&infop)), |
|
| 47 |
- uintptr(unsafe.Pointer(idp)), |
|
| 48 |
- uintptr(unsafe.Pointer(&exists))) |
|
| 49 |
- |
|
| 50 |
- use(unsafe.Pointer(&infop)) |
|
| 51 |
- use(unsafe.Pointer(idp)) |
|
| 52 |
- |
|
| 53 |
- if r1 != 0 {
|
|
| 54 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s flavour=%d", |
|
| 55 |
- r1, syscall.Errno(r1), id, info.Flavour) |
|
| 27 |
+ err = layerExists(&infop, id, &exists) |
|
| 28 |
+ if err != nil {
|
|
| 29 |
+ err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) |
|
| 56 | 30 |
logrus.Error(err) |
| 57 | 31 |
return false, err |
| 58 | 32 |
} |
| 59 | 33 |
|
| 60 | 34 |
logrus.Debugf(title+"succeeded flavour=%d id=%s exists=%d", info.Flavour, id, exists) |
| 61 |
- return exists, nil |
|
| 35 |
+ return exists != 0, nil |
|
| 62 | 36 |
} |
| 63 | 37 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,797 @@ |
| 0 |
+// Copyright 2013 The Go Authors. All rights reserved. |
|
| 1 |
+// Use of this source code is governed by a BSD-style |
|
| 2 |
+// license that can be found in the LICENSE file. |
|
| 3 |
+ |
|
| 4 |
+// +build ignore |
|
| 5 |
+ |
|
| 6 |
+/* |
|
| 7 |
+mksyscall_windows generates windows system call bodies |
|
| 8 |
+ |
|
| 9 |
+It parses all files specified on command line containing function |
|
| 10 |
+prototypes (like syscall_windows.go) and prints system call bodies |
|
| 11 |
+to standard output. |
|
| 12 |
+ |
|
| 13 |
+The prototypes are marked by lines beginning with "//sys" and read |
|
| 14 |
+like func declarations if //sys is replaced by func, but: |
|
| 15 |
+ |
|
| 16 |
+* The parameter lists must give a name for each argument. This |
|
| 17 |
+ includes return parameters. |
|
| 18 |
+ |
|
| 19 |
+* The parameter lists must give a type for each argument: |
|
| 20 |
+ the (x, y, z int) shorthand is not allowed. |
|
| 21 |
+ |
|
| 22 |
+* If the return parameter is an error number, it must be named err. |
|
| 23 |
+ |
|
| 24 |
+* If go func name needs to be different from it's winapi dll name, |
|
| 25 |
+ the winapi name could be specified at the end, after "=" sign, like |
|
| 26 |
+ //sys LoadLibrary(libname string) (handle uint32, err error) = LoadLibraryA |
|
| 27 |
+ |
|
| 28 |
+* Each function that returns err needs to supply a condition, that |
|
| 29 |
+ return value of winapi will be tested against to detect failure. |
|
| 30 |
+ This would set err to windows "last-error", otherwise it will be nil. |
|
| 31 |
+ The value can be provided at end of //sys declaration, like |
|
| 32 |
+ //sys LoadLibrary(libname string) (handle uint32, err error) [failretval==-1] = LoadLibraryA |
|
| 33 |
+ and is [failretval==0] by default. |
|
| 34 |
+ |
|
| 35 |
+Usage: |
|
| 36 |
+ mksyscall_windows [flags] [path ...] |
|
| 37 |
+ |
|
| 38 |
+The flags are: |
|
| 39 |
+ -output |
|
| 40 |
+ Specify output file name (outputs to console if blank). |
|
| 41 |
+ -trace |
|
| 42 |
+ Generate print statement after every syscall. |
|
| 43 |
+*/ |
|
| 44 |
+package main |
|
| 45 |
+ |
|
| 46 |
+import ( |
|
| 47 |
+ "bufio" |
|
| 48 |
+ "bytes" |
|
| 49 |
+ "errors" |
|
| 50 |
+ "flag" |
|
| 51 |
+ "fmt" |
|
| 52 |
+ "go/format" |
|
| 53 |
+ "go/parser" |
|
| 54 |
+ "go/token" |
|
| 55 |
+ "io" |
|
| 56 |
+ "io/ioutil" |
|
| 57 |
+ "log" |
|
| 58 |
+ "os" |
|
| 59 |
+ "strconv" |
|
| 60 |
+ "strings" |
|
| 61 |
+ "text/template" |
|
| 62 |
+) |
|
| 63 |
+ |
|
| 64 |
+var ( |
|
| 65 |
+ filename = flag.String("output", "", "output file name (standard output if omitted)")
|
|
| 66 |
+ printTraceFlag = flag.Bool("trace", false, "generate print statement after every syscall")
|
|
| 67 |
+) |
|
| 68 |
+ |
|
| 69 |
+func trim(s string) string {
|
|
| 70 |
+ return strings.Trim(s, " \t") |
|
| 71 |
+} |
|
| 72 |
+ |
|
| 73 |
+var packageName string |
|
| 74 |
+ |
|
| 75 |
+func packagename() string {
|
|
| 76 |
+ return packageName |
|
| 77 |
+} |
|
| 78 |
+ |
|
| 79 |
+func syscalldot() string {
|
|
| 80 |
+ if packageName == "syscall" {
|
|
| 81 |
+ return "" |
|
| 82 |
+ } |
|
| 83 |
+ return "syscall." |
|
| 84 |
+} |
|
| 85 |
+ |
|
| 86 |
+// Param is function parameter |
|
| 87 |
+type Param struct {
|
|
| 88 |
+ Name string |
|
| 89 |
+ Type string |
|
| 90 |
+ fn *Fn |
|
| 91 |
+ tmpVarIdx int |
|
| 92 |
+} |
|
| 93 |
+ |
|
| 94 |
+// tmpVar returns temp variable name that will be used to represent p during syscall. |
|
| 95 |
+func (p *Param) tmpVar() string {
|
|
| 96 |
+ if p.tmpVarIdx < 0 {
|
|
| 97 |
+ p.tmpVarIdx = p.fn.curTmpVarIdx |
|
| 98 |
+ p.fn.curTmpVarIdx++ |
|
| 99 |
+ } |
|
| 100 |
+ return fmt.Sprintf("_p%d", p.tmpVarIdx)
|
|
| 101 |
+} |
|
| 102 |
+ |
|
| 103 |
+// BoolTmpVarCode returns source code for bool temp variable. |
|
| 104 |
+func (p *Param) BoolTmpVarCode() string {
|
|
| 105 |
+ const code = `var %s uint32 |
|
| 106 |
+ if %s {
|
|
| 107 |
+ %s = 1 |
|
| 108 |
+ } else {
|
|
| 109 |
+ %s = 0 |
|
| 110 |
+ }` |
|
| 111 |
+ tmp := p.tmpVar() |
|
| 112 |
+ return fmt.Sprintf(code, tmp, p.Name, tmp, tmp) |
|
| 113 |
+} |
|
| 114 |
+ |
|
| 115 |
+// SliceTmpVarCode returns source code for slice temp variable. |
|
| 116 |
+func (p *Param) SliceTmpVarCode() string {
|
|
| 117 |
+ const code = `var %s *%s |
|
| 118 |
+ if len(%s) > 0 {
|
|
| 119 |
+ %s = &%s[0] |
|
| 120 |
+ }` |
|
| 121 |
+ tmp := p.tmpVar() |
|
| 122 |
+ return fmt.Sprintf(code, tmp, p.Type[2:], p.Name, tmp, p.Name) |
|
| 123 |
+} |
|
| 124 |
+ |
|
| 125 |
+// StringTmpVarCode returns source code for string temp variable. |
|
| 126 |
+func (p *Param) StringTmpVarCode() string {
|
|
| 127 |
+ errvar := p.fn.Rets.ErrorVarName() |
|
| 128 |
+ if errvar == "" {
|
|
| 129 |
+ errvar = "_" |
|
| 130 |
+ } |
|
| 131 |
+ tmp := p.tmpVar() |
|
| 132 |
+ const code = `var %s %s |
|
| 133 |
+ %s, %s = %s(%s)` |
|
| 134 |
+ s := fmt.Sprintf(code, tmp, p.fn.StrconvType(), tmp, errvar, p.fn.StrconvFunc(), p.Name) |
|
| 135 |
+ if errvar == "-" {
|
|
| 136 |
+ return s |
|
| 137 |
+ } |
|
| 138 |
+ const morecode = ` |
|
| 139 |
+ if %s != nil {
|
|
| 140 |
+ return |
|
| 141 |
+ }` |
|
| 142 |
+ return s + fmt.Sprintf(morecode, errvar) |
|
| 143 |
+} |
|
| 144 |
+ |
|
| 145 |
+// TmpVarCode returns source code for temp variable. |
|
| 146 |
+func (p *Param) TmpVarCode() string {
|
|
| 147 |
+ switch {
|
|
| 148 |
+ case p.Type == "bool": |
|
| 149 |
+ return p.BoolTmpVarCode() |
|
| 150 |
+ case strings.HasPrefix(p.Type, "[]"): |
|
| 151 |
+ return p.SliceTmpVarCode() |
|
| 152 |
+ default: |
|
| 153 |
+ return "" |
|
| 154 |
+ } |
|
| 155 |
+} |
|
| 156 |
+ |
|
| 157 |
+// TmpVarHelperCode returns source code for helper's temp variable. |
|
| 158 |
+func (p *Param) TmpVarHelperCode() string {
|
|
| 159 |
+ if p.Type != "string" {
|
|
| 160 |
+ return "" |
|
| 161 |
+ } |
|
| 162 |
+ return p.StringTmpVarCode() |
|
| 163 |
+} |
|
| 164 |
+ |
|
| 165 |
+// SyscallArgList returns source code fragments representing p parameter |
|
| 166 |
+// in syscall. Slices are translated into 2 syscall parameters: pointer to |
|
| 167 |
+// the first element and length. |
|
| 168 |
+func (p *Param) SyscallArgList() []string {
|
|
| 169 |
+ t := p.HelperType() |
|
| 170 |
+ var s string |
|
| 171 |
+ switch {
|
|
| 172 |
+ case t[0] == '*': |
|
| 173 |
+ s = fmt.Sprintf("unsafe.Pointer(%s)", p.Name)
|
|
| 174 |
+ case t == "bool": |
|
| 175 |
+ s = p.tmpVar() |
|
| 176 |
+ case strings.HasPrefix(t, "[]"): |
|
| 177 |
+ return []string{
|
|
| 178 |
+ fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.tmpVar()),
|
|
| 179 |
+ fmt.Sprintf("uintptr(len(%s))", p.Name),
|
|
| 180 |
+ } |
|
| 181 |
+ default: |
|
| 182 |
+ s = p.Name |
|
| 183 |
+ } |
|
| 184 |
+ return []string{fmt.Sprintf("uintptr(%s)", s)}
|
|
| 185 |
+} |
|
| 186 |
+ |
|
| 187 |
+// IsError determines if p parameter is used to return error. |
|
| 188 |
+func (p *Param) IsError() bool {
|
|
| 189 |
+ return p.Name == "err" && p.Type == "error" |
|
| 190 |
+} |
|
| 191 |
+ |
|
| 192 |
+// HelperType returns type of parameter p used in helper function. |
|
| 193 |
+func (p *Param) HelperType() string {
|
|
| 194 |
+ if p.Type == "string" {
|
|
| 195 |
+ return p.fn.StrconvType() |
|
| 196 |
+ } |
|
| 197 |
+ return p.Type |
|
| 198 |
+} |
|
| 199 |
+ |
|
| 200 |
+// join concatenates parameters ps into a string with sep separator. |
|
| 201 |
+// Each parameter is converted into string by applying fn to it |
|
| 202 |
+// before conversion. |
|
| 203 |
+func join(ps []*Param, fn func(*Param) string, sep string) string {
|
|
| 204 |
+ if len(ps) == 0 {
|
|
| 205 |
+ return "" |
|
| 206 |
+ } |
|
| 207 |
+ a := make([]string, 0) |
|
| 208 |
+ for _, p := range ps {
|
|
| 209 |
+ a = append(a, fn(p)) |
|
| 210 |
+ } |
|
| 211 |
+ return strings.Join(a, sep) |
|
| 212 |
+} |
|
| 213 |
+ |
|
| 214 |
+// Rets describes function return parameters. |
|
| 215 |
+type Rets struct {
|
|
| 216 |
+ Name string |
|
| 217 |
+ Type string |
|
| 218 |
+ ReturnsError bool |
|
| 219 |
+ FailCond string |
|
| 220 |
+} |
|
| 221 |
+ |
|
| 222 |
+// ErrorVarName returns error variable name for r. |
|
| 223 |
+func (r *Rets) ErrorVarName() string {
|
|
| 224 |
+ if r.ReturnsError {
|
|
| 225 |
+ return "err" |
|
| 226 |
+ } |
|
| 227 |
+ if r.Type == "error" {
|
|
| 228 |
+ return r.Name |
|
| 229 |
+ } |
|
| 230 |
+ return "" |
|
| 231 |
+} |
|
| 232 |
+ |
|
| 233 |
+// ToParams converts r into slice of *Param. |
|
| 234 |
+func (r *Rets) ToParams() []*Param {
|
|
| 235 |
+ ps := make([]*Param, 0) |
|
| 236 |
+ if len(r.Name) > 0 {
|
|
| 237 |
+ ps = append(ps, &Param{Name: r.Name, Type: r.Type})
|
|
| 238 |
+ } |
|
| 239 |
+ if r.ReturnsError {
|
|
| 240 |
+ ps = append(ps, &Param{Name: "err", Type: "error"})
|
|
| 241 |
+ } |
|
| 242 |
+ return ps |
|
| 243 |
+} |
|
| 244 |
+ |
|
| 245 |
+// List returns source code of syscall return parameters. |
|
| 246 |
+func (r *Rets) List() string {
|
|
| 247 |
+ s := join(r.ToParams(), func(p *Param) string { return p.Name + " " + p.Type }, ", ")
|
|
| 248 |
+ if len(s) > 0 {
|
|
| 249 |
+ s = "(" + s + ")"
|
|
| 250 |
+ } |
|
| 251 |
+ return s |
|
| 252 |
+} |
|
| 253 |
+ |
|
| 254 |
+// PrintList returns source code of trace printing part correspondent |
|
| 255 |
+// to syscall return values. |
|
| 256 |
+func (r *Rets) PrintList() string {
|
|
| 257 |
+ return join(r.ToParams(), func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `)
|
|
| 258 |
+} |
|
| 259 |
+ |
|
| 260 |
+// SetReturnValuesCode returns source code that accepts syscall return values. |
|
| 261 |
+func (r *Rets) SetReturnValuesCode() string {
|
|
| 262 |
+ if r.Name == "" && !r.ReturnsError {
|
|
| 263 |
+ return "" |
|
| 264 |
+ } |
|
| 265 |
+ retvar := "r0" |
|
| 266 |
+ if r.Name == "" {
|
|
| 267 |
+ retvar = "r1" |
|
| 268 |
+ } |
|
| 269 |
+ errvar := "_" |
|
| 270 |
+ if r.ReturnsError {
|
|
| 271 |
+ errvar = "e1" |
|
| 272 |
+ } |
|
| 273 |
+ return fmt.Sprintf("%s, _, %s := ", retvar, errvar)
|
|
| 274 |
+} |
|
| 275 |
+ |
|
| 276 |
+func (r *Rets) useLongHandleErrorCode(retvar string) string {
|
|
| 277 |
+ const code = `if %s {
|
|
| 278 |
+ if e1 != 0 {
|
|
| 279 |
+ err = error(e1) |
|
| 280 |
+ } else {
|
|
| 281 |
+ err = %sEINVAL |
|
| 282 |
+ } |
|
| 283 |
+ }` |
|
| 284 |
+ cond := retvar + " == 0" |
|
| 285 |
+ if r.FailCond != "" {
|
|
| 286 |
+ cond = strings.Replace(r.FailCond, "failretval", retvar, 1) |
|
| 287 |
+ } |
|
| 288 |
+ return fmt.Sprintf(code, cond, syscalldot()) |
|
| 289 |
+} |
|
| 290 |
+ |
|
| 291 |
+// SetErrorCode returns source code that sets return parameters. |
|
| 292 |
+func (r *Rets) SetErrorCode() string {
|
|
| 293 |
+ const code = `if r0 != 0 {
|
|
| 294 |
+ %s = %sErrno(r0) |
|
| 295 |
+ }` |
|
| 296 |
+ if r.Name == "" && !r.ReturnsError {
|
|
| 297 |
+ return "" |
|
| 298 |
+ } |
|
| 299 |
+ if r.Name == "" {
|
|
| 300 |
+ return r.useLongHandleErrorCode("r1")
|
|
| 301 |
+ } |
|
| 302 |
+ if r.Type == "error" {
|
|
| 303 |
+ return fmt.Sprintf(code, r.Name, syscalldot()) |
|
| 304 |
+ } |
|
| 305 |
+ s := "" |
|
| 306 |
+ switch {
|
|
| 307 |
+ case r.Type[0] == '*': |
|
| 308 |
+ s = fmt.Sprintf("%s = (%s)(unsafe.Pointer(r0))", r.Name, r.Type)
|
|
| 309 |
+ case r.Type == "bool": |
|
| 310 |
+ s = fmt.Sprintf("%s = r0 != 0", r.Name)
|
|
| 311 |
+ default: |
|
| 312 |
+ s = fmt.Sprintf("%s = %s(r0)", r.Name, r.Type)
|
|
| 313 |
+ } |
|
| 314 |
+ if !r.ReturnsError {
|
|
| 315 |
+ return s |
|
| 316 |
+ } |
|
| 317 |
+ return s + "\n\t" + r.useLongHandleErrorCode(r.Name) |
|
| 318 |
+} |
|
| 319 |
+ |
|
| 320 |
+// Fn describes syscall function. |
|
| 321 |
+type Fn struct {
|
|
| 322 |
+ Name string |
|
| 323 |
+ Params []*Param |
|
| 324 |
+ Rets *Rets |
|
| 325 |
+ PrintTrace bool |
|
| 326 |
+ confirmproc bool |
|
| 327 |
+ dllname string |
|
| 328 |
+ dllfuncname string |
|
| 329 |
+ src string |
|
| 330 |
+ // TODO: get rid of this field and just use parameter index instead |
|
| 331 |
+ curTmpVarIdx int // insure tmp variables have uniq names |
|
| 332 |
+} |
|
| 333 |
+ |
|
| 334 |
+// extractParams parses s to extract function parameters. |
|
| 335 |
+func extractParams(s string, f *Fn) ([]*Param, error) {
|
|
| 336 |
+ s = trim(s) |
|
| 337 |
+ if s == "" {
|
|
| 338 |
+ return nil, nil |
|
| 339 |
+ } |
|
| 340 |
+ a := strings.Split(s, ",") |
|
| 341 |
+ ps := make([]*Param, len(a)) |
|
| 342 |
+ for i := range ps {
|
|
| 343 |
+ s2 := trim(a[i]) |
|
| 344 |
+ b := strings.Split(s2, " ") |
|
| 345 |
+ if len(b) != 2 {
|
|
| 346 |
+ b = strings.Split(s2, "\t") |
|
| 347 |
+ if len(b) != 2 {
|
|
| 348 |
+ return nil, errors.New("Could not extract function parameter from \"" + s2 + "\"")
|
|
| 349 |
+ } |
|
| 350 |
+ } |
|
| 351 |
+ ps[i] = &Param{
|
|
| 352 |
+ Name: trim(b[0]), |
|
| 353 |
+ Type: trim(b[1]), |
|
| 354 |
+ fn: f, |
|
| 355 |
+ tmpVarIdx: -1, |
|
| 356 |
+ } |
|
| 357 |
+ } |
|
| 358 |
+ return ps, nil |
|
| 359 |
+} |
|
| 360 |
+ |
|
| 361 |
+// extractSection extracts text out of string s starting after start |
|
| 362 |
+// and ending just before end. found return value will indicate success, |
|
| 363 |
+// and prefix, body and suffix will contain correspondent parts of string s. |
|
| 364 |
+func extractSection(s string, start, end rune) (prefix, body, suffix string, found bool) {
|
|
| 365 |
+ s = trim(s) |
|
| 366 |
+ if strings.HasPrefix(s, string(start)) {
|
|
| 367 |
+ // no prefix |
|
| 368 |
+ body = s[1:] |
|
| 369 |
+ } else {
|
|
| 370 |
+ a := strings.SplitN(s, string(start), 2) |
|
| 371 |
+ if len(a) != 2 {
|
|
| 372 |
+ return "", "", s, false |
|
| 373 |
+ } |
|
| 374 |
+ prefix = a[0] |
|
| 375 |
+ body = a[1] |
|
| 376 |
+ } |
|
| 377 |
+ a := strings.SplitN(body, string(end), 2) |
|
| 378 |
+ if len(a) != 2 {
|
|
| 379 |
+ return "", "", "", false |
|
| 380 |
+ } |
|
| 381 |
+ return prefix, a[0], a[1], true |
|
| 382 |
+} |
|
| 383 |
+ |
|
| 384 |
+// newFn parses string s and return created function Fn. |
|
| 385 |
+func newFn(s string) (*Fn, error) {
|
|
| 386 |
+ s = trim(s) |
|
| 387 |
+ f := &Fn{
|
|
| 388 |
+ Rets: &Rets{},
|
|
| 389 |
+ src: s, |
|
| 390 |
+ PrintTrace: *printTraceFlag, |
|
| 391 |
+ } |
|
| 392 |
+ // function name and args |
|
| 393 |
+ prefix, body, s, found := extractSection(s, '(', ')')
|
|
| 394 |
+ if !found || prefix == "" {
|
|
| 395 |
+ return nil, errors.New("Could not extract function name and parameters from \"" + f.src + "\"")
|
|
| 396 |
+ } |
|
| 397 |
+ f.Name = prefix |
|
| 398 |
+ var err error |
|
| 399 |
+ f.Params, err = extractParams(body, f) |
|
| 400 |
+ if err != nil {
|
|
| 401 |
+ return nil, err |
|
| 402 |
+ } |
|
| 403 |
+ // return values |
|
| 404 |
+ _, body, s, found = extractSection(s, '(', ')')
|
|
| 405 |
+ if found {
|
|
| 406 |
+ r, err := extractParams(body, f) |
|
| 407 |
+ if err != nil {
|
|
| 408 |
+ return nil, err |
|
| 409 |
+ } |
|
| 410 |
+ switch len(r) {
|
|
| 411 |
+ case 0: |
|
| 412 |
+ case 1: |
|
| 413 |
+ if r[0].IsError() {
|
|
| 414 |
+ f.Rets.ReturnsError = true |
|
| 415 |
+ } else {
|
|
| 416 |
+ f.Rets.Name = r[0].Name |
|
| 417 |
+ f.Rets.Type = r[0].Type |
|
| 418 |
+ } |
|
| 419 |
+ case 2: |
|
| 420 |
+ if !r[1].IsError() {
|
|
| 421 |
+ return nil, errors.New("Only last windows error is allowed as second return value in \"" + f.src + "\"")
|
|
| 422 |
+ } |
|
| 423 |
+ f.Rets.ReturnsError = true |
|
| 424 |
+ f.Rets.Name = r[0].Name |
|
| 425 |
+ f.Rets.Type = r[0].Type |
|
| 426 |
+ default: |
|
| 427 |
+ return nil, errors.New("Too many return values in \"" + f.src + "\"")
|
|
| 428 |
+ } |
|
| 429 |
+ } |
|
| 430 |
+ // fail condition |
|
| 431 |
+ _, body, s, found = extractSection(s, '[', ']') |
|
| 432 |
+ if found {
|
|
| 433 |
+ f.Rets.FailCond = body |
|
| 434 |
+ } |
|
| 435 |
+ // dll and dll function names |
|
| 436 |
+ s = trim(s) |
|
| 437 |
+ if s == "" {
|
|
| 438 |
+ return f, nil |
|
| 439 |
+ } |
|
| 440 |
+ if !strings.HasPrefix(s, "=") {
|
|
| 441 |
+ return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
|
|
| 442 |
+ } |
|
| 443 |
+ s = trim(s[1:]) |
|
| 444 |
+ a := strings.Split(s, ".") |
|
| 445 |
+ switch len(a) {
|
|
| 446 |
+ case 1: |
|
| 447 |
+ f.dllfuncname = a[0] |
|
| 448 |
+ case 2: |
|
| 449 |
+ f.dllname = a[0] |
|
| 450 |
+ f.dllfuncname = a[1] |
|
| 451 |
+ default: |
|
| 452 |
+ return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
|
|
| 453 |
+ } |
|
| 454 |
+ if f.dllfuncname[len(f.dllfuncname)-1] == '?' {
|
|
| 455 |
+ f.confirmproc = true |
|
| 456 |
+ f.dllfuncname = f.dllfuncname[0 : len(f.dllfuncname)-1] |
|
| 457 |
+ } |
|
| 458 |
+ return f, nil |
|
| 459 |
+} |
|
| 460 |
+ |
|
| 461 |
+// DLLName returns DLL name for function f. |
|
| 462 |
+func (f *Fn) DLLName() string {
|
|
| 463 |
+ if f.dllname == "" {
|
|
| 464 |
+ return "kernel32" |
|
| 465 |
+ } |
|
| 466 |
+ return f.dllname |
|
| 467 |
+} |
|
| 468 |
+ |
|
| 469 |
+// DLLName returns DLL function name for function f. |
|
| 470 |
+func (f *Fn) DLLFuncName() string {
|
|
| 471 |
+ if f.dllfuncname == "" {
|
|
| 472 |
+ return f.Name |
|
| 473 |
+ } |
|
| 474 |
+ return f.dllfuncname |
|
| 475 |
+} |
|
| 476 |
+ |
|
| 477 |
+func (f *Fn) ConfirmProc() bool {
|
|
| 478 |
+ return f.confirmproc |
|
| 479 |
+} |
|
| 480 |
+ |
|
| 481 |
+// ParamList returns source code for function f parameters. |
|
| 482 |
+func (f *Fn) ParamList() string {
|
|
| 483 |
+ return join(f.Params, func(p *Param) string { return p.Name + " " + p.Type }, ", ")
|
|
| 484 |
+} |
|
| 485 |
+ |
|
| 486 |
+// HelperParamList returns source code for helper function f parameters. |
|
| 487 |
+func (f *Fn) HelperParamList() string {
|
|
| 488 |
+ return join(f.Params, func(p *Param) string { return p.Name + " " + p.HelperType() }, ", ")
|
|
| 489 |
+} |
|
| 490 |
+ |
|
| 491 |
+// ParamPrintList returns source code of trace printing part correspondent |
|
| 492 |
+// to syscall input parameters. |
|
| 493 |
+func (f *Fn) ParamPrintList() string {
|
|
| 494 |
+ return join(f.Params, func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `)
|
|
| 495 |
+} |
|
| 496 |
+ |
|
| 497 |
+// ParamCount return number of syscall parameters for function f. |
|
| 498 |
+func (f *Fn) ParamCount() int {
|
|
| 499 |
+ n := 0 |
|
| 500 |
+ for _, p := range f.Params {
|
|
| 501 |
+ n += len(p.SyscallArgList()) |
|
| 502 |
+ } |
|
| 503 |
+ return n |
|
| 504 |
+} |
|
| 505 |
+ |
|
| 506 |
+// SyscallParamCount determines which version of Syscall/Syscall6/Syscall9/... |
|
| 507 |
+// to use. It returns parameter count for correspondent SyscallX function. |
|
| 508 |
+func (f *Fn) SyscallParamCount() int {
|
|
| 509 |
+ n := f.ParamCount() |
|
| 510 |
+ switch {
|
|
| 511 |
+ case n <= 3: |
|
| 512 |
+ return 3 |
|
| 513 |
+ case n <= 6: |
|
| 514 |
+ return 6 |
|
| 515 |
+ case n <= 9: |
|
| 516 |
+ return 9 |
|
| 517 |
+ case n <= 12: |
|
| 518 |
+ return 12 |
|
| 519 |
+ case n <= 15: |
|
| 520 |
+ return 15 |
|
| 521 |
+ default: |
|
| 522 |
+ panic("too many arguments to system call")
|
|
| 523 |
+ } |
|
| 524 |
+} |
|
| 525 |
+ |
|
| 526 |
+// Syscall determines which SyscallX function to use for function f. |
|
| 527 |
+func (f *Fn) Syscall() string {
|
|
| 528 |
+ c := f.SyscallParamCount() |
|
| 529 |
+ if c == 3 {
|
|
| 530 |
+ return syscalldot() + "Syscall" |
|
| 531 |
+ } |
|
| 532 |
+ return syscalldot() + "Syscall" + strconv.Itoa(c) |
|
| 533 |
+} |
|
| 534 |
+ |
|
| 535 |
+// SyscallParamList returns source code for SyscallX parameters for function f. |
|
| 536 |
+func (f *Fn) SyscallParamList() string {
|
|
| 537 |
+ a := make([]string, 0) |
|
| 538 |
+ for _, p := range f.Params {
|
|
| 539 |
+ a = append(a, p.SyscallArgList()...) |
|
| 540 |
+ } |
|
| 541 |
+ for len(a) < f.SyscallParamCount() {
|
|
| 542 |
+ a = append(a, "0") |
|
| 543 |
+ } |
|
| 544 |
+ return strings.Join(a, ", ") |
|
| 545 |
+} |
|
| 546 |
+ |
|
| 547 |
+// HelperCallParamList returns source code of call into function f helper. |
|
| 548 |
+func (f *Fn) HelperCallParamList() string {
|
|
| 549 |
+ a := make([]string, 0, len(f.Params)) |
|
| 550 |
+ for _, p := range f.Params {
|
|
| 551 |
+ s := p.Name |
|
| 552 |
+ if p.Type == "string" {
|
|
| 553 |
+ s = p.tmpVar() |
|
| 554 |
+ } |
|
| 555 |
+ a = append(a, s) |
|
| 556 |
+ } |
|
| 557 |
+ return strings.Join(a, ", ") |
|
| 558 |
+} |
|
| 559 |
+ |
|
| 560 |
+// IsUTF16 is true, if f is W (utf16) function. It is false |
|
| 561 |
+// for all A (ascii) functions. |
|
| 562 |
+func (_ *Fn) IsUTF16() bool {
|
|
| 563 |
+ return true |
|
| 564 |
+} |
|
| 565 |
+ |
|
| 566 |
+// StrconvFunc returns name of Go string to OS string function for f. |
|
| 567 |
+func (f *Fn) StrconvFunc() string {
|
|
| 568 |
+ if f.IsUTF16() {
|
|
| 569 |
+ return syscalldot() + "UTF16PtrFromString" |
|
| 570 |
+ } |
|
| 571 |
+ return syscalldot() + "BytePtrFromString" |
|
| 572 |
+} |
|
| 573 |
+ |
|
| 574 |
+// StrconvType returns Go type name used for OS string for f. |
|
| 575 |
+func (f *Fn) StrconvType() string {
|
|
| 576 |
+ if f.IsUTF16() {
|
|
| 577 |
+ return "*uint16" |
|
| 578 |
+ } |
|
| 579 |
+ return "*byte" |
|
| 580 |
+} |
|
| 581 |
+ |
|
| 582 |
+// HasStringParam is true, if f has at least one string parameter. |
|
| 583 |
+// Otherwise it is false. |
|
| 584 |
+func (f *Fn) HasStringParam() bool {
|
|
| 585 |
+ for _, p := range f.Params {
|
|
| 586 |
+ if p.Type == "string" {
|
|
| 587 |
+ return true |
|
| 588 |
+ } |
|
| 589 |
+ } |
|
| 590 |
+ return false |
|
| 591 |
+} |
|
| 592 |
+ |
|
| 593 |
+// HelperName returns name of function f helper. |
|
| 594 |
+func (f *Fn) HelperName() string {
|
|
| 595 |
+ if !f.HasStringParam() {
|
|
| 596 |
+ return f.Name |
|
| 597 |
+ } |
|
| 598 |
+ return "_" + f.Name |
|
| 599 |
+} |
|
| 600 |
+ |
|
| 601 |
+// Source files and functions. |
|
| 602 |
+type Source struct {
|
|
| 603 |
+ Funcs []*Fn |
|
| 604 |
+ Files []string |
|
| 605 |
+} |
|
| 606 |
+ |
|
| 607 |
+// ParseFiles parses files listed in fs and extracts all syscall |
|
| 608 |
+// functions listed in sys comments. It returns source files |
|
| 609 |
+// and functions collection *Source if successful. |
|
| 610 |
+func ParseFiles(fs []string) (*Source, error) {
|
|
| 611 |
+ src := &Source{
|
|
| 612 |
+ Funcs: make([]*Fn, 0), |
|
| 613 |
+ Files: make([]string, 0), |
|
| 614 |
+ } |
|
| 615 |
+ for _, file := range fs {
|
|
| 616 |
+ if err := src.ParseFile(file); err != nil {
|
|
| 617 |
+ return nil, err |
|
| 618 |
+ } |
|
| 619 |
+ } |
|
| 620 |
+ return src, nil |
|
| 621 |
+} |
|
| 622 |
+ |
|
| 623 |
+// DLLs return dll names for a source set src. |
|
| 624 |
+func (src *Source) DLLs() []string {
|
|
| 625 |
+ uniq := make(map[string]bool) |
|
| 626 |
+ r := make([]string, 0) |
|
| 627 |
+ for _, f := range src.Funcs {
|
|
| 628 |
+ name := f.DLLName() |
|
| 629 |
+ if _, found := uniq[name]; !found {
|
|
| 630 |
+ uniq[name] = true |
|
| 631 |
+ r = append(r, name) |
|
| 632 |
+ } |
|
| 633 |
+ } |
|
| 634 |
+ return r |
|
| 635 |
+} |
|
| 636 |
+ |
|
| 637 |
+// ParseFile adds additional file path to a source set src. |
|
| 638 |
+func (src *Source) ParseFile(path string) error {
|
|
| 639 |
+ file, err := os.Open(path) |
|
| 640 |
+ if err != nil {
|
|
| 641 |
+ return err |
|
| 642 |
+ } |
|
| 643 |
+ defer file.Close() |
|
| 644 |
+ |
|
| 645 |
+ s := bufio.NewScanner(file) |
|
| 646 |
+ for s.Scan() {
|
|
| 647 |
+ t := trim(s.Text()) |
|
| 648 |
+ if len(t) < 7 {
|
|
| 649 |
+ continue |
|
| 650 |
+ } |
|
| 651 |
+ if !strings.HasPrefix(t, "//sys") {
|
|
| 652 |
+ continue |
|
| 653 |
+ } |
|
| 654 |
+ t = t[5:] |
|
| 655 |
+ if !(t[0] == ' ' || t[0] == '\t') {
|
|
| 656 |
+ continue |
|
| 657 |
+ } |
|
| 658 |
+ f, err := newFn(t[1:]) |
|
| 659 |
+ if err != nil {
|
|
| 660 |
+ return err |
|
| 661 |
+ } |
|
| 662 |
+ src.Funcs = append(src.Funcs, f) |
|
| 663 |
+ } |
|
| 664 |
+ if err := s.Err(); err != nil {
|
|
| 665 |
+ return err |
|
| 666 |
+ } |
|
| 667 |
+ src.Files = append(src.Files, path) |
|
| 668 |
+ |
|
| 669 |
+ // get package name |
|
| 670 |
+ fset := token.NewFileSet() |
|
| 671 |
+ _, err = file.Seek(0, 0) |
|
| 672 |
+ if err != nil {
|
|
| 673 |
+ return err |
|
| 674 |
+ } |
|
| 675 |
+ pkg, err := parser.ParseFile(fset, "", file, parser.PackageClauseOnly) |
|
| 676 |
+ if err != nil {
|
|
| 677 |
+ return err |
|
| 678 |
+ } |
|
| 679 |
+ packageName = pkg.Name.Name |
|
| 680 |
+ |
|
| 681 |
+ return nil |
|
| 682 |
+} |
|
| 683 |
+ |
|
| 684 |
+// Generate output source file from a source set src. |
|
| 685 |
+func (src *Source) Generate(w io.Writer) error {
|
|
| 686 |
+ funcMap := template.FuncMap{
|
|
| 687 |
+ "packagename": packagename, |
|
| 688 |
+ "syscalldot": syscalldot, |
|
| 689 |
+ } |
|
| 690 |
+ t := template.Must(template.New("main").Funcs(funcMap).Parse(srcTemplate))
|
|
| 691 |
+ err := t.Execute(w, src) |
|
| 692 |
+ if err != nil {
|
|
| 693 |
+ return errors.New("Failed to execute template: " + err.Error())
|
|
| 694 |
+ } |
|
| 695 |
+ return nil |
|
| 696 |
+} |
|
| 697 |
+ |
|
| 698 |
+func usage() {
|
|
| 699 |
+ fmt.Fprintf(os.Stderr, "usage: mksyscall_windows [flags] [path ...]\n") |
|
| 700 |
+ flag.PrintDefaults() |
|
| 701 |
+ os.Exit(1) |
|
| 702 |
+} |
|
| 703 |
+ |
|
| 704 |
+func main() {
|
|
| 705 |
+ flag.Usage = usage |
|
| 706 |
+ flag.Parse() |
|
| 707 |
+ if len(flag.Args()) <= 0 {
|
|
| 708 |
+ fmt.Fprintf(os.Stderr, "no files to parse provided\n") |
|
| 709 |
+ usage() |
|
| 710 |
+ } |
|
| 711 |
+ |
|
| 712 |
+ src, err := ParseFiles(flag.Args()) |
|
| 713 |
+ if err != nil {
|
|
| 714 |
+ log.Fatal(err) |
|
| 715 |
+ } |
|
| 716 |
+ |
|
| 717 |
+ var buf bytes.Buffer |
|
| 718 |
+ if err := src.Generate(&buf); err != nil {
|
|
| 719 |
+ log.Fatal(err) |
|
| 720 |
+ } |
|
| 721 |
+ |
|
| 722 |
+ data, err := format.Source(buf.Bytes()) |
|
| 723 |
+ if err != nil {
|
|
| 724 |
+ log.Fatal(err) |
|
| 725 |
+ } |
|
| 726 |
+ if *filename == "" {
|
|
| 727 |
+ _, err = os.Stdout.Write(data) |
|
| 728 |
+ } else {
|
|
| 729 |
+ err = ioutil.WriteFile(*filename, data, 0644) |
|
| 730 |
+ } |
|
| 731 |
+ if err != nil {
|
|
| 732 |
+ log.Fatal(err) |
|
| 733 |
+ } |
|
| 734 |
+} |
|
| 735 |
+ |
|
| 736 |
+// TODO: use println instead to print in the following template |
|
| 737 |
+const srcTemplate = ` |
|
| 738 |
+ |
|
| 739 |
+{{define "main"}}// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
|
|
| 740 |
+ |
|
| 741 |
+package {{packagename}}
|
|
| 742 |
+ |
|
| 743 |
+import "unsafe"{{if syscalldot}}
|
|
| 744 |
+import "syscall"{{end}}
|
|
| 745 |
+ |
|
| 746 |
+var _ unsafe.Pointer |
|
| 747 |
+ |
|
| 748 |
+var ( |
|
| 749 |
+{{template "dlls" .}}
|
|
| 750 |
+{{template "funcnames" .}})
|
|
| 751 |
+{{range .Funcs}}{{if .HasStringParam}}{{template "helperbody" .}}{{end}}{{template "funcbody" .}}{{end}}
|
|
| 752 |
+{{end}}
|
|
| 753 |
+ |
|
| 754 |
+{{/* help functions */}}
|
|
| 755 |
+ |
|
| 756 |
+{{define "dlls"}}{{range .DLLs}} mod{{.}} = {{syscalldot}}NewLazyDLL("{{.}}.dll")
|
|
| 757 |
+{{end}}{{end}}
|
|
| 758 |
+ |
|
| 759 |
+{{define "funcnames"}}{{range .Funcs}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}")
|
|
| 760 |
+{{end}}{{end}}
|
|
| 761 |
+ |
|
| 762 |
+{{define "helperbody"}}
|
|
| 763 |
+func {{.Name}}({{.ParamList}}) {{template "results" .}}{
|
|
| 764 |
+{{template "helpertmpvars" .}} return {{.HelperName}}({{.HelperCallParamList}})
|
|
| 765 |
+} |
|
| 766 |
+{{end}}
|
|
| 767 |
+ |
|
| 768 |
+{{define "funcbody"}}
|
|
| 769 |
+func {{.HelperName}}({{.HelperParamList}}) {{template "results" .}}{
|
|
| 770 |
+{{template "tmpvars" .}} {{template "syscallcheck" .}}{{template "syscall" .}}
|
|
| 771 |
+{{template "seterror" .}}{{template "printtrace" .}} return
|
|
| 772 |
+} |
|
| 773 |
+{{end}}
|
|
| 774 |
+ |
|
| 775 |
+{{define "helpertmpvars"}}{{range .Params}}{{if .TmpVarHelperCode}} {{.TmpVarHelperCode}}
|
|
| 776 |
+{{end}}{{end}}{{end}}
|
|
| 777 |
+ |
|
| 778 |
+{{define "tmpvars"}}{{range .Params}}{{if .TmpVarCode}} {{.TmpVarCode}}
|
|
| 779 |
+{{end}}{{end}}{{end}}
|
|
| 780 |
+ |
|
| 781 |
+{{define "results"}}{{if .Rets.List}}{{.Rets.List}} {{end}}{{end}}
|
|
| 782 |
+ |
|
| 783 |
+{{define "syscallcheck"}}{{if .ConfirmProc}}if {{.Rets.ErrorVarName}} = proc{{.DLLFuncName}}.Find(); {{.Rets.ErrorVarName}} != nil {
|
|
| 784 |
+ return |
|
| 785 |
+} |
|
| 786 |
+{{end}}{{end}}
|
|
| 787 |
+ |
|
| 788 |
+{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(), {{.ParamCount}}, {{.SyscallParamList}}){{end}}
|
|
| 789 |
+ |
|
| 790 |
+{{define "seterror"}}{{if .Rets.SetErrorCode}} {{.Rets.SetErrorCode}}
|
|
| 791 |
+{{end}}{{end}}
|
|
| 792 |
+ |
|
| 793 |
+{{define "printtrace"}}{{if .PrintTrace}} print("SYSCALL: {{.Name}}(", {{.ParamPrintList}}") (", {{.Rets.PrintList}}")\n")
|
|
| 794 |
+{{end}}{{end}}
|
|
| 795 |
+ |
|
| 796 |
+` |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// NameToGuid converts the given string into a GUID using the algorithm in the |
| 12 | 6 |
// Host Compute Service, ensuring GUIDs generated with the same string are common |
| ... | ... |
@@ -15,32 +9,9 @@ func NameToGuid(name string) (id GUID, err error) {
|
| 15 | 15 |
title := "hcsshim::NameToGuid " |
| 16 | 16 |
logrus.Debugf(title+"Name %s", name) |
| 17 | 17 |
|
| 18 |
- // Load the DLL and get a handle to the procedure we need |
|
| 19 |
- dll, proc, err := loadAndFind(procNameToGuid) |
|
| 20 |
- if dll != nil {
|
|
| 21 |
- defer dll.Release() |
|
| 22 |
- } |
|
| 23 |
- if err != nil {
|
|
| 24 |
- return |
|
| 25 |
- } |
|
| 26 |
- |
|
| 27 |
- // Convert name to uint16 pointer for calling the procedure |
|
| 28 |
- namep, err := syscall.UTF16PtrFromString(name) |
|
| 18 |
+ err = nameToGuid(name, &id) |
|
| 29 | 19 |
if err != nil {
|
| 30 |
- err = fmt.Errorf(title+" - Failed conversion of name %s to pointer %s", name, err) |
|
| 31 |
- logrus.Error(err) |
|
| 32 |
- return |
|
| 33 |
- } |
|
| 34 |
- |
|
| 35 |
- // Call the procedure itself. |
|
| 36 |
- logrus.Debugf("Calling proc")
|
|
| 37 |
- r1, _, _ := proc.Call( |
|
| 38 |
- uintptr(unsafe.Pointer(namep)), |
|
| 39 |
- uintptr(unsafe.Pointer(&id))) |
|
| 40 |
- |
|
| 41 |
- if r1 != 0 {
|
|
| 42 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s name=%s", |
|
| 43 |
- r1, syscall.Errno(r1), name) |
|
| 20 |
+ err = makeErrorf(err, title, "name=%s", name) |
|
| 44 | 21 |
logrus.Error(err) |
| 45 | 22 |
return |
| 46 | 23 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// PrepareLayer finds a mounted read-write layer matching layerId and enables the |
| 12 | 6 |
// the filesystem filter for use on that layer. This requires the paths to all |
| ... | ... |
@@ -17,58 +11,22 @@ func PrepareLayer(info DriverInfo, layerId string, parentLayerPaths []string) er |
| 17 | 17 |
title := "hcsshim::PrepareLayer " |
| 18 | 18 |
logrus.Debugf(title+"flavour %d layerId %s", info.Flavour, layerId) |
| 19 | 19 |
|
| 20 |
- // Load the DLL and get a handle to the procedure we need |
|
| 21 |
- dll, proc, err := loadAndFind(procPrepareLayer) |
|
| 22 |
- if dll != nil {
|
|
| 23 |
- defer dll.Release() |
|
| 24 |
- } |
|
| 25 |
- if err != nil {
|
|
| 26 |
- return err |
|
| 27 |
- } |
|
| 28 |
- |
|
| 29 | 20 |
// Generate layer descriptors |
| 30 | 21 |
layers, err := layerPathsToDescriptors(parentLayerPaths) |
| 31 | 22 |
if err != nil {
|
| 32 |
- err = fmt.Errorf(title+"- Failed to generate layer descriptors ", err) |
|
| 33 |
- return err |
|
| 34 |
- } |
|
| 35 |
- |
|
| 36 |
- // Convert layerId to uint16 pointer for calling the procedure |
|
| 37 |
- layerIdp, err := syscall.UTF16PtrFromString(layerId) |
|
| 38 |
- if err != nil {
|
|
| 39 |
- err = fmt.Errorf(title+"- Failed conversion of layerId %s to pointer %s", layerId, err) |
|
| 40 |
- logrus.Error(err) |
|
| 41 | 23 |
return err |
| 42 | 24 |
} |
| 43 | 25 |
|
| 44 | 26 |
// Convert info to API calling convention |
| 45 | 27 |
infop, err := convertDriverInfo(info) |
| 46 | 28 |
if err != nil {
|
| 47 |
- err = fmt.Errorf(title+"- Failed conversion info struct %s", err) |
|
| 48 | 29 |
logrus.Error(err) |
| 49 | 30 |
return err |
| 50 | 31 |
} |
| 51 | 32 |
|
| 52 |
- var layerDescriptorsp *WC_LAYER_DESCRIPTOR |
|
| 53 |
- if len(layers) > 0 {
|
|
| 54 |
- layerDescriptorsp = &(layers[0]) |
|
| 55 |
- } else {
|
|
| 56 |
- layerDescriptorsp = nil |
|
| 57 |
- } |
|
| 58 |
- |
|
| 59 |
- // Call the procedure itself. |
|
| 60 |
- r1, _, _ := proc.Call( |
|
| 61 |
- uintptr(unsafe.Pointer(&infop)), |
|
| 62 |
- uintptr(unsafe.Pointer(layerIdp)), |
|
| 63 |
- uintptr(unsafe.Pointer(layerDescriptorsp)), |
|
| 64 |
- uintptr(len(layers))) |
|
| 65 |
- use(unsafe.Pointer(&infop)) |
|
| 66 |
- use(unsafe.Pointer(layerIdp)) |
|
| 67 |
- use(unsafe.Pointer(layerDescriptorsp)) |
|
| 68 |
- |
|
| 69 |
- if r1 != 0 {
|
|
| 70 |
- err = fmt.Errorf(title+"- Win32 API call returned error r1=%d err=%s layerId=%s flavour=%d", |
|
| 71 |
- r1, syscall.Errno(r1), layerId, info.Flavour) |
|
| 33 |
+ err = prepareLayer(&infop, layerId, layers) |
|
| 34 |
+ if err != nil {
|
|
| 35 |
+ err = makeErrorf(err, title, "layerId=%s flavour=%d", layerId, info.Flavour) |
|
| 72 | 36 |
logrus.Error(err) |
| 73 | 37 |
return err |
| 74 | 38 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// ResizeConsoleInComputeSystem updates the height and width of the console |
| 12 | 6 |
// session for the process with the given id in the container with the given id. |
| ... | ... |
@@ -15,29 +9,9 @@ func ResizeConsoleInComputeSystem(id string, processid uint32, h, w int) error {
|
| 15 | 15 |
title := "HCSShim::ResizeConsoleInComputeSystem" |
| 16 | 16 |
logrus.Debugf(title+" id=%s processid=%d (%d,%d)", id, processid, h, w) |
| 17 | 17 |
|
| 18 |
- // Load the DLL and get a handle to the procedure we need |
|
| 19 |
- dll, proc, err := loadAndFind(procResizeConsoleInComputeSystem) |
|
| 20 |
- if dll != nil {
|
|
| 21 |
- defer dll.Release() |
|
| 22 |
- } |
|
| 23 |
- if err != nil {
|
|
| 24 |
- return err |
|
| 25 |
- } |
|
| 26 |
- |
|
| 27 |
- // Convert id to uint16 pointer for calling the procedure |
|
| 28 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 18 |
+ err := resizeConsoleInComputeSystem(id, processid, uint16(h), uint16(w), 0) |
|
| 29 | 19 |
if err != nil {
|
| 30 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 31 |
- logrus.Error(err) |
|
| 32 |
- return err |
|
| 33 |
- } |
|
| 34 |
- |
|
| 35 |
- h16 := uint16(h) |
|
| 36 |
- w16 := uint16(w) |
|
| 37 |
- |
|
| 38 |
- r1, _, _ := proc.Call(uintptr(unsafe.Pointer(idp)), uintptr(processid), uintptr(h16), uintptr(w16), uintptr(0)) |
|
| 39 |
- if r1 != 0 {
|
|
| 40 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s, id=%s pid=%d", r1, syscall.Errno(r1), id, processid) |
|
| 20 |
+ err = makeErrorf(err, title, "id=%s pid=%d", id, processid) |
|
| 41 | 21 |
logrus.Error(err) |
| 42 | 22 |
return err |
| 43 | 23 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// TerminateComputeSystem force terminates a container. |
| 12 | 6 |
func TerminateComputeSystem(id string, timeout uint32, context string) (uint32, error) {
|
| ... | ... |
@@ -24,44 +18,25 @@ func ShutdownComputeSystem(id string, timeout uint32, context string) (uint32, e |
| 24 | 24 |
func shutdownTerminate(shutdown bool, id string, timeout uint32, context string) (uint32, error) {
|
| 25 | 25 |
|
| 26 | 26 |
var ( |
| 27 |
- title = "HCSShim::" |
|
| 28 |
- procName string |
|
| 27 |
+ title = "HCSShim::" |
|
| 29 | 28 |
) |
| 30 | 29 |
if shutdown {
|
| 31 | 30 |
title = title + "ShutdownComputeSystem" |
| 32 |
- procName = procShutdownComputeSystem |
|
| 33 | 31 |
} else {
|
| 34 | 32 |
title = title + "TerminateComputeSystem" |
| 35 |
- procName = procTerminateComputeSystem |
|
| 36 | 33 |
} |
| 37 | 34 |
logrus.Debugf(title+" id=%s context=%s", id, context) |
| 38 | 35 |
|
| 39 |
- // Load the DLL and get a handle to the procedure we need |
|
| 40 |
- dll, proc, err := loadAndFind(procName) |
|
| 41 |
- if dll != nil {
|
|
| 42 |
- defer dll.Release() |
|
| 43 |
- } |
|
| 44 |
- if err != nil {
|
|
| 45 |
- return 0xffffffff, err |
|
| 36 |
+ var err error |
|
| 37 |
+ if shutdown {
|
|
| 38 |
+ err = shutdownComputeSystem(id, timeout) |
|
| 39 |
+ } else {
|
|
| 40 |
+ err = terminateComputeSystem(id) |
|
| 46 | 41 |
} |
| 47 | 42 |
|
| 48 |
- // Convert id to uint16 pointers for calling the procedure |
|
| 49 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 50 | 43 |
if err != nil {
|
| 51 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 52 |
- logrus.Error(err) |
|
| 53 |
- return 0xffffffff, err |
|
| 54 |
- } |
|
| 55 |
- |
|
| 56 |
- // Call the procedure itself. |
|
| 57 |
- r1, _, err := proc.Call( |
|
| 58 |
- uintptr(unsafe.Pointer(idp)), uintptr(timeout)) |
|
| 59 |
- |
|
| 60 |
- use(unsafe.Pointer(idp)) |
|
| 61 |
- |
|
| 62 |
- if r1 != 0 {
|
|
| 63 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=0x%X err=%s id=%s context=%s", r1, syscall.Errno(r1), id, context) |
|
| 64 |
- return uint32(r1), err |
|
| 44 |
+ err := makeErrorf(err, title, "id=%s context=%s", id, context) |
|
| 45 |
+ return err.HResult(), err |
|
| 65 | 46 |
} |
| 66 | 47 |
|
| 67 | 48 |
logrus.Debugf(title+" succeeded id=%s context=%s", id, context) |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// StartComputeSystem starts a container that has previously been created via |
| 12 | 6 |
// CreateComputeSystem. |
| ... | ... |
@@ -15,30 +9,9 @@ func StartComputeSystem(id string) error {
|
| 15 | 15 |
title := "HCSShim::StartComputeSystem" |
| 16 | 16 |
logrus.Debugf(title+" id=%s", id) |
| 17 | 17 |
|
| 18 |
- // Load the DLL and get a handle to the procedure we need |
|
| 19 |
- dll, proc, err := loadAndFind(procStartComputeSystem) |
|
| 20 |
- if dll != nil {
|
|
| 21 |
- defer dll.Release() |
|
| 22 |
- } |
|
| 23 |
- if err != nil {
|
|
| 24 |
- return err |
|
| 25 |
- } |
|
| 26 |
- |
|
| 27 |
- // Convert ID to uint16 pointers for calling the procedure |
|
| 28 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 18 |
+ err := startComputeSystem(id) |
|
| 29 | 19 |
if err != nil {
|
| 30 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 31 |
- logrus.Error(err) |
|
| 32 |
- return err |
|
| 33 |
- } |
|
| 34 |
- |
|
| 35 |
- // Call the procedure itself. |
|
| 36 |
- r1, _, _ := proc.Call(uintptr(unsafe.Pointer(idp))) |
|
| 37 |
- |
|
| 38 |
- use(unsafe.Pointer(idp)) |
|
| 39 |
- |
|
| 40 |
- if r1 != 0 {
|
|
| 41 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s", r1, syscall.Errno(r1), id) |
|
| 20 |
+ err = makeErrorf(err, title, "id=%s", id) |
|
| 42 | 21 |
logrus.Error(err) |
| 43 | 22 |
return err |
| 44 | 23 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// TerminateProcessInComputeSystem kills a process in a running container. |
| 12 | 6 |
func TerminateProcessInComputeSystem(id string, processid uint32) (err error) {
|
| ... | ... |
@@ -14,32 +8,9 @@ func TerminateProcessInComputeSystem(id string, processid uint32) (err error) {
|
| 14 | 14 |
title := "HCSShim::TerminateProcessInComputeSystem" |
| 15 | 15 |
logrus.Debugf(title+" id=%s processid=%d", id, processid) |
| 16 | 16 |
|
| 17 |
- // Load the DLL and get a handle to the procedure we need |
|
| 18 |
- dll, proc, err := loadAndFind(procTerminateProcessInComputeSystem) |
|
| 19 |
- if dll != nil {
|
|
| 20 |
- defer dll.Release() |
|
| 21 |
- } |
|
| 22 |
- if err != nil {
|
|
| 23 |
- return err |
|
| 24 |
- } |
|
| 25 |
- |
|
| 26 |
- // Convert ID to uint16 pointer for calling the procedure |
|
| 27 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 17 |
+ err = terminateProcessInComputeSystem(id, processid) |
|
| 28 | 18 |
if err != nil {
|
| 29 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 30 |
- logrus.Error(err) |
|
| 31 |
- return err |
|
| 32 |
- } |
|
| 33 |
- |
|
| 34 |
- // Call the procedure itself. |
|
| 35 |
- r1, _, err := proc.Call( |
|
| 36 |
- uintptr(unsafe.Pointer(idp)), |
|
| 37 |
- uintptr(processid)) |
|
| 38 |
- |
|
| 39 |
- use(unsafe.Pointer(idp)) |
|
| 40 |
- |
|
| 41 |
- if r1 != 0 {
|
|
| 42 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s", r1, syscall.Errno(r1), id) |
|
| 19 |
+ err = makeErrorf(err, title, "err=%s id=%s", id) |
|
| 43 | 20 |
logrus.Error(err) |
| 44 | 21 |
return err |
| 45 | 22 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// UnprepareLayer disables the filesystem filter for the read-write layer with |
| 12 | 6 |
// the given id. |
| ... | ... |
@@ -14,42 +8,16 @@ func UnprepareLayer(info DriverInfo, layerId string) error {
|
| 14 | 14 |
title := "hcsshim::UnprepareLayer " |
| 15 | 15 |
logrus.Debugf(title+"flavour %d layerId %s", info.Flavour, layerId) |
| 16 | 16 |
|
| 17 |
- // Load the DLL and get a handle to the procedure we need |
|
| 18 |
- dll, proc, err := loadAndFind(procUnprepareLayer) |
|
| 19 |
- if dll != nil {
|
|
| 20 |
- defer dll.Release() |
|
| 21 |
- } |
|
| 22 |
- if err != nil {
|
|
| 23 |
- return err |
|
| 24 |
- } |
|
| 25 |
- |
|
| 26 |
- // Convert layerId to uint16 pointer for calling the procedure |
|
| 27 |
- layerIdp, err := syscall.UTF16PtrFromString(layerId) |
|
| 28 |
- if err != nil {
|
|
| 29 |
- err = fmt.Errorf(title+"- Failed conversion of layerId %s to pointer %s", layerId, err) |
|
| 30 |
- logrus.Error(err) |
|
| 31 |
- return err |
|
| 32 |
- } |
|
| 33 |
- |
|
| 34 | 17 |
// Convert info to API calling convention |
| 35 | 18 |
infop, err := convertDriverInfo(info) |
| 36 | 19 |
if err != nil {
|
| 37 |
- err = fmt.Errorf(title+"- Failed conversion info struct %s", err) |
|
| 38 | 20 |
logrus.Error(err) |
| 39 | 21 |
return err |
| 40 | 22 |
} |
| 41 | 23 |
|
| 42 |
- // Call the procedure itself. |
|
| 43 |
- r1, _, _ := proc.Call( |
|
| 44 |
- uintptr(unsafe.Pointer(&infop)), |
|
| 45 |
- uintptr(unsafe.Pointer(layerIdp))) |
|
| 46 |
- |
|
| 47 |
- use(unsafe.Pointer(&infop)) |
|
| 48 |
- use(unsafe.Pointer(layerIdp)) |
|
| 49 |
- |
|
| 50 |
- if r1 != 0 {
|
|
| 51 |
- err = fmt.Errorf(title+"- Win32 API call returned error r1=%d err=%s layerId=%s flavour=%d", |
|
| 52 |
- r1, syscall.Errno(r1), layerId, info.Flavour) |
|
| 24 |
+ err = unprepareLayer(&infop, layerId) |
|
| 25 |
+ if err != nil {
|
|
| 26 |
+ err = makeErrorf(err, title, "layerId=%s flavour=%d", layerId, info.Flavour) |
|
| 53 | 27 |
logrus.Error(err) |
| 54 | 28 |
return err |
| 55 | 29 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package hcsshim |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 3 |
+import "github.com/Sirupsen/logrus" |
|
| 10 | 4 |
|
| 11 | 5 |
// WaitForProcessInComputeSystem waits for a process ID to terminate and returns |
| 12 | 6 |
// the exit code. Returns exitcode, errno, error |
| ... | ... |
@@ -15,40 +9,13 @@ func WaitForProcessInComputeSystem(id string, processid uint32, timeout uint32) |
| 15 | 15 |
title := "HCSShim::WaitForProcessInComputeSystem" |
| 16 | 16 |
logrus.Debugf(title+" id=%s processid=%d", id, processid) |
| 17 | 17 |
|
| 18 |
- // Load the DLL and get a handle to the procedure we need |
|
| 19 |
- dll, proc, err := loadAndFind(procWaitForProcessInComputeSystem) |
|
| 20 |
- if dll != nil {
|
|
| 21 |
- defer dll.Release() |
|
| 22 |
- } |
|
| 23 |
- if err != nil {
|
|
| 24 |
- return 0, 0, err |
|
| 25 |
- } |
|
| 26 |
- |
|
| 27 |
- // Convert id to uint16 pointer for calling the procedure |
|
| 28 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 18 |
+ var exitCode uint32 |
|
| 19 |
+ err := waitForProcessInComputeSystem(id, processid, timeout, &exitCode) |
|
| 29 | 20 |
if err != nil {
|
| 30 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 31 |
- logrus.Error(err) |
|
| 32 |
- return 0, 0, err |
|
| 33 |
- } |
|
| 34 |
- |
|
| 35 |
- // To get a POINTER to the ExitCode |
|
| 36 |
- ec := new(int32) |
|
| 37 |
- |
|
| 38 |
- // Call the procedure itself. |
|
| 39 |
- r1, _, err := proc.Call( |
|
| 40 |
- uintptr(unsafe.Pointer(idp)), |
|
| 41 |
- uintptr(processid), |
|
| 42 |
- uintptr(timeout), |
|
| 43 |
- uintptr(unsafe.Pointer(ec))) |
|
| 44 |
- |
|
| 45 |
- use(unsafe.Pointer(idp)) |
|
| 46 |
- |
|
| 47 |
- if r1 != 0 {
|
|
| 48 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=0x%X err=%s id=%s", r1, syscall.Errno(r1), id) |
|
| 49 |
- return 0, uint32(r1), err |
|
| 21 |
+ err := makeErrorf(err, title, "id=%s", id) |
|
| 22 |
+ return 0, err.HResult(), err |
|
| 50 | 23 |
} |
| 51 | 24 |
|
| 52 |
- logrus.Debugf(title+" succeeded id=%s processid=%d exitcode=%d", id, processid, *ec) |
|
| 53 |
- return *ec, 0, nil |
|
| 25 |
+ logrus.Debugf(title+" succeeded id=%s processid=%d exitcode=%d", id, processid, exitCode) |
|
| 26 |
+ return int32(exitCode), 0, nil |
|
| 54 | 27 |
} |
| 55 | 28 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,559 @@ |
| 0 |
+// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT |
|
| 1 |
+ |
|
| 2 |
+package hcsshim |
|
| 3 |
+ |
|
| 4 |
+import "unsafe" |
|
| 5 |
+import "syscall" |
|
| 6 |
+ |
|
| 7 |
+var _ unsafe.Pointer |
|
| 8 |
+ |
|
| 9 |
+var ( |
|
| 10 |
+ modole32 = syscall.NewLazyDLL("ole32.dll")
|
|
| 11 |
+ modvmcompute = syscall.NewLazyDLL("vmcompute.dll")
|
|
| 12 |
+ |
|
| 13 |
+ procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
|
| 14 |
+ procActivateLayer = modvmcompute.NewProc("ActivateLayer")
|
|
| 15 |
+ procCopyLayer = modvmcompute.NewProc("CopyLayer")
|
|
| 16 |
+ procCreateLayer = modvmcompute.NewProc("CreateLayer")
|
|
| 17 |
+ procCreateSandboxLayer = modvmcompute.NewProc("CreateSandboxLayer")
|
|
| 18 |
+ procDeactivateLayer = modvmcompute.NewProc("DeactivateLayer")
|
|
| 19 |
+ procDestroyLayer = modvmcompute.NewProc("DestroyLayer")
|
|
| 20 |
+ procExportLayer = modvmcompute.NewProc("ExportLayer")
|
|
| 21 |
+ procGetLayerMountPath = modvmcompute.NewProc("GetLayerMountPath")
|
|
| 22 |
+ procGetBaseImages = modvmcompute.NewProc("GetBaseImages")
|
|
| 23 |
+ procImportLayer = modvmcompute.NewProc("ImportLayer")
|
|
| 24 |
+ procLayerExists = modvmcompute.NewProc("LayerExists")
|
|
| 25 |
+ procNameToGuid = modvmcompute.NewProc("NameToGuid")
|
|
| 26 |
+ procPrepareLayer = modvmcompute.NewProc("PrepareLayer")
|
|
| 27 |
+ procUnprepareLayer = modvmcompute.NewProc("UnprepareLayer")
|
|
| 28 |
+ procCreateComputeSystem = modvmcompute.NewProc("CreateComputeSystem")
|
|
| 29 |
+ procCreateProcessWithStdHandlesInComputeSystem = modvmcompute.NewProc("CreateProcessWithStdHandlesInComputeSystem")
|
|
| 30 |
+ procResizeConsoleInComputeSystem = modvmcompute.NewProc("ResizeConsoleInComputeSystem")
|
|
| 31 |
+ procShutdownComputeSystem = modvmcompute.NewProc("ShutdownComputeSystem")
|
|
| 32 |
+ procStartComputeSystem = modvmcompute.NewProc("StartComputeSystem")
|
|
| 33 |
+ procTerminateComputeSystem = modvmcompute.NewProc("TerminateComputeSystem")
|
|
| 34 |
+ procTerminateProcessInComputeSystem = modvmcompute.NewProc("TerminateProcessInComputeSystem")
|
|
| 35 |
+ procWaitForProcessInComputeSystem = modvmcompute.NewProc("WaitForProcessInComputeSystem")
|
|
| 36 |
+ procHNSCall = modvmcompute.NewProc("HNSCall")
|
|
| 37 |
+) |
|
| 38 |
+ |
|
| 39 |
+func coTaskMemFree(buffer unsafe.Pointer) {
|
|
| 40 |
+ syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(buffer), 0, 0) |
|
| 41 |
+ return |
|
| 42 |
+} |
|
| 43 |
+ |
|
| 44 |
+func activateLayer(info *driverInfo, id string) (hr error) {
|
|
| 45 |
+ var _p0 *uint16 |
|
| 46 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 47 |
+ if hr != nil {
|
|
| 48 |
+ return |
|
| 49 |
+ } |
|
| 50 |
+ return _activateLayer(info, _p0) |
|
| 51 |
+} |
|
| 52 |
+ |
|
| 53 |
+func _activateLayer(info *driverInfo, id *uint16) (hr error) {
|
|
| 54 |
+ if hr = procActivateLayer.Find(); hr != nil {
|
|
| 55 |
+ return |
|
| 56 |
+ } |
|
| 57 |
+ r0, _, _ := syscall.Syscall(procActivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) |
|
| 58 |
+ if r0 != 0 {
|
|
| 59 |
+ hr = syscall.Errno(r0) |
|
| 60 |
+ } |
|
| 61 |
+ return |
|
| 62 |
+} |
|
| 63 |
+ |
|
| 64 |
+func copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
|
|
| 65 |
+ var _p0 *uint16 |
|
| 66 |
+ _p0, hr = syscall.UTF16PtrFromString(srcId) |
|
| 67 |
+ if hr != nil {
|
|
| 68 |
+ return |
|
| 69 |
+ } |
|
| 70 |
+ var _p1 *uint16 |
|
| 71 |
+ _p1, hr = syscall.UTF16PtrFromString(dstId) |
|
| 72 |
+ if hr != nil {
|
|
| 73 |
+ return |
|
| 74 |
+ } |
|
| 75 |
+ return _copyLayer(info, _p0, _p1, descriptors) |
|
| 76 |
+} |
|
| 77 |
+ |
|
| 78 |
+func _copyLayer(info *driverInfo, srcId *uint16, dstId *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
|
|
| 79 |
+ var _p2 *WC_LAYER_DESCRIPTOR |
|
| 80 |
+ if len(descriptors) > 0 {
|
|
| 81 |
+ _p2 = &descriptors[0] |
|
| 82 |
+ } |
|
| 83 |
+ if hr = procCopyLayer.Find(); hr != nil {
|
|
| 84 |
+ return |
|
| 85 |
+ } |
|
| 86 |
+ r0, _, _ := syscall.Syscall6(procCopyLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(srcId)), uintptr(unsafe.Pointer(dstId)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) |
|
| 87 |
+ if r0 != 0 {
|
|
| 88 |
+ hr = syscall.Errno(r0) |
|
| 89 |
+ } |
|
| 90 |
+ return |
|
| 91 |
+} |
|
| 92 |
+ |
|
| 93 |
+func createLayer(info *driverInfo, id string, parent string) (hr error) {
|
|
| 94 |
+ var _p0 *uint16 |
|
| 95 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 96 |
+ if hr != nil {
|
|
| 97 |
+ return |
|
| 98 |
+ } |
|
| 99 |
+ var _p1 *uint16 |
|
| 100 |
+ _p1, hr = syscall.UTF16PtrFromString(parent) |
|
| 101 |
+ if hr != nil {
|
|
| 102 |
+ return |
|
| 103 |
+ } |
|
| 104 |
+ return _createLayer(info, _p0, _p1) |
|
| 105 |
+} |
|
| 106 |
+ |
|
| 107 |
+func _createLayer(info *driverInfo, id *uint16, parent *uint16) (hr error) {
|
|
| 108 |
+ if hr = procCreateLayer.Find(); hr != nil {
|
|
| 109 |
+ return |
|
| 110 |
+ } |
|
| 111 |
+ r0, _, _ := syscall.Syscall(procCreateLayer.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(parent))) |
|
| 112 |
+ if r0 != 0 {
|
|
| 113 |
+ hr = syscall.Errno(r0) |
|
| 114 |
+ } |
|
| 115 |
+ return |
|
| 116 |
+} |
|
| 117 |
+ |
|
| 118 |
+func createSandboxLayer(info *driverInfo, id string, parent string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
|
|
| 119 |
+ var _p0 *uint16 |
|
| 120 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 121 |
+ if hr != nil {
|
|
| 122 |
+ return |
|
| 123 |
+ } |
|
| 124 |
+ var _p1 *uint16 |
|
| 125 |
+ _p1, hr = syscall.UTF16PtrFromString(parent) |
|
| 126 |
+ if hr != nil {
|
|
| 127 |
+ return |
|
| 128 |
+ } |
|
| 129 |
+ return _createSandboxLayer(info, _p0, _p1, descriptors) |
|
| 130 |
+} |
|
| 131 |
+ |
|
| 132 |
+func _createSandboxLayer(info *driverInfo, id *uint16, parent *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
|
|
| 133 |
+ var _p2 *WC_LAYER_DESCRIPTOR |
|
| 134 |
+ if len(descriptors) > 0 {
|
|
| 135 |
+ _p2 = &descriptors[0] |
|
| 136 |
+ } |
|
| 137 |
+ if hr = procCreateSandboxLayer.Find(); hr != nil {
|
|
| 138 |
+ return |
|
| 139 |
+ } |
|
| 140 |
+ r0, _, _ := syscall.Syscall6(procCreateSandboxLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(parent)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) |
|
| 141 |
+ if r0 != 0 {
|
|
| 142 |
+ hr = syscall.Errno(r0) |
|
| 143 |
+ } |
|
| 144 |
+ return |
|
| 145 |
+} |
|
| 146 |
+ |
|
| 147 |
+func deactivateLayer(info *driverInfo, id string) (hr error) {
|
|
| 148 |
+ var _p0 *uint16 |
|
| 149 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 150 |
+ if hr != nil {
|
|
| 151 |
+ return |
|
| 152 |
+ } |
|
| 153 |
+ return _deactivateLayer(info, _p0) |
|
| 154 |
+} |
|
| 155 |
+ |
|
| 156 |
+func _deactivateLayer(info *driverInfo, id *uint16) (hr error) {
|
|
| 157 |
+ if hr = procDeactivateLayer.Find(); hr != nil {
|
|
| 158 |
+ return |
|
| 159 |
+ } |
|
| 160 |
+ r0, _, _ := syscall.Syscall(procDeactivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) |
|
| 161 |
+ if r0 != 0 {
|
|
| 162 |
+ hr = syscall.Errno(r0) |
|
| 163 |
+ } |
|
| 164 |
+ return |
|
| 165 |
+} |
|
| 166 |
+ |
|
| 167 |
+func destroyLayer(info *driverInfo, id string) (hr error) {
|
|
| 168 |
+ var _p0 *uint16 |
|
| 169 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 170 |
+ if hr != nil {
|
|
| 171 |
+ return |
|
| 172 |
+ } |
|
| 173 |
+ return _destroyLayer(info, _p0) |
|
| 174 |
+} |
|
| 175 |
+ |
|
| 176 |
+func _destroyLayer(info *driverInfo, id *uint16) (hr error) {
|
|
| 177 |
+ if hr = procDestroyLayer.Find(); hr != nil {
|
|
| 178 |
+ return |
|
| 179 |
+ } |
|
| 180 |
+ r0, _, _ := syscall.Syscall(procDestroyLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) |
|
| 181 |
+ if r0 != 0 {
|
|
| 182 |
+ hr = syscall.Errno(r0) |
|
| 183 |
+ } |
|
| 184 |
+ return |
|
| 185 |
+} |
|
| 186 |
+ |
|
| 187 |
+func exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
|
|
| 188 |
+ var _p0 *uint16 |
|
| 189 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 190 |
+ if hr != nil {
|
|
| 191 |
+ return |
|
| 192 |
+ } |
|
| 193 |
+ var _p1 *uint16 |
|
| 194 |
+ _p1, hr = syscall.UTF16PtrFromString(path) |
|
| 195 |
+ if hr != nil {
|
|
| 196 |
+ return |
|
| 197 |
+ } |
|
| 198 |
+ return _exportLayer(info, _p0, _p1, descriptors) |
|
| 199 |
+} |
|
| 200 |
+ |
|
| 201 |
+func _exportLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
|
|
| 202 |
+ var _p2 *WC_LAYER_DESCRIPTOR |
|
| 203 |
+ if len(descriptors) > 0 {
|
|
| 204 |
+ _p2 = &descriptors[0] |
|
| 205 |
+ } |
|
| 206 |
+ if hr = procExportLayer.Find(); hr != nil {
|
|
| 207 |
+ return |
|
| 208 |
+ } |
|
| 209 |
+ r0, _, _ := syscall.Syscall6(procExportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) |
|
| 210 |
+ if r0 != 0 {
|
|
| 211 |
+ hr = syscall.Errno(r0) |
|
| 212 |
+ } |
|
| 213 |
+ return |
|
| 214 |
+} |
|
| 215 |
+ |
|
| 216 |
+func getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) {
|
|
| 217 |
+ var _p0 *uint16 |
|
| 218 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 219 |
+ if hr != nil {
|
|
| 220 |
+ return |
|
| 221 |
+ } |
|
| 222 |
+ return _getLayerMountPath(info, _p0, length, buffer) |
|
| 223 |
+} |
|
| 224 |
+ |
|
| 225 |
+func _getLayerMountPath(info *driverInfo, id *uint16, length *uintptr, buffer *uint16) (hr error) {
|
|
| 226 |
+ if hr = procGetLayerMountPath.Find(); hr != nil {
|
|
| 227 |
+ return |
|
| 228 |
+ } |
|
| 229 |
+ r0, _, _ := syscall.Syscall6(procGetLayerMountPath.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(length)), uintptr(unsafe.Pointer(buffer)), 0, 0) |
|
| 230 |
+ if r0 != 0 {
|
|
| 231 |
+ hr = syscall.Errno(r0) |
|
| 232 |
+ } |
|
| 233 |
+ return |
|
| 234 |
+} |
|
| 235 |
+ |
|
| 236 |
+func getBaseImages(buffer **uint16) (hr error) {
|
|
| 237 |
+ if hr = procGetBaseImages.Find(); hr != nil {
|
|
| 238 |
+ return |
|
| 239 |
+ } |
|
| 240 |
+ r0, _, _ := syscall.Syscall(procGetBaseImages.Addr(), 1, uintptr(unsafe.Pointer(buffer)), 0, 0) |
|
| 241 |
+ if r0 != 0 {
|
|
| 242 |
+ hr = syscall.Errno(r0) |
|
| 243 |
+ } |
|
| 244 |
+ return |
|
| 245 |
+} |
|
| 246 |
+ |
|
| 247 |
+func importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
|
|
| 248 |
+ var _p0 *uint16 |
|
| 249 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 250 |
+ if hr != nil {
|
|
| 251 |
+ return |
|
| 252 |
+ } |
|
| 253 |
+ var _p1 *uint16 |
|
| 254 |
+ _p1, hr = syscall.UTF16PtrFromString(path) |
|
| 255 |
+ if hr != nil {
|
|
| 256 |
+ return |
|
| 257 |
+ } |
|
| 258 |
+ return _importLayer(info, _p0, _p1, descriptors) |
|
| 259 |
+} |
|
| 260 |
+ |
|
| 261 |
+func _importLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
|
|
| 262 |
+ var _p2 *WC_LAYER_DESCRIPTOR |
|
| 263 |
+ if len(descriptors) > 0 {
|
|
| 264 |
+ _p2 = &descriptors[0] |
|
| 265 |
+ } |
|
| 266 |
+ if hr = procImportLayer.Find(); hr != nil {
|
|
| 267 |
+ return |
|
| 268 |
+ } |
|
| 269 |
+ r0, _, _ := syscall.Syscall6(procImportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) |
|
| 270 |
+ if r0 != 0 {
|
|
| 271 |
+ hr = syscall.Errno(r0) |
|
| 272 |
+ } |
|
| 273 |
+ return |
|
| 274 |
+} |
|
| 275 |
+ |
|
| 276 |
+func layerExists(info *driverInfo, id string, exists *uint32) (hr error) {
|
|
| 277 |
+ var _p0 *uint16 |
|
| 278 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 279 |
+ if hr != nil {
|
|
| 280 |
+ return |
|
| 281 |
+ } |
|
| 282 |
+ return _layerExists(info, _p0, exists) |
|
| 283 |
+} |
|
| 284 |
+ |
|
| 285 |
+func _layerExists(info *driverInfo, id *uint16, exists *uint32) (hr error) {
|
|
| 286 |
+ if hr = procLayerExists.Find(); hr != nil {
|
|
| 287 |
+ return |
|
| 288 |
+ } |
|
| 289 |
+ r0, _, _ := syscall.Syscall(procLayerExists.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(exists))) |
|
| 290 |
+ if r0 != 0 {
|
|
| 291 |
+ hr = syscall.Errno(r0) |
|
| 292 |
+ } |
|
| 293 |
+ return |
|
| 294 |
+} |
|
| 295 |
+ |
|
| 296 |
+func nameToGuid(name string, guid *GUID) (hr error) {
|
|
| 297 |
+ var _p0 *uint16 |
|
| 298 |
+ _p0, hr = syscall.UTF16PtrFromString(name) |
|
| 299 |
+ if hr != nil {
|
|
| 300 |
+ return |
|
| 301 |
+ } |
|
| 302 |
+ return _nameToGuid(_p0, guid) |
|
| 303 |
+} |
|
| 304 |
+ |
|
| 305 |
+func _nameToGuid(name *uint16, guid *GUID) (hr error) {
|
|
| 306 |
+ if hr = procNameToGuid.Find(); hr != nil {
|
|
| 307 |
+ return |
|
| 308 |
+ } |
|
| 309 |
+ r0, _, _ := syscall.Syscall(procNameToGuid.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(guid)), 0) |
|
| 310 |
+ if r0 != 0 {
|
|
| 311 |
+ hr = syscall.Errno(r0) |
|
| 312 |
+ } |
|
| 313 |
+ return |
|
| 314 |
+} |
|
| 315 |
+ |
|
| 316 |
+func prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
|
|
| 317 |
+ var _p0 *uint16 |
|
| 318 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 319 |
+ if hr != nil {
|
|
| 320 |
+ return |
|
| 321 |
+ } |
|
| 322 |
+ return _prepareLayer(info, _p0, descriptors) |
|
| 323 |
+} |
|
| 324 |
+ |
|
| 325 |
+func _prepareLayer(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
|
|
| 326 |
+ var _p1 *WC_LAYER_DESCRIPTOR |
|
| 327 |
+ if len(descriptors) > 0 {
|
|
| 328 |
+ _p1 = &descriptors[0] |
|
| 329 |
+ } |
|
| 330 |
+ if hr = procPrepareLayer.Find(); hr != nil {
|
|
| 331 |
+ return |
|
| 332 |
+ } |
|
| 333 |
+ r0, _, _ := syscall.Syscall6(procPrepareLayer.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), 0, 0) |
|
| 334 |
+ if r0 != 0 {
|
|
| 335 |
+ hr = syscall.Errno(r0) |
|
| 336 |
+ } |
|
| 337 |
+ return |
|
| 338 |
+} |
|
| 339 |
+ |
|
| 340 |
+func unprepareLayer(info *driverInfo, id string) (hr error) {
|
|
| 341 |
+ var _p0 *uint16 |
|
| 342 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 343 |
+ if hr != nil {
|
|
| 344 |
+ return |
|
| 345 |
+ } |
|
| 346 |
+ return _unprepareLayer(info, _p0) |
|
| 347 |
+} |
|
| 348 |
+ |
|
| 349 |
+func _unprepareLayer(info *driverInfo, id *uint16) (hr error) {
|
|
| 350 |
+ if hr = procUnprepareLayer.Find(); hr != nil {
|
|
| 351 |
+ return |
|
| 352 |
+ } |
|
| 353 |
+ r0, _, _ := syscall.Syscall(procUnprepareLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) |
|
| 354 |
+ if r0 != 0 {
|
|
| 355 |
+ hr = syscall.Errno(r0) |
|
| 356 |
+ } |
|
| 357 |
+ return |
|
| 358 |
+} |
|
| 359 |
+ |
|
| 360 |
+func createComputeSystem(id string, configuration string) (hr error) {
|
|
| 361 |
+ var _p0 *uint16 |
|
| 362 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 363 |
+ if hr != nil {
|
|
| 364 |
+ return |
|
| 365 |
+ } |
|
| 366 |
+ var _p1 *uint16 |
|
| 367 |
+ _p1, hr = syscall.UTF16PtrFromString(configuration) |
|
| 368 |
+ if hr != nil {
|
|
| 369 |
+ return |
|
| 370 |
+ } |
|
| 371 |
+ return _createComputeSystem(_p0, _p1) |
|
| 372 |
+} |
|
| 373 |
+ |
|
| 374 |
+func _createComputeSystem(id *uint16, configuration *uint16) (hr error) {
|
|
| 375 |
+ if hr = procCreateComputeSystem.Find(); hr != nil {
|
|
| 376 |
+ return |
|
| 377 |
+ } |
|
| 378 |
+ r0, _, _ := syscall.Syscall(procCreateComputeSystem.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(configuration)), 0) |
|
| 379 |
+ if r0 != 0 {
|
|
| 380 |
+ hr = syscall.Errno(r0) |
|
| 381 |
+ } |
|
| 382 |
+ return |
|
| 383 |
+} |
|
| 384 |
+ |
|
| 385 |
+func createProcessWithStdHandlesInComputeSystem(id string, paramsJson string, pid *uint32, stdin *syscall.Handle, stdout *syscall.Handle, stderr *syscall.Handle) (hr error) {
|
|
| 386 |
+ var _p0 *uint16 |
|
| 387 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 388 |
+ if hr != nil {
|
|
| 389 |
+ return |
|
| 390 |
+ } |
|
| 391 |
+ var _p1 *uint16 |
|
| 392 |
+ _p1, hr = syscall.UTF16PtrFromString(paramsJson) |
|
| 393 |
+ if hr != nil {
|
|
| 394 |
+ return |
|
| 395 |
+ } |
|
| 396 |
+ return _createProcessWithStdHandlesInComputeSystem(_p0, _p1, pid, stdin, stdout, stderr) |
|
| 397 |
+} |
|
| 398 |
+ |
|
| 399 |
+func _createProcessWithStdHandlesInComputeSystem(id *uint16, paramsJson *uint16, pid *uint32, stdin *syscall.Handle, stdout *syscall.Handle, stderr *syscall.Handle) (hr error) {
|
|
| 400 |
+ if hr = procCreateProcessWithStdHandlesInComputeSystem.Find(); hr != nil {
|
|
| 401 |
+ return |
|
| 402 |
+ } |
|
| 403 |
+ r0, _, _ := syscall.Syscall6(procCreateProcessWithStdHandlesInComputeSystem.Addr(), 6, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(paramsJson)), uintptr(unsafe.Pointer(pid)), uintptr(unsafe.Pointer(stdin)), uintptr(unsafe.Pointer(stdout)), uintptr(unsafe.Pointer(stderr))) |
|
| 404 |
+ if r0 != 0 {
|
|
| 405 |
+ hr = syscall.Errno(r0) |
|
| 406 |
+ } |
|
| 407 |
+ return |
|
| 408 |
+} |
|
| 409 |
+ |
|
| 410 |
+func resizeConsoleInComputeSystem(id string, pid uint32, height uint16, width uint16, flags uint32) (hr error) {
|
|
| 411 |
+ var _p0 *uint16 |
|
| 412 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 413 |
+ if hr != nil {
|
|
| 414 |
+ return |
|
| 415 |
+ } |
|
| 416 |
+ return _resizeConsoleInComputeSystem(_p0, pid, height, width, flags) |
|
| 417 |
+} |
|
| 418 |
+ |
|
| 419 |
+func _resizeConsoleInComputeSystem(id *uint16, pid uint32, height uint16, width uint16, flags uint32) (hr error) {
|
|
| 420 |
+ if hr = procResizeConsoleInComputeSystem.Find(); hr != nil {
|
|
| 421 |
+ return |
|
| 422 |
+ } |
|
| 423 |
+ r0, _, _ := syscall.Syscall6(procResizeConsoleInComputeSystem.Addr(), 5, uintptr(unsafe.Pointer(id)), uintptr(pid), uintptr(height), uintptr(width), uintptr(flags), 0) |
|
| 424 |
+ if r0 != 0 {
|
|
| 425 |
+ hr = syscall.Errno(r0) |
|
| 426 |
+ } |
|
| 427 |
+ return |
|
| 428 |
+} |
|
| 429 |
+ |
|
| 430 |
+func shutdownComputeSystem(id string, timeout uint32) (hr error) {
|
|
| 431 |
+ var _p0 *uint16 |
|
| 432 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 433 |
+ if hr != nil {
|
|
| 434 |
+ return |
|
| 435 |
+ } |
|
| 436 |
+ return _shutdownComputeSystem(_p0, timeout) |
|
| 437 |
+} |
|
| 438 |
+ |
|
| 439 |
+func _shutdownComputeSystem(id *uint16, timeout uint32) (hr error) {
|
|
| 440 |
+ if hr = procShutdownComputeSystem.Find(); hr != nil {
|
|
| 441 |
+ return |
|
| 442 |
+ } |
|
| 443 |
+ r0, _, _ := syscall.Syscall(procShutdownComputeSystem.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(timeout), 0) |
|
| 444 |
+ if r0 != 0 {
|
|
| 445 |
+ hr = syscall.Errno(r0) |
|
| 446 |
+ } |
|
| 447 |
+ return |
|
| 448 |
+} |
|
| 449 |
+ |
|
| 450 |
+func startComputeSystem(id string) (hr error) {
|
|
| 451 |
+ var _p0 *uint16 |
|
| 452 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 453 |
+ if hr != nil {
|
|
| 454 |
+ return |
|
| 455 |
+ } |
|
| 456 |
+ return _startComputeSystem(_p0) |
|
| 457 |
+} |
|
| 458 |
+ |
|
| 459 |
+func _startComputeSystem(id *uint16) (hr error) {
|
|
| 460 |
+ if hr = procStartComputeSystem.Find(); hr != nil {
|
|
| 461 |
+ return |
|
| 462 |
+ } |
|
| 463 |
+ r0, _, _ := syscall.Syscall(procStartComputeSystem.Addr(), 1, uintptr(unsafe.Pointer(id)), 0, 0) |
|
| 464 |
+ if r0 != 0 {
|
|
| 465 |
+ hr = syscall.Errno(r0) |
|
| 466 |
+ } |
|
| 467 |
+ return |
|
| 468 |
+} |
|
| 469 |
+ |
|
| 470 |
+func terminateComputeSystem(id string) (hr error) {
|
|
| 471 |
+ var _p0 *uint16 |
|
| 472 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 473 |
+ if hr != nil {
|
|
| 474 |
+ return |
|
| 475 |
+ } |
|
| 476 |
+ return _terminateComputeSystem(_p0) |
|
| 477 |
+} |
|
| 478 |
+ |
|
| 479 |
+func _terminateComputeSystem(id *uint16) (hr error) {
|
|
| 480 |
+ if hr = procTerminateComputeSystem.Find(); hr != nil {
|
|
| 481 |
+ return |
|
| 482 |
+ } |
|
| 483 |
+ r0, _, _ := syscall.Syscall(procTerminateComputeSystem.Addr(), 1, uintptr(unsafe.Pointer(id)), 0, 0) |
|
| 484 |
+ if r0 != 0 {
|
|
| 485 |
+ hr = syscall.Errno(r0) |
|
| 486 |
+ } |
|
| 487 |
+ return |
|
| 488 |
+} |
|
| 489 |
+ |
|
| 490 |
+func terminateProcessInComputeSystem(id string, pid uint32) (hr error) {
|
|
| 491 |
+ var _p0 *uint16 |
|
| 492 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 493 |
+ if hr != nil {
|
|
| 494 |
+ return |
|
| 495 |
+ } |
|
| 496 |
+ return _terminateProcessInComputeSystem(_p0, pid) |
|
| 497 |
+} |
|
| 498 |
+ |
|
| 499 |
+func _terminateProcessInComputeSystem(id *uint16, pid uint32) (hr error) {
|
|
| 500 |
+ if hr = procTerminateProcessInComputeSystem.Find(); hr != nil {
|
|
| 501 |
+ return |
|
| 502 |
+ } |
|
| 503 |
+ r0, _, _ := syscall.Syscall(procTerminateProcessInComputeSystem.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(pid), 0) |
|
| 504 |
+ if r0 != 0 {
|
|
| 505 |
+ hr = syscall.Errno(r0) |
|
| 506 |
+ } |
|
| 507 |
+ return |
|
| 508 |
+} |
|
| 509 |
+ |
|
| 510 |
+func waitForProcessInComputeSystem(id string, pid uint32, timeout uint32, exitCode *uint32) (hr error) {
|
|
| 511 |
+ var _p0 *uint16 |
|
| 512 |
+ _p0, hr = syscall.UTF16PtrFromString(id) |
|
| 513 |
+ if hr != nil {
|
|
| 514 |
+ return |
|
| 515 |
+ } |
|
| 516 |
+ return _waitForProcessInComputeSystem(_p0, pid, timeout, exitCode) |
|
| 517 |
+} |
|
| 518 |
+ |
|
| 519 |
+func _waitForProcessInComputeSystem(id *uint16, pid uint32, timeout uint32, exitCode *uint32) (hr error) {
|
|
| 520 |
+ if hr = procWaitForProcessInComputeSystem.Find(); hr != nil {
|
|
| 521 |
+ return |
|
| 522 |
+ } |
|
| 523 |
+ r0, _, _ := syscall.Syscall6(procWaitForProcessInComputeSystem.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(pid), uintptr(timeout), uintptr(unsafe.Pointer(exitCode)), 0, 0) |
|
| 524 |
+ if r0 != 0 {
|
|
| 525 |
+ hr = syscall.Errno(r0) |
|
| 526 |
+ } |
|
| 527 |
+ return |
|
| 528 |
+} |
|
| 529 |
+ |
|
| 530 |
+func _hnsCall(method string, path string, object string, response **uint16) (hr error) {
|
|
| 531 |
+ var _p0 *uint16 |
|
| 532 |
+ _p0, hr = syscall.UTF16PtrFromString(method) |
|
| 533 |
+ if hr != nil {
|
|
| 534 |
+ return |
|
| 535 |
+ } |
|
| 536 |
+ var _p1 *uint16 |
|
| 537 |
+ _p1, hr = syscall.UTF16PtrFromString(path) |
|
| 538 |
+ if hr != nil {
|
|
| 539 |
+ return |
|
| 540 |
+ } |
|
| 541 |
+ var _p2 *uint16 |
|
| 542 |
+ _p2, hr = syscall.UTF16PtrFromString(object) |
|
| 543 |
+ if hr != nil {
|
|
| 544 |
+ return |
|
| 545 |
+ } |
|
| 546 |
+ return __hnsCall(_p0, _p1, _p2, response) |
|
| 547 |
+} |
|
| 548 |
+ |
|
| 549 |
+func __hnsCall(method *uint16, path *uint16, object *uint16, response **uint16) (hr error) {
|
|
| 550 |
+ if hr = procHNSCall.Find(); hr != nil {
|
|
| 551 |
+ return |
|
| 552 |
+ } |
|
| 553 |
+ r0, _, _ := syscall.Syscall6(procHNSCall.Addr(), 4, uintptr(unsafe.Pointer(method)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(object)), uintptr(unsafe.Pointer(response)), 0, 0) |
|
| 554 |
+ if r0 != 0 {
|
|
| 555 |
+ hr = syscall.Errno(r0) |
|
| 556 |
+ } |
|
| 557 |
+ return |
|
| 558 |
+} |