mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
commit
c8b7dad9e9
18 changed files with 1036 additions and 312 deletions
|
@ -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
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
6
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
|
@ -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
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
Normal file
305
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
Normal file
|
@ -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)
|
||||
}
|
247
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
247
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
|
@ -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
|
||||
|
||||
cPIPE_REJECT_REMOTE_CLIENTS = 0x8
|
||||
|
||||
cPIPE_UNLIMITED_INSTANCES = 255
|
||||
|
||||
cNMPWAIT_USE_DEFAULT_WAIT = 0
|
||||
cNMPWAIT_NOWAIT = 1
|
||||
cSECURITY_SQOS_PRESENT = 0x100000
|
||||
cSECURITY_ANONYMOUS = 0
|
||||
|
||||
cPIPE_TYPE_MESSAGE = 4
|
||||
|
||||
cPIPE_READMODE_MESSAGE = 2
|
||||
|
||||
cFILE_OPEN = 1
|
||||
cFILE_CREATE = 2
|
||||
|
||||
cFILE_PIPE_MESSAGE_TYPE = 1
|
||||
cFILE_PIPE_REJECT_REMOTE_CLIENTS = 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
|
||||
if first {
|
||||
flags |= cFILE_FLAG_FIRST_PIPE_INSTANCE
|
||||
}
|
||||
|
||||
var mode uint32 = cPIPE_REJECT_REMOTE_CLIENTS
|
||||
if c.MessageMode {
|
||||
mode |= cPIPE_TYPE_MESSAGE
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
h, err := createNamedPipe(path, flags, mode, cPIPE_UNLIMITED_INSTANCES, uint32(c.OutputBufferSize), uint32(c.InputBufferSize), 0, sa)
|
||||
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 {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS)
|
||||
if c.MessageMode {
|
||||
typ |= cFILE_PIPE_MESSAGE_TYPE
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
|
|
13
vendor/github.com/Microsoft/go-winio/pkg/etw/etw.go
generated
vendored
13
vendor/github.com/Microsoft/go-winio/pkg/etw/etw.go
generated
vendored
|
@ -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
|
||||
|
|
21
vendor/github.com/Microsoft/go-winio/pkg/etw/eventdescriptor.go
generated
vendored
21
vendor/github.com/Microsoft/go-winio/pkg/etw/eventdescriptor.go
generated
vendored
|
@ -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
|
||||
}
|
||||
|
|
20
vendor/github.com/Microsoft/go-winio/pkg/etw/eventopt.go
generated
vendored
20
vendor/github.com/Microsoft/go-winio/pkg/etw/eventopt.go
generated
vendored
|
@ -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
vendor/github.com/Microsoft/go-winio/pkg/etw/fieldopt.go
generated
vendored
123
vendor/github.com/Microsoft/go-winio/pkg/etw/fieldopt.go
generated
vendored
|
@ -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
vendor/github.com/Microsoft/go-winio/pkg/etw/newprovider.go
generated
vendored
Normal file
53
vendor/github.com/Microsoft/go-winio/pkg/etw/newprovider.go
generated
vendored
Normal file
|
@ -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
vendor/github.com/Microsoft/go-winio/pkg/etw/newprovider_unsupported.go
generated
vendored
Normal file
12
vendor/github.com/Microsoft/go-winio/pkg/etw/newprovider_unsupported.go
generated
vendored
Normal file
|
@ -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
|
||||
}
|
98
vendor/github.com/Microsoft/go-winio/pkg/etw/provider.go
generated
vendored
98
vendor/github.com/Microsoft/go-winio/pkg/etw/provider.go
generated
vendored
|
@ -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
vendor/github.com/Microsoft/go-winio/pkg/etw/wrapper_32.go
generated
vendored
Normal file
51
vendor/github.com/Microsoft/go-winio/pkg/etw/wrapper_32.go
generated
vendored
Normal file
|
@ -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
vendor/github.com/Microsoft/go-winio/pkg/etw/wrapper_64.go
generated
vendored
Normal file
41
vendor/github.com/Microsoft/go-winio/pkg/etw/wrapper_64.go
generated
vendored
Normal file
|
@ -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)
|
||||
}
|
30
vendor/github.com/Microsoft/go-winio/pkg/etw/zsyscall_windows.go
generated
vendored
30
vendor/github.com/Microsoft/go-winio/pkg/etw/zsyscall_windows.go
generated
vendored
|
@ -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
|
||||
}
|
||||
|
|
126
vendor/github.com/Microsoft/go-winio/pkg/etwlogrus/hook.go
generated
vendored
126
vendor/github.com/Microsoft/go-winio/pkg/etwlogrus/hook.go
generated
vendored
|
@ -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
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
Normal file
110
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
Normal file
|
@ -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
|
||||
}
|
2
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
|
@ -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
|
||||
|
|
88
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
88
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue