Fix dependencies
This commit is contained in:
		
							
								
								
									
										1
									
								
								vendor/github.com/Microsoft/go-winio/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/Microsoft/go-winio/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
*.exe
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/github.com/Microsoft/go-winio/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/Microsoft/go-winio/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2015 Microsoft
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/github.com/Microsoft/go-winio/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/Microsoft/go-winio/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
# go-winio
 | 
			
		||||
 | 
			
		||||
This repository contains utilities for efficiently performing Win32 IO operations in
 | 
			
		||||
Go. Currently, this is focused on accessing named pipes and other file handles, and
 | 
			
		||||
for using named pipes as a net transport.
 | 
			
		||||
 | 
			
		||||
This code relies on IO completion ports to avoid blocking IO on system threads, allowing Go
 | 
			
		||||
to reuse the thread to schedule another goroutine. This limits support to Windows Vista and
 | 
			
		||||
newer operating systems. This is similar to the implementation of network sockets in Go's net
 | 
			
		||||
package.
 | 
			
		||||
 | 
			
		||||
Please see the LICENSE file for licensing information.
 | 
			
		||||
 | 
			
		||||
This project has adopted the [Microsoft Open Source Code of
 | 
			
		||||
Conduct](https://opensource.microsoft.com/codeofconduct/). For more information
 | 
			
		||||
see the [Code of Conduct
 | 
			
		||||
FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact
 | 
			
		||||
[opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional
 | 
			
		||||
questions or comments.
 | 
			
		||||
 | 
			
		||||
Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe
 | 
			
		||||
for another named pipe implementation.
 | 
			
		||||
							
								
								
									
										280
									
								
								vendor/github.com/Microsoft/go-winio/backup.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										280
									
								
								vendor/github.com/Microsoft/go-winio/backup.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,280 @@
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
package winio
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unicode/utf16"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead
 | 
			
		||||
//sys backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	BackupData = uint32(iota + 1)
 | 
			
		||||
	BackupEaData
 | 
			
		||||
	BackupSecurity
 | 
			
		||||
	BackupAlternateData
 | 
			
		||||
	BackupLink
 | 
			
		||||
	BackupPropertyData
 | 
			
		||||
	BackupObjectId
 | 
			
		||||
	BackupReparseData
 | 
			
		||||
	BackupSparseBlock
 | 
			
		||||
	BackupTxfsData
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	StreamSparseAttributes = uint32(8)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	WRITE_DAC              = 0x40000
 | 
			
		||||
	WRITE_OWNER            = 0x80000
 | 
			
		||||
	ACCESS_SYSTEM_SECURITY = 0x1000000
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// BackupHeader represents a backup stream of a file.
 | 
			
		||||
type BackupHeader struct {
 | 
			
		||||
	Id         uint32 // The backup stream ID
 | 
			
		||||
	Attributes uint32 // Stream attributes
 | 
			
		||||
	Size       int64  // The size of the stream in bytes
 | 
			
		||||
	Name       string // The name of the stream (for BackupAlternateData only).
 | 
			
		||||
	Offset     int64  // The offset of the stream in the file (for BackupSparseBlock only).
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type win32StreamId struct {
 | 
			
		||||
	StreamId   uint32
 | 
			
		||||
	Attributes uint32
 | 
			
		||||
	Size       uint64
 | 
			
		||||
	NameSize   uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BackupStreamReader reads from a stream produced by the BackupRead Win32 API and produces a series
 | 
			
		||||
// of BackupHeader values.
 | 
			
		||||
type BackupStreamReader struct {
 | 
			
		||||
	r         io.Reader
 | 
			
		||||
	bytesLeft int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewBackupStreamReader produces a BackupStreamReader from any io.Reader.
 | 
			
		||||
func NewBackupStreamReader(r io.Reader) *BackupStreamReader {
 | 
			
		||||
	return &BackupStreamReader{r, 0}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if
 | 
			
		||||
// it was not completely read.
 | 
			
		||||
func (r *BackupStreamReader) Next() (*BackupHeader, error) {
 | 
			
		||||
	if r.bytesLeft > 0 {
 | 
			
		||||
		if s, ok := r.r.(io.Seeker); ok {
 | 
			
		||||
			// Make sure Seek on io.SeekCurrent sometimes succeeds
 | 
			
		||||
			// before trying the actual seek.
 | 
			
		||||
			if _, err := s.Seek(0, io.SeekCurrent); err == nil {
 | 
			
		||||
				if _, err = s.Seek(r.bytesLeft, io.SeekCurrent); err != nil {
 | 
			
		||||
					return nil, err
 | 
			
		||||
				}
 | 
			
		||||
				r.bytesLeft = 0
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if _, err := io.Copy(ioutil.Discard, r); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	var wsi win32StreamId
 | 
			
		||||
	if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	hdr := &BackupHeader{
 | 
			
		||||
		Id:         wsi.StreamId,
 | 
			
		||||
		Attributes: wsi.Attributes,
 | 
			
		||||
		Size:       int64(wsi.Size),
 | 
			
		||||
	}
 | 
			
		||||
	if wsi.NameSize != 0 {
 | 
			
		||||
		name := make([]uint16, int(wsi.NameSize/2))
 | 
			
		||||
		if err := binary.Read(r.r, binary.LittleEndian, name); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		hdr.Name = syscall.UTF16ToString(name)
 | 
			
		||||
	}
 | 
			
		||||
	if wsi.StreamId == BackupSparseBlock {
 | 
			
		||||
		if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		hdr.Size -= 8
 | 
			
		||||
	}
 | 
			
		||||
	r.bytesLeft = hdr.Size
 | 
			
		||||
	return hdr, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read reads from the current backup stream.
 | 
			
		||||
func (r *BackupStreamReader) Read(b []byte) (int, error) {
 | 
			
		||||
	if r.bytesLeft == 0 {
 | 
			
		||||
		return 0, io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	if int64(len(b)) > r.bytesLeft {
 | 
			
		||||
		b = b[:r.bytesLeft]
 | 
			
		||||
	}
 | 
			
		||||
	n, err := r.r.Read(b)
 | 
			
		||||
	r.bytesLeft -= int64(n)
 | 
			
		||||
	if err == io.EOF {
 | 
			
		||||
		err = io.ErrUnexpectedEOF
 | 
			
		||||
	} else if r.bytesLeft == 0 && err == nil {
 | 
			
		||||
		err = io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	return n, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BackupStreamWriter writes a stream compatible with the BackupWrite Win32 API.
 | 
			
		||||
type BackupStreamWriter struct {
 | 
			
		||||
	w         io.Writer
 | 
			
		||||
	bytesLeft int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewBackupStreamWriter produces a BackupStreamWriter on top of an io.Writer.
 | 
			
		||||
func NewBackupStreamWriter(w io.Writer) *BackupStreamWriter {
 | 
			
		||||
	return &BackupStreamWriter{w, 0}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteHeader writes the next backup stream header and prepares for calls to Write().
 | 
			
		||||
func (w *BackupStreamWriter) WriteHeader(hdr *BackupHeader) error {
 | 
			
		||||
	if w.bytesLeft != 0 {
 | 
			
		||||
		return fmt.Errorf("missing %d bytes", w.bytesLeft)
 | 
			
		||||
	}
 | 
			
		||||
	name := utf16.Encode([]rune(hdr.Name))
 | 
			
		||||
	wsi := win32StreamId{
 | 
			
		||||
		StreamId:   hdr.Id,
 | 
			
		||||
		Attributes: hdr.Attributes,
 | 
			
		||||
		Size:       uint64(hdr.Size),
 | 
			
		||||
		NameSize:   uint32(len(name) * 2),
 | 
			
		||||
	}
 | 
			
		||||
	if hdr.Id == BackupSparseBlock {
 | 
			
		||||
		// Include space for the int64 block offset
 | 
			
		||||
		wsi.Size += 8
 | 
			
		||||
	}
 | 
			
		||||
	if err := binary.Write(w.w, binary.LittleEndian, &wsi); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if len(name) != 0 {
 | 
			
		||||
		if err := binary.Write(w.w, binary.LittleEndian, name); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if hdr.Id == BackupSparseBlock {
 | 
			
		||||
		if err := binary.Write(w.w, binary.LittleEndian, hdr.Offset); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	w.bytesLeft = hdr.Size
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write writes to the current backup stream.
 | 
			
		||||
func (w *BackupStreamWriter) Write(b []byte) (int, error) {
 | 
			
		||||
	if w.bytesLeft < int64(len(b)) {
 | 
			
		||||
		return 0, fmt.Errorf("too many bytes by %d", int64(len(b))-w.bytesLeft)
 | 
			
		||||
	}
 | 
			
		||||
	n, err := w.w.Write(b)
 | 
			
		||||
	w.bytesLeft -= int64(n)
 | 
			
		||||
	return n, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BackupFileReader provides an io.ReadCloser interface on top of the BackupRead Win32 API.
 | 
			
		||||
type BackupFileReader struct {
 | 
			
		||||
	f               *os.File
 | 
			
		||||
	includeSecurity bool
 | 
			
		||||
	ctx             uintptr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewBackupFileReader returns a new BackupFileReader from a file handle. If includeSecurity is true,
 | 
			
		||||
// Read will attempt to read the security descriptor of the file.
 | 
			
		||||
func NewBackupFileReader(f *os.File, includeSecurity bool) *BackupFileReader {
 | 
			
		||||
	r := &BackupFileReader{f, includeSecurity, 0}
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read reads a backup stream from the file by calling the Win32 API BackupRead().
 | 
			
		||||
func (r *BackupFileReader) Read(b []byte) (int, error) {
 | 
			
		||||
	var bytesRead uint32
 | 
			
		||||
	err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, &os.PathError{"BackupRead", r.f.Name(), err}
 | 
			
		||||
	}
 | 
			
		||||
	runtime.KeepAlive(r.f)
 | 
			
		||||
	if bytesRead == 0 {
 | 
			
		||||
		return 0, io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	return int(bytesRead), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close frees Win32 resources associated with the BackupFileReader. It does not close
 | 
			
		||||
// the underlying file.
 | 
			
		||||
func (r *BackupFileReader) Close() error {
 | 
			
		||||
	if r.ctx != 0 {
 | 
			
		||||
		backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
 | 
			
		||||
		runtime.KeepAlive(r.f)
 | 
			
		||||
		r.ctx = 0
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BackupFileWriter provides an io.WriteCloser interface on top of the BackupWrite Win32 API.
 | 
			
		||||
type BackupFileWriter struct {
 | 
			
		||||
	f               *os.File
 | 
			
		||||
	includeSecurity bool
 | 
			
		||||
	ctx             uintptr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewBackupFileWriter returns a new BackupFileWriter from a file handle. If includeSecurity is true,
 | 
			
		||||
// Write() will attempt to restore the security descriptor from the stream.
 | 
			
		||||
func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter {
 | 
			
		||||
	w := &BackupFileWriter{f, includeSecurity, 0}
 | 
			
		||||
	return w
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write restores a portion of the file using the provided backup stream.
 | 
			
		||||
func (w *BackupFileWriter) Write(b []byte) (int, error) {
 | 
			
		||||
	var bytesWritten uint32
 | 
			
		||||
	err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, &os.PathError{"BackupWrite", w.f.Name(), err}
 | 
			
		||||
	}
 | 
			
		||||
	runtime.KeepAlive(w.f)
 | 
			
		||||
	if int(bytesWritten) != len(b) {
 | 
			
		||||
		return int(bytesWritten), errors.New("not all bytes could be written")
 | 
			
		||||
	}
 | 
			
		||||
	return len(b), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close frees Win32 resources associated with the BackupFileWriter. It does not
 | 
			
		||||
// close the underlying file.
 | 
			
		||||
func (w *BackupFileWriter) Close() error {
 | 
			
		||||
	if w.ctx != 0 {
 | 
			
		||||
		backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
 | 
			
		||||
		runtime.KeepAlive(w.f)
 | 
			
		||||
		w.ctx = 0
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OpenForBackup opens a file or directory, potentially skipping access checks if the backup
 | 
			
		||||
// or restore privileges have been acquired.
 | 
			
		||||
//
 | 
			
		||||
// If the file opened was a directory, it cannot be used with Readdir().
 | 
			
		||||
func OpenForBackup(path string, access uint32, share uint32, createmode uint32) (*os.File, error) {
 | 
			
		||||
	winPath, err := syscall.UTF16FromString(path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		err = &os.PathError{Op: "open", Path: path, Err: err}
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return os.NewFile(uintptr(h), path), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										137
									
								
								vendor/github.com/Microsoft/go-winio/ea.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								vendor/github.com/Microsoft/go-winio/ea.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,137 @@
 | 
			
		||||
package winio
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type fileFullEaInformation struct {
 | 
			
		||||
	NextEntryOffset uint32
 | 
			
		||||
	Flags           uint8
 | 
			
		||||
	NameLength      uint8
 | 
			
		||||
	ValueLength     uint16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	fileFullEaInformationSize = binary.Size(&fileFullEaInformation{})
 | 
			
		||||
 | 
			
		||||
	errInvalidEaBuffer = errors.New("invalid extended attribute buffer")
 | 
			
		||||
	errEaNameTooLarge  = errors.New("extended attribute name too large")
 | 
			
		||||
	errEaValueTooLarge = errors.New("extended attribute value too large")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ExtendedAttribute represents a single Windows EA.
 | 
			
		||||
type ExtendedAttribute struct {
 | 
			
		||||
	Name  string
 | 
			
		||||
	Value []byte
 | 
			
		||||
	Flags uint8
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
 | 
			
		||||
	var info fileFullEaInformation
 | 
			
		||||
	err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		err = errInvalidEaBuffer
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	nameOffset := fileFullEaInformationSize
 | 
			
		||||
	nameLen := int(info.NameLength)
 | 
			
		||||
	valueOffset := nameOffset + int(info.NameLength) + 1
 | 
			
		||||
	valueLen := int(info.ValueLength)
 | 
			
		||||
	nextOffset := int(info.NextEntryOffset)
 | 
			
		||||
	if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
 | 
			
		||||
		err = errInvalidEaBuffer
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ea.Name = string(b[nameOffset : nameOffset+nameLen])
 | 
			
		||||
	ea.Value = b[valueOffset : valueOffset+valueLen]
 | 
			
		||||
	ea.Flags = info.Flags
 | 
			
		||||
	if info.NextEntryOffset != 0 {
 | 
			
		||||
		nb = b[info.NextEntryOffset:]
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
 | 
			
		||||
// buffer retrieved from BackupRead, ZwQueryEaFile, etc.
 | 
			
		||||
func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {
 | 
			
		||||
	for len(b) != 0 {
 | 
			
		||||
		ea, nb, err := parseEa(b)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		eas = append(eas, ea)
 | 
			
		||||
		b = nb
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
 | 
			
		||||
	if int(uint8(len(ea.Name))) != len(ea.Name) {
 | 
			
		||||
		return errEaNameTooLarge
 | 
			
		||||
	}
 | 
			
		||||
	if int(uint16(len(ea.Value))) != len(ea.Value) {
 | 
			
		||||
		return errEaValueTooLarge
 | 
			
		||||
	}
 | 
			
		||||
	entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value))
 | 
			
		||||
	withPadding := (entrySize + 3) &^ 3
 | 
			
		||||
	nextOffset := uint32(0)
 | 
			
		||||
	if !last {
 | 
			
		||||
		nextOffset = withPadding
 | 
			
		||||
	}
 | 
			
		||||
	info := fileFullEaInformation{
 | 
			
		||||
		NextEntryOffset: nextOffset,
 | 
			
		||||
		Flags:           ea.Flags,
 | 
			
		||||
		NameLength:      uint8(len(ea.Name)),
 | 
			
		||||
		ValueLength:     uint16(len(ea.Value)),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := binary.Write(buf, binary.LittleEndian, &info)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = buf.Write([]byte(ea.Name))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = buf.WriteByte(0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = buf.Write(ea.Value)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION
 | 
			
		||||
// buffer for use with BackupWrite, ZwSetEaFile, etc.
 | 
			
		||||
func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) {
 | 
			
		||||
	var buf bytes.Buffer
 | 
			
		||||
	for i := range eas {
 | 
			
		||||
		last := false
 | 
			
		||||
		if i == len(eas)-1 {
 | 
			
		||||
			last = true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err := writeEa(&buf, &eas[i], last)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return buf.Bytes(), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										307
									
								
								vendor/github.com/Microsoft/go-winio/file.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										307
									
								
								vendor/github.com/Microsoft/go-winio/file.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,307 @@
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
package winio
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx
 | 
			
		||||
//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort
 | 
			
		||||
//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus
 | 
			
		||||
//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes
 | 
			
		||||
 | 
			
		||||
type atomicBool int32
 | 
			
		||||
 | 
			
		||||
func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
 | 
			
		||||
func (b *atomicBool) setFalse()   { atomic.StoreInt32((*int32)(b), 0) }
 | 
			
		||||
func (b *atomicBool) setTrue()    { atomic.StoreInt32((*int32)(b), 1) }
 | 
			
		||||
func (b *atomicBool) swap(new bool) bool {
 | 
			
		||||
	var newInt int32
 | 
			
		||||
	if new {
 | 
			
		||||
		newInt = 1
 | 
			
		||||
	}
 | 
			
		||||
	return atomic.SwapInt32((*int32)(b), newInt) == 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1
 | 
			
		||||
	cFILE_SKIP_SET_EVENT_ON_HANDLE        = 2
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	ErrFileClosed = errors.New("file has already been closed")
 | 
			
		||||
	ErrTimeout    = &timeoutError{}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type timeoutError struct{}
 | 
			
		||||
 | 
			
		||||
func (e *timeoutError) Error() string   { return "i/o timeout" }
 | 
			
		||||
func (e *timeoutError) Timeout() bool   { return true }
 | 
			
		||||
func (e *timeoutError) Temporary() bool { return true }
 | 
			
		||||
 | 
			
		||||
type timeoutChan chan struct{}
 | 
			
		||||
 | 
			
		||||
var ioInitOnce sync.Once
 | 
			
		||||
var ioCompletionPort syscall.Handle
 | 
			
		||||
 | 
			
		||||
// ioResult contains the result of an asynchronous IO operation
 | 
			
		||||
type ioResult struct {
 | 
			
		||||
	bytes uint32
 | 
			
		||||
	err   error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ioOperation represents an outstanding asynchronous Win32 IO
 | 
			
		||||
type ioOperation struct {
 | 
			
		||||
	o  syscall.Overlapped
 | 
			
		||||
	ch chan ioResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func initIo() {
 | 
			
		||||
	h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	ioCompletionPort = h
 | 
			
		||||
	go ioCompletionProcessor(h)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// win32File implements Reader, Writer, and Closer on a Win32 handle without blocking in a syscall.
 | 
			
		||||
// It takes ownership of this handle and will close it if it is garbage collected.
 | 
			
		||||
type win32File struct {
 | 
			
		||||
	handle        syscall.Handle
 | 
			
		||||
	wg            sync.WaitGroup
 | 
			
		||||
	wgLock        sync.RWMutex
 | 
			
		||||
	closing       atomicBool
 | 
			
		||||
	readDeadline  deadlineHandler
 | 
			
		||||
	writeDeadline deadlineHandler
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type deadlineHandler struct {
 | 
			
		||||
	setLock     sync.Mutex
 | 
			
		||||
	channel     timeoutChan
 | 
			
		||||
	channelLock sync.RWMutex
 | 
			
		||||
	timer       *time.Timer
 | 
			
		||||
	timedout    atomicBool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// makeWin32File makes a new win32File from an existing file handle
 | 
			
		||||
func makeWin32File(h syscall.Handle) (*win32File, error) {
 | 
			
		||||
	f := &win32File{handle: h}
 | 
			
		||||
	ioInitOnce.Do(initIo)
 | 
			
		||||
	_, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	f.readDeadline.channel = make(timeoutChan)
 | 
			
		||||
	f.writeDeadline.channel = make(timeoutChan)
 | 
			
		||||
	return f, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
 | 
			
		||||
	return makeWin32File(h)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// closeHandle closes the resources associated with a Win32 handle
 | 
			
		||||
func (f *win32File) closeHandle() {
 | 
			
		||||
	f.wgLock.Lock()
 | 
			
		||||
	// Atomically set that we are closing, releasing the resources only once.
 | 
			
		||||
	if !f.closing.swap(true) {
 | 
			
		||||
		f.wgLock.Unlock()
 | 
			
		||||
		// cancel all IO and wait for it to complete
 | 
			
		||||
		cancelIoEx(f.handle, nil)
 | 
			
		||||
		f.wg.Wait()
 | 
			
		||||
		// at this point, no new IO can start
 | 
			
		||||
		syscall.Close(f.handle)
 | 
			
		||||
		f.handle = 0
 | 
			
		||||
	} else {
 | 
			
		||||
		f.wgLock.Unlock()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close closes a win32File.
 | 
			
		||||
func (f *win32File) Close() error {
 | 
			
		||||
	f.closeHandle()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// prepareIo prepares for a new IO operation.
 | 
			
		||||
// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning.
 | 
			
		||||
func (f *win32File) prepareIo() (*ioOperation, error) {
 | 
			
		||||
	f.wgLock.RLock()
 | 
			
		||||
	if f.closing.isSet() {
 | 
			
		||||
		f.wgLock.RUnlock()
 | 
			
		||||
		return nil, ErrFileClosed
 | 
			
		||||
	}
 | 
			
		||||
	f.wg.Add(1)
 | 
			
		||||
	f.wgLock.RUnlock()
 | 
			
		||||
	c := &ioOperation{}
 | 
			
		||||
	c.ch = make(chan ioResult)
 | 
			
		||||
	return c, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ioCompletionProcessor processes completed async IOs forever
 | 
			
		||||
func ioCompletionProcessor(h syscall.Handle) {
 | 
			
		||||
	for {
 | 
			
		||||
		var bytes uint32
 | 
			
		||||
		var key uintptr
 | 
			
		||||
		var op *ioOperation
 | 
			
		||||
		err := getQueuedCompletionStatus(h, &bytes, &key, &op, syscall.INFINITE)
 | 
			
		||||
		if op == nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
		op.ch <- ioResult{bytes, err}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// asyncIo processes the return value from ReadFile or WriteFile, blocking until
 | 
			
		||||
// the operation has actually completed.
 | 
			
		||||
func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) {
 | 
			
		||||
	if err != syscall.ERROR_IO_PENDING {
 | 
			
		||||
		return int(bytes), err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if f.closing.isSet() {
 | 
			
		||||
		cancelIoEx(f.handle, &c.o)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var timeout timeoutChan
 | 
			
		||||
	if d != nil {
 | 
			
		||||
		d.channelLock.Lock()
 | 
			
		||||
		timeout = d.channel
 | 
			
		||||
		d.channelLock.Unlock()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var r ioResult
 | 
			
		||||
	select {
 | 
			
		||||
	case r = <-c.ch:
 | 
			
		||||
		err = r.err
 | 
			
		||||
		if err == syscall.ERROR_OPERATION_ABORTED {
 | 
			
		||||
			if f.closing.isSet() {
 | 
			
		||||
				err = ErrFileClosed
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	case <-timeout:
 | 
			
		||||
		cancelIoEx(f.handle, &c.o)
 | 
			
		||||
		r = <-c.ch
 | 
			
		||||
		err = r.err
 | 
			
		||||
		if err == syscall.ERROR_OPERATION_ABORTED {
 | 
			
		||||
			err = ErrTimeout
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// runtime.KeepAlive is needed, as c is passed via native
 | 
			
		||||
	// code to ioCompletionProcessor, c must remain alive
 | 
			
		||||
	// until the channel read is complete.
 | 
			
		||||
	runtime.KeepAlive(c)
 | 
			
		||||
	return int(r.bytes), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read reads from a file handle.
 | 
			
		||||
func (f *win32File) Read(b []byte) (int, error) {
 | 
			
		||||
	c, err := f.prepareIo()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	defer f.wg.Done()
 | 
			
		||||
 | 
			
		||||
	if f.readDeadline.timedout.isSet() {
 | 
			
		||||
		return 0, ErrTimeout
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var bytes uint32
 | 
			
		||||
	err = syscall.ReadFile(f.handle, b, &bytes, &c.o)
 | 
			
		||||
	n, err := f.asyncIo(c, &f.readDeadline, bytes, err)
 | 
			
		||||
	runtime.KeepAlive(b)
 | 
			
		||||
 | 
			
		||||
	// Handle EOF conditions.
 | 
			
		||||
	if err == nil && n == 0 && len(b) != 0 {
 | 
			
		||||
		return 0, io.EOF
 | 
			
		||||
	} else if err == syscall.ERROR_BROKEN_PIPE {
 | 
			
		||||
		return 0, io.EOF
 | 
			
		||||
	} else {
 | 
			
		||||
		return n, err
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write writes to a file handle.
 | 
			
		||||
func (f *win32File) Write(b []byte) (int, error) {
 | 
			
		||||
	c, err := f.prepareIo()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	defer f.wg.Done()
 | 
			
		||||
 | 
			
		||||
	if f.writeDeadline.timedout.isSet() {
 | 
			
		||||
		return 0, ErrTimeout
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var bytes uint32
 | 
			
		||||
	err = syscall.WriteFile(f.handle, b, &bytes, &c.o)
 | 
			
		||||
	n, err := f.asyncIo(c, &f.writeDeadline, bytes, err)
 | 
			
		||||
	runtime.KeepAlive(b)
 | 
			
		||||
	return n, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *win32File) SetReadDeadline(deadline time.Time) error {
 | 
			
		||||
	return f.readDeadline.set(deadline)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *win32File) SetWriteDeadline(deadline time.Time) error {
 | 
			
		||||
	return f.writeDeadline.set(deadline)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *win32File) Flush() error {
 | 
			
		||||
	return syscall.FlushFileBuffers(f.handle)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *deadlineHandler) set(deadline time.Time) error {
 | 
			
		||||
	d.setLock.Lock()
 | 
			
		||||
	defer d.setLock.Unlock()
 | 
			
		||||
 | 
			
		||||
	if d.timer != nil {
 | 
			
		||||
		if !d.timer.Stop() {
 | 
			
		||||
			<-d.channel
 | 
			
		||||
		}
 | 
			
		||||
		d.timer = nil
 | 
			
		||||
	}
 | 
			
		||||
	d.timedout.setFalse()
 | 
			
		||||
 | 
			
		||||
	select {
 | 
			
		||||
	case <-d.channel:
 | 
			
		||||
		d.channelLock.Lock()
 | 
			
		||||
		d.channel = make(chan struct{})
 | 
			
		||||
		d.channelLock.Unlock()
 | 
			
		||||
	default:
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if deadline.IsZero() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	timeoutIO := func() {
 | 
			
		||||
		d.timedout.setTrue()
 | 
			
		||||
		close(d.channel)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	now := time.Now()
 | 
			
		||||
	duration := deadline.Sub(now)
 | 
			
		||||
	if deadline.After(now) {
 | 
			
		||||
		// Deadline is in the future, set a timer to wait
 | 
			
		||||
		d.timer = time.AfterFunc(duration, timeoutIO)
 | 
			
		||||
	} else {
 | 
			
		||||
		// Deadline is in the past. Cancel all pending IO now.
 | 
			
		||||
		timeoutIO()
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										61
									
								
								vendor/github.com/Microsoft/go-winio/fileinfo.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								vendor/github.com/Microsoft/go-winio/fileinfo.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
package winio
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//sys getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = GetFileInformationByHandleEx
 | 
			
		||||
//sys setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = SetFileInformationByHandle
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	fileBasicInfo = 0
 | 
			
		||||
	fileIDInfo    = 0x12
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// FileBasicInfo contains file access time and file attributes information.
 | 
			
		||||
type FileBasicInfo struct {
 | 
			
		||||
	CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime
 | 
			
		||||
	FileAttributes                                          uint32
 | 
			
		||||
	pad                                                     uint32 // padding
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetFileBasicInfo retrieves times and attributes for a file.
 | 
			
		||||
func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
 | 
			
		||||
	bi := &FileBasicInfo{}
 | 
			
		||||
	if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
 | 
			
		||||
		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
 | 
			
		||||
	}
 | 
			
		||||
	runtime.KeepAlive(f)
 | 
			
		||||
	return bi, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetFileBasicInfo sets times and attributes for a file.
 | 
			
		||||
func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
 | 
			
		||||
	if err := setFileInformationByHandle(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
 | 
			
		||||
		return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
 | 
			
		||||
	}
 | 
			
		||||
	runtime.KeepAlive(f)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FileIDInfo contains the volume serial number and file ID for a file. This pair should be
 | 
			
		||||
// unique on a system.
 | 
			
		||||
type FileIDInfo struct {
 | 
			
		||||
	VolumeSerialNumber uint64
 | 
			
		||||
	FileID             [16]byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetFileID retrieves the unique (volume, file ID) pair for a file.
 | 
			
		||||
func GetFileID(f *os.File) (*FileIDInfo, error) {
 | 
			
		||||
	fileID := &FileIDInfo{}
 | 
			
		||||
	if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileIDInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
 | 
			
		||||
		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
 | 
			
		||||
	}
 | 
			
		||||
	runtime.KeepAlive(f)
 | 
			
		||||
	return fileID, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										421
									
								
								vendor/github.com/Microsoft/go-winio/pipe.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										421
									
								
								vendor/github.com/Microsoft/go-winio/pipe.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,421 @@
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
package winio
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
 | 
			
		||||
//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error)  [failretval==syscall.InvalidHandle] = CreateNamedPipeW
 | 
			
		||||
//sys createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW
 | 
			
		||||
//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
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	cERROR_PIPE_BUSY      = syscall.Errno(231)
 | 
			
		||||
	cERROR_NO_DATA        = syscall.Errno(232)
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
	cPIPE_TYPE_MESSAGE = 4
 | 
			
		||||
 | 
			
		||||
	cPIPE_READMODE_MESSAGE = 2
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed.
 | 
			
		||||
	// This error should match net.errClosing since docker takes a dependency on its text.
 | 
			
		||||
	ErrPipeListenerClosed = errors.New("use of closed network connection")
 | 
			
		||||
 | 
			
		||||
	errPipeWriteClosed = errors.New("pipe has been closed for write")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type win32Pipe struct {
 | 
			
		||||
	*win32File
 | 
			
		||||
	path string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type win32MessageBytePipe struct {
 | 
			
		||||
	win32Pipe
 | 
			
		||||
	writeClosed bool
 | 
			
		||||
	readEOF     bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type pipeAddress string
 | 
			
		||||
 | 
			
		||||
func (f *win32Pipe) LocalAddr() net.Addr {
 | 
			
		||||
	return pipeAddress(f.path)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *win32Pipe) RemoteAddr() net.Addr {
 | 
			
		||||
	return pipeAddress(f.path)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *win32Pipe) SetDeadline(t time.Time) error {
 | 
			
		||||
	f.SetReadDeadline(t)
 | 
			
		||||
	f.SetWriteDeadline(t)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CloseWrite closes the write side of a message pipe in byte mode.
 | 
			
		||||
func (f *win32MessageBytePipe) CloseWrite() error {
 | 
			
		||||
	if f.writeClosed {
 | 
			
		||||
		return errPipeWriteClosed
 | 
			
		||||
	}
 | 
			
		||||
	err := f.win32File.Flush()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	_, err = f.win32File.Write(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	f.writeClosed = true
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write writes bytes to a message pipe in byte mode. Zero-byte writes are ignored, since
 | 
			
		||||
// they are used to implement CloseWrite().
 | 
			
		||||
func (f *win32MessageBytePipe) Write(b []byte) (int, error) {
 | 
			
		||||
	if f.writeClosed {
 | 
			
		||||
		return 0, errPipeWriteClosed
 | 
			
		||||
	}
 | 
			
		||||
	if len(b) == 0 {
 | 
			
		||||
		return 0, nil
 | 
			
		||||
	}
 | 
			
		||||
	return f.win32File.Write(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read reads bytes from a message pipe in byte mode. A read of a zero-byte message on a message
 | 
			
		||||
// mode pipe will return io.EOF, as will all subsequent reads.
 | 
			
		||||
func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
 | 
			
		||||
	if f.readEOF {
 | 
			
		||||
		return 0, io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	n, err := f.win32File.Read(b)
 | 
			
		||||
	if err == io.EOF {
 | 
			
		||||
		// If this was the result of a zero-byte read, then
 | 
			
		||||
		// it is possible that the read was due to a zero-size
 | 
			
		||||
		// message. Since we are simulating CloseWrite with a
 | 
			
		||||
		// zero-byte message, ensure that all future Read() calls
 | 
			
		||||
		// also return EOF.
 | 
			
		||||
		f.readEOF = true
 | 
			
		||||
	} else if err == syscall.ERROR_MORE_DATA {
 | 
			
		||||
		// ERROR_MORE_DATA indicates that the pipe's read mode is message mode
 | 
			
		||||
		// and the message still has more bytes. Treat this as a success, since
 | 
			
		||||
		// this package presents all named pipes as byte streams.
 | 
			
		||||
		err = nil
 | 
			
		||||
	}
 | 
			
		||||
	return n, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s pipeAddress) Network() string {
 | 
			
		||||
	return "pipe"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s pipeAddress) String() string {
 | 
			
		||||
	return string(s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.)
 | 
			
		||||
func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
 | 
			
		||||
	var absTimeout time.Time
 | 
			
		||||
	if timeout != nil {
 | 
			
		||||
		absTimeout = time.Now().Add(*timeout)
 | 
			
		||||
	} else {
 | 
			
		||||
		absTimeout = time.Now().Add(time.Second * 2)
 | 
			
		||||
	}
 | 
			
		||||
	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)
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, &os.PathError{Op: "open", Path: path, Err: err}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var flags uint32
 | 
			
		||||
	err = getNamedPipeInfo(h, &flags, nil, nil, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f, err := makeWin32File(h)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		syscall.Close(h)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If the pipe is in message mode, return a message byte pipe, which
 | 
			
		||||
	// supports CloseWrite().
 | 
			
		||||
	if flags&cPIPE_TYPE_MESSAGE != 0 {
 | 
			
		||||
		return &win32MessageBytePipe{
 | 
			
		||||
			win32Pipe: win32Pipe{win32File: f, path: path},
 | 
			
		||||
		}, nil
 | 
			
		||||
	}
 | 
			
		||||
	return &win32Pipe{win32File: f, path: path}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type acceptResponse struct {
 | 
			
		||||
	f   *win32File
 | 
			
		||||
	err error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type win32PipeListener struct {
 | 
			
		||||
	firstHandle        syscall.Handle
 | 
			
		||||
	path               string
 | 
			
		||||
	securityDescriptor []byte
 | 
			
		||||
	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)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, &os.PathError{Op: "open", Path: path, Err: err}
 | 
			
		||||
	}
 | 
			
		||||
	return h, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *win32PipeListener) makeServerPipe() (*win32File, error) {
 | 
			
		||||
	h, err := makeServerPipeHandle(l.path, l.securityDescriptor, &l.config, false)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	f, err := makeWin32File(h)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		syscall.Close(h)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return f, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) {
 | 
			
		||||
	p, err := l.makeServerPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Wait for the client to connect.
 | 
			
		||||
	ch := make(chan error)
 | 
			
		||||
	go func(p *win32File) {
 | 
			
		||||
		ch <- connectPipe(p)
 | 
			
		||||
	}(p)
 | 
			
		||||
 | 
			
		||||
	select {
 | 
			
		||||
	case err = <-ch:
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			p.Close()
 | 
			
		||||
			p = nil
 | 
			
		||||
		}
 | 
			
		||||
	case <-l.closeCh:
 | 
			
		||||
		// Abort the connect request by closing the handle.
 | 
			
		||||
		p.Close()
 | 
			
		||||
		p = nil
 | 
			
		||||
		err = <-ch
 | 
			
		||||
		if err == nil || err == ErrFileClosed {
 | 
			
		||||
			err = ErrPipeListenerClosed
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return p, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *win32PipeListener) listenerRoutine() {
 | 
			
		||||
	closed := false
 | 
			
		||||
	for !closed {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-l.closeCh:
 | 
			
		||||
			closed = true
 | 
			
		||||
		case responseCh := <-l.acceptCh:
 | 
			
		||||
			var (
 | 
			
		||||
				p   *win32File
 | 
			
		||||
				err error
 | 
			
		||||
			)
 | 
			
		||||
			for {
 | 
			
		||||
				p, err = l.makeConnectedServerPipe()
 | 
			
		||||
				// If the connection was immediately closed by the client, try
 | 
			
		||||
				// again.
 | 
			
		||||
				if err != cERROR_NO_DATA {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			responseCh <- acceptResponse{p, err}
 | 
			
		||||
			closed = err == ErrPipeListenerClosed
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	syscall.Close(l.firstHandle)
 | 
			
		||||
	l.firstHandle = 0
 | 
			
		||||
	// Notify Close() and Accept() callers that the handle has been closed.
 | 
			
		||||
	close(l.doneCh)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PipeConfig contain configuration for the pipe listener.
 | 
			
		||||
type PipeConfig struct {
 | 
			
		||||
	// SecurityDescriptor contains a Windows security descriptor in SDDL format.
 | 
			
		||||
	SecurityDescriptor string
 | 
			
		||||
 | 
			
		||||
	// MessageMode determines whether the pipe is in byte or message mode. In either
 | 
			
		||||
	// case the pipe is read in byte mode by default. The only practical difference in
 | 
			
		||||
	// this implementation is that CloseWrite() is only supported for message mode pipes;
 | 
			
		||||
	// CloseWrite() is implemented as a zero-byte write, but zero-byte writes are only
 | 
			
		||||
	// transferred to the reader (and returned as io.EOF in this implementation)
 | 
			
		||||
	// when the pipe is in message mode.
 | 
			
		||||
	MessageMode bool
 | 
			
		||||
 | 
			
		||||
	// InputBufferSize specifies the size the input buffer, in bytes.
 | 
			
		||||
	InputBufferSize int32
 | 
			
		||||
 | 
			
		||||
	// OutputBufferSize specifies the size the input buffer, in bytes.
 | 
			
		||||
	OutputBufferSize int32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListenPipe creates a listener on a Windows named pipe path, e.g. \\.\pipe\mypipe.
 | 
			
		||||
// The pipe must not already exist.
 | 
			
		||||
func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		sd  []byte
 | 
			
		||||
		err error
 | 
			
		||||
	)
 | 
			
		||||
	if c == nil {
 | 
			
		||||
		c = &PipeConfig{}
 | 
			
		||||
	}
 | 
			
		||||
	if c.SecurityDescriptor != "" {
 | 
			
		||||
		sd, err = SddlToSecurityDescriptor(c.SecurityDescriptor)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	h, err := makeServerPipeHandle(path, sd, c, true)
 | 
			
		||||
	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),
 | 
			
		||||
	}
 | 
			
		||||
	go l.listenerRoutine()
 | 
			
		||||
	return l, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func connectPipe(p *win32File) error {
 | 
			
		||||
	c, err := p.prepareIo()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer p.wg.Done()
 | 
			
		||||
 | 
			
		||||
	err = connectNamedPipe(p.handle, &c.o)
 | 
			
		||||
	_, err = p.asyncIo(c, nil, 0, err)
 | 
			
		||||
	if err != nil && err != cERROR_PIPE_CONNECTED {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *win32PipeListener) Accept() (net.Conn, error) {
 | 
			
		||||
	ch := make(chan acceptResponse)
 | 
			
		||||
	select {
 | 
			
		||||
	case l.acceptCh <- ch:
 | 
			
		||||
		response := <-ch
 | 
			
		||||
		err := response.err
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if l.config.MessageMode {
 | 
			
		||||
			return &win32MessageBytePipe{
 | 
			
		||||
				win32Pipe: win32Pipe{win32File: response.f, path: l.path},
 | 
			
		||||
			}, nil
 | 
			
		||||
		}
 | 
			
		||||
		return &win32Pipe{win32File: response.f, path: l.path}, nil
 | 
			
		||||
	case <-l.doneCh:
 | 
			
		||||
		return nil, ErrPipeListenerClosed
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *win32PipeListener) Close() error {
 | 
			
		||||
	select {
 | 
			
		||||
	case l.closeCh <- 1:
 | 
			
		||||
		<-l.doneCh
 | 
			
		||||
	case <-l.doneCh:
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *win32PipeListener) Addr() net.Addr {
 | 
			
		||||
	return pipeAddress(l.path)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										202
									
								
								vendor/github.com/Microsoft/go-winio/privilege.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								vendor/github.com/Microsoft/go-winio/privilege.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,202 @@
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
package winio
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unicode/utf16"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/sys/windows"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//sys adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges
 | 
			
		||||
//sys impersonateSelf(level uint32) (err error) = advapi32.ImpersonateSelf
 | 
			
		||||
//sys revertToSelf() (err error) = advapi32.RevertToSelf
 | 
			
		||||
//sys openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) = advapi32.OpenThreadToken
 | 
			
		||||
//sys getCurrentThread() (h syscall.Handle) = GetCurrentThread
 | 
			
		||||
//sys lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) = advapi32.LookupPrivilegeValueW
 | 
			
		||||
//sys lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW
 | 
			
		||||
//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	SE_PRIVILEGE_ENABLED = 2
 | 
			
		||||
 | 
			
		||||
	ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300
 | 
			
		||||
 | 
			
		||||
	SeBackupPrivilege  = "SeBackupPrivilege"
 | 
			
		||||
	SeRestorePrivilege = "SeRestorePrivilege"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	securityAnonymous = iota
 | 
			
		||||
	securityIdentification
 | 
			
		||||
	securityImpersonation
 | 
			
		||||
	securityDelegation
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	privNames     = make(map[string]uint64)
 | 
			
		||||
	privNameMutex sync.Mutex
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PrivilegeError represents an error enabling privileges.
 | 
			
		||||
type PrivilegeError struct {
 | 
			
		||||
	privileges []uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *PrivilegeError) Error() string {
 | 
			
		||||
	s := ""
 | 
			
		||||
	if len(e.privileges) > 1 {
 | 
			
		||||
		s = "Could not enable privileges "
 | 
			
		||||
	} else {
 | 
			
		||||
		s = "Could not enable privilege "
 | 
			
		||||
	}
 | 
			
		||||
	for i, p := range e.privileges {
 | 
			
		||||
		if i != 0 {
 | 
			
		||||
			s += ", "
 | 
			
		||||
		}
 | 
			
		||||
		s += `"`
 | 
			
		||||
		s += getPrivilegeName(p)
 | 
			
		||||
		s += `"`
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RunWithPrivilege enables a single privilege for a function call.
 | 
			
		||||
func RunWithPrivilege(name string, fn func() error) error {
 | 
			
		||||
	return RunWithPrivileges([]string{name}, fn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RunWithPrivileges enables privileges for a function call.
 | 
			
		||||
func RunWithPrivileges(names []string, fn func() error) error {
 | 
			
		||||
	privileges, err := mapPrivileges(names)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	runtime.LockOSThread()
 | 
			
		||||
	defer runtime.UnlockOSThread()
 | 
			
		||||
	token, err := newThreadToken()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer releaseThreadToken(token)
 | 
			
		||||
	err = adjustPrivileges(token, privileges, SE_PRIVILEGE_ENABLED)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return fn()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func mapPrivileges(names []string) ([]uint64, error) {
 | 
			
		||||
	var privileges []uint64
 | 
			
		||||
	privNameMutex.Lock()
 | 
			
		||||
	defer privNameMutex.Unlock()
 | 
			
		||||
	for _, name := range names {
 | 
			
		||||
		p, ok := privNames[name]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			err := lookupPrivilegeValue("", name, &p)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			privNames[name] = p
 | 
			
		||||
		}
 | 
			
		||||
		privileges = append(privileges, p)
 | 
			
		||||
	}
 | 
			
		||||
	return privileges, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnableProcessPrivileges enables privileges globally for the process.
 | 
			
		||||
func EnableProcessPrivileges(names []string) error {
 | 
			
		||||
	return enableDisableProcessPrivilege(names, SE_PRIVILEGE_ENABLED)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DisableProcessPrivileges disables privileges globally for the process.
 | 
			
		||||
func DisableProcessPrivileges(names []string) error {
 | 
			
		||||
	return enableDisableProcessPrivilege(names, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func enableDisableProcessPrivilege(names []string, action uint32) error {
 | 
			
		||||
	privileges, err := mapPrivileges(names)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p, _ := windows.GetCurrentProcess()
 | 
			
		||||
	var token windows.Token
 | 
			
		||||
	err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer token.Close()
 | 
			
		||||
	return adjustPrivileges(token, privileges, action)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error {
 | 
			
		||||
	var b bytes.Buffer
 | 
			
		||||
	binary.Write(&b, binary.LittleEndian, uint32(len(privileges)))
 | 
			
		||||
	for _, p := range privileges {
 | 
			
		||||
		binary.Write(&b, binary.LittleEndian, p)
 | 
			
		||||
		binary.Write(&b, binary.LittleEndian, action)
 | 
			
		||||
	}
 | 
			
		||||
	prevState := make([]byte, b.Len())
 | 
			
		||||
	reqSize := uint32(0)
 | 
			
		||||
	success, err := adjustTokenPrivileges(token, false, &b.Bytes()[0], uint32(len(prevState)), &prevState[0], &reqSize)
 | 
			
		||||
	if !success {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err == ERROR_NOT_ALL_ASSIGNED {
 | 
			
		||||
		return &PrivilegeError{privileges}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getPrivilegeName(luid uint64) string {
 | 
			
		||||
	var nameBuffer [256]uint16
 | 
			
		||||
	bufSize := uint32(len(nameBuffer))
 | 
			
		||||
	err := lookupPrivilegeName("", &luid, &nameBuffer[0], &bufSize)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Sprintf("<unknown privilege %d>", luid)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var displayNameBuffer [256]uint16
 | 
			
		||||
	displayBufSize := uint32(len(displayNameBuffer))
 | 
			
		||||
	var langID uint32
 | 
			
		||||
	err = lookupPrivilegeDisplayName("", &nameBuffer[0], &displayNameBuffer[0], &displayBufSize, &langID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Sprintf("<unknown privilege %s>", string(utf16.Decode(nameBuffer[:bufSize])))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return string(utf16.Decode(displayNameBuffer[:displayBufSize]))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newThreadToken() (windows.Token, error) {
 | 
			
		||||
	err := impersonateSelf(securityImpersonation)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var token windows.Token
 | 
			
		||||
	err = openThreadToken(getCurrentThread(), syscall.TOKEN_ADJUST_PRIVILEGES|syscall.TOKEN_QUERY, false, &token)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		rerr := revertToSelf()
 | 
			
		||||
		if rerr != nil {
 | 
			
		||||
			panic(rerr)
 | 
			
		||||
		}
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return token, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func releaseThreadToken(h windows.Token) {
 | 
			
		||||
	err := revertToSelf()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	h.Close()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										128
									
								
								vendor/github.com/Microsoft/go-winio/reparse.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								vendor/github.com/Microsoft/go-winio/reparse.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
			
		||||
package winio
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"unicode/utf16"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	reparseTagMountPoint = 0xA0000003
 | 
			
		||||
	reparseTagSymlink    = 0xA000000C
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type reparseDataBuffer struct {
 | 
			
		||||
	ReparseTag           uint32
 | 
			
		||||
	ReparseDataLength    uint16
 | 
			
		||||
	Reserved             uint16
 | 
			
		||||
	SubstituteNameOffset uint16
 | 
			
		||||
	SubstituteNameLength uint16
 | 
			
		||||
	PrintNameOffset      uint16
 | 
			
		||||
	PrintNameLength      uint16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReparsePoint describes a Win32 symlink or mount point.
 | 
			
		||||
type ReparsePoint struct {
 | 
			
		||||
	Target       string
 | 
			
		||||
	IsMountPoint bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnsupportedReparsePointError is returned when trying to decode a non-symlink or
 | 
			
		||||
// mount point reparse point.
 | 
			
		||||
type UnsupportedReparsePointError struct {
 | 
			
		||||
	Tag uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *UnsupportedReparsePointError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("unsupported reparse point %x", e.Tag)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeReparsePoint decodes a Win32 REPARSE_DATA_BUFFER structure containing either a symlink
 | 
			
		||||
// or a mount point.
 | 
			
		||||
func DecodeReparsePoint(b []byte) (*ReparsePoint, error) {
 | 
			
		||||
	tag := binary.LittleEndian.Uint32(b[0:4])
 | 
			
		||||
	return DecodeReparsePointData(tag, b[8:])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) {
 | 
			
		||||
	isMountPoint := false
 | 
			
		||||
	switch tag {
 | 
			
		||||
	case reparseTagMountPoint:
 | 
			
		||||
		isMountPoint = true
 | 
			
		||||
	case reparseTagSymlink:
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, &UnsupportedReparsePointError{tag}
 | 
			
		||||
	}
 | 
			
		||||
	nameOffset := 8 + binary.LittleEndian.Uint16(b[4:6])
 | 
			
		||||
	if !isMountPoint {
 | 
			
		||||
		nameOffset += 4
 | 
			
		||||
	}
 | 
			
		||||
	nameLength := binary.LittleEndian.Uint16(b[6:8])
 | 
			
		||||
	name := make([]uint16, nameLength/2)
 | 
			
		||||
	err := binary.Read(bytes.NewReader(b[nameOffset:nameOffset+nameLength]), binary.LittleEndian, &name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &ReparsePoint{string(utf16.Decode(name)), isMountPoint}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isDriveLetter(c byte) bool {
 | 
			
		||||
	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeReparsePoint encodes a Win32 REPARSE_DATA_BUFFER structure describing a symlink or
 | 
			
		||||
// mount point.
 | 
			
		||||
func EncodeReparsePoint(rp *ReparsePoint) []byte {
 | 
			
		||||
	// Generate an NT path and determine if this is a relative path.
 | 
			
		||||
	var ntTarget string
 | 
			
		||||
	relative := false
 | 
			
		||||
	if strings.HasPrefix(rp.Target, `\\?\`) {
 | 
			
		||||
		ntTarget = `\??\` + rp.Target[4:]
 | 
			
		||||
	} else if strings.HasPrefix(rp.Target, `\\`) {
 | 
			
		||||
		ntTarget = `\??\UNC\` + rp.Target[2:]
 | 
			
		||||
	} else if len(rp.Target) >= 2 && isDriveLetter(rp.Target[0]) && rp.Target[1] == ':' {
 | 
			
		||||
		ntTarget = `\??\` + rp.Target
 | 
			
		||||
	} else {
 | 
			
		||||
		ntTarget = rp.Target
 | 
			
		||||
		relative = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The paths must be NUL-terminated even though they are counted strings.
 | 
			
		||||
	target16 := utf16.Encode([]rune(rp.Target + "\x00"))
 | 
			
		||||
	ntTarget16 := utf16.Encode([]rune(ntTarget + "\x00"))
 | 
			
		||||
 | 
			
		||||
	size := int(unsafe.Sizeof(reparseDataBuffer{})) - 8
 | 
			
		||||
	size += len(ntTarget16)*2 + len(target16)*2
 | 
			
		||||
 | 
			
		||||
	tag := uint32(reparseTagMountPoint)
 | 
			
		||||
	if !rp.IsMountPoint {
 | 
			
		||||
		tag = reparseTagSymlink
 | 
			
		||||
		size += 4 // Add room for symlink flags
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data := reparseDataBuffer{
 | 
			
		||||
		ReparseTag:           tag,
 | 
			
		||||
		ReparseDataLength:    uint16(size),
 | 
			
		||||
		SubstituteNameOffset: 0,
 | 
			
		||||
		SubstituteNameLength: uint16((len(ntTarget16) - 1) * 2),
 | 
			
		||||
		PrintNameOffset:      uint16(len(ntTarget16) * 2),
 | 
			
		||||
		PrintNameLength:      uint16((len(target16) - 1) * 2),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var b bytes.Buffer
 | 
			
		||||
	binary.Write(&b, binary.LittleEndian, &data)
 | 
			
		||||
	if !rp.IsMountPoint {
 | 
			
		||||
		flags := uint32(0)
 | 
			
		||||
		if relative {
 | 
			
		||||
			flags |= 1
 | 
			
		||||
		}
 | 
			
		||||
		binary.Write(&b, binary.LittleEndian, flags)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	binary.Write(&b, binary.LittleEndian, ntTarget16)
 | 
			
		||||
	binary.Write(&b, binary.LittleEndian, target16)
 | 
			
		||||
	return b.Bytes()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										98
									
								
								vendor/github.com/Microsoft/go-winio/sd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								vendor/github.com/Microsoft/go-winio/sd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
package winio
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW
 | 
			
		||||
//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW
 | 
			
		||||
//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
 | 
			
		||||
//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
 | 
			
		||||
//sys localFree(mem uintptr) = LocalFree
 | 
			
		||||
//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	cERROR_NONE_MAPPED = syscall.Errno(1332)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type AccountLookupError struct {
 | 
			
		||||
	Name string
 | 
			
		||||
	Err  error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *AccountLookupError) Error() string {
 | 
			
		||||
	if e.Name == "" {
 | 
			
		||||
		return "lookup account: empty account name specified"
 | 
			
		||||
	}
 | 
			
		||||
	var s string
 | 
			
		||||
	switch e.Err {
 | 
			
		||||
	case cERROR_NONE_MAPPED:
 | 
			
		||||
		s = "not found"
 | 
			
		||||
	default:
 | 
			
		||||
		s = e.Err.Error()
 | 
			
		||||
	}
 | 
			
		||||
	return "lookup account " + e.Name + ": " + s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SddlConversionError struct {
 | 
			
		||||
	Sddl string
 | 
			
		||||
	Err  error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *SddlConversionError) Error() string {
 | 
			
		||||
	return "convert " + e.Sddl + ": " + e.Err.Error()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LookupSidByName looks up the SID of an account by name
 | 
			
		||||
func LookupSidByName(name string) (sid string, err error) {
 | 
			
		||||
	if name == "" {
 | 
			
		||||
		return "", &AccountLookupError{name, cERROR_NONE_MAPPED}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var sidSize, sidNameUse, refDomainSize uint32
 | 
			
		||||
	err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse)
 | 
			
		||||
	if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER {
 | 
			
		||||
		return "", &AccountLookupError{name, err}
 | 
			
		||||
	}
 | 
			
		||||
	sidBuffer := make([]byte, sidSize)
 | 
			
		||||
	refDomainBuffer := make([]uint16, refDomainSize)
 | 
			
		||||
	err = lookupAccountName(nil, name, &sidBuffer[0], &sidSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", &AccountLookupError{name, err}
 | 
			
		||||
	}
 | 
			
		||||
	var strBuffer *uint16
 | 
			
		||||
	err = convertSidToStringSid(&sidBuffer[0], &strBuffer)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", &AccountLookupError{name, err}
 | 
			
		||||
	}
 | 
			
		||||
	sid = syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:])
 | 
			
		||||
	localFree(uintptr(unsafe.Pointer(strBuffer)))
 | 
			
		||||
	return sid, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
 | 
			
		||||
	var sdBuffer uintptr
 | 
			
		||||
	err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, &SddlConversionError{sddl, err}
 | 
			
		||||
	}
 | 
			
		||||
	defer localFree(sdBuffer)
 | 
			
		||||
	sd := make([]byte, getSecurityDescriptorLength(sdBuffer))
 | 
			
		||||
	copy(sd, (*[0xffff]byte)(unsafe.Pointer(sdBuffer))[:len(sd)])
 | 
			
		||||
	return sd, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SecurityDescriptorToSddl(sd []byte) (string, error) {
 | 
			
		||||
	var sddl *uint16
 | 
			
		||||
	// The returned string length seems to including an aribtrary number of terminating NULs.
 | 
			
		||||
	// Don't use it.
 | 
			
		||||
	err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	defer localFree(uintptr(unsafe.Pointer(sddl)))
 | 
			
		||||
	return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(sddl))[:]), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/github.com/Microsoft/go-winio/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/Microsoft/go-winio/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +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
 | 
			
		||||
							
								
								
									
										520
									
								
								vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										520
									
								
								vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,520 @@
 | 
			
		||||
// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
 | 
			
		||||
 | 
			
		||||
package winio
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/sys/windows"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var _ unsafe.Pointer
 | 
			
		||||
 | 
			
		||||
// Do the interface allocations only once for common
 | 
			
		||||
// Errno values.
 | 
			
		||||
const (
 | 
			
		||||
	errnoERROR_IO_PENDING = 997
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// errnoErr returns common boxed Errno values, to prevent
 | 
			
		||||
// allocations at runtime.
 | 
			
		||||
func errnoErr(e syscall.Errno) error {
 | 
			
		||||
	switch e {
 | 
			
		||||
	case 0:
 | 
			
		||||
		return nil
 | 
			
		||||
	case errnoERROR_IO_PENDING:
 | 
			
		||||
		return errERROR_IO_PENDING
 | 
			
		||||
	}
 | 
			
		||||
	// TODO: add more here, after collecting data on the common
 | 
			
		||||
	// error values see on Windows. (perhaps when running
 | 
			
		||||
	// all.bat?)
 | 
			
		||||
	return e
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
 | 
			
		||||
	modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
 | 
			
		||||
 | 
			
		||||
	procCancelIoEx                                           = modkernel32.NewProc("CancelIoEx")
 | 
			
		||||
	procCreateIoCompletionPort                               = modkernel32.NewProc("CreateIoCompletionPort")
 | 
			
		||||
	procGetQueuedCompletionStatus                            = modkernel32.NewProc("GetQueuedCompletionStatus")
 | 
			
		||||
	procSetFileCompletionNotificationModes                   = modkernel32.NewProc("SetFileCompletionNotificationModes")
 | 
			
		||||
	procConnectNamedPipe                                     = modkernel32.NewProc("ConnectNamedPipe")
 | 
			
		||||
	procCreateNamedPipeW                                     = modkernel32.NewProc("CreateNamedPipeW")
 | 
			
		||||
	procCreateFileW                                          = modkernel32.NewProc("CreateFileW")
 | 
			
		||||
	procWaitNamedPipeW                                       = modkernel32.NewProc("WaitNamedPipeW")
 | 
			
		||||
	procGetNamedPipeInfo                                     = modkernel32.NewProc("GetNamedPipeInfo")
 | 
			
		||||
	procGetNamedPipeHandleStateW                             = modkernel32.NewProc("GetNamedPipeHandleStateW")
 | 
			
		||||
	procLocalAlloc                                           = modkernel32.NewProc("LocalAlloc")
 | 
			
		||||
	procLookupAccountNameW                                   = modadvapi32.NewProc("LookupAccountNameW")
 | 
			
		||||
	procConvertSidToStringSidW                               = modadvapi32.NewProc("ConvertSidToStringSidW")
 | 
			
		||||
	procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
 | 
			
		||||
	procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW")
 | 
			
		||||
	procLocalFree                                            = modkernel32.NewProc("LocalFree")
 | 
			
		||||
	procGetSecurityDescriptorLength                          = modadvapi32.NewProc("GetSecurityDescriptorLength")
 | 
			
		||||
	procGetFileInformationByHandleEx                         = modkernel32.NewProc("GetFileInformationByHandleEx")
 | 
			
		||||
	procSetFileInformationByHandle                           = modkernel32.NewProc("SetFileInformationByHandle")
 | 
			
		||||
	procAdjustTokenPrivileges                                = modadvapi32.NewProc("AdjustTokenPrivileges")
 | 
			
		||||
	procImpersonateSelf                                      = modadvapi32.NewProc("ImpersonateSelf")
 | 
			
		||||
	procRevertToSelf                                         = modadvapi32.NewProc("RevertToSelf")
 | 
			
		||||
	procOpenThreadToken                                      = modadvapi32.NewProc("OpenThreadToken")
 | 
			
		||||
	procGetCurrentThread                                     = modkernel32.NewProc("GetCurrentThread")
 | 
			
		||||
	procLookupPrivilegeValueW                                = modadvapi32.NewProc("LookupPrivilegeValueW")
 | 
			
		||||
	procLookupPrivilegeNameW                                 = modadvapi32.NewProc("LookupPrivilegeNameW")
 | 
			
		||||
	procLookupPrivilegeDisplayNameW                          = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
 | 
			
		||||
	procBackupRead                                           = modkernel32.NewProc("BackupRead")
 | 
			
		||||
	procBackupWrite                                          = modkernel32.NewProc("BackupWrite")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) {
 | 
			
		||||
	r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0)
 | 
			
		||||
	newport = syscall.Handle(r0)
 | 
			
		||||
	if newport == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = 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 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
 | 
			
		||||
	var _p0 *uint16
 | 
			
		||||
	_p0, err = syscall.UTF16PtrFromString(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
 | 
			
		||||
	r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0)
 | 
			
		||||
	handle = syscall.Handle(r0)
 | 
			
		||||
	if handle == syscall.InvalidHandle {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
 | 
			
		||||
	var _p0 *uint16
 | 
			
		||||
	_p0, err = syscall.UTF16PtrFromString(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
 | 
			
		||||
	r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
 | 
			
		||||
	handle = syscall.Handle(r0)
 | 
			
		||||
	if handle == syscall.InvalidHandle {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func waitNamedPipe(name string, timeout uint32) (err error) {
 | 
			
		||||
	var _p0 *uint16
 | 
			
		||||
	_p0, err = syscall.UTF16PtrFromString(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return _waitNamedPipe(_p0, timeout)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func _waitNamedPipe(name *uint16, timeout uint32) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall(procWaitNamedPipeW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(timeout), 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = 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 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func localAlloc(uFlags uint32, length uint32) (ptr uintptr) {
 | 
			
		||||
	r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0)
 | 
			
		||||
	ptr = uintptr(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)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func convertSidToStringSid(sid *byte, str **uint16) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) {
 | 
			
		||||
	var _p0 *uint16
 | 
			
		||||
	_p0, err = syscall.UTF16PtrFromString(str)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func localFree(mem uintptr) {
 | 
			
		||||
	syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getSecurityDescriptorLength(sd uintptr) (len uint32) {
 | 
			
		||||
	r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0)
 | 
			
		||||
	len = uint32(r0)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
 | 
			
		||||
	var _p0 uint32
 | 
			
		||||
	if releaseAll {
 | 
			
		||||
		_p0 = 1
 | 
			
		||||
	} else {
 | 
			
		||||
		_p0 = 0
 | 
			
		||||
	}
 | 
			
		||||
	r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize)))
 | 
			
		||||
	success = r0 != 0
 | 
			
		||||
	if true {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func impersonateSelf(level uint32) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func revertToSelf() (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) {
 | 
			
		||||
	var _p0 uint32
 | 
			
		||||
	if openAsSelf {
 | 
			
		||||
		_p0 = 1
 | 
			
		||||
	} else {
 | 
			
		||||
		_p0 = 0
 | 
			
		||||
	}
 | 
			
		||||
	r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getCurrentThread() (h syscall.Handle) {
 | 
			
		||||
	r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0)
 | 
			
		||||
	h = syscall.Handle(r0)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) {
 | 
			
		||||
	var _p0 *uint16
 | 
			
		||||
	_p0, err = syscall.UTF16PtrFromString(systemName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var _p1 *uint16
 | 
			
		||||
	_p1, err = syscall.UTF16PtrFromString(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return _lookupPrivilegeValue(_p0, _p1, luid)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) {
 | 
			
		||||
	var _p0 *uint16
 | 
			
		||||
	_p0, err = syscall.UTF16PtrFromString(systemName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return _lookupPrivilegeName(_p0, luid, buffer, size)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
 | 
			
		||||
	var _p0 *uint16
 | 
			
		||||
	_p0, err = syscall.UTF16PtrFromString(systemName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
 | 
			
		||||
	r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
 | 
			
		||||
	var _p0 *byte
 | 
			
		||||
	if len(b) > 0 {
 | 
			
		||||
		_p0 = &b[0]
 | 
			
		||||
	}
 | 
			
		||||
	var _p1 uint32
 | 
			
		||||
	if abort {
 | 
			
		||||
		_p1 = 1
 | 
			
		||||
	} else {
 | 
			
		||||
		_p1 = 0
 | 
			
		||||
	}
 | 
			
		||||
	var _p2 uint32
 | 
			
		||||
	if processSecurity {
 | 
			
		||||
		_p2 = 1
 | 
			
		||||
	} else {
 | 
			
		||||
		_p2 = 0
 | 
			
		||||
	}
 | 
			
		||||
	r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
 | 
			
		||||
	var _p0 *byte
 | 
			
		||||
	if len(b) > 0 {
 | 
			
		||||
		_p0 = &b[0]
 | 
			
		||||
	}
 | 
			
		||||
	var _p1 uint32
 | 
			
		||||
	if abort {
 | 
			
		||||
		_p1 = 1
 | 
			
		||||
	} else {
 | 
			
		||||
		_p1 = 0
 | 
			
		||||
	}
 | 
			
		||||
	var _p2 uint32
 | 
			
		||||
	if processSecurity {
 | 
			
		||||
		_p2 = 1
 | 
			
		||||
	} else {
 | 
			
		||||
		_p2 = 0
 | 
			
		||||
	}
 | 
			
		||||
	r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
 | 
			
		||||
	if r1 == 0 {
 | 
			
		||||
		if e1 != 0 {
 | 
			
		||||
			err = errnoErr(e1)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user