Support detecting mountpoints correctly (#7288)

Currently windows support was relying on Symlink as
a way to detect a drive, this doesn't work in latest
Windows 2016, fix this to use a proper mechanism by
using win32 APIs.

Additionally also add support for detecting bind mounts
on Linux.
master
Harshavardhana 6 years ago committed by kannappanr
parent 5085bef397
commit 5e69a107d8
  1. 24
      pkg/mountinfo/mountinfo_linux.go
  2. 35
      pkg/mountinfo/mountinfo_windows.go
  3. 13
      vendor/golang.org/x/sys/windows/aliases.go
  4. 13
      vendor/golang.org/x/sys/windows/asm_windows_386.s
  5. 13
      vendor/golang.org/x/sys/windows/asm_windows_amd64.s
  6. 11
      vendor/golang.org/x/sys/windows/asm_windows_arm.s
  7. 378
      vendor/golang.org/x/sys/windows/dll_windows.go
  8. 29
      vendor/golang.org/x/sys/windows/env_windows.go
  9. 20
      vendor/golang.org/x/sys/windows/eventlog.go
  10. 97
      vendor/golang.org/x/sys/windows/exec_windows.go
  11. 26
      vendor/golang.org/x/sys/windows/memory_windows.go
  12. 7
      vendor/golang.org/x/sys/windows/mksyscall.go
  13. 30
      vendor/golang.org/x/sys/windows/race.go
  14. 25
      vendor/golang.org/x/sys/windows/race0.go
  15. 478
      vendor/golang.org/x/sys/windows/security_windows.go
  16. 183
      vendor/golang.org/x/sys/windows/service.go
  17. 22
      vendor/golang.org/x/sys/windows/str.go
  18. 74
      vendor/golang.org/x/sys/windows/syscall.go
  19. 1218
      vendor/golang.org/x/sys/windows/syscall_windows.go
  20. 1469
      vendor/golang.org/x/sys/windows/types_windows.go
  21. 22
      vendor/golang.org/x/sys/windows/types_windows_386.go
  22. 22
      vendor/golang.org/x/sys/windows/types_windows_amd64.go
  23. 22
      vendor/golang.org/x/sys/windows/types_windows_arm.go
  24. 2720
      vendor/golang.org/x/sys/windows/zsyscall_windows.go
  25. 6
      vendor/vendor.json

@ -37,24 +37,30 @@ const (
)
// IsLikelyMountPoint determines if a directory is a mountpoint.
// It is fast but not necessarily ALWAYS correct. If the path is in fact
// a bind mount from one part of a mount to another it will not be detected.
// mkdir /tmp/a /tmp/b; mount --bin /tmp/a /tmp/b; IsLikelyMountPoint("/tmp/b")
// will return false. When in fact /tmp/b is a mount point. If this situation
// if of interest to you, don't use this function...
func IsLikelyMountPoint(file string) bool {
stat, err := os.Stat(file)
func IsLikelyMountPoint(path string) bool {
s1, err := os.Lstat(path)
if err != nil {
return false
}
rootStat, err := os.Lstat(filepath.Dir(strings.TrimSuffix(file, "/")))
// A symlink can never be a mount point
if s1.Mode()&os.ModeSymlink != 0 {
return false
}
s2, err := os.Lstat(filepath.Dir(strings.TrimSuffix(path, "/")))
if err != nil {
return false
}
// If the directory has a different device as parent, then it is a mountpoint.
return stat.Sys().(*syscall.Stat_t).Dev != rootStat.Sys().(*syscall.Stat_t).Dev
if s1.Sys().(*syscall.Stat_t).Dev != s2.Sys().(*syscall.Stat_t).Dev {
// path/.. on a different device as path
return true
}
// path/.. is the same i-node as path - this check is for bind mounts.
return s1.Sys().(*syscall.Stat_t).Ino == s2.Sys().(*syscall.Stat_t).Ino
}
// CheckCrossDevice - check if any list of paths has any sub-mounts at /proc/mounts.

@ -19,7 +19,7 @@
package mountinfo
import (
"os"
"golang.org/x/sys/windows"
)
// CheckCrossDevice - check if any input path has multiple sub-mounts.
@ -28,32 +28,21 @@ func CheckCrossDevice(paths []string) error {
return nil
}
// fileExists checks if specified file exists.
func fileExists(filename string) (bool, error) {
if _, err := os.Stat(filename); os.IsNotExist(err) {
return false, nil
} else if err != nil {
return false, err
}
return true, nil
}
// IsLikelyMountPoint determines if a directory is a mountpoint.
func IsLikelyMountPoint(file string) bool {
stat, err := os.Lstat(file)
if err != nil {
func IsLikelyMountPoint(path string) bool {
wpath, _ := windows.UTF16PtrFromString(path)
wvolume := make([]uint16, len(path)+1)
if err := windows.GetVolumePathName(wpath, &wvolume[0], uint32(len(wvolume))); err != nil {
return false
}
// If current file is a symlink, then it is a mountpoint.
if stat.Mode()&os.ModeSymlink != 0 {
target, err := os.Readlink(file)
if err != nil {
return false
}
exists, _ := fileExists(target)
return exists
switch windows.GetDriveType(&wvolume[0]) {
case windows.DRIVE_FIXED, windows.DRIVE_REMOVABLE, windows.DRIVE_REMOTE, windows.DRIVE_RAMDISK:
// Recognize "fixed", "removable", "remote" and "ramdisk" drives as proper drives
// which can be treated as an actual mount-point, rest can be ignored.
// https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getdrivetypew
return true
}
return false
}

@ -0,0 +1,13 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
// +build go1.9
package windows
import "syscall"
type Errno = syscall.Errno
type SysProcAttr = syscall.SysProcAttr

@ -0,0 +1,13 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// System calls for 386, Windows are implemented in runtime/syscall_windows.goc
//
TEXT ·getprocaddress(SB), 7, $0-16
JMP syscall·getprocaddress(SB)
TEXT ·loadlibrary(SB), 7, $0-12
JMP syscall·loadlibrary(SB)

@ -0,0 +1,13 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// System calls for amd64, Windows are implemented in runtime/syscall_windows.goc
//
TEXT ·getprocaddress(SB), 7, $0-32
JMP syscall·getprocaddress(SB)
TEXT ·loadlibrary(SB), 7, $0-24
JMP syscall·loadlibrary(SB)

@ -0,0 +1,11 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "textflag.h"
TEXT ·getprocaddress(SB),NOSPLIT,$0
B syscall·getprocaddress(SB)
TEXT ·loadlibrary(SB),NOSPLIT,$0
B syscall·loadlibrary(SB)

@ -0,0 +1,378 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package windows
import (
"sync"
"sync/atomic"
"syscall"
"unsafe"
)
// DLLError describes reasons for DLL load failures.
type DLLError struct {
Err error
ObjName string
Msg string
}
func (e *DLLError) Error() string { return e.Msg }
// Implemented in runtime/syscall_windows.goc; we provide jumps to them in our assembly file.
func loadlibrary(filename *uint16) (handle uintptr, err syscall.Errno)
func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err syscall.Errno)
// A DLL implements access to a single DLL.
type DLL struct {
Name string
Handle Handle
}
// LoadDLL loads DLL file into memory.
//
// Warning: using LoadDLL without an absolute path name is subject to
// DLL preloading attacks. To safely load a system DLL, use LazyDLL
// with System set to true, or use LoadLibraryEx directly.
func LoadDLL(name string) (dll *DLL, err error) {
namep, err := UTF16PtrFromString(name)
if err != nil {
return nil, err
}
h, e := loadlibrary(namep)
if e != 0 {
return nil, &DLLError{
Err: e,
ObjName: name,
Msg: "Failed to load " + name + ": " + e.Error(),
}
}
d := &DLL{
Name: name,
Handle: Handle(h),
}
return d, nil
}
// MustLoadDLL is like LoadDLL but panics if load operation failes.
func MustLoadDLL(name string) *DLL {
d, e := LoadDLL(name)
if e != nil {
panic(e)
}
return d
}
// FindProc searches DLL d for procedure named name and returns *Proc
// if found. It returns an error if search fails.
func (d *DLL) FindProc(name string) (proc *Proc, err error) {
namep, err := BytePtrFromString(name)
if err != nil {
return nil, err
}
a, e := getprocaddress(uintptr(d.Handle), namep)
if e != 0 {
return nil, &DLLError{
Err: e,
ObjName: name,
Msg: "Failed to find " + name + " procedure in " + d.Name + ": " + e.Error(),
}
}
p := &Proc{
Dll: d,
Name: name,
addr: a,
}
return p, nil
}
// MustFindProc is like FindProc but panics if search fails.
func (d *DLL) MustFindProc(name string) *Proc {
p, e := d.FindProc(name)
if e != nil {
panic(e)
}
return p
}
// Release unloads DLL d from memory.
func (d *DLL) Release() (err error) {
return FreeLibrary(d.Handle)
}
// A Proc implements access to a procedure inside a DLL.
type Proc struct {
Dll *DLL
Name string
addr uintptr
}
// Addr returns the address of the procedure represented by p.
// The return value can be passed to Syscall to run the procedure.
func (p *Proc) Addr() uintptr {
return p.addr
}
//go:uintptrescapes
// Call executes procedure p with arguments a. It will panic, if more than 15 arguments
// are supplied.
//
// The returned error is always non-nil, constructed from the result of GetLastError.
// Callers must inspect the primary return value to decide whether an error occurred
// (according to the semantics of the specific function being called) before consulting
// the error. The error will be guaranteed to contain windows.Errno.
func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
switch len(a) {
case 0:
return syscall.Syscall(p.Addr(), uintptr(len(a)), 0, 0, 0)
case 1:
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], 0, 0)
case 2:
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], 0)
case 3:
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], a[2])
case 4:
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], 0, 0)
case 5:
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], 0)
case 6:
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5])
case 7:
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0)
case 8:
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0)
case 9:
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8])
case 10:
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0)
case 11:
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0)
case 12:
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11])
case 13:
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0)
case 14:
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0)
case 15:
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14])
default:
panic("Call " + p.Name + " with too many arguments " + itoa(len(a)) + ".")
}
}
// A LazyDLL implements access to a single DLL.
// It will delay the load of the DLL until the first
// call to its Handle method or to one of its
// LazyProc's Addr method.
type LazyDLL struct {
Name string
// System determines whether the DLL must be loaded from the
// Windows System directory, bypassing the normal DLL search
// path.
System bool
mu sync.Mutex
dll *DLL // non nil once DLL is loaded
}
// Load loads DLL file d.Name into memory. It returns an error if fails.
// Load will not try to load DLL, if it is already loaded into memory.
func (d *LazyDLL) Load() error {
// Non-racy version of:
// if d.dll != nil {
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll))) != nil {
return nil
}
d.mu.Lock()
defer d.mu.Unlock()
if d.dll != nil {
return nil
}
// kernel32.dll is special, since it's where LoadLibraryEx comes from.
// The kernel already special-cases its name, so it's always
// loaded from system32.
var dll *DLL
var err error
if d.Name == "kernel32.dll" {
dll, err = LoadDLL(d.Name)
} else {
dll, err = loadLibraryEx(d.Name, d.System)
}
if err != nil {
return err
}
// Non-racy version of:
// d.dll = dll
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll)), unsafe.Pointer(dll))
return nil
}
// mustLoad is like Load but panics if search fails.
func (d *LazyDLL) mustLoad() {
e := d.Load()
if e != nil {
panic(e)
}
}
// Handle returns d's module handle.
func (d *LazyDLL) Handle() uintptr {
d.mustLoad()
return uintptr(d.dll.Handle)
}
// NewProc returns a LazyProc for accessing the named procedure in the DLL d.
func (d *LazyDLL) NewProc(name string) *LazyProc {
return &LazyProc{l: d, Name: name}
}
// NewLazyDLL creates new LazyDLL associated with DLL file.
func NewLazyDLL(name string) *LazyDLL {
return &LazyDLL{Name: name}
}
// NewLazySystemDLL is like NewLazyDLL, but will only
// search Windows System directory for the DLL if name is
// a base name (like "advapi32.dll").
func NewLazySystemDLL(name string) *LazyDLL {
return &LazyDLL{Name: name, System: true}
}
// A LazyProc implements access to a procedure inside a LazyDLL.
// It delays the lookup until the Addr method is called.
type LazyProc struct {
Name string
mu sync.Mutex
l *LazyDLL
proc *Proc
}
// Find searches DLL for procedure named p.Name. It returns
// an error if search fails. Find will not search procedure,
// if it is already found and loaded into memory.
func (p *LazyProc) Find() error {
// Non-racy version of:
// if p.proc == nil {
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc))) == nil {
p.mu.Lock()
defer p.mu.Unlock()
if p.proc == nil {
e := p.l.Load()
if e != nil {
return e
}
proc, e := p.l.dll.FindProc(p.Name)
if e != nil {
return e
}
// Non-racy version of:
// p.proc = proc
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc)), unsafe.Pointer(proc))
}
}
return nil
}
// mustFind is like Find but panics if search fails.
func (p *LazyProc) mustFind() {
e := p.Find()
if e != nil {
panic(e)
}
}
// Addr returns the address of the procedure represented by p.
// The return value can be passed to Syscall to run the procedure.
// It will panic if the procedure cannot be found.
func (p *LazyProc) Addr() uintptr {
p.mustFind()
return p.proc.Addr()
}
//go:uintptrescapes
// Call executes procedure p with arguments a. It will panic, if more than 15 arguments
// are supplied. It will also panic if the procedure cannot be found.
//
// The returned error is always non-nil, constructed from the result of GetLastError.
// Callers must inspect the primary return value to decide whether an error occurred
// (according to the semantics of the specific function being called) before consulting
// the error. The error will be guaranteed to contain windows.Errno.
func (p *LazyProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
p.mustFind()
return p.proc.Call(a...)
}
var canDoSearchSystem32Once struct {
sync.Once
v bool
}
func initCanDoSearchSystem32() {
// https://msdn.microsoft.com/en-us/library/ms684179(v=vs.85).aspx says:
// "Windows 7, Windows Server 2008 R2, Windows Vista, and Windows
// Server 2008: The LOAD_LIBRARY_SEARCH_* flags are available on
// systems that have KB2533623 installed. To determine whether the
// flags are available, use GetProcAddress to get the address of the
// AddDllDirectory, RemoveDllDirectory, or SetDefaultDllDirectories
// function. If GetProcAddress succeeds, the LOAD_LIBRARY_SEARCH_*
// flags can be used with LoadLibraryEx."
canDoSearchSystem32Once.v = (modkernel32.NewProc("AddDllDirectory").Find() == nil)
}
func canDoSearchSystem32() bool {
canDoSearchSystem32Once.Do(initCanDoSearchSystem32)
return canDoSearchSystem32Once.v
}
func isBaseName(name string) bool {
for _, c := range name {
if c == ':' || c == '/' || c == '\\' {
return false
}
}
return true
}
// loadLibraryEx wraps the Windows LoadLibraryEx function.
//
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx
//
// If name is not an absolute path, LoadLibraryEx searches for the DLL
// in a variety of automatic locations unless constrained by flags.
// See: https://msdn.microsoft.com/en-us/library/ff919712%28VS.85%29.aspx
func loadLibraryEx(name string, system bool) (*DLL, error) {
loadDLL := name
var flags uintptr
if system {
if canDoSearchSystem32() {
const LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
flags = LOAD_LIBRARY_SEARCH_SYSTEM32
} else if isBaseName(name) {
// WindowsXP or unpatched Windows machine
// trying to load "foo.dll" out of the system
// folder, but LoadLibraryEx doesn't support
// that yet on their system, so emulate it.
windir, _ := Getenv("WINDIR") // old var; apparently works on XP
if windir == "" {
return nil, errString("%WINDIR% not defined")
}
loadDLL = windir + "\\System32\\" + name
}
}
h, err := LoadLibraryEx(loadDLL, 0, flags)
if err != nil {
return nil, err
}
return &DLL{Name: name, Handle: h}, nil
}
type errString string
func (s errString) Error() string { return string(s) }

