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
parent
5085bef397
commit
5e69a107d8
@ -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
Loading…
Reference in new issue