From 7ccc0e2101a66e0621faf1f043bf7cd5515501d5 Mon Sep 17 00:00:00 2001 From: John Starks Date: Mon, 1 Feb 2016 23:09:35 +0000 Subject: [PATCH] Revendor Microsoft/hcsshim and vendor Microsoft/go-winio 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 --- hack/vendor.sh | 3 +- .../src/github.com/Microsoft/go-winio/LICENSE | 22 + .../github.com/Microsoft/go-winio/README.md | 15 + .../src/github.com/Microsoft/go-winio/file.go | 216 +++++ .../Microsoft/go-winio/mksyscall_windows.go | 797 ++++++++++++++++++ .../src/github.com/Microsoft/go-winio/pipe.go | 280 ++++++ .../src/github.com/Microsoft/go-winio/sd.go | 83 ++ .../github.com/Microsoft/go-winio/syscall.go | 3 + .../github.com/Microsoft/go-winio/zsyscall.go | 218 +++++ .../microsoft/hcsshim/activatelayer.go | 41 +- .../github.com/microsoft/hcsshim/copylayer.go | 63 +- .../microsoft/hcsshim/createcomputesystem.go | 43 +- .../microsoft/hcsshim/createlayer.go | 50 +- .../microsoft/hcsshim/createprocess.go | 153 +--- .../microsoft/hcsshim/createsandboxlayer.go | 61 +- .../microsoft/hcsshim/deactivatelayer.go | 40 +- .../microsoft/hcsshim/destroylayer.go | 40 +- .../microsoft/hcsshim/exportlayer.go | 60 +- .../microsoft/hcsshim/getlayermountpath.go | 50 +- .../microsoft/hcsshim/getsharedbaseimages.go | 46 +- .../github.com/microsoft/hcsshim/hcsshim.go | 133 ++- .../github.com/microsoft/hcsshim/hnsfuncs.go | 131 +++ .../microsoft/hcsshim/importlayer.go | 60 +- .../microsoft/hcsshim/layerexists.go | 44 +- .../microsoft/hcsshim/mksyscall_windows.go | 797 ++++++++++++++++++ .../microsoft/hcsshim/nametoguid.go | 35 +- .../microsoft/hcsshim/preparelayer.go | 50 +- .../microsoft/hcsshim/resizeconsole.go | 32 +- .../hcsshim/shutdownterminatecomputesystem.go | 45 +- .../microsoft/hcsshim/startcomputesystem.go | 33 +- .../microsoft/hcsshim/terminateprocess.go | 35 +- .../microsoft/hcsshim/unpreparelayer.go | 40 +- .../microsoft/hcsshim/waitprocess.go | 47 +- .../github.com/microsoft/hcsshim/zhcsshim.go | 559 ++++++++++++ 34 files changed, 3320 insertions(+), 1005 deletions(-) create mode 100644 vendor/src/github.com/Microsoft/go-winio/LICENSE create mode 100644 vendor/src/github.com/Microsoft/go-winio/README.md create mode 100644 vendor/src/github.com/Microsoft/go-winio/file.go create mode 100644 vendor/src/github.com/Microsoft/go-winio/mksyscall_windows.go create mode 100644 vendor/src/github.com/Microsoft/go-winio/pipe.go create mode 100644 vendor/src/github.com/Microsoft/go-winio/sd.go create mode 100644 vendor/src/github.com/Microsoft/go-winio/syscall.go create mode 100644 vendor/src/github.com/Microsoft/go-winio/zsyscall.go create mode 100644 vendor/src/github.com/microsoft/hcsshim/hnsfuncs.go create mode 100644 vendor/src/github.com/microsoft/hcsshim/mksyscall_windows.go create mode 100644 vendor/src/github.com/microsoft/hcsshim/zhcsshim.go diff --git a/hack/vendor.sh b/hack/vendor.sh index 5c91621f26..92c6342688 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -7,6 +7,7 @@ source 'hack/.vendor-helpers.sh' # the following lines are in sorted order, FYI clone git github.com/Azure/go-ansiterm 70b2c90b260171e829f1ebd7c17f600c11858dbe +clone git github.com/Microsoft/go-winio 2b085935f02c272e7a1855df6f8fe03029ffcadd clone git github.com/Sirupsen/logrus v0.8.7 # logrus is a common dependency among multiple deps clone git github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a clone git github.com/go-check/check 11d3bc7aa68e238947792f30573146a3231fc0f1 @@ -15,7 +16,7 @@ clone git github.com/gorilla/mux e444e69cbd clone git github.com/kr/pty 5cf931ef8f clone git github.com/mattn/go-shellwords v1.0.0 clone git github.com/mattn/go-sqlite3 v1.1.0 -clone git github.com/microsoft/hcsshim de43b42b5ce14dfdcbeedb0628b0032174d89caa +clone git github.com/microsoft/hcsshim 35ad4d808a97203cb1748d7c43167e91f51e7f86 clone git github.com/mistifyio/go-zfs v2.1.1 clone git github.com/tchap/go-patricia v2.1.0 clone git github.com/vdemeester/shakers 3c10293ce22b900c27acad7b28656196fcc2f73b diff --git a/vendor/src/github.com/Microsoft/go-winio/LICENSE b/vendor/src/github.com/Microsoft/go-winio/LICENSE new file mode 100644 index 0000000000..b8b569d774 --- /dev/null +++ b/vendor/src/github.com/Microsoft/go-winio/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/src/github.com/Microsoft/go-winio/README.md b/vendor/src/github.com/Microsoft/go-winio/README.md new file mode 100644 index 0000000000..478862a8b9 --- /dev/null +++ b/vendor/src/github.com/Microsoft/go-winio/README.md @@ -0,0 +1,15 @@ +# go-winio + +This repository contains utilities for efficiently performing Win32 IO operations in +Go. Currently, this is focused on accessing named pipes and other file handles, and +for using named pipes as a net transport. + +This code relies on IO completion ports to avoid blocking IO on system threads, allowing Go +to reuse the thread to schedule another goroutine. This limits support to Windows Vista and +newer operating systems. This is similar to the implementation of network sockets in Go's net +package. + +Please see the LICENSE file for licensing information. + +Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe +for another named pipe implementation. diff --git a/vendor/src/github.com/Microsoft/go-winio/file.go b/vendor/src/github.com/Microsoft/go-winio/file.go new file mode 100644 index 0000000000..02cd9a528c --- /dev/null +++ b/vendor/src/github.com/Microsoft/go-winio/file.go @@ -0,0 +1,216 @@ +package winio + +import ( + "errors" + "io" + "runtime" + "sync" + "syscall" + "time" +) + +//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx +//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort +//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus +//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes + +const ( + cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1 + cFILE_SKIP_SET_EVENT_ON_HANDLE = 2 +) + +var ( + ErrFileClosed = errors.New("file has already been closed") + ErrTimeout = &timeoutError{} +) + +type timeoutError struct{} + +func (e *timeoutError) Error() string { return "i/o timeout" } +func (e *timeoutError) Timeout() bool { return true } +func (e *timeoutError) Temporary() bool { return true } + +var ioInitOnce sync.Once +var ioCompletionPort syscall.Handle + +// ioResult contains the result of an asynchronous IO operation +type ioResult struct { + bytes uint32 + err error +} + +// ioOperation represents an outstanding asynchronous Win32 IO +type ioOperation struct { + o syscall.Overlapped + ch chan ioResult +} + +func initIo() { + h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff) + if err != nil { + panic(err) + } + ioCompletionPort = h + go ioCompletionProcessor(h) +} + +// win32File implements Reader, Writer, and Closer on a Win32 handle without blocking in a syscall. +// It takes ownership of this handle and will close it if it is garbage collected. +type win32File struct { + handle syscall.Handle + wg sync.WaitGroup + closing bool + readDeadline time.Time + writeDeadline time.Time +} + +// makeWin32File makes a new win32File from an existing file handle +func makeWin32File(h syscall.Handle) (*win32File, error) { + f := &win32File{handle: h} + ioInitOnce.Do(initIo) + _, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff) + if err != nil { + return nil, err + } + err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE) + if err != nil { + return nil, err + } + runtime.SetFinalizer(f, (*win32File).closeHandle) + return f, nil +} + +func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) { + return makeWin32File(h) +} + +// closeHandle closes the resources associated with a Win32 handle +func (f *win32File) closeHandle() { + if !f.closing { + // cancel all IO and wait for it to complete + f.closing = true + cancelIoEx(f.handle, nil) + f.wg.Wait() + // at this point, no new IO can start + syscall.Close(f.handle) + f.handle = 0 + } +} + +// Close closes a win32File. +func (f *win32File) Close() error { + f.closeHandle() + runtime.SetFinalizer(f, nil) + return nil +} + +// prepareIo prepares for a new IO operation +func (f *win32File) prepareIo() (*ioOperation, error) { + f.wg.Add(1) + if f.closing { + return nil, ErrFileClosed + } + c := &ioOperation{} + c.ch = make(chan ioResult) + return c, nil +} + +// ioCompletionProcessor processes completed async IOs forever +func ioCompletionProcessor(h syscall.Handle) { + for { + var bytes uint32 + var key uintptr + var op *ioOperation + err := getQueuedCompletionStatus(h, &bytes, &key, &op, syscall.INFINITE) + if op == nil { + panic(err) + } + op.ch <- ioResult{bytes, err} + } +} + +// asyncIo processes the return value from ReadFile or WriteFile, blocking until +// the operation has actually completed. +func (f *win32File) asyncIo(c *ioOperation, deadline time.Time, bytes uint32, err error) (int, error) { + if err != syscall.ERROR_IO_PENDING { + f.wg.Done() + return int(bytes), err + } else { + var r ioResult + wait := true + timedout := false + if f.closing { + cancelIoEx(f.handle, &c.o) + } else if !deadline.IsZero() { + now := time.Now() + if !deadline.After(now) { + timedout = true + } else { + timeout := time.After(deadline.Sub(now)) + select { + case r = <-c.ch: + wait = false + case <-timeout: + timedout = true + } + } + } + if timedout { + cancelIoEx(f.handle, &c.o) + } + if wait { + r = <-c.ch + } + err = r.err + if err == syscall.ERROR_OPERATION_ABORTED { + if f.closing { + err = ErrFileClosed + } else if timedout { + err = ErrTimeout + } + } + f.wg.Done() + return int(r.bytes), err + } +} + +// Read reads from a file handle. +func (f *win32File) Read(b []byte) (int, error) { + c, err := f.prepareIo() + if err != nil { + return 0, err + } + var bytes uint32 + err = syscall.ReadFile(f.handle, b, &bytes, &c.o) + n, err := f.asyncIo(c, f.readDeadline, bytes, err) + + // Handle EOF conditions. + if err == nil && n == 0 && len(b) != 0 { + return 0, io.EOF + } else if err == syscall.ERROR_BROKEN_PIPE { + return 0, io.EOF + } else { + return n, err + } +} + +// Write writes to a file handle. +func (f *win32File) Write(b []byte) (int, error) { + c, err := f.prepareIo() + if err != nil { + return 0, err + } + var bytes uint32 + err = syscall.WriteFile(f.handle, b, &bytes, &c.o) + return f.asyncIo(c, f.writeDeadline, bytes, err) +} + +func (f *win32File) SetReadDeadline(t time.Time) error { + f.readDeadline = t + return nil +} + +func (f *win32File) SetWriteDeadline(t time.Time) error { + f.writeDeadline = t + return nil +} diff --git a/vendor/src/github.com/Microsoft/go-winio/mksyscall_windows.go b/vendor/src/github.com/Microsoft/go-winio/mksyscall_windows.go new file mode 100644 index 0000000000..652074c7f1 --- /dev/null +++ b/vendor/src/github.com/Microsoft/go-winio/mksyscall_windows.go @@ -0,0 +1,797 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +mksyscall_windows generates windows system call bodies + +It parses all files specified on command line containing function +prototypes (like syscall_windows.go) and prints system call bodies +to standard output. + +The prototypes are marked by lines beginning with "//sys" and read +like func declarations if //sys is replaced by func, but: + +* The parameter lists must give a name for each argument. This + includes return parameters. + +* The parameter lists must give a type for each argument: + the (x, y, z int) shorthand is not allowed. + +* If the return parameter is an error number, it must be named err. + +* If go func name needs to be different from it's winapi dll name, + the winapi name could be specified at the end, after "=" sign, like + //sys LoadLibrary(libname string) (handle uint32, err error) = LoadLibraryA + +* Each function that returns err needs to supply a condition, that + return value of winapi will be tested against to detect failure. + This would set err to windows "last-error", otherwise it will be nil. + The value can be provided at end of //sys declaration, like + //sys LoadLibrary(libname string) (handle uint32, err error) [failretval==-1] = LoadLibraryA + and is [failretval==0] by default. + +Usage: + mksyscall_windows [flags] [path ...] + +The flags are: + -output + Specify output file name (outputs to console if blank). + -trace + Generate print statement after every syscall. +*/ +package main + +import ( + "bufio" + "bytes" + "errors" + "flag" + "fmt" + "go/format" + "go/parser" + "go/token" + "io" + "io/ioutil" + "log" + "os" + "strconv" + "strings" + "text/template" +) + +var ( + filename = flag.String("output", "", "output file name (standard output if omitted)") + printTraceFlag = flag.Bool("trace", false, "generate print statement after every syscall") +) + +func trim(s string) string { + return strings.Trim(s, " \t") +} + +var packageName string + +func packagename() string { + return packageName +} + +func syscalldot() string { + if packageName == "syscall" { + return "" + } + return "syscall." +} + +// Param is function parameter +type Param struct { + Name string + Type string + fn *Fn + tmpVarIdx int +} + +// tmpVar returns temp variable name that will be used to represent p during syscall. +func (p *Param) tmpVar() string { + if p.tmpVarIdx < 0 { + p.tmpVarIdx = p.fn.curTmpVarIdx + p.fn.curTmpVarIdx++ + } + return fmt.Sprintf("_p%d", p.tmpVarIdx) +} + +// BoolTmpVarCode returns source code for bool temp variable. +func (p *Param) BoolTmpVarCode() string { + const code = `var %s uint32 + if %s { + %s = 1 + } else { + %s = 0 + }` + tmp := p.tmpVar() + return fmt.Sprintf(code, tmp, p.Name, tmp, tmp) +} + +// SliceTmpVarCode returns source code for slice temp variable. +func (p *Param) SliceTmpVarCode() string { + const code = `var %s *%s + if len(%s) > 0 { + %s = &%s[0] + }` + tmp := p.tmpVar() + return fmt.Sprintf(code, tmp, p.Type[2:], p.Name, tmp, p.Name) +} + +// StringTmpVarCode returns source code for string temp variable. +func (p *Param) StringTmpVarCode() string { + errvar := p.fn.Rets.ErrorVarName() + if errvar == "" { + errvar = "_" + } + tmp := p.tmpVar() + const code = `var %s %s + %s, %s = %s(%s)` + s := fmt.Sprintf(code, tmp, p.fn.StrconvType(), tmp, errvar, p.fn.StrconvFunc(), p.Name) + if errvar == "-" { + return s + } + const morecode = ` + if %s != nil { + return + }` + return s + fmt.Sprintf(morecode, errvar) +} + +// TmpVarCode returns source code for temp variable. +func (p *Param) TmpVarCode() string { + switch { + case p.Type == "bool": + return p.BoolTmpVarCode() + case strings.HasPrefix(p.Type, "[]"): + return p.SliceTmpVarCode() + default: + return "" + } +} + +// TmpVarHelperCode returns source code for helper's temp variable. +func (p *Param) TmpVarHelperCode() string { + if p.Type != "string" { + return "" + } + return p.StringTmpVarCode() +} + +// SyscallArgList returns source code fragments representing p parameter +// in syscall. Slices are translated into 2 syscall parameters: pointer to +// the first element and length. +func (p *Param) SyscallArgList() []string { + t := p.HelperType() + var s string + switch { + case t[0] == '*': + s = fmt.Sprintf("unsafe.Pointer(%s)", p.Name) + case t == "bool": + s = p.tmpVar() + case strings.HasPrefix(t, "[]"): + return []string{ + fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.tmpVar()), + fmt.Sprintf("uintptr(len(%s))", p.Name), + } + default: + s = p.Name + } + return []string{fmt.Sprintf("uintptr(%s)", s)} +} + +// IsError determines if p parameter is used to return error. +func (p *Param) IsError() bool { + return p.Name == "err" && p.Type == "error" +} + +// HelperType returns type of parameter p used in helper function. +func (p *Param) HelperType() string { + if p.Type == "string" { + return p.fn.StrconvType() + } + return p.Type +} + +// join concatenates parameters ps into a string with sep separator. +// Each parameter is converted into string by applying fn to it +// before conversion. +func join(ps []*Param, fn func(*Param) string, sep string) string { + if len(ps) == 0 { + return "" + } + a := make([]string, 0) + for _, p := range ps { + a = append(a, fn(p)) + } + return strings.Join(a, sep) +} + +// Rets describes function return parameters. +type Rets struct { + Name string + Type string + ReturnsError bool + FailCond string +} + +// ErrorVarName returns error variable name for r. +func (r *Rets) ErrorVarName() string { + if r.ReturnsError { + return "err" + } + if r.Type == "error" { + return r.Name + } + return "" +} + +// ToParams converts r into slice of *Param. +func (r *Rets) ToParams() []*Param { + ps := make([]*Param, 0) + if len(r.Name) > 0 { + ps = append(ps, &Param{Name: r.Name, Type: r.Type}) + } + if r.ReturnsError { + ps = append(ps, &Param{Name: "err", Type: "error"}) + } + return ps +} + +// List returns source code of syscall return parameters. +func (r *Rets) List() string { + s := join(r.ToParams(), func(p *Param) string { return p.Name + " " + p.Type }, ", ") + if len(s) > 0 { + s = "(" + s + ")" + } + return s +} + +// PrintList returns source code of trace printing part correspondent +// to syscall return values. +func (r *Rets) PrintList() string { + return join(r.ToParams(), func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `) +} + +// SetReturnValuesCode returns source code that accepts syscall return values. +func (r *Rets) SetReturnValuesCode() string { + if r.Name == "" && !r.ReturnsError { + return "" + } + retvar := "r0" + if r.Name == "" { + retvar = "r1" + } + errvar := "_" + if r.ReturnsError { + errvar = "e1" + } + return fmt.Sprintf("%s, _, %s := ", retvar, errvar) +} + +func (r *Rets) useLongHandleErrorCode(retvar string) string { + const code = `if %s { + if e1 != 0 { + err = error(e1) + } else { + err = %sEINVAL + } + }` + cond := retvar + " == 0" + if r.FailCond != "" { + cond = strings.Replace(r.FailCond, "failretval", retvar, 1) + } + return fmt.Sprintf(code, cond, syscalldot()) +} + +// SetErrorCode returns source code that sets return parameters. +func (r *Rets) SetErrorCode() string { + const code = `if r0 != 0 { + %s = %sErrno(r0) + }` + if r.Name == "" && !r.ReturnsError { + return "" + } + if r.Name == "" { + return r.useLongHandleErrorCode("r1") + } + if r.Type == "error" { + return fmt.Sprintf(code, r.Name, syscalldot()) + } + s := "" + switch { + case r.Type[0] == '*': + s = fmt.Sprintf("%s = (%s)(unsafe.Pointer(r0))", r.Name, r.Type) + case r.Type == "bool": + s = fmt.Sprintf("%s = r0 != 0", r.Name) + default: + s = fmt.Sprintf("%s = %s(r0)", r.Name, r.Type) + } + if !r.ReturnsError { + return s + } + return s + "\n\t" + r.useLongHandleErrorCode(r.Name) +} + +// Fn describes syscall function. +type Fn struct { + Name string + Params []*Param + Rets *Rets + PrintTrace bool + confirmproc bool + dllname string + dllfuncname string + src string + // TODO: get rid of this field and just use parameter index instead + curTmpVarIdx int // insure tmp variables have uniq names +} + +// extractParams parses s to extract function parameters. +func extractParams(s string, f *Fn) ([]*Param, error) { + s = trim(s) + if s == "" { + return nil, nil + } + a := strings.Split(s, ",") + ps := make([]*Param, len(a)) + for i := range ps { + s2 := trim(a[i]) + b := strings.Split(s2, " ") + if len(b) != 2 { + b = strings.Split(s2, "\t") + if len(b) != 2 { + return nil, errors.New("Could not extract function parameter from \"" + s2 + "\"") + } + } + ps[i] = &Param{ + Name: trim(b[0]), + Type: trim(b[1]), + fn: f, + tmpVarIdx: -1, + } + } + return ps, nil +} + +// extractSection extracts text out of string s starting after start +// and ending just before end. found return value will indicate success, +// and prefix, body and suffix will contain correspondent parts of string s. +func extractSection(s string, start, end rune) (prefix, body, suffix string, found bool) { + s = trim(s) + if strings.HasPrefix(s, string(start)) { + // no prefix + body = s[1:] + } else { + a := strings.SplitN(s, string(start), 2) + if len(a) != 2 { + return "", "", s, false + } + prefix = a[0] + body = a[1] + } + a := strings.SplitN(body, string(end), 2) + if len(a) != 2 { + return "", "", "", false + } + return prefix, a[0], a[1], true +} + +// newFn parses string s and return created function Fn. +func newFn(s string) (*Fn, error) { + s = trim(s) + f := &Fn{ + Rets: &Rets{}, + src: s, + PrintTrace: *printTraceFlag, + } + // function name and args + prefix, body, s, found := extractSection(s, '(', ')') + if !found || prefix == "" { + return nil, errors.New("Could not extract function name and parameters from \"" + f.src + "\"") + } + f.Name = prefix + var err error + f.Params, err = extractParams(body, f) + if err != nil { + return nil, err + } + // return values + _, body, s, found = extractSection(s, '(', ')') + if found { + r, err := extractParams(body, f) + if err != nil { + return nil, err + } + switch len(r) { + case 0: + case 1: + if r[0].IsError() { + f.Rets.ReturnsError = true + } else { + f.Rets.Name = r[0].Name + f.Rets.Type = r[0].Type + } + case 2: + if !r[1].IsError() { + return nil, errors.New("Only last windows error is allowed as second return value in \"" + f.src + "\"") + } + f.Rets.ReturnsError = true + f.Rets.Name = r[0].Name + f.Rets.Type = r[0].Type + default: + return nil, errors.New("Too many return values in \"" + f.src + "\"") + } + } + // fail condition + _, body, s, found = extractSection(s, '[', ']') + if found { + f.Rets.FailCond = body + } + // dll and dll function names + s = trim(s) + if s == "" { + return f, nil + } + if !strings.HasPrefix(s, "=") { + return nil, errors.New("Could not extract dll name from \"" + f.src + "\"") + } + s = trim(s[1:]) + a := strings.Split(s, ".") + switch len(a) { + case 1: + f.dllfuncname = a[0] + case 2: + f.dllname = a[0] + f.dllfuncname = a[1] + default: + return nil, errors.New("Could not extract dll name from \"" + f.src + "\"") + } + if f.dllfuncname[len(f.dllfuncname)-1] == '?' { + f.confirmproc = true + f.dllfuncname = f.dllfuncname[0 : len(f.dllfuncname)-1] + } + return f, nil +} + +// DLLName returns DLL name for function f. +func (f *Fn) DLLName() string { + if f.dllname == "" { + return "kernel32" + } + return f.dllname +} + +// DLLName returns DLL function name for function f. +func (f *Fn) DLLFuncName() string { + if f.dllfuncname == "" { + return f.Name + } + return f.dllfuncname +} + +func (f *Fn) ConfirmProc() bool { + return f.confirmproc +} + +// ParamList returns source code for function f parameters. +func (f *Fn) ParamList() string { + return join(f.Params, func(p *Param) string { return p.Name + " " + p.Type }, ", ") +} + +// HelperParamList returns source code for helper function f parameters. +func (f *Fn) HelperParamList() string { + return join(f.Params, func(p *Param) string { return p.Name + " " + p.HelperType() }, ", ") +} + +// ParamPrintList returns source code of trace printing part correspondent +// to syscall input parameters. +func (f *Fn) ParamPrintList() string { + return join(f.Params, func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `) +} + +// ParamCount return number of syscall parameters for function f. +func (f *Fn) ParamCount() int { + n := 0 + for _, p := range f.Params { + n += len(p.SyscallArgList()) + } + return n +} + +// SyscallParamCount determines which version of Syscall/Syscall6/Syscall9/... +// to use. It returns parameter count for correspondent SyscallX function. +func (f *Fn) SyscallParamCount() int { + n := f.ParamCount() + switch { + case n <= 3: + return 3 + case n <= 6: + return 6 + case n <= 9: + return 9 + case n <= 12: + return 12 + case n <= 15: + return 15 + default: + panic("too many arguments to system call") + } +} + +// Syscall determines which SyscallX function to use for function f. +func (f *Fn) Syscall() string { + c := f.SyscallParamCount() + if c == 3 { + return syscalldot() + "Syscall" + } + return syscalldot() + "Syscall" + strconv.Itoa(c) +} + +// SyscallParamList returns source code for SyscallX parameters for function f. +func (f *Fn) SyscallParamList() string { + a := make([]string, 0) + for _, p := range f.Params { + a = append(a, p.SyscallArgList()...) + } + for len(a) < f.SyscallParamCount() { + a = append(a, "0") + } + return strings.Join(a, ", ") +} + +// HelperCallParamList returns source code of call into function f helper. +func (f *Fn) HelperCallParamList() string { + a := make([]string, 0, len(f.Params)) + for _, p := range f.Params { + s := p.Name + if p.Type == "string" { + s = p.tmpVar() + } + a = append(a, s) + } + return strings.Join(a, ", ") +} + +// IsUTF16 is true, if f is W (utf16) function. It is false +// for all A (ascii) functions. +func (_ *Fn) IsUTF16() bool { + return true +} + +// StrconvFunc returns name of Go string to OS string function for f. +func (f *Fn) StrconvFunc() string { + if f.IsUTF16() { + return syscalldot() + "UTF16PtrFromString" + } + return syscalldot() + "BytePtrFromString" +} + +// StrconvType returns Go type name used for OS string for f. +func (f *Fn) StrconvType() string { + if f.IsUTF16() { + return "*uint16" + } + return "*byte" +} + +// HasStringParam is true, if f has at least one string parameter. +// Otherwise it is false. +func (f *Fn) HasStringParam() bool { + for _, p := range f.Params { + if p.Type == "string" { + return true + } + } + return false +} + +// HelperName returns name of function f helper. +func (f *Fn) HelperName() string { + if !f.HasStringParam() { + return f.Name + } + return "_" + f.Name +} + +// Source files and functions. +type Source struct { + Funcs []*Fn + Files []string +} + +// ParseFiles parses files listed in fs and extracts all syscall +// functions listed in sys comments. It returns source files +// and functions collection *Source if successful. +func ParseFiles(fs []string) (*Source, error) { + src := &Source{ + Funcs: make([]*Fn, 0), + Files: make([]string, 0), + } + for _, file := range fs { + if err := src.ParseFile(file); err != nil { + return nil, err + } + } + return src, nil +} + +// DLLs return dll names for a source set src. +func (src *Source) DLLs() []string { + uniq := make(map[string]bool) + r := make([]string, 0) + for _, f := range src.Funcs { + name := f.DLLName() + if _, found := uniq[name]; !found { + uniq[name] = true + r = append(r, name) + } + } + return r +} + +// ParseFile adds additional file path to a source set src. +func (src *Source) ParseFile(path string) error { + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + + s := bufio.NewScanner(file) + for s.Scan() { + t := trim(s.Text()) + if len(t) < 7 { + continue + } + if !strings.HasPrefix(t, "//sys") { + continue + } + t = t[5:] + if !(t[0] == ' ' || t[0] == '\t') { + continue + } + f, err := newFn(t[1:]) + if err != nil { + return err + } + src.Funcs = append(src.Funcs, f) + } + if err := s.Err(); err != nil { + return err + } + src.Files = append(src.Files, path) + + // get package name + fset := token.NewFileSet() + _, err = file.Seek(0, 0) + if err != nil { + return err + } + pkg, err := parser.ParseFile(fset, "", file, parser.PackageClauseOnly) + if err != nil { + return err + } + packageName = pkg.Name.Name + + return nil +} + +// Generate output source file from a source set src. +func (src *Source) Generate(w io.Writer) error { + funcMap := template.FuncMap{ + "packagename": packagename, + "syscalldot": syscalldot, + } + t := template.Must(template.New("main").Funcs(funcMap).Parse(srcTemplate)) + err := t.Execute(w, src) + if err != nil { + return errors.New("Failed to execute template: " + err.Error()) + } + return nil +} + +func usage() { + fmt.Fprintf(os.Stderr, "usage: mksyscall_windows [flags] [path ...]\n") + flag.PrintDefaults() + os.Exit(1) +} + +func main() { + flag.Usage = usage + flag.Parse() + if len(flag.Args()) <= 0 { + fmt.Fprintf(os.Stderr, "no files to parse provided\n") + usage() + } + + src, err := ParseFiles(flag.Args()) + if err != nil { + log.Fatal(err) + } + + var buf bytes.Buffer + if err := src.Generate(&buf); err != nil { + log.Fatal(err) + } + + data, err := format.Source(buf.Bytes()) + if err != nil { + log.Fatal(err) + } + if *filename == "" { + _, err = os.Stdout.Write(data) + } else { + err = ioutil.WriteFile(*filename, data, 0644) + } + if err != nil { + log.Fatal(err) + } +} + +// TODO: use println instead to print in the following template +const srcTemplate = ` + +{{define "main"}}// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT + +package {{packagename}} + +import "unsafe"{{if syscalldot}} +import "syscall"{{end}} + +var _ unsafe.Pointer + +var ( +{{template "dlls" .}} +{{template "funcnames" .}}) +{{range .Funcs}}{{if .HasStringParam}}{{template "helperbody" .}}{{end}}{{template "funcbody" .}}{{end}} +{{end}} + +{{/* help functions */}} + +{{define "dlls"}}{{range .DLLs}} mod{{.}} = {{syscalldot}}NewLazyDLL("{{.}}.dll") +{{end}}{{end}} + +{{define "funcnames"}}{{range .Funcs}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}") +{{end}}{{end}} + +{{define "helperbody"}} +func {{.Name}}({{.ParamList}}) {{template "results" .}}{ +{{template "helpertmpvars" .}} return {{.HelperName}}({{.HelperCallParamList}}) +} +{{end}} + +{{define "funcbody"}} +func {{.HelperName}}({{.HelperParamList}}) {{template "results" .}}{ +{{template "tmpvars" .}} {{template "syscallcheck" .}}{{template "syscall" .}} +{{template "seterror" .}}{{template "printtrace" .}} return +} +{{end}} + +{{define "helpertmpvars"}}{{range .Params}}{{if .TmpVarHelperCode}} {{.TmpVarHelperCode}} +{{end}}{{end}}{{end}} + +{{define "tmpvars"}}{{range .Params}}{{if .TmpVarCode}} {{.TmpVarCode}} +{{end}}{{end}}{{end}} + +{{define "results"}}{{if .Rets.List}}{{.Rets.List}} {{end}}{{end}} + +{{define "syscallcheck"}}{{if .ConfirmProc}}if {{.Rets.ErrorVarName}} = proc{{.DLLFuncName}}.Find(); {{.Rets.ErrorVarName}} != nil { + return +} +{{end}}{{end}} + +{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(), {{.ParamCount}}, {{.SyscallParamList}}){{end}} + +{{define "seterror"}}{{if .Rets.SetErrorCode}} {{.Rets.SetErrorCode}} +{{end}}{{end}} + +{{define "printtrace"}}{{if .PrintTrace}} print("SYSCALL: {{.Name}}(", {{.ParamPrintList}}") (", {{.Rets.PrintList}}")\n") +{{end}}{{end}} + +` diff --git a/vendor/src/github.com/Microsoft/go-winio/pipe.go b/vendor/src/github.com/Microsoft/go-winio/pipe.go new file mode 100644 index 0000000000..b281b5e23c --- /dev/null +++ b/vendor/src/github.com/Microsoft/go-winio/pipe.go @@ -0,0 +1,280 @@ +package winio + +import ( + "errors" + "net" + "os" + "syscall" + "time" + "unsafe" +) + +//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe +//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 +//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 +//sys waitNamedPipe(name string, timeout uint32) (err error) = WaitNamedPipeW + +type securityAttributes struct { + Length uint32 + SecurityDescriptor *byte + InheritHandle uint32 +} + +const ( + cERROR_PIPE_BUSY = syscall.Errno(231) + cERROR_PIPE_CONNECTED = syscall.Errno(535) + cERROR_SEM_TIMEOUT = syscall.Errno(121) + + cPIPE_ACCESS_DUPLEX = 0x3 + cFILE_FLAG_FIRST_PIPE_INSTANCE = 0x80000 + cSECURITY_SQOS_PRESENT = 0x100000 + cSECURITY_ANONYMOUS = 0 + + cPIPE_REJECT_REMOTE_CLIENTS = 0x8 + + cPIPE_UNLIMITED_INSTANCES = 255 + + cNMPWAIT_USE_DEFAULT_WAIT = 0 + cNMPWAIT_NOWAIT = 1 +) + +var ( + // This error should match net.errClosing since docker takes a dependency on its text + ErrPipeListenerClosed = errors.New("use of closed network connection") +) + +type win32Pipe struct { + *win32File + path string +} + +type pipeAddress string + +func (f *win32Pipe) LocalAddr() net.Addr { + return pipeAddress(f.path) +} + +func (f *win32Pipe) RemoteAddr() net.Addr { + return pipeAddress(f.path) +} + +func (f *win32Pipe) SetDeadline(t time.Time) error { + f.SetReadDeadline(t) + f.SetWriteDeadline(t) + return nil +} + +func (s pipeAddress) Network() string { + return "pipe" +} + +func (s pipeAddress) String() string { + return string(s) +} + +func makeWin32Pipe(h syscall.Handle, path string) (*win32Pipe, error) { + f, err := makeWin32File(h) + if err != nil { + return nil, err + } + return &win32Pipe{f, path}, nil +} + +// DialPipe connects to a named pipe by path, timing out if the connection +// takes longer than the specified duration. If timeout is nil, then the timeout +// is the default timeout established by the pipe server. +func DialPipe(path string, timeout *time.Duration) (net.Conn, error) { + var absTimeout time.Time + if timeout != nil { + absTimeout = time.Now().Add(*timeout) + } + var err error + var h syscall.Handle + for { + 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) + if err != cERROR_PIPE_BUSY { + break + } + now := time.Now() + var ms uint32 + if absTimeout.IsZero() { + ms = cNMPWAIT_USE_DEFAULT_WAIT + } else if now.After(absTimeout) { + ms = cNMPWAIT_NOWAIT + } else { + ms = uint32(absTimeout.Sub(now).Nanoseconds() / 1000 / 1000) + } + err = waitNamedPipe(path, ms) + if err != nil { + if err == cERROR_SEM_TIMEOUT { + return nil, ErrTimeout + } + break + } + } + if err != nil { + return nil, &os.PathError{"open", path, err} + } + p, err := makeWin32Pipe(h, path) + if err != nil { + syscall.Close(h) + return nil, err + } + return p, nil +} + +type acceptResponse struct { + p *win32Pipe + err error +} + +type win32PipeListener struct { + firstHandle syscall.Handle + path string + securityDescriptor []byte + acceptCh chan (chan acceptResponse) + closeCh chan int + doneCh chan int +} + +func makeServerPipeHandle(path string, securityDescriptor []byte, first bool) (syscall.Handle, error) { + var flags uint32 = cPIPE_ACCESS_DUPLEX | syscall.FILE_FLAG_OVERLAPPED + if first { + flags |= cFILE_FLAG_FIRST_PIPE_INSTANCE + } + var sa securityAttributes + sa.Length = uint32(unsafe.Sizeof(sa)) + if securityDescriptor != nil { + sa.SecurityDescriptor = &securityDescriptor[0] + } + h, err := createNamedPipe(path, flags, cPIPE_REJECT_REMOTE_CLIENTS, cPIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, &sa) + if err != nil { + return 0, &os.PathError{"open", path, err} + } + return h, nil +} + +func (l *win32PipeListener) makeServerPipe() (*win32Pipe, error) { + h, err := makeServerPipeHandle(l.path, l.securityDescriptor, false) + if err != nil { + return nil, err + } + p, err := makeWin32Pipe(h, l.path) + if err != nil { + syscall.Close(h) + return nil, err + } + return p, nil +} + +func (l *win32PipeListener) listenerRoutine() { + closed := false + for !closed { + select { + case <-l.closeCh: + closed = true + case responseCh := <-l.acceptCh: + p, err := l.makeServerPipe() + if err == nil { + // Wait for the client to connect. + ch := make(chan error) + go func() { + ch <- connectPipe(p) + }() + select { + case err = <-ch: + if err != nil { + p.Close() + p = nil + } + case <-l.closeCh: + // Abort the connect request by closing the handle. + p.Close() + p = nil + err = <-ch + if err == nil || err == ErrFileClosed { + err = ErrPipeListenerClosed + } + closed = true + } + } + responseCh <- acceptResponse{p, err} + } + } + syscall.Close(l.firstHandle) + l.firstHandle = 0 + // Notify Close() and Accept() callers that the handle has been closed. + close(l.doneCh) +} + +func ListenPipe(path, sddl string) (net.Listener, error) { + var ( + sd []byte + err error + ) + if sddl != "" { + sd, err = sddlToSecurityDescriptor(sddl) + if err != nil { + return nil, err + } + } + h, err := makeServerPipeHandle(path, sd, true) + if err != nil { + return nil, err + } + // Immediately open and then close a client handle so that the named pipe is + // created but not currently accepting connections. + h2, err := createFile(path, 0, 0, nil, syscall.OPEN_EXISTING, cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0) + if err != nil { + syscall.Close(h) + return nil, err + } + syscall.Close(h2) + l := &win32PipeListener{ + firstHandle: h, + path: path, + securityDescriptor: sd, + acceptCh: make(chan (chan acceptResponse)), + closeCh: make(chan int), + doneCh: make(chan int), + } + go l.listenerRoutine() + return l, nil +} + +func connectPipe(p *win32Pipe) error { + c, err := p.prepareIo() + if err != nil { + return err + } + err = connectNamedPipe(p.handle, &c.o) + _, err = p.asyncIo(c, time.Time{}, 0, err) + if err != nil && err != cERROR_PIPE_CONNECTED { + return err + } + return nil +} + +func (l *win32PipeListener) Accept() (net.Conn, error) { + ch := make(chan acceptResponse) + select { + case l.acceptCh <- ch: + response := <-ch + return response.p, response.err + case <-l.doneCh: + return nil, ErrPipeListenerClosed + } +} + +func (l *win32PipeListener) Close() error { + select { + case l.closeCh <- 1: + <-l.doneCh + case <-l.doneCh: + } + return nil +} + +func (l *win32PipeListener) Addr() net.Addr { + return pipeAddress(l.path) +} diff --git a/vendor/src/github.com/Microsoft/go-winio/sd.go b/vendor/src/github.com/Microsoft/go-winio/sd.go new file mode 100644 index 0000000000..c8bc7ffa87 --- /dev/null +++ b/vendor/src/github.com/Microsoft/go-winio/sd.go @@ -0,0 +1,83 @@ +package winio + +import ( + "syscall" + "unsafe" +) + +//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW +//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW +//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW +//sys localFree(mem uintptr) = LocalFree +//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength + +const ( + cERROR_NONE_MAPPED = syscall.Errno(1332) +) + +type AccountLookupError struct { + Name string + Err error +} + +func (e *AccountLookupError) Error() string { + if e.Name == "" { + return "lookup account: empty account name specified" + } + var s string + switch e.Err { + case cERROR_NONE_MAPPED: + s = "not found" + default: + s = e.Err.Error() + } + return "lookup account " + e.Name + ": " + s +} + +type SddlConversionError struct { + Sddl string + Err error +} + +func (e *SddlConversionError) Error() string { + return "convert " + e.Sddl + ": " + e.Err.Error() +} + +// LookupSidByName looks up the SID of an account by name +func LookupSidByName(name string) (sid string, err error) { + if name == "" { + return "", &AccountLookupError{name, cERROR_NONE_MAPPED} + } + + var sidSize, sidNameUse, refDomainSize uint32 + err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse) + if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { + return "", &AccountLookupError{name, err} + } + sidBuffer := make([]byte, sidSize) + refDomainBuffer := make([]uint16, refDomainSize) + err = lookupAccountName(nil, name, &sidBuffer[0], &sidSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse) + if err != nil { + return "", &AccountLookupError{name, err} + } + var strBuffer *uint16 + err = convertSidToStringSid(&sidBuffer[0], &strBuffer) + if err != nil { + return "", &AccountLookupError{name, err} + } + sid = syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(strBuffer))[:]) + localFree(uintptr(unsafe.Pointer(strBuffer))) + return sid, nil +} + +func sddlToSecurityDescriptor(sddl string) ([]byte, error) { + var sdBuffer uintptr + err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil) + if err != nil { + return nil, &SddlConversionError{sddl, err} + } + defer localFree(sdBuffer) + sd := make([]byte, getSecurityDescriptorLength(sdBuffer)) + copy(sd, (*[1 << 30]byte)(unsafe.Pointer(sdBuffer))[:len(sd)]) + return sd, nil +} diff --git a/vendor/src/github.com/Microsoft/go-winio/syscall.go b/vendor/src/github.com/Microsoft/go-winio/syscall.go new file mode 100644 index 0000000000..20767dcb22 --- /dev/null +++ b/vendor/src/github.com/Microsoft/go-winio/syscall.go @@ -0,0 +1,3 @@ +package winio + +//go:generate go run mksyscall_windows.go -output zsyscall.go file.go pipe.go sd.go diff --git a/vendor/src/github.com/Microsoft/go-winio/zsyscall.go b/vendor/src/github.com/Microsoft/go-winio/zsyscall.go new file mode 100644 index 0000000000..bfe4ac3470 --- /dev/null +++ b/vendor/src/github.com/Microsoft/go-winio/zsyscall.go @@ -0,0 +1,218 @@ +// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT + +package winio + +import "unsafe" +import "syscall" + +var _ unsafe.Pointer + +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + modadvapi32 = syscall.NewLazyDLL("advapi32.dll") + + procCancelIoEx = modkernel32.NewProc("CancelIoEx") + procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") + procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") + procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") + procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") + procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") + procCreateFileW = modkernel32.NewProc("CreateFileW") + procWaitNamedPipeW = modkernel32.NewProc("WaitNamedPipeW") + procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") + procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") + procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") + procLocalFree = modkernel32.NewProc("LocalFree") + procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength") +) + +func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0) + newport = syscall.Handle(r0) + if newport == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) { + r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *securityAttributes) (handle syscall.Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(name) + if err != nil { + return + } + return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa) +} + +func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *securityAttributes) (handle syscall.Handle, err error) { + 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) + handle = syscall.Handle(r0) + if handle == syscall.InvalidHandle { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func createFile(name string, access uint32, mode uint32, sa *securityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(name) + if err != nil { + return + } + return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile) +} + +func _createFile(name *uint16, access uint32, mode uint32, sa *securityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { + 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) + handle = syscall.Handle(r0) + if handle == syscall.InvalidHandle { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func waitNamedPipe(name string, timeout uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(name) + if err != nil { + return + } + return _waitNamedPipe(_p0, timeout) +} + +func _waitNamedPipe(name *uint16, timeout uint32) (err error) { + r1, _, e1 := syscall.Syscall(procWaitNamedPipeW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(timeout), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(accountName) + if err != nil { + return + } + return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse) +} + +func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { + 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) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func convertSidToStringSid(sid *byte, str **uint16) (err error) { + r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(str) + if err != nil { + return + } + return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size) +} + +func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func localFree(mem uintptr) { + syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0) + return +} + +func getSecurityDescriptorLength(sd uintptr) (len uint32) { + r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0) + len = uint32(r0) + return +} diff --git a/vendor/src/github.com/microsoft/hcsshim/activatelayer.go b/vendor/src/github.com/microsoft/hcsshim/activatelayer.go index 8d2c54d43f..efc4d8029c 100644 --- a/vendor/src/github.com/microsoft/hcsshim/activatelayer.go +++ b/vendor/src/github.com/microsoft/hcsshim/activatelayer.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // ActivateLayer will find the layer with the given id and mount it's filesystem. // 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 { title := "hcsshim::ActivateLayer " logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procActivateLayer) - if dll != nil { - defer dll.Release() - } - if err != nil { - return err - } - - // Convert id to uint16 pointer for calling the procedure - idp, err := syscall.UTF16PtrFromString(id) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) - logrus.Error(err) - return err - } - - // Convert info to API calling convention infop, err := convertDriverInfo(info) if err != nil { - err = fmt.Errorf(title+" - Failed conversion info struct %s", err) logrus.Error(err) return err } - // Call the procedure itself. - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(&infop)), - uintptr(unsafe.Pointer(idp))) - - use(unsafe.Pointer(&infop)) - use(unsafe.Pointer(idp)) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s flavour=%d", - r1, syscall.Errno(r1), id, info.Flavour) + err = activateLayer(&infop, id) + if err != nil { + err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/copylayer.go b/vendor/src/github.com/microsoft/hcsshim/copylayer.go index 5176eecb35..abbe134e20 100644 --- a/vendor/src/github.com/microsoft/hcsshim/copylayer.go +++ b/vendor/src/github.com/microsoft/hcsshim/copylayer.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // CopyLayer performs a commit of the srcId (which is expected to be a read-write // 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) title := "hcsshim::CopyLayer " logrus.Debugf(title+"srcId %s dstId", srcId, dstId) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procCopyLayer) - if dll != nil { - defer dll.Release() - } - if err != nil { - return err - } - - // Convert srcId to uint16 pointer for calling the procedure - srcIdp, err := syscall.UTF16PtrFromString(srcId) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of srcId %s to pointer %s", srcId, err) - logrus.Error(err) - return err - } - - // Convert dstId to uint16 pointer for calling the procedure - dstIdp, err := syscall.UTF16PtrFromString(dstId) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of dstId %s to pointer %s", dstId, err) - logrus.Error(err) - return err - } - // Generate layer descriptors layers, err := layerPathsToDescriptors(parentLayerPaths) if err != nil { - err = fmt.Errorf(title+" - Failed to generate layer descriptors %s", err) - logrus.Error(err) return err } // Convert info to API calling convention infop, err := convertDriverInfo(info) if err != nil { - err = fmt.Errorf(title+" - Failed conversion info struct %s", err) - logrus.Error(err) return err } - var layerDescriptorsp *WC_LAYER_DESCRIPTOR - if len(layers) > 0 { - layerDescriptorsp = &(layers[0]) - } else { - layerDescriptorsp = nil - } - - // Call the procedure itself. - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(&infop)), - uintptr(unsafe.Pointer(srcIdp)), - uintptr(unsafe.Pointer(dstIdp)), - uintptr(unsafe.Pointer(layerDescriptorsp)), - uintptr(len(layers))) - - use(unsafe.Pointer(&infop)) - use(unsafe.Pointer(srcIdp)) - use(unsafe.Pointer(dstIdp)) - use(unsafe.Pointer(layerDescriptorsp)) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s srcId=%s dstId=%d", - r1, syscall.Errno(r1), srcId, dstId) + err = copyLayer(&infop, srcId, dstId, layers) + if err != nil { + err = makeErrorf(err, title, "srcId=%s dstId=%d", srcId, dstId) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/createcomputesystem.go b/vendor/src/github.com/microsoft/hcsshim/createcomputesystem.go index f456c33356..3cc12a38ef 100644 --- a/vendor/src/github.com/microsoft/hcsshim/createcomputesystem.go +++ b/vendor/src/github.com/microsoft/hcsshim/createcomputesystem.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // CreateComputeSystem creates a container, initializing its configuration in // 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 { title := "HCSShim::CreateComputeSystem" logrus.Debugln(title+" id=%s, configuration=%s", id, configuration) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procCreateComputeSystem) - if dll != nil { - defer dll.Release() - } + err := createComputeSystem(id, configuration) if err != nil { - return err - } - - // Convert id to uint16 pointers for calling the procedure - idp, err := syscall.UTF16PtrFromString(id) - if err != nil { - err = fmt.Errorf(title+"- Failed conversion of id %s to pointer %s", id, err) - logrus.Error(err) - return err - } - - // Convert configuration to uint16 pointers for calling the procedure - configurationp, err := syscall.UTF16PtrFromString(configuration) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of configuration %s to pointer %s", configuration, err) - logrus.Error(err) - return err - } - - // Call the procedure itself. - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(idp)), uintptr(unsafe.Pointer(configurationp))) - - use(unsafe.Pointer(idp)) - use(unsafe.Pointer(configurationp)) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s configuration=%s", r1, syscall.Errno(r1), id, configuration) + err = makeErrorf(err, title, "id=%s configuration=%s", id, configuration) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/createlayer.go b/vendor/src/github.com/microsoft/hcsshim/createlayer.go index c7ef74f454..9ecffb1cb0 100644 --- a/vendor/src/github.com/microsoft/hcsshim/createlayer.go +++ b/vendor/src/github.com/microsoft/hcsshim/createlayer.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // CreateLayer creates a new, empty, read-only layer on the filesystem based on // the parent layer provided. @@ -14,52 +8,16 @@ func CreateLayer(info DriverInfo, id, parent string) error { title := "hcsshim::CreateLayer " logrus.Debugf(title+"Flavour %d ID %s parent %s", info.Flavour, id, parent) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procCreateLayer) - if dll != nil { - defer dll.Release() - } - if err != nil { - return err - } - - // Convert id to uint16 pointer for calling the procedure - idp, err := syscall.UTF16PtrFromString(id) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) - logrus.Error(err) - return err - } - - // Convert parent to uint16 pointer for calling the procedure - parentp, err := syscall.UTF16PtrFromString(parent) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of parent %s to pointer %s", parent, err) - logrus.Error(err) - return err - } - // Convert info to API calling convention infop, err := convertDriverInfo(info) if err != nil { - err = fmt.Errorf(title+" - Failed conversion info struct %s", parent, err) logrus.Error(err) return err } - // Call the procedure itself. - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(&infop)), - uintptr(unsafe.Pointer(idp)), - uintptr(unsafe.Pointer(parentp))) - - use(unsafe.Pointer(&infop)) - use(unsafe.Pointer(idp)) - use(unsafe.Pointer(parentp)) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s parent=%s flavour=%d", - r1, syscall.Errno(r1), id, parent, info.Flavour) + err = createLayer(&infop, id, parent) + if err != nil { + err = makeErrorf(err, title, "id=%s parent=%s flavour=%d", id, parent, info.Flavour) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/createprocess.go b/vendor/src/github.com/microsoft/hcsshim/createprocess.go index be28bde4e6..a170a9a1e3 100644 --- a/vendor/src/github.com/microsoft/hcsshim/createprocess.go +++ b/vendor/src/github.com/microsoft/hcsshim/createprocess.go @@ -2,12 +2,10 @@ package hcsshim import ( "encoding/json" - "fmt" "io" - "runtime" "syscall" - "unsafe" + "github.com/Microsoft/go-winio" "github.com/Sirupsen/logrus" ) @@ -22,77 +20,38 @@ type CreateProcessParams struct { ConsoleSize [2]int } -// pipe struct used for the stdin/stdout/stderr pipes -type pipe struct { - handle syscall.Handle -} - -func makePipe(h syscall.Handle) *pipe { - p := &pipe{h} - runtime.SetFinalizer(p, (*pipe).closeHandle) - return p -} - -func (p *pipe) closeHandle() { - if p.handle != 0 { - syscall.CloseHandle(p.handle) - p.handle = 0 - } -} - -func (p *pipe) Close() error { - p.closeHandle() - runtime.SetFinalizer(p, nil) - return nil -} - -func (p *pipe) Read(b []byte) (int, error) { - // syscall.Read returns 0, nil on ERROR_BROKEN_PIPE, but for - // our purposes this should indicate EOF. This may be a go bug. - var read uint32 - err := syscall.ReadFile(p.handle, b, &read, nil) - if err != nil { - if err == syscall.ERROR_BROKEN_PIPE { - return 0, io.EOF +// makeOpenFiles calls winio.MakeOpenFile for each handle in a slice but closes all the handles +// if there is an error. +func makeOpenFiles(hs []syscall.Handle) (_ []io.ReadWriteCloser, err error) { + fs := make([]io.ReadWriteCloser, len(hs)) + for i, h := range hs { + if h != syscall.Handle(0) { + if err == nil { + fs[i], err = winio.MakeOpenFile(h) + } + if err != nil { + syscall.Close(h) + } } - return 0, err } - return int(read), nil -} - -func (p *pipe) Write(b []byte) (int, error) { - return syscall.Write(p.handle, b) + if err != nil { + for _, f := range fs { + if f != nil { + f.Close() + } + } + return nil, err + } + return fs, nil } // CreateProcessInComputeSystem starts a process in a container. This is invoked, for example, // as a result of docker run, docker exec, or RUN in Dockerfile. If successful, // it returns the PID of the process. -func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useStderr bool, params CreateProcessParams) (uint32, io.WriteCloser, io.ReadCloser, io.ReadCloser, uint32, error) { - - var ( - stdin io.WriteCloser - stdout, stderr io.ReadCloser - ) - +func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useStderr bool, params CreateProcessParams) (_ uint32, _ io.WriteCloser, _ io.ReadCloser, _ io.ReadCloser, hr uint32, err error) { title := "HCSShim::CreateProcessInComputeSystem" logrus.Debugf(title+" id=%s", id) - - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procCreateProcessWithStdHandlesInComputeSystem) - if dll != nil { - defer dll.Release() - } - if err != nil { - return 0, nil, nil, nil, 0xFFFFFFFF, err - } - - // Convert id to uint16 pointer for calling the procedure - idp, err := syscall.UTF16PtrFromString(id) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) - logrus.Error(err) - return 0, nil, nil, nil, 0xFFFFFFFF, err - } + hr = 0xFFFFFFFF // If we are not emulating a console, ignore any console size passed to us if !params.EmulateConsole { @@ -102,65 +61,43 @@ func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useS paramsJson, err := json.Marshal(params) if err != nil { - err = fmt.Errorf(title+" - Failed to marshall params %v %s", params, err) - return 0, nil, nil, nil, 0xFFFFFFFF, err + return } - // Convert paramsJson to uint16 pointer for calling the procedure - paramsJsonp, err := syscall.UTF16PtrFromString(string(paramsJson)) - if err != nil { - return 0, nil, nil, nil, 0xFFFFFFFF, err - } - - // Get a POINTER to variable to take the pid outparm - pid := new(uint32) - logrus.Debugf(title+" - Calling Win32 %s %s", id, paramsJson) - var stdinHandle, stdoutHandle, stderrHandle syscall.Handle - var stdinParam, stdoutParam, stderrParam uintptr + var pid uint32 + + handles := make([]syscall.Handle, 3) + var stdinParam, stdoutParam, stderrParam *syscall.Handle if useStdin { - stdinParam = uintptr(unsafe.Pointer(&stdinHandle)) + stdinParam = &handles[0] } if useStdout { - stdoutParam = uintptr(unsafe.Pointer(&stdoutHandle)) + stdoutParam = &handles[1] } if useStderr { - stderrParam = uintptr(unsafe.Pointer(&stderrHandle)) + stderrParam = &handles[2] } - // Call the procedure itself. - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(idp)), - uintptr(unsafe.Pointer(paramsJsonp)), - uintptr(unsafe.Pointer(pid)), - stdinParam, - stdoutParam, - stderrParam) - - use(unsafe.Pointer(idp)) - use(unsafe.Pointer(paramsJsonp)) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s params=%v", r1, syscall.Errno(r1), id, params) + err = createProcessWithStdHandlesInComputeSystem(id, string(paramsJson), &pid, stdinParam, stdoutParam, stderrParam) + if err != nil { + winerr := makeErrorf(err, title, "id=%s params=%v", id, params) + hr = winerr.HResult() // Windows TP4: Hyper-V Containers may return this error with more than one // concurrent exec. Do not log it as an error - if uint32(r1) != Win32InvalidArgument { - logrus.Error(err) + if hr != Win32InvalidArgument { + logrus.Error(winerr) } - return 0, nil, nil, nil, uint32(r1), err + err = winerr + return } - if useStdin { - stdin = makePipe(stdinHandle) - } - if useStdout { - stdout = makePipe(stdoutHandle) - } - if useStderr { - stderr = makePipe(stderrHandle) + pipes, err := makeOpenFiles(handles) + if err != nil { + return } - logrus.Debugf(title+" - succeeded id=%s params=%s pid=%d", id, paramsJson, *pid) - return *pid, stdin, stdout, stderr, 0, nil + logrus.Debugf(title+" - succeeded id=%s params=%s pid=%d", id, paramsJson, pid) + return pid, pipes[0], pipes[1], pipes[2], 0, nil } diff --git a/vendor/src/github.com/microsoft/hcsshim/createsandboxlayer.go b/vendor/src/github.com/microsoft/hcsshim/createsandboxlayer.go index d3175c0e05..b69c3da368 100644 --- a/vendor/src/github.com/microsoft/hcsshim/createsandboxlayer.go +++ b/vendor/src/github.com/microsoft/hcsshim/createsandboxlayer.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // CreateSandboxLayer creates and populates new read-write layer for use by a container. // 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 title := "hcsshim::CreateSandboxLayer " logrus.Debugf(title+"layerId %s parentId %s", layerId, parentId) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procCreateSandboxLayer) - if dll != nil { - defer dll.Release() - } - if err != nil { - return err - } - // Generate layer descriptors layers, err := layerPathsToDescriptors(parentLayerPaths) if err != nil { - err = fmt.Errorf(title+"- Failed to generate layer descriptors ", err) - return err - } - - // Convert layerId to uint16 pointer for calling the procedure - layerIdp, err := syscall.UTF16PtrFromString(layerId) - if err != nil { - err = fmt.Errorf(title+"- Failed conversion of layerId %s to pointer %s", layerId, err) - logrus.Error(err) - return err - } - - // Convert parentId to uint16 pointer for calling the procedure - parentIdp, err := syscall.UTF16PtrFromString(parentId) - if err != nil { - err = fmt.Errorf(title+"- Failed conversion of parentId %s to pointer %s", parentId, err) - logrus.Error(err) return err } // Convert info to API calling convention infop, err := convertDriverInfo(info) if err != nil { - err = fmt.Errorf(title+"- Failed conversion info struct %s", err) logrus.Error(err) return err } - var layerDescriptorsp *WC_LAYER_DESCRIPTOR - if len(layers) > 0 { - layerDescriptorsp = &(layers[0]) - } else { - layerDescriptorsp = nil - } - - // Call the procedure itself. - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(&infop)), - uintptr(unsafe.Pointer(layerIdp)), - uintptr(unsafe.Pointer(parentIdp)), - uintptr(unsafe.Pointer(layerDescriptorsp)), - uintptr(len(layers))) - - use(unsafe.Pointer(&infop)) - use(unsafe.Pointer(layerIdp)) - use(unsafe.Pointer(parentIdp)) - use(unsafe.Pointer(layerDescriptorsp)) - - if r1 != 0 { - err = fmt.Errorf(title+"- Win32 API call returned error r1=%d err=%s layerId=%s parentId=%s", - r1, syscall.Errno(r1), layerId, parentId) + err = createSandboxLayer(&infop, layerId, parentId, layers) + if err != nil { + err = makeErrorf(err, title, "layerId=%s parentId=%s", layerId, parentId) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/deactivatelayer.go b/vendor/src/github.com/microsoft/hcsshim/deactivatelayer.go index e03ab9da43..c02bcb3a0b 100644 --- a/vendor/src/github.com/microsoft/hcsshim/deactivatelayer.go +++ b/vendor/src/github.com/microsoft/hcsshim/deactivatelayer.go @@ -1,54 +1,22 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // DeactivateLayer will dismount a layer that was mounted via ActivateLayer. func DeactivateLayer(info DriverInfo, id string) error { title := "hcsshim::DeactivateLayer " logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procDeactivateLayer) - if dll != nil { - defer dll.Release() - } - if err != nil { - return err - } - - // Convert id to uint16 pointer for calling the procedure - idp, err := syscall.UTF16PtrFromString(id) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) - logrus.Error(err) - return err - } - // Convert info to API calling convention infop, err := convertDriverInfo(info) if err != nil { - err = fmt.Errorf(title+" - Failed conversion info struct %s", err) logrus.Error(err) return err } - // Call the procedure itself. - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(&infop)), - uintptr(unsafe.Pointer(idp))) - - use(unsafe.Pointer(&infop)) - use(unsafe.Pointer(idp)) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s flavour=%d", - r1, syscall.Errno(r1), id, info.Flavour) + err = deactivateLayer(&infop, id) + if err != nil { + err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/destroylayer.go b/vendor/src/github.com/microsoft/hcsshim/destroylayer.go index 0ba43b4b9b..91ed269eef 100644 --- a/vendor/src/github.com/microsoft/hcsshim/destroylayer.go +++ b/vendor/src/github.com/microsoft/hcsshim/destroylayer.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // DestroyLayer will remove the on-disk files representing the layer with the given // id, including that layer's containing folder, if any. @@ -14,42 +8,16 @@ func DestroyLayer(info DriverInfo, id string) error { title := "hcsshim::DestroyLayer " logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procDestroyLayer) - if dll != nil { - defer dll.Release() - } - if err != nil { - return err - } - - // Convert id to uint16 pointer for calling the procedure - idp, err := syscall.UTF16PtrFromString(id) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) - logrus.Error(err) - return err - } - // Convert info to API calling convention infop, err := convertDriverInfo(info) if err != nil { - err = fmt.Errorf(title+" - Failed conversion info struct %s", err) logrus.Error(err) return err } - // Call the procedure itself. - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(&infop)), - uintptr(unsafe.Pointer(idp))) - - use(unsafe.Pointer(&infop)) - use(unsafe.Pointer(idp)) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s flavour=%d", - r1, syscall.Errno(r1), id, info.Flavour) + err = destroyLayer(&infop, id) + if err != nil { + err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/exportlayer.go b/vendor/src/github.com/microsoft/hcsshim/exportlayer.go index 8ea61938c0..629dc04d5a 100644 --- a/vendor/src/github.com/microsoft/hcsshim/exportlayer.go +++ b/vendor/src/github.com/microsoft/hcsshim/exportlayer.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // ExportLayer will create a folder at exportFolderPath and fill that folder with // 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 title := "hcsshim::ExportLayer " logrus.Debugf(title+"flavour %d layerId %s folder %s", info.Flavour, layerId, exportFolderPath) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procExportLayer) - if dll != nil { - defer dll.Release() - } - if err != nil { - return err - } - // Generate layer descriptors layers, err := layerPathsToDescriptors(parentLayerPaths) if err != nil { - err = fmt.Errorf(title+"- Failed to generate layer descriptors ", err) - return err - } - - // Convert layerId to uint16 pointer for calling the procedure - layerIdp, err := syscall.UTF16PtrFromString(layerId) - if err != nil { - err = fmt.Errorf(title+"- Failed conversion of layerId %s to pointer %s", layerId, err) - logrus.Error(err) - return err - } - - // Convert exportFolderPath to uint16 pointer for calling the procedure - exportFolderPathp, err := syscall.UTF16PtrFromString(exportFolderPath) - if err != nil { - err = fmt.Errorf(title+"- Failed conversion of exportFolderPath %s to pointer %s", exportFolderPath, err) - logrus.Error(err) return err } // Convert info to API calling convention infop, err := convertDriverInfo(info) if err != nil { - err = fmt.Errorf(title+"- Failed conversion info struct %s", err) logrus.Error(err) return err } - var layerDescriptorsp *WC_LAYER_DESCRIPTOR - if len(layers) > 0 { - layerDescriptorsp = &(layers[0]) - } else { - layerDescriptorsp = nil - } - - // Call the procedure itself. - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(&infop)), - uintptr(unsafe.Pointer(layerIdp)), - uintptr(unsafe.Pointer(exportFolderPathp)), - uintptr(unsafe.Pointer(layerDescriptorsp)), - uintptr(len(layers))) - use(unsafe.Pointer(&infop)) - use(unsafe.Pointer(layerIdp)) - use(unsafe.Pointer(exportFolderPathp)) - use(unsafe.Pointer(layerDescriptorsp)) - - if r1 != 0 { - err = fmt.Errorf(title+"- Win32 API call returned error r1=%d err=%s layerId=%s flavour=%d folder=%s", - r1, syscall.Errno(r1), layerId, info.Flavour, exportFolderPath) + err = exportLayer(&infop, layerId, exportFolderPath, layers) + if err != nil { + err = makeErrorf(err, title, "layerId=%s flavour=%d folder=%s", layerId, info.Flavour, exportFolderPath) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/getlayermountpath.go b/vendor/src/github.com/microsoft/hcsshim/getlayermountpath.go index 18d2a4ec10..41b5758926 100644 --- a/vendor/src/github.com/microsoft/hcsshim/getlayermountpath.go +++ b/vendor/src/github.com/microsoft/hcsshim/getlayermountpath.go @@ -1,9 +1,7 @@ package hcsshim import ( - "fmt" "syscall" - "unsafe" "github.com/Sirupsen/logrus" ) @@ -16,45 +14,21 @@ func GetLayerMountPath(info DriverInfo, id string) (string, error) { title := "hcsshim::GetLayerMountPath " logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procGetLayerMountPath) - if dll != nil { - defer dll.Release() - } - if err != nil { - return "", err - } - - // Convert id to uint16 pointer for calling the procedure - idp, err := syscall.UTF16PtrFromString(id) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) - logrus.Error(err) - return "", err - } - // Convert info to API calling convention infop, err := convertDriverInfo(info) if err != nil { - err = fmt.Errorf(title+" - Failed conversion info struct %s", err) logrus.Error(err) return "", err } - var mountPathLength uint64 + var mountPathLength uintptr mountPathLength = 0 // Call the procedure itself. logrus.Debugf("Calling proc (1)") - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(&infop)), - uintptr(unsafe.Pointer(idp)), - uintptr(unsafe.Pointer(&mountPathLength)), - uintptr(unsafe.Pointer(nil))) - - if r1 != 0 { - err = fmt.Errorf(title+" - First Win32 API call returned error r1=%d err=%s id=%s flavour=%d", - r1, syscall.Errno(r1), id, info.Flavour) + err = getLayerMountPath(&infop, id, &mountPathLength, nil) + if err != nil { + err = makeErrorf(err, title, "(first call) id=%s flavour=%d", id, info.Flavour) logrus.Error(err) return "", err } @@ -68,19 +42,9 @@ func GetLayerMountPath(info DriverInfo, id string) (string, error) { // Call the procedure again logrus.Debugf("Calling proc (2)") - r1, _, _ = proc.Call( - uintptr(unsafe.Pointer(&infop)), - uintptr(unsafe.Pointer(idp)), - uintptr(unsafe.Pointer(&mountPathLength)), - uintptr(unsafe.Pointer(&mountPathp[0]))) - - use(unsafe.Pointer(&mountPathLength)) - use(unsafe.Pointer(&infop)) - use(unsafe.Pointer(idp)) - - if r1 != 0 { - err = fmt.Errorf(title+" - Second Win32 API call returned error r1=%d err=%s id=%s flavour=%d", - r1, syscall.Errno(r1), id, info.Flavour) + err = getLayerMountPath(&infop, id, &mountPathLength, &mountPathp[0]) + if err != nil { + err = makeErrorf(err, title, "(second call) id=%s flavour=%d", id, info.Flavour) logrus.Error(err) return "", err } diff --git a/vendor/src/github.com/microsoft/hcsshim/getsharedbaseimages.go b/vendor/src/github.com/microsoft/hcsshim/getsharedbaseimages.go index a6c4b7bdb1..01ab4da3dd 100644 --- a/vendor/src/github.com/microsoft/hcsshim/getsharedbaseimages.go +++ b/vendor/src/github.com/microsoft/hcsshim/getsharedbaseimages.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // GetSharedBaseImages will enumerate the images stored in the common central // image store and return descriptive info about those images for the purpose @@ -14,43 +8,15 @@ import ( func GetSharedBaseImages() (imageData string, err error) { title := "hcsshim::GetSharedBaseImages " - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procGetSharedBaseImages) - if dll != nil { - defer dll.Release() - } - if err != nil { - return - } - - // Load the OLE DLL and get a handle to the CoTaskMemFree procedure - dll2, proc2, err := loadAndFindFromDll(oleDLLName, procCoTaskMemFree) - if dll2 != nil { - defer dll2.Release() - } - if err != nil { - return - } - - var output uintptr - - // Call the procedure again logrus.Debugf("Calling proc") - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(&output))) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=%d errno=%s", - r1, syscall.Errno(r1)) + var buffer *uint16 + err = getBaseImages(&buffer) + if err != nil { + err = makeError(err, title, "") logrus.Error(err) return } - - // Defer the cleanup of the memory using CoTaskMemFree - defer proc2.Call(output) - - imageData = syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(output))[:]) + imageData = convertAndFreeCoTaskMemString(buffer) logrus.Debugf(title+" - succeeded output=%s", imageData) - return } diff --git a/vendor/src/github.com/microsoft/hcsshim/hcsshim.go b/vendor/src/github.com/microsoft/hcsshim/hcsshim.go index b23890aaa2..fc894ca935 100644 --- a/vendor/src/github.com/microsoft/hcsshim/hcsshim.go +++ b/vendor/src/github.com/microsoft/hcsshim/hcsshim.go @@ -7,46 +7,39 @@ import ( "fmt" "syscall" "unsafe" - - "github.com/Sirupsen/logrus" ) +//go:generate go run mksyscall_windows.go -output zhcsshim.go hcsshim.go + +//sys coTaskMemFree(buffer unsafe.Pointer) = ole32.CoTaskMemFree + +//sys activateLayer(info *driverInfo, id string) (hr error) = vmcompute.ActivateLayer? +//sys copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CopyLayer? +//sys createLayer(info *driverInfo, id string, parent string) (hr error) = vmcompute.CreateLayer? +//sys createSandboxLayer(info *driverInfo, id string, parent string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CreateSandboxLayer? +//sys deactivateLayer(info *driverInfo, id string) (hr error) = vmcompute.DeactivateLayer? +//sys destroyLayer(info *driverInfo, id string) (hr error) = vmcompute.DestroyLayer? +//sys exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ExportLayer? +//sys getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) = vmcompute.GetLayerMountPath? +//sys getBaseImages(buffer **uint16) (hr error) = vmcompute.GetBaseImages? +//sys importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ImportLayer? +//sys layerExists(info *driverInfo, id string, exists *uint32) (hr error) = vmcompute.LayerExists? +//sys nameToGuid(name string, guid *GUID) (hr error) = vmcompute.NameToGuid? +//sys prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.PrepareLayer? +//sys unprepareLayer(info *driverInfo, id string) (hr error) = vmcompute.UnprepareLayer? + +//sys createComputeSystem(id string, configuration string) (hr error) = vmcompute.CreateComputeSystem? +//sys createProcessWithStdHandlesInComputeSystem(id string, paramsJson string, pid *uint32, stdin *syscall.Handle, stdout *syscall.Handle, stderr *syscall.Handle) (hr error) = vmcompute.CreateProcessWithStdHandlesInComputeSystem? +//sys resizeConsoleInComputeSystem(id string, pid uint32, height uint16, width uint16, flags uint32) (hr error) = vmcompute.ResizeConsoleInComputeSystem? +//sys shutdownComputeSystem(id string, timeout uint32) (hr error) = vmcompute.ShutdownComputeSystem? +//sys startComputeSystem(id string) (hr error) = vmcompute.StartComputeSystem? +//sys terminateComputeSystem(id string) (hr error) = vmcompute.TerminateComputeSystem? +//sys terminateProcessInComputeSystem(id string, pid uint32) (hr error) = vmcompute.TerminateProcessInComputeSystem? +//sys waitForProcessInComputeSystem(id string, pid uint32, timeout uint32, exitCode *uint32) (hr error) = vmcompute.WaitForProcessInComputeSystem? + +//sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall? + const ( - // Name of the shim DLL for access to the HCS - shimDLLName = "vmcompute.dll" - - // Container related functions in the shim DLL - procCreateComputeSystem = "CreateComputeSystem" - procStartComputeSystem = "StartComputeSystem" - procCreateProcessWithStdHandlesInComputeSystem = "CreateProcessWithStdHandlesInComputeSystem" - procWaitForProcessInComputeSystem = "WaitForProcessInComputeSystem" - procShutdownComputeSystem = "ShutdownComputeSystem" - procTerminateComputeSystem = "TerminateComputeSystem" - procTerminateProcessInComputeSystem = "TerminateProcessInComputeSystem" - procResizeConsoleInComputeSystem = "ResizeConsoleInComputeSystem" - - // Storage related functions in the shim DLL - procLayerExists = "LayerExists" - procCreateLayer = "CreateLayer" - procDestroyLayer = "DestroyLayer" - procActivateLayer = "ActivateLayer" - procDeactivateLayer = "DeactivateLayer" - procGetLayerMountPath = "GetLayerMountPath" - procCopyLayer = "CopyLayer" - procCreateSandboxLayer = "CreateSandboxLayer" - procPrepareLayer = "PrepareLayer" - procUnprepareLayer = "UnprepareLayer" - procExportLayer = "ExportLayer" - procImportLayer = "ImportLayer" - procGetSharedBaseImages = "GetBaseImages" - procNameToGuid = "NameToGuid" - - // Name of the standard OLE dll - oleDLLName = "Ole32.dll" - - // Utility functions - procCoTaskMemFree = "CoTaskMemFree" - // Specific user-visible exit codes WaitErrExecFailed = 32767 @@ -56,49 +49,45 @@ const ( Win32SpecifiedPathInvalid = 0x800700A1 // ShutdownComputeSystem: The specified path is invalid Win32SystemCannotFindThePathSpecified = 0x80070003 // ShutdownComputeSystem: The system cannot find the path specified Win32InvalidArgument = 0x80072726 // CreateProcessInComputeSystem: An invalid argument was supplied + EFail = 0x80004005 // Timeout on wait calls TimeoutInfinite = 0xFFFFFFFF ) -// loadAndFindFromDll finds a procedure in the given DLL. Note we do NOT do lazy loading as -// go is particularly unfriendly in the case of a mismatch. By that - it panics -// if a function can't be found. By explicitly loading, we can control error -// handling gracefully without the daemon terminating. -func loadAndFindFromDll(dllName, procedure string) (dll *syscall.DLL, proc *syscall.Proc, err error) { - dll, err = syscall.LoadDLL(dllName) - if err != nil { - err = fmt.Errorf("Failed to load %s - error %s", dllName, err) - logrus.Error(err) - return +type hcsError struct { + title string + rest string + err error +} + +type Win32Error interface { + error + HResult() uint32 +} + +func makeError(err error, title, rest string) Win32Error { + return &hcsError{title, rest, err} +} + +func makeErrorf(err error, title, format string, a ...interface{}) Win32Error { + return makeError(err, title, fmt.Sprintf(format, a...)) +} + +func (e *hcsError) HResult() uint32 { + if hr, ok := e.err.(syscall.Errno); ok { + return uint32(hr) + } else { + return EFail } - - proc, err = dll.FindProc(procedure) - if err != nil { - err = fmt.Errorf("Failed to find %s in %s", procedure, dllName) - logrus.Error(err) - return - } - - return } -// loadAndFind finds a procedure in the shim DLL. -func loadAndFind(procedure string) (*syscall.DLL, *syscall.Proc, error) { - - return loadAndFindFromDll(shimDLLName, procedure) +func (e *hcsError) Error() string { + return fmt.Sprintf("%s- Win32 API call returned error r1=0x%x err=%s%s", e.title, e.HResult(), e.err, e.rest) } -// use is a no-op, but the compiler cannot see that it is. -// Calling use(p) ensures that p is kept live until that point. -/* -//go:noescape -func use(p unsafe.Pointer) -*/ - -// Alternate without using //go:noescape and asm.s -var temp unsafe.Pointer - -func use(p unsafe.Pointer) { - temp = p +func convertAndFreeCoTaskMemString(buffer *uint16) string { + str := syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(buffer))[:]) + coTaskMemFree(unsafe.Pointer(buffer)) + return str } diff --git a/vendor/src/github.com/microsoft/hcsshim/hnsfuncs.go b/vendor/src/github.com/microsoft/hcsshim/hnsfuncs.go new file mode 100644 index 0000000000..affff7f86f --- /dev/null +++ b/vendor/src/github.com/microsoft/hcsshim/hnsfuncs.go @@ -0,0 +1,131 @@ +package hcsshim + +import ( + "encoding/json" + "fmt" + "net" + + "github.com/Sirupsen/logrus" +) + +type NatPolicy struct { + Type string + Protocol string + InternalPort uint16 + ExternalPort uint16 +} + +type QosPolicy struct { + Type string + MaximumOutgoingBandwidthInBytes uint64 +} + +// Subnet is assoicated with a network and represents a list +// of subnets available to the network +type Subnet struct { + AddressPrefix string `json:",omitempty"` + GatewayAddress string `json:",omitempty"` +} + +// MacPool is assoicated with a network and represents a list +// of macaddresses available to the network +type MacPool struct { + StartMacAddress string `json:",omitempty"` + EndMacAddress string `json:",omitempty"` +} + +// HNSNetwork represents a network in HNS +type HNSNetwork struct { + Id string `json:",omitempty"` + Name string `json:",omitempty"` + Type string `json:",omitempty"` + Policies []json.RawMessage `json:",omitempty"` + MacPools []MacPool `json:",omitempty"` + Subnets []Subnet `json:",omitempty"` +} + +// HNSEndpoint represents a network endpoint in HNS +type HNSEndpoint struct { + Id string `json:",omitempty"` + Name string `json:",omitempty"` + VirtualNetwork string `json:",omitempty"` + VirtualNetworkName string `json:",omitempty"` + Policies []json.RawMessage `json:",omitempty"` + MacAddress string `json:",omitempty"` + IPAddress net.IP `json:",omitempty"` +} + +type hnsNetworkResponse struct { + Success bool + Error string + Output HNSNetwork +} + +type hnsResponse struct { + Success bool + Error string + Output json.RawMessage +} + +func hnsCall(method, path, request string, returnResponse interface{}) error { + var responseBuffer *uint16 + err := _hnsCall(method, path, request, &responseBuffer) + if err != nil { + return makeError(err, "hnsCall ", "") + } + response := convertAndFreeCoTaskMemString(responseBuffer) + + hnsresponse := &hnsResponse{} + if err = json.Unmarshal([]byte(response), &hnsresponse); err != nil { + return err + } + + if !hnsresponse.Success { + return fmt.Errorf("HNS failed with error : %s", hnsresponse.Error) + } + + if len(hnsresponse.Output) == 0 { + return nil + } + + logrus.Debugf("Network Response : %s", hnsresponse.Output) + err = json.Unmarshal(hnsresponse.Output, returnResponse) + if err != nil { + return err + } + + return nil +} + +// HNSNetworkRequest makes a call into HNS to update/query a single network +func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) { + var network HNSNetwork + err := hnsCall(method, "/networks/"+path, request, &network) + if err != nil { + return nil, err + } + + return &network, nil +} + +// HNSListNetworkRequest makes a HNS call to query the list of available networks +func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) { + var network []HNSNetwork + err := hnsCall(method, "/networks/"+path, request, &network) + if err != nil { + return nil, err + } + + return network, nil +} + +// HNSEndpointRequest makes a HNS call to modify/query a network endpoint +func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) { + endpoint := &HNSEndpoint{} + err := hnsCall(method, "/endpoints/"+path, request, &endpoint) + if err != nil { + return nil, err + } + + return endpoint, nil +} diff --git a/vendor/src/github.com/microsoft/hcsshim/importlayer.go b/vendor/src/github.com/microsoft/hcsshim/importlayer.go index 4e0848b9c2..3ab1124e9c 100644 --- a/vendor/src/github.com/microsoft/hcsshim/importlayer.go +++ b/vendor/src/github.com/microsoft/hcsshim/importlayer.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // ImportLayer will take the contents of the folder at importFolderPath and import // 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 title := "hcsshim::ImportLayer " logrus.Debugf(title+"flavour %d layerId %s folder %s", info.Flavour, layerId, importFolderPath) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procImportLayer) - if dll != nil { - defer dll.Release() - } - if err != nil { - return err - } - // Generate layer descriptors layers, err := layerPathsToDescriptors(parentLayerPaths) if err != nil { - err = fmt.Errorf(title+"- Failed to generate layer descriptors ", err) - return err - } - - // Convert layerId to uint16 pointer for calling the procedure - layerIdp, err := syscall.UTF16PtrFromString(layerId) - if err != nil { - err = fmt.Errorf(title+"- Failed conversion of layerId %s to pointer %s", layerId, err) - logrus.Error(err) - return err - } - - // Convert importFolderPath to uint16 pointer for calling the procedure - importFolderPathp, err := syscall.UTF16PtrFromString(importFolderPath) - if err != nil { - err = fmt.Errorf(title+"- Failed conversion of importFolderPath %s to pointer %s", importFolderPath, err) - logrus.Error(err) return err } // Convert info to API calling convention infop, err := convertDriverInfo(info) if err != nil { - err = fmt.Errorf(title+"- Failed conversion info struct %s", err) logrus.Error(err) return err } - var layerDescriptorsp *WC_LAYER_DESCRIPTOR - if len(layers) > 0 { - layerDescriptorsp = &(layers[0]) - } else { - layerDescriptorsp = nil - } - - // Call the procedure itself. - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(&infop)), - uintptr(unsafe.Pointer(layerIdp)), - uintptr(unsafe.Pointer(importFolderPathp)), - uintptr(unsafe.Pointer(layerDescriptorsp)), - uintptr(len(layers))) - use(unsafe.Pointer(&infop)) - use(unsafe.Pointer(layerIdp)) - use(unsafe.Pointer(importFolderPathp)) - use(unsafe.Pointer(layerDescriptorsp)) - - if r1 != 0 { - err = fmt.Errorf(title+"- Win32 API call returned error r1=%d err=%s layerId=%s flavour=%d folder=%s", - r1, syscall.Errno(r1), layerId, info.Flavour, importFolderPath) + err = importLayer(&infop, layerId, importFolderPath, layers) + if err != nil { + err = makeErrorf(err, title, "layerId=%s flavour=%d folder=%s", layerId, info.Flavour, importFolderPath) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/layerexists.go b/vendor/src/github.com/microsoft/hcsshim/layerexists.go index 78b17ef20d..522d95cce4 100644 --- a/vendor/src/github.com/microsoft/hcsshim/layerexists.go +++ b/vendor/src/github.com/microsoft/hcsshim/layerexists.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // LayerExists will return true if a layer with the given id exists and is known // to the system. @@ -14,49 +8,23 @@ func LayerExists(info DriverInfo, id string) (bool, error) { title := "hcsshim::LayerExists " logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procLayerExists) - if dll != nil { - defer dll.Release() - } - if err != nil { - return false, err - } - - // Convert id to uint16 pointer for calling the procedure - idp, err := syscall.UTF16PtrFromString(id) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) - logrus.Error(err) - return false, err - } - // Convert info to API calling convention infop, err := convertDriverInfo(info) if err != nil { - err = fmt.Errorf(title+" - Failed conversion info struct %s", err) logrus.Error(err) return false, err } // Call the procedure itself. - var exists bool // Outparam from Win32 + var exists uint32 - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(&infop)), - uintptr(unsafe.Pointer(idp)), - uintptr(unsafe.Pointer(&exists))) - - use(unsafe.Pointer(&infop)) - use(unsafe.Pointer(idp)) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s flavour=%d", - r1, syscall.Errno(r1), id, info.Flavour) + err = layerExists(&infop, id, &exists) + if err != nil { + err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) logrus.Error(err) return false, err } logrus.Debugf(title+"succeeded flavour=%d id=%s exists=%d", info.Flavour, id, exists) - return exists, nil + return exists != 0, nil } diff --git a/vendor/src/github.com/microsoft/hcsshim/mksyscall_windows.go b/vendor/src/github.com/microsoft/hcsshim/mksyscall_windows.go new file mode 100644 index 0000000000..652074c7f1 --- /dev/null +++ b/vendor/src/github.com/microsoft/hcsshim/mksyscall_windows.go @@ -0,0 +1,797 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +mksyscall_windows generates windows system call bodies + +It parses all files specified on command line containing function +prototypes (like syscall_windows.go) and prints system call bodies +to standard output. + +The prototypes are marked by lines beginning with "//sys" and read +like func declarations if //sys is replaced by func, but: + +* The parameter lists must give a name for each argument. This + includes return parameters. + +* The parameter lists must give a type for each argument: + the (x, y, z int) shorthand is not allowed. + +* If the return parameter is an error number, it must be named err. + +* If go func name needs to be different from it's winapi dll name, + the winapi name could be specified at the end, after "=" sign, like + //sys LoadLibrary(libname string) (handle uint32, err error) = LoadLibraryA + +* Each function that returns err needs to supply a condition, that + return value of winapi will be tested against to detect failure. + This would set err to windows "last-error", otherwise it will be nil. + The value can be provided at end of //sys declaration, like + //sys LoadLibrary(libname string) (handle uint32, err error) [failretval==-1] = LoadLibraryA + and is [failretval==0] by default. + +Usage: + mksyscall_windows [flags] [path ...] + +The flags are: + -output + Specify output file name (outputs to console if blank). + -trace + Generate print statement after every syscall. +*/ +package main + +import ( + "bufio" + "bytes" + "errors" + "flag" + "fmt" + "go/format" + "go/parser" + "go/token" + "io" + "io/ioutil" + "log" + "os" + "strconv" + "strings" + "text/template" +) + +var ( + filename = flag.String("output", "", "output file name (standard output if omitted)") + printTraceFlag = flag.Bool("trace", false, "generate print statement after every syscall") +) + +func trim(s string) string { + return strings.Trim(s, " \t") +} + +var packageName string + +func packagename() string { + return packageName +} + +func syscalldot() string { + if packageName == "syscall" { + return "" + } + return "syscall." +} + +// Param is function parameter +type Param struct { + Name string + Type string + fn *Fn + tmpVarIdx int +} + +// tmpVar returns temp variable name that will be used to represent p during syscall. +func (p *Param) tmpVar() string { + if p.tmpVarIdx < 0 { + p.tmpVarIdx = p.fn.curTmpVarIdx + p.fn.curTmpVarIdx++ + } + return fmt.Sprintf("_p%d", p.tmpVarIdx) +} + +// BoolTmpVarCode returns source code for bool temp variable. +func (p *Param) BoolTmpVarCode() string { + const code = `var %s uint32 + if %s { + %s = 1 + } else { + %s = 0 + }` + tmp := p.tmpVar() + return fmt.Sprintf(code, tmp, p.Name, tmp, tmp) +} + +// SliceTmpVarCode returns source code for slice temp variable. +func (p *Param) SliceTmpVarCode() string { + const code = `var %s *%s + if len(%s) > 0 { + %s = &%s[0] + }` + tmp := p.tmpVar() + return fmt.Sprintf(code, tmp, p.Type[2:], p.Name, tmp, p.Name) +} + +// StringTmpVarCode returns source code for string temp variable. +func (p *Param) StringTmpVarCode() string { + errvar := p.fn.Rets.ErrorVarName() + if errvar == "" { + errvar = "_" + } + tmp := p.tmpVar() + const code = `var %s %s + %s, %s = %s(%s)` + s := fmt.Sprintf(code, tmp, p.fn.StrconvType(), tmp, errvar, p.fn.StrconvFunc(), p.Name) + if errvar == "-" { + return s + } + const morecode = ` + if %s != nil { + return + }` + return s + fmt.Sprintf(morecode, errvar) +} + +// TmpVarCode returns source code for temp variable. +func (p *Param) TmpVarCode() string { + switch { + case p.Type == "bool": + return p.BoolTmpVarCode() + case strings.HasPrefix(p.Type, "[]"): + return p.SliceTmpVarCode() + default: + return "" + } +} + +// TmpVarHelperCode returns source code for helper's temp variable. +func (p *Param) TmpVarHelperCode() string { + if p.Type != "string" { + return "" + } + return p.StringTmpVarCode() +} + +// SyscallArgList returns source code fragments representing p parameter +// in syscall. Slices are translated into 2 syscall parameters: pointer to +// the first element and length. +func (p *Param) SyscallArgList() []string { + t := p.HelperType() + var s string + switch { + case t[0] == '*': + s = fmt.Sprintf("unsafe.Pointer(%s)", p.Name) + case t == "bool": + s = p.tmpVar() + case strings.HasPrefix(t, "[]"): + return []string{ + fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.tmpVar()), + fmt.Sprintf("uintptr(len(%s))", p.Name), + } + default: + s = p.Name + } + return []string{fmt.Sprintf("uintptr(%s)", s)} +} + +// IsError determines if p parameter is used to return error. +func (p *Param) IsError() bool { + return p.Name == "err" && p.Type == "error" +} + +// HelperType returns type of parameter p used in helper function. +func (p *Param) HelperType() string { + if p.Type == "string" { + return p.fn.StrconvType() + } + return p.Type +} + +// join concatenates parameters ps into a string with sep separator. +// Each parameter is converted into string by applying fn to it +// before conversion. +func join(ps []*Param, fn func(*Param) string, sep string) string { + if len(ps) == 0 { + return "" + } + a := make([]string, 0) + for _, p := range ps { + a = append(a, fn(p)) + } + return strings.Join(a, sep) +} + +// Rets describes function return parameters. +type Rets struct { + Name string + Type string + ReturnsError bool + FailCond string +} + +// ErrorVarName returns error variable name for r. +func (r *Rets) ErrorVarName() string { + if r.ReturnsError { + return "err" + } + if r.Type == "error" { + return r.Name + } + return "" +} + +// ToParams converts r into slice of *Param. +func (r *Rets) ToParams() []*Param { + ps := make([]*Param, 0) + if len(r.Name) > 0 { + ps = append(ps, &Param{Name: r.Name, Type: r.Type}) + } + if r.ReturnsError { + ps = append(ps, &Param{Name: "err", Type: "error"}) + } + return ps +} + +// List returns source code of syscall return parameters. +func (r *Rets) List() string { + s := join(r.ToParams(), func(p *Param) string { return p.Name + " " + p.Type }, ", ") + if len(s) > 0 { + s = "(" + s + ")" + } + return s +} + +// PrintList returns source code of trace printing part correspondent +// to syscall return values. +func (r *Rets) PrintList() string { + return join(r.ToParams(), func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `) +} + +// SetReturnValuesCode returns source code that accepts syscall return values. +func (r *Rets) SetReturnValuesCode() string { + if r.Name == "" && !r.ReturnsError { + return "" + } + retvar := "r0" + if r.Name == "" { + retvar = "r1" + } + errvar := "_" + if r.ReturnsError { + errvar = "e1" + } + return fmt.Sprintf("%s, _, %s := ", retvar, errvar) +} + +func (r *Rets) useLongHandleErrorCode(retvar string) string { + const code = `if %s { + if e1 != 0 { + err = error(e1) + } else { + err = %sEINVAL + } + }` + cond := retvar + " == 0" + if r.FailCond != "" { + cond = strings.Replace(r.FailCond, "failretval", retvar, 1) + } + return fmt.Sprintf(code, cond, syscalldot()) +} + +// SetErrorCode returns source code that sets return parameters. +func (r *Rets) SetErrorCode() string { + const code = `if r0 != 0 { + %s = %sErrno(r0) + }` + if r.Name == "" && !r.ReturnsError { + return "" + } + if r.Name == "" { + return r.useLongHandleErrorCode("r1") + } + if r.Type == "error" { + return fmt.Sprintf(code, r.Name, syscalldot()) + } + s := "" + switch { + case r.Type[0] == '*': + s = fmt.Sprintf("%s = (%s)(unsafe.Pointer(r0))", r.Name, r.Type) + case r.Type == "bool": + s = fmt.Sprintf("%s = r0 != 0", r.Name) + default: + s = fmt.Sprintf("%s = %s(r0)", r.Name, r.Type) + } + if !r.ReturnsError { + return s + } + return s + "\n\t" + r.useLongHandleErrorCode(r.Name) +} + +// Fn describes syscall function. +type Fn struct { + Name string + Params []*Param + Rets *Rets + PrintTrace bool + confirmproc bool + dllname string + dllfuncname string + src string + // TODO: get rid of this field and just use parameter index instead + curTmpVarIdx int // insure tmp variables have uniq names +} + +// extractParams parses s to extract function parameters. +func extractParams(s string, f *Fn) ([]*Param, error) { + s = trim(s) + if s == "" { + return nil, nil + } + a := strings.Split(s, ",") + ps := make([]*Param, len(a)) + for i := range ps { + s2 := trim(a[i]) + b := strings.Split(s2, " ") + if len(b) != 2 { + b = strings.Split(s2, "\t") + if len(b) != 2 { + return nil, errors.New("Could not extract function parameter from \"" + s2 + "\"") + } + } + ps[i] = &Param{ + Name: trim(b[0]), + Type: trim(b[1]), + fn: f, + tmpVarIdx: -1, + } + } + return ps, nil +} + +// extractSection extracts text out of string s starting after start +// and ending just before end. found return value will indicate success, +// and prefix, body and suffix will contain correspondent parts of string s. +func extractSection(s string, start, end rune) (prefix, body, suffix string, found bool) { + s = trim(s) + if strings.HasPrefix(s, string(start)) { + // no prefix + body = s[1:] + } else { + a := strings.SplitN(s, string(start), 2) + if len(a) != 2 { + return "", "", s, false + } + prefix = a[0] + body = a[1] + } + a := strings.SplitN(body, string(end), 2) + if len(a) != 2 { + return "", "", "", false + } + return prefix, a[0], a[1], true +} + +// newFn parses string s and return created function Fn. +func newFn(s string) (*Fn, error) { + s = trim(s) + f := &Fn{ + Rets: &Rets{}, + src: s, + PrintTrace: *printTraceFlag, + } + // function name and args + prefix, body, s, found := extractSection(s, '(', ')') + if !found || prefix == "" { + return nil, errors.New("Could not extract function name and parameters from \"" + f.src + "\"") + } + f.Name = prefix + var err error + f.Params, err = extractParams(body, f) + if err != nil { + return nil, err + } + // return values + _, body, s, found = extractSection(s, '(', ')') + if found { + r, err := extractParams(body, f) + if err != nil { + return nil, err + } + switch len(r) { + case 0: + case 1: + if r[0].IsError() { + f.Rets.ReturnsError = true + } else { + f.Rets.Name = r[0].Name + f.Rets.Type = r[0].Type + } + case 2: + if !r[1].IsError() { + return nil, errors.New("Only last windows error is allowed as second return value in \"" + f.src + "\"") + } + f.Rets.ReturnsError = true + f.Rets.Name = r[0].Name + f.Rets.Type = r[0].Type + default: + return nil, errors.New("Too many return values in \"" + f.src + "\"") + } + } + // fail condition + _, body, s, found = extractSection(s, '[', ']') + if found { + f.Rets.FailCond = body + } + // dll and dll function names + s = trim(s) + if s == "" { + return f, nil + } + if !strings.HasPrefix(s, "=") { + return nil, errors.New("Could not extract dll name from \"" + f.src + "\"") + } + s = trim(s[1:]) + a := strings.Split(s, ".") + switch len(a) { + case 1: + f.dllfuncname = a[0] + case 2: + f.dllname = a[0] + f.dllfuncname = a[1] + default: + return nil, errors.New("Could not extract dll name from \"" + f.src + "\"") + } + if f.dllfuncname[len(f.dllfuncname)-1] == '?' { + f.confirmproc = true + f.dllfuncname = f.dllfuncname[0 : len(f.dllfuncname)-1] + } + return f, nil +} + +// DLLName returns DLL name for function f. +func (f *Fn) DLLName() string { + if f.dllname == "" { + return "kernel32" + } + return f.dllname +} + +// DLLName returns DLL function name for function f. +func (f *Fn) DLLFuncName() string { + if f.dllfuncname == "" { + return f.Name + } + return f.dllfuncname +} + +func (f *Fn) ConfirmProc() bool { + return f.confirmproc +} + +// ParamList returns source code for function f parameters. +func (f *Fn) ParamList() string { + return join(f.Params, func(p *Param) string { return p.Name + " " + p.Type }, ", ") +} + +// HelperParamList returns source code for helper function f parameters. +func (f *Fn) HelperParamList() string { + return join(f.Params, func(p *Param) string { return p.Name + " " + p.HelperType() }, ", ") +} + +// ParamPrintList returns source code of trace printing part correspondent +// to syscall input parameters. +func (f *Fn) ParamPrintList() string { + return join(f.Params, func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `) +} + +// ParamCount return number of syscall parameters for function f. +func (f *Fn) ParamCount() int { + n := 0 + for _, p := range f.Params { + n += len(p.SyscallArgList()) + } + return n +} + +// SyscallParamCount determines which version of Syscall/Syscall6/Syscall9/... +// to use. It returns parameter count for correspondent SyscallX function. +func (f *Fn) SyscallParamCount() int { + n := f.ParamCount() + switch { + case n <= 3: + return 3 + case n <= 6: + return 6 + case n <= 9: + return 9 + case n <= 12: + return 12 + case n <= 15: + return 15 + default: + panic("too many arguments to system call") + } +} + +// Syscall determines which SyscallX function to use for function f. +func (f *Fn) Syscall() string { + c := f.SyscallParamCount() + if c == 3 { + return syscalldot() + "Syscall" + } + return syscalldot() + "Syscall" + strconv.Itoa(c) +} + +// SyscallParamList returns source code for SyscallX parameters for function f. +func (f *Fn) SyscallParamList() string { + a := make([]string, 0) + for _, p := range f.Params { + a = append(a, p.SyscallArgList()...) + } + for len(a) < f.SyscallParamCount() { + a = append(a, "0") + } + return strings.Join(a, ", ") +} + +// HelperCallParamList returns source code of call into function f helper. +func (f *Fn) HelperCallParamList() string { + a := make([]string, 0, len(f.Params)) + for _, p := range f.Params { + s := p.Name + if p.Type == "string" { + s = p.tmpVar() + } + a = append(a, s) + } + return strings.Join(a, ", ") +} + +// IsUTF16 is true, if f is W (utf16) function. It is false +// for all A (ascii) functions. +func (_ *Fn) IsUTF16() bool { + return true +} + +// StrconvFunc returns name of Go string to OS string function for f. +func (f *Fn) StrconvFunc() string { + if f.IsUTF16() { + return syscalldot() + "UTF16PtrFromString" + } + return syscalldot() + "BytePtrFromString" +} + +// StrconvType returns Go type name used for OS string for f. +func (f *Fn) StrconvType() string { + if f.IsUTF16() { + return "*uint16" + } + return "*byte" +} + +// HasStringParam is true, if f has at least one string parameter. +// Otherwise it is false. +func (f *Fn) HasStringParam() bool { + for _, p := range f.Params { + if p.Type == "string" { + return true + } + } + return false +} + +// HelperName returns name of function f helper. +func (f *Fn) HelperName() string { + if !f.HasStringParam() { + return f.Name + } + return "_" + f.Name +} + +// Source files and functions. +type Source struct { + Funcs []*Fn + Files []string +} + +// ParseFiles parses files listed in fs and extracts all syscall +// functions listed in sys comments. It returns source files +// and functions collection *Source if successful. +func ParseFiles(fs []string) (*Source, error) { + src := &Source{ + Funcs: make([]*Fn, 0), + Files: make([]string, 0), + } + for _, file := range fs { + if err := src.ParseFile(file); err != nil { + return nil, err + } + } + return src, nil +} + +// DLLs return dll names for a source set src. +func (src *Source) DLLs() []string { + uniq := make(map[string]bool) + r := make([]string, 0) + for _, f := range src.Funcs { + name := f.DLLName() + if _, found := uniq[name]; !found { + uniq[name] = true + r = append(r, name) + } + } + return r +} + +// ParseFile adds additional file path to a source set src. +func (src *Source) ParseFile(path string) error { + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + + s := bufio.NewScanner(file) + for s.Scan() { + t := trim(s.Text()) + if len(t) < 7 { + continue + } + if !strings.HasPrefix(t, "//sys") { + continue + } + t = t[5:] + if !(t[0] == ' ' || t[0] == '\t') { + continue + } + f, err := newFn(t[1:]) + if err != nil { + return err + } + src.Funcs = append(src.Funcs, f) + } + if err := s.Err(); err != nil { + return err + } + src.Files = append(src.Files, path) + + // get package name + fset := token.NewFileSet() + _, err = file.Seek(0, 0) + if err != nil { + return err + } + pkg, err := parser.ParseFile(fset, "", file, parser.PackageClauseOnly) + if err != nil { + return err + } + packageName = pkg.Name.Name + + return nil +} + +// Generate output source file from a source set src. +func (src *Source) Generate(w io.Writer) error { + funcMap := template.FuncMap{ + "packagename": packagename, + "syscalldot": syscalldot, + } + t := template.Must(template.New("main").Funcs(funcMap).Parse(srcTemplate)) + err := t.Execute(w, src) + if err != nil { + return errors.New("Failed to execute template: " + err.Error()) + } + return nil +} + +func usage() { + fmt.Fprintf(os.Stderr, "usage: mksyscall_windows [flags] [path ...]\n") + flag.PrintDefaults() + os.Exit(1) +} + +func main() { + flag.Usage = usage + flag.Parse() + if len(flag.Args()) <= 0 { + fmt.Fprintf(os.Stderr, "no files to parse provided\n") + usage() + } + + src, err := ParseFiles(flag.Args()) + if err != nil { + log.Fatal(err) + } + + var buf bytes.Buffer + if err := src.Generate(&buf); err != nil { + log.Fatal(err) + } + + data, err := format.Source(buf.Bytes()) + if err != nil { + log.Fatal(err) + } + if *filename == "" { + _, err = os.Stdout.Write(data) + } else { + err = ioutil.WriteFile(*filename, data, 0644) + } + if err != nil { + log.Fatal(err) + } +} + +// TODO: use println instead to print in the following template +const srcTemplate = ` + +{{define "main"}}// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT + +package {{packagename}} + +import "unsafe"{{if syscalldot}} +import "syscall"{{end}} + +var _ unsafe.Pointer + +var ( +{{template "dlls" .}} +{{template "funcnames" .}}) +{{range .Funcs}}{{if .HasStringParam}}{{template "helperbody" .}}{{end}}{{template "funcbody" .}}{{end}} +{{end}} + +{{/* help functions */}} + +{{define "dlls"}}{{range .DLLs}} mod{{.}} = {{syscalldot}}NewLazyDLL("{{.}}.dll") +{{end}}{{end}} + +{{define "funcnames"}}{{range .Funcs}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}") +{{end}}{{end}} + +{{define "helperbody"}} +func {{.Name}}({{.ParamList}}) {{template "results" .}}{ +{{template "helpertmpvars" .}} return {{.HelperName}}({{.HelperCallParamList}}) +} +{{end}} + +{{define "funcbody"}} +func {{.HelperName}}({{.HelperParamList}}) {{template "results" .}}{ +{{template "tmpvars" .}} {{template "syscallcheck" .}}{{template "syscall" .}} +{{template "seterror" .}}{{template "printtrace" .}} return +} +{{end}} + +{{define "helpertmpvars"}}{{range .Params}}{{if .TmpVarHelperCode}} {{.TmpVarHelperCode}} +{{end}}{{end}}{{end}} + +{{define "tmpvars"}}{{range .Params}}{{if .TmpVarCode}} {{.TmpVarCode}} +{{end}}{{end}}{{end}} + +{{define "results"}}{{if .Rets.List}}{{.Rets.List}} {{end}}{{end}} + +{{define "syscallcheck"}}{{if .ConfirmProc}}if {{.Rets.ErrorVarName}} = proc{{.DLLFuncName}}.Find(); {{.Rets.ErrorVarName}} != nil { + return +} +{{end}}{{end}} + +{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(), {{.ParamCount}}, {{.SyscallParamList}}){{end}} + +{{define "seterror"}}{{if .Rets.SetErrorCode}} {{.Rets.SetErrorCode}} +{{end}}{{end}} + +{{define "printtrace"}}{{if .PrintTrace}} print("SYSCALL: {{.Name}}(", {{.ParamPrintList}}") (", {{.Rets.PrintList}}")\n") +{{end}}{{end}} + +` diff --git a/vendor/src/github.com/microsoft/hcsshim/nametoguid.go b/vendor/src/github.com/microsoft/hcsshim/nametoguid.go index 048e978286..1a522f95e0 100644 --- a/vendor/src/github.com/microsoft/hcsshim/nametoguid.go +++ b/vendor/src/github.com/microsoft/hcsshim/nametoguid.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // NameToGuid converts the given string into a GUID using the algorithm in the // Host Compute Service, ensuring GUIDs generated with the same string are common @@ -15,32 +9,9 @@ func NameToGuid(name string) (id GUID, err error) { title := "hcsshim::NameToGuid " logrus.Debugf(title+"Name %s", name) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procNameToGuid) - if dll != nil { - defer dll.Release() - } + err = nameToGuid(name, &id) if err != nil { - return - } - - // Convert name to uint16 pointer for calling the procedure - namep, err := syscall.UTF16PtrFromString(name) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of name %s to pointer %s", name, err) - logrus.Error(err) - return - } - - // Call the procedure itself. - logrus.Debugf("Calling proc") - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(namep)), - uintptr(unsafe.Pointer(&id))) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s name=%s", - r1, syscall.Errno(r1), name) + err = makeErrorf(err, title, "name=%s", name) logrus.Error(err) return } diff --git a/vendor/src/github.com/microsoft/hcsshim/preparelayer.go b/vendor/src/github.com/microsoft/hcsshim/preparelayer.go index b6a627c896..69b5fe045e 100644 --- a/vendor/src/github.com/microsoft/hcsshim/preparelayer.go +++ b/vendor/src/github.com/microsoft/hcsshim/preparelayer.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // PrepareLayer finds a mounted read-write layer matching layerId and enables the // 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 title := "hcsshim::PrepareLayer " logrus.Debugf(title+"flavour %d layerId %s", info.Flavour, layerId) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procPrepareLayer) - if dll != nil { - defer dll.Release() - } - if err != nil { - return err - } - // Generate layer descriptors layers, err := layerPathsToDescriptors(parentLayerPaths) if err != nil { - err = fmt.Errorf(title+"- Failed to generate layer descriptors ", err) - return err - } - - // Convert layerId to uint16 pointer for calling the procedure - layerIdp, err := syscall.UTF16PtrFromString(layerId) - if err != nil { - err = fmt.Errorf(title+"- Failed conversion of layerId %s to pointer %s", layerId, err) - logrus.Error(err) return err } // Convert info to API calling convention infop, err := convertDriverInfo(info) if err != nil { - err = fmt.Errorf(title+"- Failed conversion info struct %s", err) logrus.Error(err) return err } - var layerDescriptorsp *WC_LAYER_DESCRIPTOR - if len(layers) > 0 { - layerDescriptorsp = &(layers[0]) - } else { - layerDescriptorsp = nil - } - - // Call the procedure itself. - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(&infop)), - uintptr(unsafe.Pointer(layerIdp)), - uintptr(unsafe.Pointer(layerDescriptorsp)), - uintptr(len(layers))) - use(unsafe.Pointer(&infop)) - use(unsafe.Pointer(layerIdp)) - use(unsafe.Pointer(layerDescriptorsp)) - - if r1 != 0 { - err = fmt.Errorf(title+"- Win32 API call returned error r1=%d err=%s layerId=%s flavour=%d", - r1, syscall.Errno(r1), layerId, info.Flavour) + err = prepareLayer(&infop, layerId, layers) + if err != nil { + err = makeErrorf(err, title, "layerId=%s flavour=%d", layerId, info.Flavour) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/resizeconsole.go b/vendor/src/github.com/microsoft/hcsshim/resizeconsole.go index d4194ad85a..d04ce70d85 100644 --- a/vendor/src/github.com/microsoft/hcsshim/resizeconsole.go +++ b/vendor/src/github.com/microsoft/hcsshim/resizeconsole.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // ResizeConsoleInComputeSystem updates the height and width of the console // 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 { title := "HCSShim::ResizeConsoleInComputeSystem" logrus.Debugf(title+" id=%s processid=%d (%d,%d)", id, processid, h, w) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procResizeConsoleInComputeSystem) - if dll != nil { - defer dll.Release() - } + err := resizeConsoleInComputeSystem(id, processid, uint16(h), uint16(w), 0) if err != nil { - return err - } - - // Convert id to uint16 pointer for calling the procedure - idp, err := syscall.UTF16PtrFromString(id) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) - logrus.Error(err) - return err - } - - h16 := uint16(h) - w16 := uint16(w) - - r1, _, _ := proc.Call(uintptr(unsafe.Pointer(idp)), uintptr(processid), uintptr(h16), uintptr(w16), uintptr(0)) - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s, id=%s pid=%d", r1, syscall.Errno(r1), id, processid) + err = makeErrorf(err, title, "id=%s pid=%d", id, processid) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/shutdownterminatecomputesystem.go b/vendor/src/github.com/microsoft/hcsshim/shutdownterminatecomputesystem.go index 2787691d90..d006edf77c 100644 --- a/vendor/src/github.com/microsoft/hcsshim/shutdownterminatecomputesystem.go +++ b/vendor/src/github.com/microsoft/hcsshim/shutdownterminatecomputesystem.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // TerminateComputeSystem force terminates a container. func TerminateComputeSystem(id string, timeout uint32, context string) (uint32, error) { @@ -24,44 +18,25 @@ func ShutdownComputeSystem(id string, timeout uint32, context string) (uint32, e func shutdownTerminate(shutdown bool, id string, timeout uint32, context string) (uint32, error) { var ( - title = "HCSShim::" - procName string + title = "HCSShim::" ) if shutdown { title = title + "ShutdownComputeSystem" - procName = procShutdownComputeSystem } else { title = title + "TerminateComputeSystem" - procName = procTerminateComputeSystem } logrus.Debugf(title+" id=%s context=%s", id, context) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procName) - if dll != nil { - defer dll.Release() + var err error + if shutdown { + err = shutdownComputeSystem(id, timeout) + } else { + err = terminateComputeSystem(id) } + if err != nil { - return 0xffffffff, err - } - - // Convert id to uint16 pointers for calling the procedure - idp, err := syscall.UTF16PtrFromString(id) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) - logrus.Error(err) - return 0xffffffff, err - } - - // Call the procedure itself. - r1, _, err := proc.Call( - uintptr(unsafe.Pointer(idp)), uintptr(timeout)) - - use(unsafe.Pointer(idp)) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=0x%X err=%s id=%s context=%s", r1, syscall.Errno(r1), id, context) - return uint32(r1), err + err := makeErrorf(err, title, "id=%s context=%s", id, context) + return err.HResult(), err } logrus.Debugf(title+" succeeded id=%s context=%s", id, context) diff --git a/vendor/src/github.com/microsoft/hcsshim/startcomputesystem.go b/vendor/src/github.com/microsoft/hcsshim/startcomputesystem.go index 61b7233b43..41a7e676f7 100644 --- a/vendor/src/github.com/microsoft/hcsshim/startcomputesystem.go +++ b/vendor/src/github.com/microsoft/hcsshim/startcomputesystem.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // StartComputeSystem starts a container that has previously been created via // CreateComputeSystem. @@ -15,30 +9,9 @@ func StartComputeSystem(id string) error { title := "HCSShim::StartComputeSystem" logrus.Debugf(title+" id=%s", id) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procStartComputeSystem) - if dll != nil { - defer dll.Release() - } + err := startComputeSystem(id) if err != nil { - return err - } - - // Convert ID to uint16 pointers for calling the procedure - idp, err := syscall.UTF16PtrFromString(id) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) - logrus.Error(err) - return err - } - - // Call the procedure itself. - r1, _, _ := proc.Call(uintptr(unsafe.Pointer(idp))) - - use(unsafe.Pointer(idp)) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s", r1, syscall.Errno(r1), id) + err = makeErrorf(err, title, "id=%s", id) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/terminateprocess.go b/vendor/src/github.com/microsoft/hcsshim/terminateprocess.go index c444d383b3..47880afce1 100644 --- a/vendor/src/github.com/microsoft/hcsshim/terminateprocess.go +++ b/vendor/src/github.com/microsoft/hcsshim/terminateprocess.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // TerminateProcessInComputeSystem kills a process in a running container. func TerminateProcessInComputeSystem(id string, processid uint32) (err error) { @@ -14,32 +8,9 @@ func TerminateProcessInComputeSystem(id string, processid uint32) (err error) { title := "HCSShim::TerminateProcessInComputeSystem" logrus.Debugf(title+" id=%s processid=%d", id, processid) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procTerminateProcessInComputeSystem) - if dll != nil { - defer dll.Release() - } + err = terminateProcessInComputeSystem(id, processid) if err != nil { - return err - } - - // Convert ID to uint16 pointer for calling the procedure - idp, err := syscall.UTF16PtrFromString(id) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) - logrus.Error(err) - return err - } - - // Call the procedure itself. - r1, _, err := proc.Call( - uintptr(unsafe.Pointer(idp)), - uintptr(processid)) - - use(unsafe.Pointer(idp)) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s", r1, syscall.Errno(r1), id) + err = makeErrorf(err, title, "err=%s id=%s", id) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/unpreparelayer.go b/vendor/src/github.com/microsoft/hcsshim/unpreparelayer.go index 8599749df7..d0ead0bdda 100644 --- a/vendor/src/github.com/microsoft/hcsshim/unpreparelayer.go +++ b/vendor/src/github.com/microsoft/hcsshim/unpreparelayer.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // UnprepareLayer disables the filesystem filter for the read-write layer with // the given id. @@ -14,42 +8,16 @@ func UnprepareLayer(info DriverInfo, layerId string) error { title := "hcsshim::UnprepareLayer " logrus.Debugf(title+"flavour %d layerId %s", info.Flavour, layerId) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procUnprepareLayer) - if dll != nil { - defer dll.Release() - } - if err != nil { - return err - } - - // Convert layerId to uint16 pointer for calling the procedure - layerIdp, err := syscall.UTF16PtrFromString(layerId) - if err != nil { - err = fmt.Errorf(title+"- Failed conversion of layerId %s to pointer %s", layerId, err) - logrus.Error(err) - return err - } - // Convert info to API calling convention infop, err := convertDriverInfo(info) if err != nil { - err = fmt.Errorf(title+"- Failed conversion info struct %s", err) logrus.Error(err) return err } - // Call the procedure itself. - r1, _, _ := proc.Call( - uintptr(unsafe.Pointer(&infop)), - uintptr(unsafe.Pointer(layerIdp))) - - use(unsafe.Pointer(&infop)) - use(unsafe.Pointer(layerIdp)) - - if r1 != 0 { - err = fmt.Errorf(title+"- Win32 API call returned error r1=%d err=%s layerId=%s flavour=%d", - r1, syscall.Errno(r1), layerId, info.Flavour) + err = unprepareLayer(&infop, layerId) + if err != nil { + err = makeErrorf(err, title, "layerId=%s flavour=%d", layerId, info.Flavour) logrus.Error(err) return err } diff --git a/vendor/src/github.com/microsoft/hcsshim/waitprocess.go b/vendor/src/github.com/microsoft/hcsshim/waitprocess.go index 6520a8902b..c9f4617711 100644 --- a/vendor/src/github.com/microsoft/hcsshim/waitprocess.go +++ b/vendor/src/github.com/microsoft/hcsshim/waitprocess.go @@ -1,12 +1,6 @@ package hcsshim -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Sirupsen/logrus" -) +import "github.com/Sirupsen/logrus" // WaitForProcessInComputeSystem waits for a process ID to terminate and returns // the exit code. Returns exitcode, errno, error @@ -15,40 +9,13 @@ func WaitForProcessInComputeSystem(id string, processid uint32, timeout uint32) title := "HCSShim::WaitForProcessInComputeSystem" logrus.Debugf(title+" id=%s processid=%d", id, processid) - // Load the DLL and get a handle to the procedure we need - dll, proc, err := loadAndFind(procWaitForProcessInComputeSystem) - if dll != nil { - defer dll.Release() - } + var exitCode uint32 + err := waitForProcessInComputeSystem(id, processid, timeout, &exitCode) if err != nil { - return 0, 0, err + err := makeErrorf(err, title, "id=%s", id) + return 0, err.HResult(), err } - // Convert id to uint16 pointer for calling the procedure - idp, err := syscall.UTF16PtrFromString(id) - if err != nil { - err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) - logrus.Error(err) - return 0, 0, err - } - - // To get a POINTER to the ExitCode - ec := new(int32) - - // Call the procedure itself. - r1, _, err := proc.Call( - uintptr(unsafe.Pointer(idp)), - uintptr(processid), - uintptr(timeout), - uintptr(unsafe.Pointer(ec))) - - use(unsafe.Pointer(idp)) - - if r1 != 0 { - err = fmt.Errorf(title+" - Win32 API call returned error r1=0x%X err=%s id=%s", r1, syscall.Errno(r1), id) - return 0, uint32(r1), err - } - - logrus.Debugf(title+" succeeded id=%s processid=%d exitcode=%d", id, processid, *ec) - return *ec, 0, nil + logrus.Debugf(title+" succeeded id=%s processid=%d exitcode=%d", id, processid, exitCode) + return int32(exitCode), 0, nil } diff --git a/vendor/src/github.com/microsoft/hcsshim/zhcsshim.go b/vendor/src/github.com/microsoft/hcsshim/zhcsshim.go new file mode 100644 index 0000000000..15528aaa23 --- /dev/null +++ b/vendor/src/github.com/microsoft/hcsshim/zhcsshim.go @@ -0,0 +1,559 @@ +// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT + +package hcsshim + +import "unsafe" +import "syscall" + +var _ unsafe.Pointer + +var ( + modole32 = syscall.NewLazyDLL("ole32.dll") + modvmcompute = syscall.NewLazyDLL("vmcompute.dll") + + procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") + procActivateLayer = modvmcompute.NewProc("ActivateLayer") + procCopyLayer = modvmcompute.NewProc("CopyLayer") + procCreateLayer = modvmcompute.NewProc("CreateLayer") + procCreateSandboxLayer = modvmcompute.NewProc("CreateSandboxLayer") + procDeactivateLayer = modvmcompute.NewProc("DeactivateLayer") + procDestroyLayer = modvmcompute.NewProc("DestroyLayer") + procExportLayer = modvmcompute.NewProc("ExportLayer") + procGetLayerMountPath = modvmcompute.NewProc("GetLayerMountPath") + procGetBaseImages = modvmcompute.NewProc("GetBaseImages") + procImportLayer = modvmcompute.NewProc("ImportLayer") + procLayerExists = modvmcompute.NewProc("LayerExists") + procNameToGuid = modvmcompute.NewProc("NameToGuid") + procPrepareLayer = modvmcompute.NewProc("PrepareLayer") + procUnprepareLayer = modvmcompute.NewProc("UnprepareLayer") + procCreateComputeSystem = modvmcompute.NewProc("CreateComputeSystem") + procCreateProcessWithStdHandlesInComputeSystem = modvmcompute.NewProc("CreateProcessWithStdHandlesInComputeSystem") + procResizeConsoleInComputeSystem = modvmcompute.NewProc("ResizeConsoleInComputeSystem") + procShutdownComputeSystem = modvmcompute.NewProc("ShutdownComputeSystem") + procStartComputeSystem = modvmcompute.NewProc("StartComputeSystem") + procTerminateComputeSystem = modvmcompute.NewProc("TerminateComputeSystem") + procTerminateProcessInComputeSystem = modvmcompute.NewProc("TerminateProcessInComputeSystem") + procWaitForProcessInComputeSystem = modvmcompute.NewProc("WaitForProcessInComputeSystem") + procHNSCall = modvmcompute.NewProc("HNSCall") +) + +func coTaskMemFree(buffer unsafe.Pointer) { + syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(buffer), 0, 0) + return +} + +func activateLayer(info *driverInfo, id string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _activateLayer(info, _p0) +} + +func _activateLayer(info *driverInfo, id *uint16) (hr error) { + if hr = procActivateLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procActivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(srcId) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(dstId) + if hr != nil { + return + } + return _copyLayer(info, _p0, _p1, descriptors) +} + +func _copyLayer(info *driverInfo, srcId *uint16, dstId *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p2 *WC_LAYER_DESCRIPTOR + if len(descriptors) > 0 { + _p2 = &descriptors[0] + } + if hr = procCopyLayer.Find(); hr != nil { + return + } + 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) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func createLayer(info *driverInfo, id string, parent string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(parent) + if hr != nil { + return + } + return _createLayer(info, _p0, _p1) +} + +func _createLayer(info *driverInfo, id *uint16, parent *uint16) (hr error) { + if hr = procCreateLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procCreateLayer.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(parent))) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func createSandboxLayer(info *driverInfo, id string, parent string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(parent) + if hr != nil { + return + } + return _createSandboxLayer(info, _p0, _p1, descriptors) +} + +func _createSandboxLayer(info *driverInfo, id *uint16, parent *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p2 *WC_LAYER_DESCRIPTOR + if len(descriptors) > 0 { + _p2 = &descriptors[0] + } + if hr = procCreateSandboxLayer.Find(); hr != nil { + return + } + 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) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func deactivateLayer(info *driverInfo, id string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _deactivateLayer(info, _p0) +} + +func _deactivateLayer(info *driverInfo, id *uint16) (hr error) { + if hr = procDeactivateLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procDeactivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func destroyLayer(info *driverInfo, id string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _destroyLayer(info, _p0) +} + +func _destroyLayer(info *driverInfo, id *uint16) (hr error) { + if hr = procDestroyLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procDestroyLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(path) + if hr != nil { + return + } + return _exportLayer(info, _p0, _p1, descriptors) +} + +func _exportLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p2 *WC_LAYER_DESCRIPTOR + if len(descriptors) > 0 { + _p2 = &descriptors[0] + } + if hr = procExportLayer.Find(); hr != nil { + return + } + 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) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _getLayerMountPath(info, _p0, length, buffer) +} + +func _getLayerMountPath(info *driverInfo, id *uint16, length *uintptr, buffer *uint16) (hr error) { + if hr = procGetLayerMountPath.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procGetLayerMountPath.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(length)), uintptr(unsafe.Pointer(buffer)), 0, 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func getBaseImages(buffer **uint16) (hr error) { + if hr = procGetBaseImages.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procGetBaseImages.Addr(), 1, uintptr(unsafe.Pointer(buffer)), 0, 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(path) + if hr != nil { + return + } + return _importLayer(info, _p0, _p1, descriptors) +} + +func _importLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p2 *WC_LAYER_DESCRIPTOR + if len(descriptors) > 0 { + _p2 = &descriptors[0] + } + if hr = procImportLayer.Find(); hr != nil { + return + } + 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) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func layerExists(info *driverInfo, id string, exists *uint32) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _layerExists(info, _p0, exists) +} + +func _layerExists(info *driverInfo, id *uint16, exists *uint32) (hr error) { + if hr = procLayerExists.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procLayerExists.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(exists))) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func nameToGuid(name string, guid *GUID) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(name) + if hr != nil { + return + } + return _nameToGuid(_p0, guid) +} + +func _nameToGuid(name *uint16, guid *GUID) (hr error) { + if hr = procNameToGuid.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procNameToGuid.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(guid)), 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _prepareLayer(info, _p0, descriptors) +} + +func _prepareLayer(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p1 *WC_LAYER_DESCRIPTOR + if len(descriptors) > 0 { + _p1 = &descriptors[0] + } + if hr = procPrepareLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procPrepareLayer.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), 0, 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func unprepareLayer(info *driverInfo, id string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _unprepareLayer(info, _p0) +} + +func _unprepareLayer(info *driverInfo, id *uint16) (hr error) { + if hr = procUnprepareLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procUnprepareLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func createComputeSystem(id string, configuration string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(configuration) + if hr != nil { + return + } + return _createComputeSystem(_p0, _p1) +} + +func _createComputeSystem(id *uint16, configuration *uint16) (hr error) { + if hr = procCreateComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procCreateComputeSystem.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(configuration)), 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func createProcessWithStdHandlesInComputeSystem(id string, paramsJson string, pid *uint32, stdin *syscall.Handle, stdout *syscall.Handle, stderr *syscall.Handle) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(paramsJson) + if hr != nil { + return + } + return _createProcessWithStdHandlesInComputeSystem(_p0, _p1, pid, stdin, stdout, stderr) +} + +func _createProcessWithStdHandlesInComputeSystem(id *uint16, paramsJson *uint16, pid *uint32, stdin *syscall.Handle, stdout *syscall.Handle, stderr *syscall.Handle) (hr error) { + if hr = procCreateProcessWithStdHandlesInComputeSystem.Find(); hr != nil { + return + } + 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))) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func resizeConsoleInComputeSystem(id string, pid uint32, height uint16, width uint16, flags uint32) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _resizeConsoleInComputeSystem(_p0, pid, height, width, flags) +} + +func _resizeConsoleInComputeSystem(id *uint16, pid uint32, height uint16, width uint16, flags uint32) (hr error) { + if hr = procResizeConsoleInComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procResizeConsoleInComputeSystem.Addr(), 5, uintptr(unsafe.Pointer(id)), uintptr(pid), uintptr(height), uintptr(width), uintptr(flags), 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func shutdownComputeSystem(id string, timeout uint32) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _shutdownComputeSystem(_p0, timeout) +} + +func _shutdownComputeSystem(id *uint16, timeout uint32) (hr error) { + if hr = procShutdownComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procShutdownComputeSystem.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(timeout), 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func startComputeSystem(id string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _startComputeSystem(_p0) +} + +func _startComputeSystem(id *uint16) (hr error) { + if hr = procStartComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procStartComputeSystem.Addr(), 1, uintptr(unsafe.Pointer(id)), 0, 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func terminateComputeSystem(id string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _terminateComputeSystem(_p0) +} + +func _terminateComputeSystem(id *uint16) (hr error) { + if hr = procTerminateComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procTerminateComputeSystem.Addr(), 1, uintptr(unsafe.Pointer(id)), 0, 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func terminateProcessInComputeSystem(id string, pid uint32) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _terminateProcessInComputeSystem(_p0, pid) +} + +func _terminateProcessInComputeSystem(id *uint16, pid uint32) (hr error) { + if hr = procTerminateProcessInComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procTerminateProcessInComputeSystem.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(pid), 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func waitForProcessInComputeSystem(id string, pid uint32, timeout uint32, exitCode *uint32) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _waitForProcessInComputeSystem(_p0, pid, timeout, exitCode) +} + +func _waitForProcessInComputeSystem(id *uint16, pid uint32, timeout uint32, exitCode *uint32) (hr error) { + if hr = procWaitForProcessInComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procWaitForProcessInComputeSystem.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(pid), uintptr(timeout), uintptr(unsafe.Pointer(exitCode)), 0, 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +} + +func _hnsCall(method string, path string, object string, response **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(method) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(path) + if hr != nil { + return + } + var _p2 *uint16 + _p2, hr = syscall.UTF16PtrFromString(object) + if hr != nil { + return + } + return __hnsCall(_p0, _p1, _p2, response) +} + +func __hnsCall(method *uint16, path *uint16, object *uint16, response **uint16) (hr error) { + if hr = procHNSCall.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procHNSCall.Addr(), 4, uintptr(unsafe.Pointer(method)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(object)), uintptr(unsafe.Pointer(response)), 0, 0) + if r0 != 0 { + hr = syscall.Errno(r0) + } + return +}