@ -0,0 +1,29 @@
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Windows environment variables.
package windows
import "syscall"
func Getenv(key string) (value string, found bool) {
return syscall.Getenv(key)
}
func Setenv(key, value string) error {
return syscall.Setenv(key, value)
}
func Clearenv() {
syscall.Clearenv()
}
func Environ() []string {
return syscall.Environ()
}
func Unsetenv(key string) error {
return syscall.Unsetenv(key)
}

@ -0,0 +1,20 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package windows
const (
EVENTLOG_SUCCESS = 0
EVENTLOG_ERROR_TYPE = 1
EVENTLOG_WARNING_TYPE = 2
EVENTLOG_INFORMATION_TYPE = 4
EVENTLOG_AUDIT_SUCCESS = 8
EVENTLOG_AUDIT_FAILURE = 16
)
//sys RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Handle, err error) [failretval==0] = advapi32.RegisterEventSourceW
//sys DeregisterEventSource(handle Handle) (err error) = advapi32.DeregisterEventSource
//sys ReportEvent(log Handle, etype uint16, category uint16, eventId uint32, usrSId uintptr, numStrings uint16, dataSize uint32, strings **uint16, rawData *byte) (err error) = advapi32.ReportEventW

@ -0,0 +1,97 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Fork, exec, wait, etc.
package windows
// EscapeArg rewrites command line argument s as prescribed
// in http://msdn.microsoft.com/en-us/library/ms880421.
// This function returns "" (2 double quotes) if s is empty.
// Alternatively, these transformations are done:
// - every back slash (\) is doubled, but only if immediately
// followed by double quote (");
// - every double quote (") is escaped by back slash (\);
// - finally, s is wrapped with double quotes (arg -> "arg"),
// but only if there is space or tab inside s.
func EscapeArg(s string) string {
if len(s) == 0 {
return "\"\""
}
n := len(s)
hasSpace := false
for i := 0; i < len(s); i++ {
switch s[i] {
case '"', '\\':
n++
case ' ', '\t':
hasSpace = true
}
}
if hasSpace {
n += 2
}
if n == len(s) {
return s
}
qs := make([]byte, n)
j := 0
if hasSpace {
qs[j] = '"'
j++
}
slashes := 0
for i := 0; i < len(s); i++ {
switch s[i] {
default:
slashes = 0
qs[j] = s[i]
case '\\':
slashes++
qs[j] = s[i]
case '"':
for ; slashes > 0; slashes-- {
qs[j] = '\\'
j++
}
qs[j] = '\\'
j++
qs[j] = s[i]
}
j++
}
if hasSpace {
for ; slashes > 0; slashes-- {
qs[j] = '\\'
j++
}
qs[j] = '"'
j++
}
return string(qs[:j])
}
func CloseOnExec(fd Handle) {
SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
}
// FullPath retrieves the full path of the specified file.
func FullPath(name string) (path string, err error) {
p, err := UTF16PtrFromString(name)
if err != nil {
return "", err
}
n := uint32(100)
for {
buf := make([]uint16, n)
n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
if err != nil {
return "", err
}
if n <= uint32(len(buf)) {
return UTF16ToString(buf[:n]), nil
}
}
}

