浏览代码

Revendor go-winio

This is needed to provide fixes for ETW on ARM. The updated ETW package will
no-op on ARM, rather than crashing. Further changes are needed to Go itself to
allow ETW on ARM to work properly.

Signed-off-by: Kevin Parsons <kevpar@microsoft.com>
Kevin Parsons 6 年之前
父节点
当前提交
e1f0f77bf4

+ 1 - 1
vendor.conf

@@ -1,6 +1,6 @@
 github.com/Azure/go-ansiterm                        d6e3b3328b783f23731bc4d058875b0371ff8109
 github.com/Microsoft/hcsshim                        672e52e9209d1e53718c1b6a7d68cc9272654ab5
-github.com/Microsoft/go-winio                       c599b533b43b1363d7d7c6cfda5ede70ed73ff13
+github.com/Microsoft/go-winio                       3fe4fa31662f6ede2353d913e93907b8e096e0b6
 github.com/docker/libtrust                          9cbd2a1374f46905c68a4eb3694a130610adc62a
 github.com/go-check/check                           4ed411733c5785b40214c70bce814c3a3a689609 https://github.com/cpuguy83/check.git
 github.com/golang/gddo                              9b12a26f3fbd7397dee4e20939ddca719d840d2a

+ 6 - 0
vendor/github.com/Microsoft/go-winio/file.go

@@ -16,6 +16,7 @@ import (
 //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
+//sys wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult
 
 type atomicBool int32
 
@@ -79,6 +80,7 @@ type win32File struct {
 	wg            sync.WaitGroup
 	wgLock        sync.RWMutex
 	closing       atomicBool
+	socket        bool
 	readDeadline  deadlineHandler
 	writeDeadline deadlineHandler
 }
@@ -190,6 +192,10 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er
 			if f.closing.isSet() {
 				err = ErrFileClosed
 			}
+		} else if err != nil && f.socket {
+			// err is from Win32. Query the overlapped structure to get the winsock error.
+			var bytes, flags uint32
+			err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags)
 		}
 	case <-timeout:
 		cancelIoEx(f.handle, &c.o)

+ 305 - 0
vendor/github.com/Microsoft/go-winio/hvsock.go

@@ -0,0 +1,305 @@
+package winio
+
+import (
+	"fmt"
+	"io"
+	"net"
+	"os"
+	"syscall"
+	"time"
+	"unsafe"
+
+	"github.com/Microsoft/go-winio/pkg/guid"
+)
+
+//sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind
+
+const (
+	afHvSock = 34 // AF_HYPERV
+
+	socketError = ^uintptr(0)
+)
+
+// An HvsockAddr is an address for a AF_HYPERV socket.
+type HvsockAddr struct {
+	VMID      guid.GUID
+	ServiceID guid.GUID
+}
+
+type rawHvsockAddr struct {
+	Family    uint16
+	_         uint16
+	VMID      guid.GUID
+	ServiceID guid.GUID
+}
+
+// Network returns the address's network name, "hvsock".
+func (addr *HvsockAddr) Network() string {
+	return "hvsock"
+}
+
+func (addr *HvsockAddr) String() string {
+	return fmt.Sprintf("%s:%s", &addr.VMID, &addr.ServiceID)
+}
+
+// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port.
+func VsockServiceID(port uint32) guid.GUID {
+	g, _ := guid.FromString("00000000-facb-11e6-bd58-64006a7986d3")
+	g.Data1 = port
+	return *g
+}
+
+func (addr *HvsockAddr) raw() rawHvsockAddr {
+	return rawHvsockAddr{
+		Family:    afHvSock,
+		VMID:      addr.VMID,
+		ServiceID: addr.ServiceID,
+	}
+}
+
+func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) {
+	addr.VMID = raw.VMID
+	addr.ServiceID = raw.ServiceID
+}
+
+// HvsockListener is a socket listener for the AF_HYPERV address family.
+type HvsockListener struct {
+	sock *win32File
+	addr HvsockAddr
+}
+
+// HvsockConn is a connected socket of the AF_HYPERV address family.
+type HvsockConn struct {
+	sock          *win32File
+	local, remote HvsockAddr
+}
+
+func newHvSocket() (*win32File, error) {
+	fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1)
+	if err != nil {
+		return nil, os.NewSyscallError("socket", err)
+	}
+	f, err := makeWin32File(fd)
+	if err != nil {
+		syscall.Close(fd)
+		return nil, err
+	}
+	f.socket = true
+	return f, nil
+}
+
+// ListenHvsock listens for connections on the specified hvsock address.
+func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) {
+	l := &HvsockListener{addr: *addr}
+	sock, err := newHvSocket()
+	if err != nil {
+		return nil, l.opErr("listen", err)
+	}
+	sa := addr.raw()
+	err = bind(sock.handle, unsafe.Pointer(&sa), int32(unsafe.Sizeof(sa)))
+	if err != nil {
+		return nil, l.opErr("listen", os.NewSyscallError("socket", err))
+	}
+	err = syscall.Listen(sock.handle, 16)
+	if err != nil {
+		return nil, l.opErr("listen", os.NewSyscallError("listen", err))
+	}
+	return &HvsockListener{sock: sock, addr: *addr}, nil
+}
+
+func (l *HvsockListener) opErr(op string, err error) error {
+	return &net.OpError{Op: op, Net: "hvsock", Addr: &l.addr, Err: err}
+}
+
+// Addr returns the listener's network address.
+func (l *HvsockListener) Addr() net.Addr {
+	return &l.addr
+}
+
+// Accept waits for the next connection and returns it.
+func (l *HvsockListener) Accept() (_ net.Conn, err error) {
+	sock, err := newHvSocket()
+	if err != nil {
+		return nil, l.opErr("accept", err)
+	}
+	defer func() {
+		if sock != nil {
+			sock.Close()
+		}
+	}()
+	c, err := l.sock.prepareIo()
+	if err != nil {
+		return nil, l.opErr("accept", err)
+	}
+	defer l.sock.wg.Done()
+
+	// AcceptEx, per documentation, requires an extra 16 bytes per address.
+	const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{}))
+	var addrbuf [addrlen * 2]byte
+
+	var bytes uint32
+	err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o)
+	_, err = l.sock.asyncIo(c, nil, bytes, err)
+	if err != nil {
+		return nil, l.opErr("accept", os.NewSyscallError("acceptex", err))
+	}
+	conn := &HvsockConn{
+		sock: sock,
+	}
+	conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0])))
+	conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen])))
+	sock = nil
+	return conn, nil
+}
+
+// Close closes the listener, causing any pending Accept calls to fail.
+func (l *HvsockListener) Close() error {
+	return l.sock.Close()
+}
+
+/* Need to finish ConnectEx handling
+func DialHvsock(ctx context.Context, addr *HvsockAddr) (*HvsockConn, error) {
+	sock, err := newHvSocket()
+	if err != nil {
+		return nil, err
+	}
+	defer func() {
+		if sock != nil {
+			sock.Close()
+		}
+	}()
+	c, err := sock.prepareIo()
+	if err != nil {
+		return nil, err
+	}
+	defer sock.wg.Done()
+	var bytes uint32
+	err = windows.ConnectEx(windows.Handle(sock.handle), sa, nil, 0, &bytes, &c.o)
+	_, err = sock.asyncIo(ctx, c, nil, bytes, err)
+	if err != nil {
+		return nil, err
+	}
+	conn := &HvsockConn{
+		sock:   sock,
+		remote: *addr,
+	}
+	sock = nil
+	return conn, nil
+}
+*/
+
+func (conn *HvsockConn) opErr(op string, err error) error {
+	return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err}
+}
+
+func (conn *HvsockConn) Read(b []byte) (int, error) {
+	c, err := conn.sock.prepareIo()
+	if err != nil {
+		return 0, conn.opErr("read", err)
+	}
+	defer conn.sock.wg.Done()
+	buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
+	var flags, bytes uint32
+	err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil)
+	n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err)
+	if err != nil {
+		if _, ok := err.(syscall.Errno); ok {
+			err = os.NewSyscallError("wsarecv", err)
+		}
+		return 0, conn.opErr("read", err)
+	} else if n == 0 {
+		err = io.EOF
+	}
+	return n, err
+}
+
+func (conn *HvsockConn) Write(b []byte) (int, error) {
+	t := 0
+	for len(b) != 0 {
+		n, err := conn.write(b)
+		if err != nil {
+			return t + n, err
+		}
+		t += n
+		b = b[n:]
+	}
+	return t, nil
+}
+
+func (conn *HvsockConn) write(b []byte) (int, error) {
+	c, err := conn.sock.prepareIo()
+	if err != nil {
+		return 0, conn.opErr("write", err)
+	}
+	defer conn.sock.wg.Done()
+	buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
+	var bytes uint32
+	err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil)
+	n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err)
+	if err != nil {
+		if _, ok := err.(syscall.Errno); ok {
+			err = os.NewSyscallError("wsasend", err)
+		}
+		return 0, conn.opErr("write", err)
+	}
+	return n, err
+}
+
+// Close closes the socket connection, failing any pending read or write calls.
+func (conn *HvsockConn) Close() error {
+	return conn.sock.Close()
+}
+
+func (conn *HvsockConn) shutdown(how int) error {
+	err := syscall.Shutdown(conn.sock.handle, syscall.SHUT_RD)
+	if err != nil {
+		return os.NewSyscallError("shutdown", err)
+	}
+	return nil
+}
+
+// CloseRead shuts down the read end of the socket.
+func (conn *HvsockConn) CloseRead() error {
+	err := conn.shutdown(syscall.SHUT_RD)
+	if err != nil {
+		return conn.opErr("close", err)
+	}
+	return nil
+}
+
+// CloseWrite shuts down the write end of the socket, notifying the other endpoint that
+// no more data will be written.
+func (conn *HvsockConn) CloseWrite() error {
+	err := conn.shutdown(syscall.SHUT_WR)
+	if err != nil {
+		return conn.opErr("close", err)
+	}
+	return nil
+}
+
+// LocalAddr returns the local address of the connection.
+func (conn *HvsockConn) LocalAddr() net.Addr {
+	return &conn.local
+}
+
+// RemoteAddr returns the remote address of the connection.
+func (conn *HvsockConn) RemoteAddr() net.Addr {
+	return &conn.remote
+}
+
+// SetDeadline implements the net.Conn SetDeadline method.
+func (conn *HvsockConn) SetDeadline(t time.Time) error {
+	conn.SetReadDeadline(t)
+	conn.SetWriteDeadline(t)
+	return nil
+}
+
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (conn *HvsockConn) SetReadDeadline(t time.Time) error {
+	return conn.sock.SetReadDeadline(t)
+}
+
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (conn *HvsockConn) SetWriteDeadline(t time.Time) error {
+	return conn.sock.SetWriteDeadline(t)
+}

