1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #19902 from Microsoft/jstarks/revendor_hcsshim_fix_docker_crash

Revendor Microsoft/hcsshim and vendor Microsoft/go-winio
This commit is contained in:
Brian Goff 2016-02-01 22:30:08 -05:00
commit a034ac66eb
34 changed files with 3320 additions and 1005 deletions

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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
}

View file

@ -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}}
`

View file

@ -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)
}

View file

@ -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
}

View file

@ -0,0 +1,3 @@
package winio
//go:generate go run mksyscall_windows.go -output zsyscall.go file.go pipe.go sd.go

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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}}
`

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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)

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}