@ -0,0 +1,26 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package windows
const (
MEM_COMMIT = 0x00001000
MEM_RESERVE = 0x00002000
MEM_DECOMMIT = 0x00004000
MEM_RELEASE = 0x00008000
MEM_RESET = 0x00080000
MEM_TOP_DOWN = 0x00100000
MEM_WRITE_WATCH = 0x00200000
MEM_PHYSICAL = 0x00400000
MEM_RESET_UNDO = 0x01000000
MEM_LARGE_PAGES = 0x20000000
PAGE_NOACCESS = 0x01
PAGE_READONLY = 0x02
PAGE_READWRITE = 0x04
PAGE_WRITECOPY = 0x08
PAGE_EXECUTE_READ = 0x20
PAGE_EXECUTE_READWRITE = 0x40
PAGE_EXECUTE_WRITECOPY = 0x80
)

@ -0,0 +1,7 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package windows
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go

@ -0,0 +1,30 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows,race
package windows
import (
"runtime"
"unsafe"
)
const raceenabled = true
func raceAcquire(addr unsafe.Pointer) {
runtime.RaceAcquire(addr)
}
func raceReleaseMerge(addr unsafe.Pointer) {
runtime.RaceReleaseMerge(addr)
}
func raceReadRange(addr unsafe.Pointer, len int) {
runtime.RaceReadRange(addr, len)
}
func raceWriteRange(addr unsafe.Pointer, len int) {
runtime.RaceWriteRange(addr, len)
}