+ 160 - 71
vendor/github.com/Microsoft/go-winio/pipe.go

@@ -3,10 +3,13 @@
 package winio
 
 import (
+	"context"
 	"errors"
+	"fmt"
 	"io"
 	"net"
 	"os"
+	"runtime"
 	"syscall"
 	"time"
 	"unsafe"
@@ -18,6 +21,48 @@ import (
 //sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
 //sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
 //sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc
+//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) = ntdll.NtCreateNamedPipeFile
+//sys rtlNtStatusToDosError(status ntstatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
+//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) = ntdll.RtlDosPathNameToNtPathName_U
+//sys rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) = ntdll.RtlDefaultNpAcl
+
+type ioStatusBlock struct {
+	Status, Information uintptr
+}
+
+type objectAttributes struct {
+	Length             uintptr
+	RootDirectory      uintptr
+	ObjectName         *unicodeString
+	Attributes         uintptr
+	SecurityDescriptor *securityDescriptor
+	SecurityQoS        uintptr
+}
+
+type unicodeString struct {
+	Length        uint16
+	MaximumLength uint16
+	Buffer        uintptr
+}
+
+type securityDescriptor struct {
+	Revision byte
+	Sbz1     byte
+	Control  uint16
+	Owner    uintptr
+	Group    uintptr
+	Sacl     uintptr
+	Dacl     uintptr
+}
+
+type ntstatus int32
+
+func (status ntstatus) Err() error {
+	if status >= 0 {
+		return nil
+	}
+	return rtlNtStatusToDosError(status)
+}
 
 const (
 	cERROR_PIPE_BUSY      = syscall.Errno(231)
@@ -25,21 +70,20 @@ const (
 	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
+	cSECURITY_SQOS_PRESENT = 0x100000
+	cSECURITY_ANONYMOUS    = 0
 
-	cPIPE_REJECT_REMOTE_CLIENTS = 0x8
+	cPIPE_TYPE_MESSAGE = 4
 
-	cPIPE_UNLIMITED_INSTANCES = 255
+	cPIPE_READMODE_MESSAGE = 2
 
-	cNMPWAIT_USE_DEFAULT_WAIT = 0
-	cNMPWAIT_NOWAIT           = 1
+	cFILE_OPEN   = 1
+	cFILE_CREATE = 2
 
-	cPIPE_TYPE_MESSAGE = 4
+	cFILE_PIPE_MESSAGE_TYPE          = 1
+	cFILE_PIPE_REJECT_REMOTE_CLIENTS = 2
 
-	cPIPE_READMODE_MESSAGE = 2
+	cSE_DACL_PRESENT = 4
 )
 
 var (
@@ -137,9 +181,30 @@ func (s pipeAddress) String() string {
 	return string(s)
 }
 
+// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
+func tryDialPipe(ctx context.Context, path *string) (syscall.Handle, error) {
+	for {
+		select {
+		case <-ctx.Done():
+			return syscall.Handle(0), ctx.Err()
+		default:
+			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 == nil {
+				return h, nil
+			}
+			if err != cERROR_PIPE_BUSY {
+				return h, &os.PathError{Err: err, Op: "open", Path: *path}
+			}
+			// Wait 10 msec and try again. This is a rather simplistic
+			// view, as we always try each 10 milliseconds.
+			time.Sleep(time.Millisecond * 10)
+		}
+	}
+}
+
 // DialPipe connects to a named pipe by path, timing out if the connection
 // takes longer than the specified duration. If timeout is nil, then we use
-// a default timeout of 5 seconds.  (We do not use WaitNamedPipe.)
+// a default timeout of 2 seconds.  (We do not use WaitNamedPipe.)
 func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
 	var absTimeout time.Time
 	if timeout != nil {
@@ -147,23 +212,22 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
 	} else {
 		absTimeout = time.Now().Add(time.Second * 2)
 	}
+	ctx, _ := context.WithDeadline(context.Background(), absTimeout)
+	conn, err := DialPipeContext(ctx, path)
+	if err == context.DeadlineExceeded {
+		return nil, ErrTimeout
+	}
+	return conn, err
+}
+
+// DialPipeContext attempts to connect to a named pipe by `path` until `ctx`
+// cancellation or timeout.
+func DialPipeContext(ctx context.Context, path string) (net.Conn, error) {
 	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
-		}
-		if time.Now().After(absTimeout) {
-			return nil, ErrTimeout
-		}
-
-		// Wait 10 msec and try again. This is a rather simplistic
-		// view, as we always try each 10 milliseconds.
-		time.Sleep(time.Millisecond * 10)
-	}
+	h, err = tryDialPipe(ctx, &path)
 	if err != nil {
-		return nil, &os.PathError{Op: "open", Path: path, Err: err}
+		return nil, err
 	}
 
 	var flags uint32
@@ -194,43 +258,87 @@ type acceptResponse struct {
 }
 
 type win32PipeListener struct {
-	firstHandle        syscall.Handle
-	path               string
-	securityDescriptor []byte
-	config             PipeConfig
-	acceptCh           chan (chan acceptResponse)
-	closeCh            chan int
-	doneCh             chan int
+	firstHandle syscall.Handle
+	path        string
+	config      PipeConfig
+	acceptCh    chan (chan acceptResponse)
+	closeCh     chan int
+	doneCh      chan int
 }
 
-func makeServerPipeHandle(path string, securityDescriptor []byte, c *PipeConfig, first bool) (syscall.Handle, error) {
-	var flags uint32 = cPIPE_ACCESS_DUPLEX | syscall.FILE_FLAG_OVERLAPPED
+func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (syscall.Handle, error) {
+	path16, err := syscall.UTF16FromString(path)
+	if err != nil {
+		return 0, &os.PathError{Op: "open", Path: path, Err: err}
+	}
+
+	var oa objectAttributes
+	oa.Length = unsafe.Sizeof(oa)
+
+	var ntPath unicodeString
+	if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil {
+		return 0, &os.PathError{Op: "open", Path: path, Err: err}
+	}
+	defer localFree(ntPath.Buffer)
+	oa.ObjectName = &ntPath
+
+	// The security descriptor is only needed for the first pipe.
 	if first {
-		flags |= cFILE_FLAG_FIRST_PIPE_INSTANCE
+		if sd != nil {
+			len := uint32(len(sd))
+			sdb := localAlloc(0, len)
+			defer localFree(sdb)
+			copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd)
+			oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb))
+		} else {
+			// Construct the default named pipe security descriptor.
+			var dacl uintptr
+			if err := rtlDefaultNpAcl(&dacl).Err(); err != nil {
+				return 0, fmt.Errorf("getting default named pipe ACL: %s", err)
+			}
+			defer localFree(dacl)
+
+			sdb := &securityDescriptor{
+				Revision: 1,
+				Control:  cSE_DACL_PRESENT,
+				Dacl:     dacl,
+			}
+			oa.SecurityDescriptor = sdb
+		}
 	}
 
-	var mode uint32 = cPIPE_REJECT_REMOTE_CLIENTS
+	typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS)
 	if c.MessageMode {
-		mode |= cPIPE_TYPE_MESSAGE
+		typ |= cFILE_PIPE_MESSAGE_TYPE
 	}
 