@ -0,0 +1,25 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows,!race
package windows
import (
"unsafe"
)
const raceenabled = false
func raceAcquire(addr unsafe.Pointer) {
}
func raceReleaseMerge(addr unsafe.Pointer) {
}
func raceReadRange(addr unsafe.Pointer, len int) {
}
func raceWriteRange(addr unsafe.Pointer, len int) {
}

@ -0,0 +1,478 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package windows
import (
"syscall"
"unsafe"
)
const (
STANDARD_RIGHTS_REQUIRED = 0xf0000
STANDARD_RIGHTS_READ = 0x20000
STANDARD_RIGHTS_WRITE = 0x20000
STANDARD_RIGHTS_EXECUTE = 0x20000
STANDARD_RIGHTS_ALL = 0x1F0000
)
const (
NameUnknown = 0
NameFullyQualifiedDN = 1
NameSamCompatible = 2
NameDisplay = 3
NameUniqueId = 6
NameCanonical = 7
NameUserPrincipal = 8
NameCanonicalEx = 9
NameServicePrincipal = 10
NameDnsDomain = 12
)
// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
// http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
//sys TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
//sys GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
// TranslateAccountName converts a directory service
// object name from one format to another.
func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
u, e := UTF16PtrFromString(username)
if e != nil {
return "", e
}
n := uint32(50)
for {
b := make([]uint16, n)
e = TranslateName(u, from, to, &b[0], &n)
if e == nil {
return UTF16ToString(b[:n]), nil
}
if e != ERROR_INSUFFICIENT_BUFFER {
return "", e
}
if n <= uint32(len(b)) {
return "", e
}
}
}
const (
// do not reorder
NetSetupUnknownStatus = iota
NetSetupUnjoined
NetSetupWorkgroupName
NetSetupDomainName
)
type UserInfo10 struct {
Name *uint16
Comment *uint16
UsrComment *uint16
FullName *uint16
}
//sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
//sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
//sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
const (
// do not reorder
SidTypeUser = 1 + iota
SidTypeGroup
SidTypeDomain
SidTypeAlias
SidTypeWellKnownGroup
SidTypeDeletedAccount
SidTypeInvalid
SidTypeUnknown
SidTypeComputer
SidTypeLabel
)
type SidIdentifierAuthority struct {
Value [6]byte
}
var (
SECURITY_NULL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 0}}
SECURITY_WORLD_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 1}}
SECURITY_LOCAL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 2}}
SECURITY_CREATOR_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 3}}
SECURITY_NON_UNIQUE_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 4}}
SECURITY_NT_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 5}}
SECURITY_MANDATORY_LABEL_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 16}}
)
const (
SECURITY_NULL_RID = 0
SECURITY_WORLD_RID = 0
SECURITY_LOCAL_RID = 0
SECURITY_CREATOR_OWNER_RID = 0
SECURITY_CREATOR_GROUP_RID = 1
SECURITY_DIALUP_RID = 1
SECURITY_NETWORK_RID = 2
SECURITY_BATCH_RID = 3
SECURITY_INTERACTIVE_RID = 4
SECURITY_LOGON_IDS_RID = 5
SECURITY_SERVICE_RID = 6
SECURITY_LOCAL_SYSTEM_RID = 18
SECURITY_BUILTIN_DOMAIN_RID = 32
SECURITY_PRINCIPAL_SELF_RID = 10
SECURITY_CREATOR_OWNER_SERVER_RID = 0x2
SECURITY_CREATOR_GROUP_SERVER_RID = 0x3
SECURITY_LOGON_IDS_RID_COUNT = 0x3
SECURITY_ANONYMOUS_LOGON_RID = 0x7
SECURITY_PROXY_RID = 0x8
SECURITY_ENTERPRISE_CONTROLLERS_RID = 0x9
SECURITY_SERVER_LOGON_RID = SECURITY_ENTERPRISE_CONTROLLERS_RID
SECURITY_AUTHENTICATED_USER_RID = 0xb
SECURITY_RESTRICTED_CODE_RID = 0xc
SECURITY_NT_NON_UNIQUE_RID = 0x15
)
// Predefined domain-relative RIDs for local groups.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa379649(v=vs.85).aspx
const (
DOMAIN_ALIAS_RID_ADMINS = 0x220
DOMAIN_ALIAS_RID_USERS = 0x221
DOMAIN_ALIAS_RID_GUESTS = 0x222
DOMAIN_ALIAS_RID_POWER_USERS = 0x223
DOMAIN_ALIAS_RID_ACCOUNT_OPS = 0x224
DOMAIN_ALIAS_RID_SYSTEM_OPS = 0x225
DOMAIN_ALIAS_RID_PRINT_OPS = 0x226
DOMAIN_ALIAS_RID_BACKUP_OPS = 0x227
DOMAIN_ALIAS_RID_REPLICATOR = 0x228
DOMAIN_ALIAS_RID_RAS_SERVERS = 0x229
DOMAIN_ALIAS_RID_PREW2KCOMPACCESS = 0x22a
DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS = 0x22b
DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS = 0x22c
DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS = 0x22d
DOMAIN_ALIAS_RID_MONITORING_USERS = 0x22e
DOMAIN_ALIAS_RID_LOGGING_USERS = 0x22f
DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS = 0x230
DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS = 0x231
DOMAIN_ALIAS_RID_DCOM_USERS = 0x232
DOMAIN_ALIAS_RID_IUSERS = 0x238
DOMAIN_ALIAS_RID_CRYPTO_OPERATORS = 0x239
DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP = 0x23b
DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP = 0x23c
DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP = 0x23d
DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP = 0x23e
)
//sys LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
//sys LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
//sys ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
//sys ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
//sys GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
//sys CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
//sys AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) = advapi32.AllocateAndInitializeSid
//sys FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid
//sys EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid
// The security identifier (SID) structure is a variable-length
// structure used to uniquely identify users or groups.
type SID struct{}
// StringToSid converts a string-format security identifier
// sid into a valid, functional sid.
func StringToSid(s string) (*SID, error) {
var sid *SID
p, e := UTF16PtrFromString(s)
if e != nil {
return nil, e
}
e = ConvertStringSidToSid(p, &sid)
if e != nil {
return nil, e
}
defer LocalFree((Handle)(unsafe.Pointer(sid)))
return sid.Copy()
}
// LookupSID retrieves a security identifier sid for the account
// and the name of the domain on which the account was found.
// System specify target computer to search.
func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
if len(account) == 0 {
return nil, "", 0, syscall.EINVAL
}
acc, e := UTF16PtrFromString(account)
if e != nil {
return nil, "", 0, e
}
var sys *uint16
if len(system) > 0 {
sys, e = UTF16PtrFromString(system)
if e != nil {
return nil, "", 0, e
}
}
n := uint32(50)
dn := uint32(50)
for {
b := make([]byte, n)
db := make([]uint16, dn)
sid = (*SID)(unsafe.Pointer(&b[0]))
e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
if e == nil {
return sid, UTF16ToString(db), accType, nil
}
if e != ERROR_INSUFFICIENT_BUFFER {
return nil, "", 0, e
}
if n <= uint32(len(b)) {
return nil, "", 0, e
}
}
}
// String converts sid to a string format
// suitable for display, storage, or transmission.
func (sid *SID) String() (string, error) {
var s *uint16
e := ConvertSidToStringSid(sid, &s)
if e != nil {
return "", e
}
defer LocalFree((Handle)(unsafe.Pointer(s)))
return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
}
// Len returns the length, in bytes, of a valid security identifier sid.
func (sid *SID) Len() int {
return int(GetLengthSid(sid))
}
// Copy creates a duplicate of security identifier sid.
func (sid *SID) Copy() (*SID, error) {
b := make([]byte, sid.Len())
sid2 := (*SID)(unsafe.Pointer(&b[0]))
e := CopySid(uint32(len(b)), sid2, sid)
if e != nil {
return nil, e
}
return sid2, nil
}
// LookupAccount retrieves the name of the account for this sid
// and the name of the first domain on which this sid is found.
// System specify target computer to search for.
func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
var sys *uint16
if len(system) > 0 {
sys, err = UTF16PtrFromString(system)
if err != nil {
return "", "", 0, err
}
}
n := uint32(50)
dn := uint32(50)
for {
b := make([]uint16, n)
db := make([]uint16, dn)
e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
if e == nil {
return UTF16ToString(b), UTF16ToString(db), accType, nil
}
if e != ERROR_INSUFFICIENT_BUFFER {
return "", "", 0, e
}
if n <= uint32(len(b)) {
return "", "", 0, e
}
}
}
const (
// do not reorder
TOKEN_ASSIGN_PRIMARY = 1 << iota
TOKEN_DUPLICATE
TOKEN_IMPERSONATE
TOKEN_QUERY
TOKEN_QUERY_SOURCE
TOKEN_ADJUST_PRIVILEGES
TOKEN_ADJUST_GROUPS
TOKEN_ADJUST_DEFAULT
TOKEN_ADJUST_SESSIONID
TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
TOKEN_ASSIGN_PRIMARY |
TOKEN_DUPLICATE |
TOKEN_IMPERSONATE |
TOKEN_QUERY |
TOKEN_QUERY_SOURCE |
TOKEN_ADJUST_PRIVILEGES |
TOKEN_ADJUST_GROUPS |
TOKEN_ADJUST_DEFAULT |
TOKEN_ADJUST_SESSIONID
TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY
TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
TOKEN_ADJUST_PRIVILEGES |
TOKEN_ADJUST_GROUPS |
TOKEN_ADJUST_DEFAULT
TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
)
const (
// do not reorder
TokenUser = 1 + iota
TokenGroups
TokenPrivileges
TokenOwner
TokenPrimaryGroup
TokenDefaultDacl
TokenSource
TokenType
TokenImpersonationLevel
TokenStatistics
TokenRestrictedSids
TokenSessionId
TokenGroupsAndPrivileges
TokenSessionReference
TokenSandBoxInert
TokenAuditPolicy
TokenOrigin
TokenElevationType
TokenLinkedToken
TokenElevation
TokenHasRestrictions
TokenAccessInformation
TokenVirtualizationAllowed
TokenVirtualizationEnabled
TokenIntegrityLevel
TokenUIAccess
TokenMandatoryPolicy
TokenLogonSid
MaxTokenInfoClass
)
type SIDAndAttributes struct {
Sid *SID
Attributes uint32
}
type Tokenuser struct {
User SIDAndAttributes
}
type Tokenprimarygroup struct {
PrimaryGroup *SID
}
type Tokengroups struct {
GroupCount uint32
Groups [1]SIDAndAttributes
}
// Authorization Functions
//sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
//sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
//sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
// An access token contains the security information for a logon session.
// The system creates an access token when a user logs on, and every
// process executed on behalf of the user has a copy of the token.
// The token identifies the user, the user's groups, and the user's
// privileges. The system uses the token to control access to securable
// objects and to control the ability of the user to perform various
// system-related operations on the local computer.
type Token Handle
// OpenCurrentProcessToken opens the access token
// associated with current process.
func OpenCurrentProcessToken() (Token, error) {
p, e := GetCurrentProcess()
if e != nil {
return 0, e
}
var t Token
e = OpenProcessToken(p, TOKEN_QUERY, &t)
if e != nil {
return 0, e
}
return t, nil
}
// Close releases access to access token.
func (t Token) Close() error {
return CloseHandle(Handle(t))
}
// getInfo retrieves a specified type of information about an access token.
func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
n := uint32(initSize)
for {
b := make([]byte, n)
e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
if e == nil {
return unsafe.Pointer(&b[0]), nil
}
if e != ERROR_INSUFFICIENT_BUFFER {
return nil, e
}
if n <= uint32(len(b)) {
return nil, e
}
}
}
// GetTokenUser retrieves access token t user account information.
func (t Token) GetTokenUser() (*Tokenuser, error) {
i, e := t.getInfo(TokenUser, 50)
if e != nil {
return nil, e
}
return (*Tokenuser)(i), nil
}
// GetTokenGroups retrieves group accounts associated with access token t.
func (t Token) GetTokenGroups() (*Tokengroups, error) {
i, e := t.getInfo(TokenGroups, 50)
if e != nil {
return nil, e
}
return (*Tokengroups)(i), nil
}
// GetTokenPrimaryGroup retrieves access token t primary group information.
// A pointer to a SID structure representing a group that will become
// the primary group of any objects created by a process using this access token.
func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
i, e := t.getInfo(TokenPrimaryGroup, 50)
if e != nil {
return nil, e
}
return (*Tokenprimarygroup)(i), nil
}
// GetUserProfileDirectory retrieves path to the
// root directory of the access token t user's profile.
func (t Token) GetUserProfileDirectory() (string, error) {
n := uint32(100)
for {
b := make([]uint16, n)
e := GetUserProfileDirectory(t, &b[0], &n)
if e == nil {
return UTF16ToString(b), nil
}
if e != ERROR_INSUFFICIENT_BUFFER {
return "", e
}
if n <= uint32(len(b)) {
return "", e
}
}
}
// IsMember reports whether the access token t is a member of the provided SID.
func (t Token) IsMember(sid *SID) (bool, error) {
var b int32
if e := checkTokenMembership(t, sid, &b); e != nil {
return false, e
}
return b != 0, nil
}

@ -0,0 +1,183 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package windows
const (
SC_MANAGER_CONNECT = 1
SC_MANAGER_CREATE_SERVICE = 2
SC_MANAGER_ENUMERATE_SERVICE = 4
SC_MANAGER_LOCK = 8
SC_MANAGER_QUERY_LOCK_STATUS = 16
SC_MANAGER_MODIFY_BOOT_CONFIG = 32
SC_MANAGER_ALL_ACCESS = 0xf003f
)
//sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenSCManagerW
const (
SERVICE_KERNEL_DRIVER = 1
SERVICE_FILE_SYSTEM_DRIVER = 2
SERVICE_ADAPTER = 4
SERVICE_RECOGNIZER_DRIVER = 8
SERVICE_WIN32_OWN_PROCESS = 16
SERVICE_WIN32_SHARE_PROCESS = 32
SERVICE_WIN32 = SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS
SERVICE_INTERACTIVE_PROCESS = 256
SERVICE_DRIVER = SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_RECOGNIZER_DRIVER
SERVICE_TYPE_ALL = SERVICE_WIN32 | SERVICE_ADAPTER | SERVICE_DRIVER | SERVICE_INTERACTIVE_PROCESS
SERVICE_BOOT_START = 0
SERVICE_SYSTEM_START = 1
SERVICE_AUTO_START = 2
SERVICE_DEMAND_START = 3
SERVICE_DISABLED = 4
SERVICE_ERROR_IGNORE = 0
SERVICE_ERROR_NORMAL = 1
SERVICE_ERROR_SEVERE = 2
SERVICE_ERROR_CRITICAL = 3
SC_STATUS_PROCESS_INFO = 0
SC_ACTION_NONE = 0
SC_ACTION_RESTART = 1
SC_ACTION_REBOOT = 2
SC_ACTION_RUN_COMMAND = 3
SERVICE_STOPPED = 1
SERVICE_START_PENDING = 2
SERVICE_STOP_PENDING = 3
SERVICE_RUNNING = 4
SERVICE_CONTINUE_PENDING = 5
SERVICE_PAUSE_PENDING = 6
SERVICE_PAUSED = 7
SERVICE_NO_CHANGE = 0xffffffff
SERVICE_ACCEPT_STOP = 1
SERVICE_ACCEPT_PAUSE_CONTINUE = 2
SERVICE_ACCEPT_SHUTDOWN = 4
SERVICE_ACCEPT_PARAMCHANGE = 8
SERVICE_ACCEPT_NETBINDCHANGE = 16
SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 32
SERVICE_ACCEPT_POWEREVENT = 64
SERVICE_ACCEPT_SESSIONCHANGE = 128
SERVICE_CONTROL_STOP = 1
SERVICE_CONTROL_PAUSE = 2
SERVICE_CONTROL_CONTINUE = 3
SERVICE_CONTROL_INTERROGATE = 4
SERVICE_CONTROL_SHUTDOWN = 5
SERVICE_CONTROL_PARAMCHANGE = 6
SERVICE_CONTROL_NETBINDADD = 7
SERVICE_CONTROL_NETBINDREMOVE = 8
SERVICE_CONTROL_NETBINDENABLE = 9
SERVICE_CONTROL_NETBINDDISABLE = 10
SERVICE_CONTROL_DEVICEEVENT = 11
SERVICE_CONTROL_HARDWAREPROFILECHANGE = 12
SERVICE_CONTROL_POWEREVENT = 13
SERVICE_CONTROL_SESSIONCHANGE = 14
SERVICE_ACTIVE = 1
SERVICE_INACTIVE = 2
SERVICE_STATE_ALL = 3
SERVICE_QUERY_CONFIG = 1
SERVICE_CHANGE_CONFIG = 2
SERVICE_QUERY_STATUS = 4
SERVICE_ENUMERATE_DEPENDENTS = 8
SERVICE_START = 16
SERVICE_STOP = 32
SERVICE_PAUSE_CONTINUE = 64
SERVICE_INTERROGATE = 128
SERVICE_USER_DEFINED_CONTROL = 256
SERVICE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_USER_DEFINED_CONTROL
SERVICE_RUNS_IN_SYSTEM_PROCESS = 1
SERVICE_CONFIG_DESCRIPTION = 1
SERVICE_CONFIG_FAILURE_ACTIONS = 2
NO_ERROR = 0
SC_ENUM_PROCESS_INFO = 0
)
type SERVICE_STATUS struct {
ServiceType uint32
CurrentState uint32
ControlsAccepted uint32
Win32ExitCode uint32
ServiceSpecificExitCode uint32
CheckPoint uint32
WaitHint uint32
}
type SERVICE_TABLE_ENTRY struct {
ServiceName *uint16
ServiceProc uintptr
}
type QUERY_SERVICE_CONFIG struct {
ServiceType uint32
StartType uint32
ErrorControl uint32
BinaryPathName *uint16
LoadOrderGroup *uint16
TagId uint32
Dependencies *uint16
ServiceStartName *uint16
DisplayName *uint16
}
type SERVICE_DESCRIPTION struct {
Description *uint16
}
type SERVICE_STATUS_PROCESS struct {
ServiceType uint32
CurrentState uint32
ControlsAccepted uint32
Win32ExitCode uint32
ServiceSpecificExitCode uint32
CheckPoint uint32
WaitHint uint32
ProcessId uint32
ServiceFlags uint32
}
type ENUM_SERVICE_STATUS_PROCESS struct {
ServiceName *uint16
DisplayName *uint16
ServiceStatusProcess SERVICE_STATUS_PROCESS
}
type SERVICE_FAILURE_ACTIONS struct {
ResetPeriod uint32
RebootMsg *uint16
Command *uint16
ActionsCount uint32
Actions *SC_ACTION
}
type SC_ACTION struct {
Type uint32
Delay uint32
}
//sys CloseServiceHandle(handle Handle) (err error) = advapi32.CloseServiceHandle
//sys CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access uint32, srvType uint32, startType uint32, errCtl uint32, pathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16) (handle Handle, err error) [failretval==0] = advapi32.CreateServiceW
//sys OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenServiceW
//sys DeleteService(service Handle) (err error) = advapi32.DeleteService
//sys StartService(service Handle, numArgs uint32, argVectors **uint16) (err error) = advapi32.StartServiceW
//sys QueryServiceStatus(service Handle, status *SERVICE_STATUS) (err error) = advapi32.QueryServiceStatus
//sys ControlService(service Handle, control uint32, status *SERVICE_STATUS) (err error) = advapi32.ControlService
//sys StartServiceCtrlDispatcher(serviceTable *SERVICE_TABLE_ENTRY) (err error) = advapi32.StartServiceCtrlDispatcherW
//sys SetServiceStatus(service Handle, serviceStatus *SERVICE_STATUS) (err error) = advapi32.SetServiceStatus
//sys ChangeServiceConfig(service Handle, serviceType uint32, startType uint32, errorControl uint32, binaryPathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16, displayName *uint16) (err error) = advapi32.ChangeServiceConfigW
//sys QueryServiceConfig(service Handle, serviceConfig *QUERY_SERVICE_CONFIG, bufSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceConfigW
//sys ChangeServiceConfig2(service Handle, infoLevel uint32, info *byte) (err error) = advapi32.ChangeServiceConfig2W
//sys QueryServiceConfig2(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceConfig2W
//sys EnumServicesStatusEx(mgr Handle, infoLevel uint32, serviceType uint32, serviceState uint32, services *byte, bufSize uint32, bytesNeeded *uint32, servicesReturned *uint32, resumeHandle *uint32, groupName *uint16) (err error) = advapi32.EnumServicesStatusExW
//sys QueryServiceStatusEx(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceStatusEx

@ -0,0 +1,22 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package windows
func itoa(val int) string { // do it here rather than with fmt to avoid dependency
if val < 0 {
return "-" + itoa(-val)
}
var buf [32]byte // big enough for int64
i := len(buf) - 1
for val >= 10 {
buf[i] = byte(val%10 + '0')
i--
val /= 10
}
buf[i] = byte(val + '0')
return string(buf[i:])
}

@ -0,0 +1,74 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
// Package windows contains an interface to the low-level operating system
// primitives. OS details vary depending on the underlying system, and
// by default, godoc will display the OS-specific documentation for the current
// system. If you want godoc to display syscall documentation for another
// system, set $GOOS and $GOARCH to the desired system. For example, if
// you want to view documentation for freebsd/arm on linux/amd64, set $GOOS
// to freebsd and $GOARCH to arm.
//
// The primary use of this package is inside other packages that provide a more
// portable interface to the system, such as "os", "time" and "net". Use
// those packages rather than this one if you can.
//
// For details of the functions and data types in this package consult
// the manuals for the appropriate operating system.
//
// These calls return err == nil to indicate success; otherwise
// err represents an operating system error describing the failure and
// holds a value of type syscall.Errno.
package windows // import "golang.org/x/sys/windows"
import (
"syscall"
)
// ByteSliceFromString returns a NUL-terminated slice of bytes
// containing the text of s. If s contains a NUL byte at any
// location, it returns (nil, syscall.EINVAL).
func ByteSliceFromString(s string) ([]byte, error) {
for i := 0; i < len(s); i++ {
if s[i] == 0 {
return nil, syscall.EINVAL
}
}
a := make([]byte, len(s)+1)
copy(a, s)
return a, nil
}
// BytePtrFromString returns a pointer to a NUL-terminated array of
// bytes containing the text of s. If s contains a NUL byte at any
// location, it returns (nil, syscall.EINVAL).
func BytePtrFromString(s string) (*byte, error) {
a, err := ByteSliceFromString(s)
if err != nil {
return nil, err
}
return &a[0], nil
}
// Single-word zero for use when we need a valid pointer to 0 bytes.
// See mksyscall.pl.
var _zero uintptr
func (ts *Timespec) Unix() (sec int64, nsec int64) {
return int64(ts.Sec), int64(ts.Nsec)
}
func (tv *Timeval) Unix() (sec int64, nsec int64) {
return int64(tv.Sec), int64(tv.Usec) * 1000
}
func (ts *Timespec) Nano() int64 {
return int64(ts.Sec)*1e9 + int64(ts.Nsec)
}
func (tv *Timeval) Nano() int64 {
return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,22 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package windows
type WSAData struct {
Version uint16
HighVersion uint16
Description [WSADESCRIPTION_LEN + 1]byte
SystemStatus [WSASYS_STATUS_LEN + 1]byte
MaxSockets uint16
MaxUdpDg uint16
VendorInfo *byte
}
type Servent struct {
Name *byte
Aliases **byte
Port uint16
Proto *byte
}

@ -0,0 +1,22 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package windows
type WSAData struct {
Version uint16
HighVersion uint16
MaxSockets uint16
MaxUdpDg uint16
VendorInfo *byte
Description [WSADESCRIPTION_LEN + 1]byte
SystemStatus [WSASYS_STATUS_LEN + 1]byte
}
type Servent struct {
Name *byte
Aliases **byte
Proto *byte
Port uint16
}

@ -0,0 +1,22 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package windows
type WSAData struct {
Version uint16
HighVersion uint16
Description [WSADESCRIPTION_LEN + 1]byte
SystemStatus [WSASYS_STATUS_LEN + 1]byte
MaxSockets uint16
MaxUdpDg uint16
VendorInfo *byte
}
type Servent struct {
Name *byte
Aliases **byte
Port uint16
Proto *byte
}

File diff suppressed because it is too large Load Diff

@ -1178,6 +1178,12 @@
"revision": "1e2299c37cc91a509f1b12369872d27be0ce98a6",
"revisionTime": "2017-11-09T13:50:42Z"
},
{
"checksumSHA1": "Hu8GoQK1euwtE4UjrhXepmk2NM8=",
"path": "golang.org/x/sys/windows",
"revision": "cd391775e71e684db52b63df9affd58269495083",
"revisionTime": "2019-02-22T15:12:32Z"
},
{
"checksumSHA1": "faFDXp++cLjLBlvsr+izZ+go1WU=",
"path": "golang.org/x/text/secure/bidirule",

Loading…
Cancel
Save