-	sa := &syscall.SecurityAttributes{}
-	sa.Length = uint32(unsafe.Sizeof(*sa))
-	if securityDescriptor != nil {
-		len := uint32(len(securityDescriptor))
-		sa.SecurityDescriptor = localAlloc(0, len)
-		defer localFree(sa.SecurityDescriptor)
-		copy((*[0xffff]byte)(unsafe.Pointer(sa.SecurityDescriptor))[:], securityDescriptor)
+	disposition := uint32(cFILE_OPEN)
+	access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE)
+	if first {
+		disposition = cFILE_CREATE
+		// By not asking for read or write access, the named pipe file system
+		// will put this pipe into an initially disconnected state, blocking
+		// client connections until the next call with first == false.
+		access = syscall.SYNCHRONIZE
 	}
-	h, err := createNamedPipe(path, flags, mode, cPIPE_UNLIMITED_INSTANCES, uint32(c.OutputBufferSize), uint32(c.InputBufferSize), 0, sa)
+
+	timeout := int64(-50 * 10000) // 50ms
+
+	var (
+		h    syscall.Handle
+		iosb ioStatusBlock
+	)
+	err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err()
 	if err != nil {
 		return 0, &os.PathError{Op: "open", Path: path, Err: err}
 	}
+
+	runtime.KeepAlive(ntPath)
 	return h, nil
 }
 
 func (l *win32PipeListener) makeServerPipe() (*win32File, error) {
-	h, err := makeServerPipeHandle(l.path, l.securityDescriptor, &l.config, false)
+	h, err := makeServerPipeHandle(l.path, nil, &l.config, false)
 	if err != nil {
 		return nil, err
 	}
@@ -341,32 +449,13 @@ func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {
 	if err != nil {
 		return nil, err
 	}
-	// Create a client handle and connect it.  This results in the pipe
-	// instance always existing, so that clients see ERROR_PIPE_BUSY
-	// rather than ERROR_FILE_NOT_FOUND.  This ties the first instance
-	// up so that no other instances can be used.  This would have been
-	// cleaner if the Win32 API matched CreateFile with ConnectNamedPipe
-	// instead of CreateNamedPipe.  (Apparently created named pipes are
-	// considered to be in listening state regardless of whether any
-	// active calls to ConnectNamedPipe are outstanding.)
-	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
-	}
-	// Close the client handle. The server side of the instance will
-	// still be busy, leading to ERROR_PIPE_BUSY instead of
-	// ERROR_NOT_FOUND, as long as we don't close the server handle,
-	// or disconnect the client with DisconnectNamedPipe.
-	syscall.Close(h2)
 	l := &win32PipeListener{
-		firstHandle:        h,
-		path:               path,
-		securityDescriptor: sd,
-		config:             *c,
-		acceptCh:           make(chan (chan acceptResponse)),
-		closeCh:            make(chan int),
-		doneCh:             make(chan int),
+		firstHandle: h,
+		path:        path,
+		config:      *c,
+		acceptCh:    make(chan (chan acceptResponse)),
+		closeCh:     make(chan int),
+		doneCh:      make(chan int),
 	}
 	go l.listenerRoutine()
 	return l, nil

+ 9 - 4
vendor/github.com/Microsoft/go-winio/pkg/etw/etw.go

@@ -7,9 +7,14 @@
 // set of C macros.
 package etw
 
-//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go etw.go
+//go:generate go run mksyscall_windows.go -output zsyscall_windows.go etw.go
 
 //sys eventRegister(providerId *windows.GUID, callback uintptr, callbackContext uintptr, providerHandle *providerHandle) (win32err error) = advapi32.EventRegister
-//sys eventUnregister(providerHandle providerHandle) (win32err error) = advapi32.EventUnregister
-//sys eventWriteTransfer(providerHandle providerHandle, descriptor *eventDescriptor, activityID *windows.GUID, relatedActivityID *windows.GUID, dataDescriptorCount uint32, dataDescriptors *eventDataDescriptor) (win32err error) = advapi32.EventWriteTransfer
-//sys eventSetInformation(providerHandle providerHandle, class eventInfoClass, information uintptr, length uint32) (win32err error) = advapi32.EventSetInformation
+
+//sys eventUnregister_64(providerHandle providerHandle) (win32err error) = advapi32.EventUnregister
+//sys eventWriteTransfer_64(providerHandle providerHandle, descriptor *eventDescriptor, activityID *windows.GUID, relatedActivityID *windows.GUID, dataDescriptorCount uint32, dataDescriptors *eventDataDescriptor) (win32err error) = advapi32.EventWriteTransfer
+//sys eventSetInformation_64(providerHandle providerHandle, class eventInfoClass, information uintptr, length uint32) (win32err error) = advapi32.EventSetInformation
+
+//sys eventUnregister_32(providerHandle_low uint32, providerHandle_high uint32) (win32err error) = advapi32.EventUnregister
+//sys eventWriteTransfer_32(providerHandle_low uint32, providerHandle_high uint32, descriptor *eventDescriptor, activityID *windows.GUID, relatedActivityID *windows.GUID, dataDescriptorCount uint32, dataDescriptors *eventDataDescriptor) (win32err error) = advapi32.EventWriteTransfer
+//sys eventSetInformation_32(providerHandle_low uint32, providerHandle_high uint32, class eventInfoClass, information uintptr, length uint32) (win32err error) = advapi32.EventSetInformation

+ 19 - 2
vendor/github.com/Microsoft/go-winio/pkg/etw/eventdescriptor.go

@@ -17,7 +17,7 @@ const (
 // will always be collected.
 type Level uint8
 
-// Predefined ETW log levels.
+// Predefined ETW log levels from winmeta.xml in the Windows SDK.
 const (
 	LevelAlways Level = iota
 	LevelCritical
@@ -27,13 +27,30 @@ const (
 	LevelVerbose
 )
 
+// Opcode represents the operation that the event indicates is being performed.
+type Opcode uint8
+
+// Predefined ETW opcodes from winmeta.xml in the Windows SDK.
+const (
+	// OpcodeInfo indicates an informational event.
+	OpcodeInfo Opcode = iota
+	// OpcodeStart indicates the start of an operation.
+	OpcodeStart
+	// OpcodeStop indicates the end of an operation.
+	OpcodeStop
+	// OpcodeDCStart indicates the start of a provider capture state operation.
+	OpcodeDCStart
+	// OpcodeDCStop indicates the end of a provider capture state operation.
+	OpcodeDCStop
+)
+
 // EventDescriptor represents various metadata for an ETW event.
 type eventDescriptor struct {
 	id      uint16
 	version uint8
 	channel Channel
 	level   Level
-	opcode  uint8
+	opcode  Opcode
 	task    uint16
 	keyword uint64
 }

+ 15 - 5
vendor/github.com/Microsoft/go-winio/pkg/etw/eventopt.go

@@ -1,13 +1,13 @@
 package etw
 
 import (
-	"golang.org/x/sys/windows"
+	"github.com/Microsoft/go-winio/pkg/guid"
 )
 
 type eventOptions struct {
 	descriptor        *eventDescriptor
-	activityID        *windows.GUID
-	relatedActivityID *windows.GUID
+	activityID        *guid.GUID
+	relatedActivityID *guid.GUID
 	tags              uint32
 }
 
@@ -36,12 +36,20 @@ func WithKeyword(keyword uint64) EventOpt {
 	}
 }
 
+// WithChannel specifies the channel of the event to be written.
 func WithChannel(channel Channel) EventOpt {
 	return func(options *eventOptions) {
 		options.descriptor.channel = channel
 	}
 }
 
+// WithOpcode specifies the opcode of the event to be written.
+func WithOpcode(opcode Opcode) EventOpt {
+	return func(options *eventOptions) {
+		options.descriptor.opcode = opcode
+	}
+}
+
 // WithTags specifies the tags of the event to be written. Tags is a 28-bit
 // value (top 4 bits are ignored) which are interpreted by the event consumer.
 func WithTags(newTags uint32) EventOpt {
@@ -50,13 +58,15 @@ func WithTags(newTags uint32) EventOpt {
 	}
 }
 
-func WithActivityID(activityID *windows.GUID) EventOpt {
+// WithActivityID specifies the activity ID of the event to be written.
+func WithActivityID(activityID *guid.GUID) EventOpt {
 	return func(options *eventOptions) {
 		options.activityID = activityID
 	}
 }
 
-func WithRelatedActivityID(activityID *windows.GUID) EventOpt {
+// WithRelatedActivityID specifies the parent activity ID of the event to be written.
+func WithRelatedActivityID(activityID *guid.GUID) EventOpt {
 	return func(options *eventOptions) {
 		options.relatedActivityID = activityID
 	}

+ 123 - 0
vendor/github.com/Microsoft/go-winio/pkg/etw/fieldopt.go

@@ -1,7 +1,9 @@
 package etw
 
 import (
+	"fmt"
 	"math"
+	"reflect"
 	"unsafe"
 )
 
@@ -377,3 +379,124 @@ func Struct(name string, opts ...FieldOpt) FieldOpt {
 		}
 	}
 }
+
+// Currently, we support logging basic builtin types (int, string, etc), slices
+// of basic builtin types, error, types derived from the basic types (e.g. "type
+// foo int"), and structs (recursively logging their fields). We do not support
+// slices of derived types (e.g. "[]foo").
+//
+// For types that we don't support, the value is formatted via fmt.Sprint, and
+// we also log a message that the type is unsupported along with the formatted
+// type. The intent of this is to make it easier to see which types are not
+// supported in traces, so we can evaluate adding support for more types in the
+// future.
+func SmartField(name string, v interface{}) FieldOpt {
+	switch v := v.(type) {
+	case bool:
+		return BoolField(name, v)
+	case []bool:
+		return BoolArray(name, v)
+	case string:
+		return StringField(name, v)
+	case []string:
+		return StringArray(name, v)
+	case int:
+		return IntField(name, v)
+	case []int:
+		return IntArray(name, v)
+	case int8:
+		return Int8Field(name, v)
+	case []int8:
+		return Int8Array(name, v)
+	case int16:
+		return Int16Field(name, v)
+	case []int16:
+		return Int16Array(name, v)
+	case int32:
+		return Int32Field(name, v)
+	case []int32:
+		return Int32Array(name, v)
+	case int64:
+		return Int64Field(name, v)
+	case []int64:
+		return Int64Array(name, v)
+	case uint:
+		return UintField(name, v)
+	case []uint:
+		return UintArray(name, v)
+	case uint8:
+		return Uint8Field(name, v)
+	case []uint8:
+		return Uint8Array(name, v)
+	case uint16:
+		return Uint16Field(name, v)
+	case []uint16:
+		return Uint16Array(name, v)
+	case uint32:
+		return Uint32Field(name, v)
+	case []uint32:
+		return Uint32Array(name, v)
+	case uint64:
+		return Uint64Field(name, v)
+	case []uint64:
+		return Uint64Array(name, v)
+	case uintptr:
+		return UintptrField(name, v)
+	case []uintptr:
+		return UintptrArray(name, v)
+	case float32:
+		return Float32Field(name, v)
+	case []float32:
+		return Float32Array(name, v)
+	case float64:
+		return Float64Field(name, v)
+	case []float64:
+		return Float64Array(name, v)
+	case error:
+		return StringField(name, v.Error())
+	default:
+		switch rv := reflect.ValueOf(v); rv.Kind() {
+		case reflect.Bool:
+			return SmartField(name, rv.Bool())
+		case reflect.Int:
+			return SmartField(name, int(rv.Int()))
+		case reflect.Int8:
+			return SmartField(name, int8(rv.Int()))
+		case reflect.Int16:
+			return SmartField(name, int16(rv.Int()))
+		case reflect.Int32:
+			return SmartField(name, int32(rv.Int()))
+		case reflect.Int64:
+			return SmartField(name, int64(rv.Int()))
+		case reflect.Uint:
+			return SmartField(name, uint(rv.Uint()))
+		case reflect.Uint8:
+			return SmartField(name, uint8(rv.Uint()))
+		case reflect.Uint16:
+			return SmartField(name, uint16(rv.Uint()))
+		case reflect.Uint32:
+			return SmartField(name, uint32(rv.Uint()))
+		case reflect.Uint64:
+			return SmartField(name, uint64(rv.Uint()))
+		case reflect.Uintptr:
+			return SmartField(name, uintptr(rv.Uint()))
+		case reflect.Float32:
+			return SmartField(name, float32(rv.Float()))
+		case reflect.Float64:
+			return SmartField(name, float64(rv.Float()))
+		case reflect.String:
+			return SmartField(name, rv.String())
+		case reflect.Struct:
+			fields := make([]FieldOpt, 0, rv.NumField())
+			for i := 0; i < rv.NumField(); i++ {
+				field := rv.Field(i)
+				if field.CanInterface() {
+					fields = append(fields, SmartField(name, field.Interface()))
+				}
+			}
+			return Struct(name, fields...)
+		}
+	}
+
+	return StringField(name, fmt.Sprintf("(Unsupported: %T) %v", v, v))
+}

+ 53 - 0
vendor/github.com/Microsoft/go-winio/pkg/etw/newprovider.go

@@ -0,0 +1,53 @@
+// +build amd64 arm64 386
+
+package etw
+
+import (
+	"bytes"
+	"encoding/binary"
+	"unsafe"
+
+	"github.com/Microsoft/go-winio/pkg/guid"
+	"golang.org/x/sys/windows"
+)
+
+// NewProviderWithID creates and registers a new ETW provider, allowing the
+// provider ID to be manually specified. This is most useful when there is an
+// existing provider ID that must be used to conform to existing diagnostic
+// infrastructure.
+func NewProviderWithID(name string, id *guid.GUID, callback EnableCallback) (provider *Provider, err error) {
+	providerCallbackOnce.Do(func() {
+		globalProviderCallback = windows.NewCallback(providerCallbackAdapter)
+	})
+
+	provider = providers.newProvider()
+	defer func(provider *Provider) {
+		if err != nil {
+			providers.removeProvider(provider)
+		}
+	}(provider)
+	provider.ID = id
+	provider.callback = callback
+
+	if err := eventRegister((*windows.GUID)(provider.ID), globalProviderCallback, uintptr(provider.index), &provider.handle); err != nil {
+		return nil, err
+	}
+
+	metadata := &bytes.Buffer{}
+	binary.Write(metadata, binary.LittleEndian, uint16(0)) // Write empty size for buffer (to update later)
+	metadata.WriteString(name)
+	metadata.WriteByte(0)                                                   // Null terminator for name
+	binary.LittleEndian.PutUint16(metadata.Bytes(), uint16(metadata.Len())) // Update the size at the beginning of the buffer
+	provider.metadata = metadata.Bytes()
+
+	if err := eventSetInformation(
+		provider.handle,
+		eventInfoClassProviderSetTraits,
+		uintptr(unsafe.Pointer(&provider.metadata[0])),
+		uint32(len(provider.metadata))); err != nil {
+
+		return nil, err
+	}
+
+	return provider, nil
+}

+ 12 - 0
vendor/github.com/Microsoft/go-winio/pkg/etw/newprovider_unsupported.go

@@ -0,0 +1,12 @@
+// +build arm
+
+package etw
+
+import (
+	"github.com/Microsoft/go-winio/pkg/guid"
+)
+
+// NewProviderWithID returns a nil provider on unsupported platforms.
+func NewProviderWithID(name string, id *guid.GUID, callback EnableCallback) (provider *Provider, err error) {
+	return nil, nil
+}

+ 29 - 69
vendor/github.com/Microsoft/go-winio/pkg/etw/provider.go

@@ -1,15 +1,12 @@
 package etw
 
 import (
-	"bytes"
 	"crypto/sha1"
 	"encoding/binary"
-	"encoding/hex"
-	"fmt"
 	"strings"
 	"unicode/utf16"
-	"unsafe"
 
+	"github.com/Microsoft/go-winio/pkg/guid"
 	"golang.org/x/sys/windows"
 )
 
@@ -17,7 +14,7 @@ import (
 // name and ID (GUID), which should always have a 1:1 mapping to each other
 // (e.g. don't use multiple provider names with the same ID, or vice versa).
 type Provider struct {
-	ID         *windows.GUID
+	ID         *guid.GUID
 	handle     providerHandle
 	metadata   []byte
 	callback   EnableCallback
@@ -30,22 +27,14 @@ type Provider struct {
 
 // String returns the `provider`.ID as a string
 func (provider *Provider) String() string {
-	data1 := make([]byte, 4)
-	binary.BigEndian.PutUint32(data1, provider.ID.Data1)
-	data2 := make([]byte, 2)
-	binary.BigEndian.PutUint16(data2, provider.ID.Data2)
-	data3 := make([]byte, 2)
-	binary.BigEndian.PutUint16(data3, provider.ID.Data3)
-	return fmt.Sprintf(
-		"%s-%s-%s-%s-%s",
-		hex.EncodeToString(data1),
-		hex.EncodeToString(data2),
-		hex.EncodeToString(data3),
-		hex.EncodeToString(provider.ID.Data4[:2]),
-		hex.EncodeToString(provider.ID.Data4[2:]))
+	if provider == nil {
+		return "<nil>"
+	}
+
+	return provider.ID.String()
 }
 
-type providerHandle windows.Handle
+type providerHandle uint64
 
 // ProviderState informs the provider EnableCallback what action is being
 // performed.
@@ -72,9 +61,9 @@ const (
 
 // EnableCallback is the form of the callback function that receives provider
 // enable/disable notifications from ETW.
-type EnableCallback func(*windows.GUID, ProviderState, Level, uint64, uint64, uintptr)
+type EnableCallback func(*guid.GUID, ProviderState, Level, uint64, uint64, uintptr)
 
-func providerCallback(sourceID *windows.GUID, state ProviderState, level Level, matchAnyKeyword uint64, matchAllKeyword uint64, filterData uintptr, i uintptr) {
+func providerCallback(sourceID *guid.GUID, state ProviderState, level Level, matchAnyKeyword uint64, matchAllKeyword uint64, filterData uintptr, i uintptr) {
 	provider := providers.getProvider(uint(i))
 
 	switch state {
@@ -96,7 +85,7 @@ func providerCallback(sourceID *windows.GUID, state ProviderState, level Level,
 // for provider notifications. Because Go has trouble with callback arguments of
 // different size, it has only pointer-sized arguments, which are then cast to
 // the appropriate types when calling providerCallback.
-func providerCallbackAdapter(sourceID *windows.GUID, state uintptr, level uintptr, matchAnyKeyword uintptr, matchAllKeyword uintptr, filterData uintptr, i uintptr) uintptr {
+func providerCallbackAdapter(sourceID *guid.GUID, state uintptr, level uintptr, matchAnyKeyword uintptr, matchAllKeyword uintptr, filterData uintptr, i uintptr) uintptr {
 	providerCallback(sourceID, ProviderState(state), Level(level), uint64(matchAnyKeyword), uint64(matchAllKeyword), filterData, i)
 	return 0
 }
@@ -108,7 +97,7 @@ func providerCallbackAdapter(sourceID *windows.GUID, state uintptr, level uintpt
 // The algorithm is roughly:
 // Hash = Sha1(namespace + arg.ToUpper().ToUtf16be())
 // Guid = Hash[0..15], with Hash[7] tweaked according to RFC 4122
-func providerIDFromName(name string) *windows.GUID {
+func providerIDFromName(name string) *guid.GUID {
 	buffer := sha1.New()
 
 	namespace := []byte{0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8, 0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB}
@@ -119,7 +108,7 @@ func providerIDFromName(name string) *windows.GUID {
 	sum := buffer.Sum(nil)
 	sum[7] = (sum[7] & 0xf) | 0x50
 
-	return &windows.GUID{
+	return &guid.GUID{
 		Data1: binary.LittleEndian.Uint32(sum[0:4]),
 		Data2: binary.LittleEndian.Uint16(sum[4:6]),
 		Data3: binary.LittleEndian.Uint16(sum[6:8]),
@@ -133,49 +122,12 @@ func NewProvider(name string, callback EnableCallback) (provider *Provider, err
 	return NewProviderWithID(name, providerIDFromName(name), callback)
 }
 
-// NewProviderWithID creates and registers a new ETW provider, allowing the
-// provider ID to be manually specified. This is most useful when there is an
-// existing provider ID that must be used to conform to existing diagnostic
-// infrastructure.
-func NewProviderWithID(name string, id *windows.GUID, callback EnableCallback) (provider *Provider, err error) {
-	providerCallbackOnce.Do(func() {
-		globalProviderCallback = windows.NewCallback(providerCallbackAdapter)
-	})
-
-	provider = providers.newProvider()
-	defer func() {
-		if err != nil {
-			providers.removeProvider(provider)
-		}
-	}()
-	provider.ID = id
-	provider.callback = callback
-
-	if err := eventRegister(provider.ID, globalProviderCallback, uintptr(provider.index), &provider.handle); err != nil {
-		return nil, err
-	}
-
-	metadata := &bytes.Buffer{}
-	binary.Write(metadata, binary.LittleEndian, uint16(0)) // Write empty size for buffer (to update later)
-	metadata.WriteString(name)
-	metadata.WriteByte(0)                                                   // Null terminator for name
-	binary.LittleEndian.PutUint16(metadata.Bytes(), uint16(metadata.Len())) // Update the size at the beginning of the buffer
-	provider.metadata = metadata.Bytes()
-
-	if err := eventSetInformation(
-		provider.handle,
-		eventInfoClassProviderSetTraits,
-		uintptr(unsafe.Pointer(&provider.metadata[0])),
-		uint32(len(provider.metadata))); err != nil {
-
-		return nil, err
-	}
-
-	return provider, nil
-}
-
 // Close unregisters the provider.
 func (provider *Provider) Close() error {
+	if provider == nil {
+		return nil
+	}
+
 	providers.removeProvider(provider)
 	return eventUnregister(provider.handle)
 }
@@ -198,6 +150,10 @@ func (provider *Provider) IsEnabledForLevel(level Level) bool {
 // infrastructure, it can be useful to check if an event will actually be
 // consumed before doing expensive work to build the event data.
 func (provider *Provider) IsEnabledForLevelAndKeywords(level Level, keywords uint64) bool {
+	if provider == nil {
+		return false
+	}
+
 	if !provider.enabled {
 		return false
 	}
@@ -219,6 +175,10 @@ func (provider *Provider) IsEnabledForLevelAndKeywords(level Level, keywords uin
 // constructed based on the EventOpt and FieldOpt values that are passed as
 // opts.
 func (provider *Provider) WriteEvent(name string, eventOpts []EventOpt, fieldOpts []FieldOpt) error {
+	if provider == nil {
+		return nil
+	}
+
 	options := eventOptions{descriptor: newEventDescriptor()}
 	em := &eventMetadata{}
 	ed := &eventData{}
@@ -247,7 +207,7 @@ func (provider *Provider) WriteEvent(name string, eventOpts []EventOpt, fieldOpt
 		dataBlobs = [][]byte{ed.bytes()}
 	}
 
-	return provider.writeEventRaw(options.descriptor, nil, nil, [][]byte{em.bytes()}, dataBlobs)
+	return provider.writeEventRaw(options.descriptor, options.activityID, options.relatedActivityID, [][]byte{em.bytes()}, dataBlobs)
 }
 
 // writeEventRaw writes a single ETW event from the provider. This function is
@@ -259,8 +219,8 @@ func (provider *Provider) WriteEvent(name string, eventOpts []EventOpt, fieldOpt
 // the ETW infrastructure.
 func (provider *Provider) writeEventRaw(
 	descriptor *eventDescriptor,
-	activityID *windows.GUID,
-	relatedActivityID *windows.GUID,
+	activityID *guid.GUID,
+	relatedActivityID *guid.GUID,
 	metadataBlobs [][]byte,
 	dataBlobs [][]byte) error {
 
@@ -275,5 +235,5 @@ func (provider *Provider) writeEventRaw(
 		dataDescriptors = append(dataDescriptors, newEventDataDescriptor(eventDataDescriptorTypeUserData, blob))
 	}
 
-	return eventWriteTransfer(provider.handle, descriptor, activityID, relatedActivityID, dataDescriptorCount, &dataDescriptors[0])
+	return eventWriteTransfer(provider.handle, descriptor, (*windows.GUID)(activityID), (*windows.GUID)(relatedActivityID), dataDescriptorCount, &dataDescriptors[0])
 }

+ 51 - 0
vendor/github.com/Microsoft/go-winio/pkg/etw/wrapper_32.go

@@ -0,0 +1,51 @@
+// +build 386 arm
+
+package etw
+
+import (
+	"golang.org/x/sys/windows"
+)
+
+func low(v providerHandle) uint32 {
+	return uint32(v & 0xffffffff)
+}
+
+func high(v providerHandle) uint32 {
+	return low(v >> 32)
+}
+
+func eventUnregister(providerHandle providerHandle) (win32err error) {
+	return eventUnregister_32(low(providerHandle), high(providerHandle))
+}
+
+func eventWriteTransfer(
+	providerHandle providerHandle,
+	descriptor *eventDescriptor,
+	activityID *windows.GUID,
+	relatedActivityID *windows.GUID,
+	dataDescriptorCount uint32,
+	dataDescriptors *eventDataDescriptor) (win32err error) {
+
+	return eventWriteTransfer_32(
+		low(providerHandle),
+		high(providerHandle),
+		descriptor,
+		activityID,
+		relatedActivityID,
+		dataDescriptorCount,
+		dataDescriptors)
+}
+
+func eventSetInformation(
+	providerHandle providerHandle,
+	class eventInfoClass,
+	information uintptr,
+	length uint32) (win32err error) {
+
+	return eventSetInformation_32(
+		low(providerHandle),
+		high(providerHandle),
+		class,
+		information,
+		length)
+}

+ 41 - 0
vendor/github.com/Microsoft/go-winio/pkg/etw/wrapper_64.go

@@ -0,0 +1,41 @@
+// +build amd64 arm64
+
+package etw
+
+import (
+	"golang.org/x/sys/windows"
+)
+
+func eventUnregister(providerHandle providerHandle) (win32err error) {
+	return eventUnregister_64(providerHandle)
+}
+
+func eventWriteTransfer(
+	providerHandle providerHandle,
+	descriptor *eventDescriptor,
+	activityID *windows.GUID,
+	relatedActivityID *windows.GUID,
+	dataDescriptorCount uint32,
+	dataDescriptors *eventDataDescriptor) (win32err error) {
+
+	return eventWriteTransfer_64(
+		providerHandle,
+		descriptor,
+		activityID,
+		relatedActivityID,
+		dataDescriptorCount,
+		dataDescriptors)
+}
+
+func eventSetInformation(
+	providerHandle providerHandle,
+	class eventInfoClass,
+	information uintptr,
+	length uint32) (win32err error) {
+
+	return eventSetInformation_64(
+		providerHandle,
+		class,
+		information,
+		length)
+}

+ 27 - 3
vendor/github.com/Microsoft/go-winio/pkg/etw/zsyscall_windows.go

@@ -53,7 +53,7 @@ func eventRegister(providerId *windows.GUID, callback uintptr, callbackContext u
 	return
 }
 
-func eventUnregister(providerHandle providerHandle) (win32err error) {
+func eventUnregister_64(providerHandle providerHandle) (win32err error) {
 	r0, _, _ := syscall.Syscall(procEventUnregister.Addr(), 1, uintptr(providerHandle), 0, 0)
 	if r0 != 0 {
 		win32err = syscall.Errno(r0)
@@ -61,7 +61,7 @@ func eventUnregister(providerHandle providerHandle) (win32err error) {
 	return
 }
 
-func eventWriteTransfer(providerHandle providerHandle, descriptor *eventDescriptor, activityID *windows.GUID, relatedActivityID *windows.GUID, dataDescriptorCount uint32, dataDescriptors *eventDataDescriptor) (win32err error) {
+func eventWriteTransfer_64(providerHandle providerHandle, descriptor *eventDescriptor, activityID *windows.GUID, relatedActivityID *windows.GUID, dataDescriptorCount uint32, dataDescriptors *eventDataDescriptor) (win32err error) {
 	r0, _, _ := syscall.Syscall6(procEventWriteTransfer.Addr(), 6, uintptr(providerHandle), uintptr(unsafe.Pointer(descriptor)), uintptr(unsafe.Pointer(activityID)), uintptr(unsafe.Pointer(relatedActivityID)), uintptr(dataDescriptorCount), uintptr(unsafe.Pointer(dataDescriptors)))
 	if r0 != 0 {
 		win32err = syscall.Errno(r0)
@@ -69,10 +69,34 @@ func eventWriteTransfer(providerHandle providerHandle, descriptor *eventDescript
 	return
 }
 
-func eventSetInformation(providerHandle providerHandle, class eventInfoClass, information uintptr, length uint32) (win32err error) {
+func eventSetInformation_64(providerHandle providerHandle, class eventInfoClass, information uintptr, length uint32) (win32err error) {
 	r0, _, _ := syscall.Syscall6(procEventSetInformation.Addr(), 4, uintptr(providerHandle), uintptr(class), uintptr(information), uintptr(length), 0, 0)
 	if r0 != 0 {
 		win32err = syscall.Errno(r0)
 	}
 	return
 }
+
+func eventUnregister_32(providerHandle_low uint32, providerHandle_high uint32) (win32err error) {
+	r0, _, _ := syscall.Syscall(procEventUnregister.Addr(), 2, uintptr(providerHandle_low), uintptr(providerHandle_high), 0)
+	if r0 != 0 {
+		win32err = syscall.Errno(r0)
+	}
+	return
+}
+
+func eventWriteTransfer_32(providerHandle_low uint32, providerHandle_high uint32, descriptor *eventDescriptor, activityID *windows.GUID, relatedActivityID *windows.GUID, dataDescriptorCount uint32, dataDescriptors *eventDataDescriptor) (win32err error) {
+	r0, _, _ := syscall.Syscall9(procEventWriteTransfer.Addr(), 7, uintptr(providerHandle_low), uintptr(providerHandle_high), uintptr(unsafe.Pointer(descriptor)), uintptr(unsafe.Pointer(activityID)), uintptr(unsafe.Pointer(relatedActivityID)), uintptr(dataDescriptorCount), uintptr(unsafe.Pointer(dataDescriptors)), 0, 0)
+	if r0 != 0 {
+		win32err = syscall.Errno(r0)
+	}
+	return
+}
+
+func eventSetInformation_32(providerHandle_low uint32, providerHandle_high uint32, class eventInfoClass, information uintptr, length uint32) (win32err error) {
+	r0, _, _ := syscall.Syscall6(procEventSetInformation.Addr(), 5, uintptr(providerHandle_low), uintptr(providerHandle_high), uintptr(class), uintptr(information), uintptr(length), 0)
+	if r0 != 0 {
+		win32err = syscall.Errno(r0)
+	}
+	return
+}

+ 1 - 125
vendor/github.com/Microsoft/go-winio/pkg/etwlogrus/hook.go

@@ -1,9 +1,6 @@
 package etwlogrus
 
 import (
-	"fmt"
-	"reflect"
-
 	"github.com/Microsoft/go-winio/pkg/etw"
 	"github.com/sirupsen/logrus"
 )
@@ -71,7 +68,7 @@ func (h *Hook) Fire(e *logrus.Entry) error {
 	fields = append(fields, etw.StringField("Message", e.Message))
 
 	for k, v := range e.Data {
-		fields = append(fields, getFieldOpt(k, v))
+		fields = append(fields, etw.SmartField(k, v))
 	}
 
 	return h.provider.WriteEvent(
@@ -80,127 +77,6 @@ func (h *Hook) Fire(e *logrus.Entry) error {
 		fields)
 }
 
-// Currently, we support logging basic builtin types (int, string, etc), slices
-// of basic builtin types, error, types derived from the basic types (e.g. "type
-// foo int"), and structs (recursively logging their fields). We do not support
-// slices of derived types (e.g. "[]foo").
-//
-// For types that we don't support, the value is formatted via fmt.Sprint, and
-// we also log a message that the type is unsupported along with the formatted
-// type. The intent of this is to make it easier to see which types are not
-// supported in traces, so we can evaluate adding support for more types in the
-// future.
-func getFieldOpt(k string, v interface{}) etw.FieldOpt {
-	switch v := v.(type) {
-	case bool:
-		return etw.BoolField(k, v)
-	case []bool:
-		return etw.BoolArray(k, v)
-	case string:
-		return etw.StringField(k, v)
-	case []string:
-		return etw.StringArray(k, v)
-	case int:
-		return etw.IntField(k, v)
-	case []int:
-		return etw.IntArray(k, v)
-	case int8:
-		return etw.Int8Field(k, v)
-	case []int8:
-		return etw.Int8Array(k, v)
-	case int16:
-		return etw.Int16Field(k, v)
-	case []int16:
-		return etw.Int16Array(k, v)
-	case int32:
-		return etw.Int32Field(k, v)
-	case []int32:
-		return etw.Int32Array(k, v)
-	case int64:
-		return etw.Int64Field(k, v)
-	case []int64:
-		return etw.Int64Array(k, v)
-	case uint:
-		return etw.UintField(k, v)
-	case []uint:
-		return etw.UintArray(k, v)
-	case uint8:
-		return etw.Uint8Field(k, v)
-	case []uint8:
-		return etw.Uint8Array(k, v)
-	case uint16:
-		return etw.Uint16Field(k, v)
-	case []uint16:
-		return etw.Uint16Array(k, v)
-	case uint32:
-		return etw.Uint32Field(k, v)
-	case []uint32:
-		return etw.Uint32Array(k, v)
-	case uint64:
-		return etw.Uint64Field(k, v)
-	case []uint64:
-		return etw.Uint64Array(k, v)
-	case uintptr:
-		return etw.UintptrField(k, v)
-	case []uintptr:
-		return etw.UintptrArray(k, v)
-	case float32:
-		return etw.Float32Field(k, v)
-	case []float32:
-		return etw.Float32Array(k, v)
-	case float64:
-		return etw.Float64Field(k, v)
-	case []float64:
-		return etw.Float64Array(k, v)
-	case error:
-		return etw.StringField(k, v.Error())
-	default:
-		switch rv := reflect.ValueOf(v); rv.Kind() {
-		case reflect.Bool:
-			return getFieldOpt(k, rv.Bool())
-		case reflect.Int:
-			return getFieldOpt(k, int(rv.Int()))
-		case reflect.Int8:
-			return getFieldOpt(k, int8(rv.Int()))
-		case reflect.Int16:
-			return getFieldOpt(k, int16(rv.Int()))
-		case reflect.Int32:
-			return getFieldOpt(k, int32(rv.Int()))
-		case reflect.Int64:
-			return getFieldOpt(k, int64(rv.Int()))
-		case reflect.Uint:
-			return getFieldOpt(k, uint(rv.Uint()))
-		case reflect.Uint8:
-			return getFieldOpt(k, uint8(rv.Uint()))
-		case reflect.Uint16:
-			return getFieldOpt(k, uint16(rv.Uint()))
-		case reflect.Uint32:
-			return getFieldOpt(k, uint32(rv.Uint()))
-		case reflect.Uint64:
-			return getFieldOpt(k, uint64(rv.Uint()))
-		case reflect.Uintptr:
-			return getFieldOpt(k, uintptr(rv.Uint()))
-		case reflect.Float32:
-			return getFieldOpt(k, float32(rv.Float()))
-		case reflect.Float64:
-			return getFieldOpt(k, float64(rv.Float()))
-		case reflect.String:
-			return getFieldOpt(k, rv.String())
-		case reflect.Struct:
-			fields := make([]etw.FieldOpt, 0, rv.NumField())
-			for i := 0; i < rv.NumField(); i++ {
-				field := rv.Field(i)
-				if field.CanInterface() {
-					fields = append(fields, getFieldOpt(k, field.Interface()))
-				}
-			}
-			return etw.Struct(k, fields...)
-		}
-	}
-
-	return etw.StringField(k, fmt.Sprintf("(Unsupported: %T) %v", v, v))
-}
-
 // Close cleans up the hook and closes the ETW provider. If the provder was
 // registered by etwlogrus, it will be closed as part of `Close`. If the
 // provider was passed in, it will not be closed.

+ 110 - 0
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go

@@ -0,0 +1,110 @@
+package guid
+
+import (
+	"crypto/rand"
+	"encoding/binary"
+	"encoding/json"
+	"fmt"
+	"strconv"
+	"strings"
+
+	"github.com/pkg/errors"
+	"golang.org/x/sys/windows"
+)
+
+var _ = (json.Marshaler)(&GUID{})
+var _ = (json.Unmarshaler)(&GUID{})
+
+// GUID represents a GUID/UUID. It has the same structure as
+// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
+// that type. It is defined as its own type so that stringification and
+// marshaling can be supported. The representation matches that used by native
+// Windows code.
+type GUID windows.GUID
+
+// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122.
+func NewV4() (*GUID, error) {
+	var b [16]byte
+	if _, err := rand.Read(b[:]); err != nil {
+		return nil, err
+	}
+
+	var g GUID
+	g.Data1 = binary.LittleEndian.Uint32(b[0:4])
+	g.Data2 = binary.LittleEndian.Uint16(b[4:6])
+	g.Data3 = binary.LittleEndian.Uint16(b[6:8])
+	copy(g.Data4[:], b[8:16])
+
+	g.Data3 = (g.Data3 & 0x0fff) | 0x4000   // Version 4 (randomly generated)
+	g.Data4[0] = (g.Data4[0] & 0x3f) | 0x80 // RFC4122 variant
+	return &g, nil
+}
+
+func (g *GUID) String() string {
+	return fmt.Sprintf(
+		"%08x-%04x-%04x-%04x-%012x",
+		g.Data1,
+		g.Data2,
+		g.Data3,
+		g.Data4[:2],
+		g.Data4[2:])
+}
+
+// FromString parses a string containing a GUID and returns the GUID. The only
+// format currently supported is the `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
+// format.
+func FromString(s string) (*GUID, error) {
+	if len(s) != 36 {
+		return nil, errors.New("invalid GUID format (length)")
+	}
+	if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
+		return nil, errors.New("invalid GUID format (dashes)")
+	}
+
+	var g GUID
+
+	data1, err := strconv.ParseUint(s[0:8], 16, 32)
+	if err != nil {
+		return nil, errors.Wrap(err, "invalid GUID format (Data1)")
+	}
+	g.Data1 = uint32(data1)
+
+	data2, err := strconv.ParseUint(s[9:13], 16, 16)
+	if err != nil {
+		return nil, errors.Wrap(err, "invalid GUID format (Data2)")
+	}
+	g.Data2 = uint16(data2)
+
+	data3, err := strconv.ParseUint(s[14:18], 16, 16)
+	if err != nil {
+		return nil, errors.Wrap(err, "invalid GUID format (Data3)")
+	}
+	g.Data3 = uint16(data3)
+
+	for i, x := range []int{19, 21, 24, 26, 28, 30, 32, 34} {
+		v, err := strconv.ParseUint(s[x:x+2], 16, 8)
+		if err != nil {
+			return nil, errors.Wrap(err, "invalid GUID format (Data4)")
+		}
+		g.Data4[i] = uint8(v)
+	}
+
+	return &g, nil
+}
+
+// MarshalJSON marshals the GUID to JSON representation and returns it as a
+// slice of bytes.
+func (g *GUID) MarshalJSON() ([]byte, error) {
+	return json.Marshal(g.String())
+}
+
+// UnmarshalJSON unmarshals a GUID from JSON representation and sets itself to
+// the unmarshaled GUID.
+func (g *GUID) UnmarshalJSON(data []byte) error {
+	g2, err := FromString(strings.Trim(string(data), "\""))
+	if err != nil {
+		return err
+	}
+	*g = *g2
+	return nil
+}

+ 1 - 1
vendor/github.com/Microsoft/go-winio/syscall.go

@@ -1,3 +1,3 @@
 package winio
 
-//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go
+//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go

+ 65 - 23
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go

@@ -1,4 +1,4 @@
-// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
+// Code generated by 'go generate'; DO NOT EDIT.
 
 package winio
 
@@ -38,19 +38,25 @@ func errnoErr(e syscall.Errno) error {
 
 var (
 	modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
+	modws2_32   = windows.NewLazySystemDLL("ws2_32.dll")
+	modntdll    = windows.NewLazySystemDLL("ntdll.dll")
 	modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
 
 	procCancelIoEx                                           = modkernel32.NewProc("CancelIoEx")
 	procCreateIoCompletionPort                               = modkernel32.NewProc("CreateIoCompletionPort")
 	procGetQueuedCompletionStatus                            = modkernel32.NewProc("GetQueuedCompletionStatus")
 	procSetFileCompletionNotificationModes                   = modkernel32.NewProc("SetFileCompletionNotificationModes")
+	procWSAGetOverlappedResult                               = modws2_32.NewProc("WSAGetOverlappedResult")
 	procConnectNamedPipe                                     = modkernel32.NewProc("ConnectNamedPipe")
 	procCreateNamedPipeW                                     = modkernel32.NewProc("CreateNamedPipeW")
 	procCreateFileW                                          = modkernel32.NewProc("CreateFileW")
-	procWaitNamedPipeW                                       = modkernel32.NewProc("WaitNamedPipeW")
 	procGetNamedPipeInfo                                     = modkernel32.NewProc("GetNamedPipeInfo")
 	procGetNamedPipeHandleStateW                             = modkernel32.NewProc("GetNamedPipeHandleStateW")
 	procLocalAlloc                                           = modkernel32.NewProc("LocalAlloc")
+	procNtCreateNamedPipeFile                                = modntdll.NewProc("NtCreateNamedPipeFile")
+	procRtlNtStatusToDosErrorNoTeb                           = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
+	procRtlDosPathNameToNtPathName_U                         = modntdll.NewProc("RtlDosPathNameToNtPathName_U")
+	procRtlDefaultNpAcl                                      = modntdll.NewProc("RtlDefaultNpAcl")
 	procLookupAccountNameW                                   = modadvapi32.NewProc("LookupAccountNameW")
 	procConvertSidToStringSidW                               = modadvapi32.NewProc("ConvertSidToStringSidW")
 	procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
@@ -69,6 +75,7 @@ var (
 	procLookupPrivilegeDisplayNameW                          = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
 	procBackupRead                                           = modkernel32.NewProc("BackupRead")
 	procBackupWrite                                          = modkernel32.NewProc("BackupWrite")
+	procbind                                                 = modws2_32.NewProc("bind")
 )
 
 func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
@@ -120,6 +127,24 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro
 	return
 }
 
+func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) {
+	var _p0 uint32
+	if wait {
+		_p0 = 1
+	} else {
+		_p0 = 0
+	}
+	r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(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 {
@@ -176,27 +201,6 @@ func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityA
 	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 = errnoErr(e1)
-		} else {
-			err = syscall.EINVAL
-		}
-	}
-	return
-}
-
 func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) {
 	r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0)
 	if r1 == 0 {
@@ -227,6 +231,32 @@ func localAlloc(uFlags uint32, length uint32) (ptr uintptr) {
 	return
 }
 
+func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) {
+	r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0)
+	status = ntstatus(r0)
+	return
+}
+
+func rtlNtStatusToDosError(status ntstatus) (winerr error) {
+	r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
+	if r0 != 0 {
+		winerr = syscall.Errno(r0)
+	}
+	return
+}
+
+func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) {
+	r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0)
+	status = ntstatus(r0)
+	return
+}
+
+func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) {
+	r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0)
+	status = ntstatus(r0)
+	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)
@@ -518,3 +548,15 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p
 	}
 	return
 }
+
+func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) {
+	r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
+	if r1 == socketError {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}