Compare commits
No commits in common. "v0.6.0" and "master" have entirely different histories.
4
go.mod
4
go.mod
|
@ -1,8 +1,8 @@
|
||||||
module git.rootprojects.org/root/pathman
|
module git.rootprojects.org/root/pathman
|
||||||
|
|
||||||
go 1.21
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.rootprojects.org/root/go-gitver v1.1.3
|
git.rootprojects.org/root/go-gitver v1.1.3
|
||||||
golang.org/x/sys v0.14.0
|
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7
|
||||||
)
|
)
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -1,4 +1,4 @@
|
||||||
git.rootprojects.org/root/go-gitver v1.1.3 h1:/qR9z53vY+IFhWRxLkF9cjaiWh8xRJIm6gyuW+MG81A=
|
git.rootprojects.org/root/go-gitver v1.1.3 h1:/qR9z53vY+IFhWRxLkF9cjaiWh8xRJIm6gyuW+MG81A=
|
||||||
git.rootprojects.org/root/go-gitver v1.1.3/go.mod h1:Rj1v3TBhvdaSphFEqMynUYwAz/4f+wY/+syBTvRrmlI=
|
git.rootprojects.org/root/go-gitver v1.1.3/go.mod h1:Rj1v3TBhvdaSphFEqMynUYwAz/4f+wY/+syBTvRrmlI=
|
||||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7 h1:LepdCS8Gf/MVejFIt8lsiexZATdoGVyp5bcyS+rYoUI=
|
||||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
set -u
|
|
||||||
|
|
||||||
# NOTE
|
|
||||||
# building for linux on linux seems to yield smaller sizes
|
|
||||||
|
|
||||||
# TODO use the git log describe thing
|
|
||||||
my_version="$(
|
|
||||||
git describe --tags
|
|
||||||
)"
|
|
||||||
export GOOS="linux"
|
|
||||||
|
|
||||||
fn_package() { (
|
|
||||||
if test -n "${GOARM:-}"; then
|
|
||||||
my_arch="${GOARCH}v${GOARM}"
|
|
||||||
elif test -n "${GOAMD64:-}"; then
|
|
||||||
my_arch="${GOARCH}_${GOAMD64}"
|
|
||||||
else
|
|
||||||
my_arch="${GOARCH}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
my_bin="pathman-${my_version}-${GOOS}-${my_arch}"
|
|
||||||
tinygo build -no-debug -o "${my_bin}"
|
|
||||||
strip "${my_bin}" || true
|
|
||||||
|
|
||||||
tar cvf "$my_bin.tar" "$my_bin"
|
|
||||||
gzip --keep "$my_bin.tar"
|
|
||||||
xz --keep "$my_bin.tar"
|
|
||||||
|
|
||||||
echo "$my_bin.tar.xz"
|
|
||||||
); }
|
|
||||||
|
|
||||||
export GOAMD64=v1
|
|
||||||
export GOARCH=amd64
|
|
||||||
fn_package
|
|
||||||
export GOAMD64=''
|
|
||||||
|
|
||||||
export GOARCH=386
|
|
||||||
fn_package
|
|
||||||
|
|
||||||
export GOARCH=arm64
|
|
||||||
fn_package
|
|
||||||
|
|
||||||
export GOARCH=arm
|
|
||||||
export GOARM=7
|
|
||||||
fn_package
|
|
||||||
|
|
||||||
export GOARCH=arm
|
|
||||||
export GOARM=6
|
|
||||||
fn_package
|
|
||||||
|
|
||||||
# no longer supported
|
|
||||||
# export GOARCH=arm
|
|
||||||
# export GOARM=5
|
|
||||||
# fn_package
|
|
|
@ -1,39 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
set -u
|
|
||||||
|
|
||||||
# NOTE
|
|
||||||
# building for macOS on macOS seems to yield smaller sizes
|
|
||||||
|
|
||||||
my_version="$(
|
|
||||||
git describe --tags
|
|
||||||
)"
|
|
||||||
export GOOS="darwin"
|
|
||||||
|
|
||||||
fn_package() { (
|
|
||||||
if test -n "${GOARM:-}"; then
|
|
||||||
my_arch="${GOARCH}v${GOARM}"
|
|
||||||
elif test -n "${GOAMD64:-}"; then
|
|
||||||
my_arch="${GOARCH}_${GOAMD64}"
|
|
||||||
else
|
|
||||||
my_arch="${GOARCH}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
my_bin="pathman-${my_version}-${GOOS}-${my_arch}"
|
|
||||||
tinygo build -no-debug -o "${my_bin}"
|
|
||||||
strip "${my_bin}" || true
|
|
||||||
|
|
||||||
tar cvf "$my_bin.tar" "$my_bin"
|
|
||||||
gzip --keep "$my_bin.tar"
|
|
||||||
xz --keep "$my_bin.tar"
|
|
||||||
|
|
||||||
echo "$my_bin.tar.xz"
|
|
||||||
); }
|
|
||||||
|
|
||||||
export GOAMD64=v2
|
|
||||||
export GOARCH=amd64
|
|
||||||
fn_package
|
|
||||||
export GOAMD64=''
|
|
||||||
|
|
||||||
export GOARCH=arm64
|
|
||||||
fn_package
|
|
|
@ -1,49 +0,0 @@
|
||||||
#!/bin/bin/env pwsh
|
|
||||||
|
|
||||||
# TODO use the git log describe thing
|
|
||||||
$my_version = git describe --tags
|
|
||||||
$Env:GOOS = "windows"
|
|
||||||
|
|
||||||
function fn_package() {
|
|
||||||
IF ($Env:GOARM.Length -gt 0) {
|
|
||||||
$my_arch = "${Env:GOARCH}v${Env:GOARM}"
|
|
||||||
} ELSEIF ($Env:GOAMD64.Length -gt 0) {
|
|
||||||
$my_arch = "${Env:GOARCH}_${Env:GOAMD64}"
|
|
||||||
} ELSE {
|
|
||||||
$my_arch = "${Env:GOARCH}"
|
|
||||||
}
|
|
||||||
|
|
||||||
$my_bin = "pathman-${my_version}-${Env:GOOS}-${my_arch}"
|
|
||||||
tinygo build -no-debug -o "${my_bin}"
|
|
||||||
#strip "${my_bin}" || true
|
|
||||||
|
|
||||||
tar cvzf "$my_bin.tar" "$my_bin"
|
|
||||||
Compress-Archive "$my_bin" "$my_bin.zip"
|
|
||||||
|
|
||||||
Write-Output "$my_bin.zip"
|
|
||||||
}
|
|
||||||
|
|
||||||
$Env:GOAMD64 = "v1"
|
|
||||||
$Env:GOARCH = "amd64"
|
|
||||||
fn_package
|
|
||||||
$Env:GOAMD64 = ""
|
|
||||||
|
|
||||||
# $Env:GOARCH = "386"
|
|
||||||
# fn_package
|
|
||||||
|
|
||||||
$Env:GOARCH = "arm64"
|
|
||||||
fn_package
|
|
||||||
|
|
||||||
# $Env:GOARCH = "arm"
|
|
||||||
# $Env:GOARM = "7"
|
|
||||||
# fn_package
|
|
||||||
|
|
||||||
# $Env:GOARCH = "arm"
|
|
||||||
# $Env:GOARM = "6"
|
|
||||||
# fn_package
|
|
||||||
|
|
||||||
# unset vars
|
|
||||||
$Env:GOOS = ""
|
|
||||||
$Env:GOARCH = ""
|
|
||||||
$Env:GOARM = ""
|
|
||||||
$Env:GOAMD64 = ""
|
|
|
@ -1,52 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
set -u
|
|
||||||
|
|
||||||
# NOTE
|
|
||||||
# building for macOS on macOS seems to yield smaller sizes
|
|
||||||
|
|
||||||
# TODO use the git log describe thing
|
|
||||||
my_version="$(
|
|
||||||
git describe --tags
|
|
||||||
)"
|
|
||||||
export GOOS="windows"
|
|
||||||
|
|
||||||
fn_package() { (
|
|
||||||
if test -n "${GOARM:-}"; then
|
|
||||||
my_arch="${GOARCH}v${GOARM}"
|
|
||||||
elif test -n "${GOAMD64:-}"; then
|
|
||||||
my_arch="${GOARCH}_${GOAMD64}"
|
|
||||||
else
|
|
||||||
my_arch="${GOARCH}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
my_bin="pathman-${my_version}-${GOOS}-${my_arch}"
|
|
||||||
tinygo build -no-debug -o "${my_bin}"
|
|
||||||
#strip "${my_bin}" || true
|
|
||||||
|
|
||||||
tar cvf "$my_bin.tar" "$my_bin"
|
|
||||||
gzip --keep "$my_bin.tar"
|
|
||||||
#xz --keep "$my_bin.tar"
|
|
||||||
zip "$my_bin.zip" "$my_bin"
|
|
||||||
|
|
||||||
echo "$my_bin.zip"
|
|
||||||
); }
|
|
||||||
|
|
||||||
export GOAMD64=v1
|
|
||||||
export GOARCH=amd64
|
|
||||||
fn_package
|
|
||||||
export GOAMD64=''
|
|
||||||
|
|
||||||
# export GOARCH=386
|
|
||||||
# fn_package
|
|
||||||
|
|
||||||
export GOARCH=arm64
|
|
||||||
fn_package
|
|
||||||
|
|
||||||
# export GOARCH=arm
|
|
||||||
# export GOARM=7
|
|
||||||
# fn_package
|
|
||||||
|
|
||||||
# export GOARCH=arm
|
|
||||||
# export GOARM=6
|
|
||||||
# fn_package
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
module git.rootprojects.org/root/go-gitver
|
||||||
|
|
||||||
|
go 1.12
|
|
@ -0,0 +1,3 @@
|
||||||
|
# This source code refers to The Go Authors for copyright purposes.
|
||||||
|
# The master list of authors is in the main Go distribution,
|
||||||
|
# visible at http://tip.golang.org/AUTHORS.
|
|
@ -0,0 +1,3 @@
|
||||||
|
# This source code was written by the Go contributors.
|
||||||
|
# The master list of contributors is in the main Go distribution,
|
||||||
|
# visible at http://tip.golang.org/CONTRIBUTORS.
|
|
@ -2,7 +2,8 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build windows && go1.9
|
// +build windows
|
||||||
|
// +build go1.9
|
||||||
|
|
||||||
package windows
|
package windows
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
@ -11,18 +11,6 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// We need to use LoadLibrary and GetProcAddress from the Go runtime, because
|
|
||||||
// the these symbols are loaded by the system linker and are required to
|
|
||||||
// dynamically load additional symbols. Note that in the Go runtime, these
|
|
||||||
// return syscall.Handle and syscall.Errno, but these are the same, in fact,
|
|
||||||
// as windows.Handle and windows.Errno, and we intend to keep these the same.
|
|
||||||
|
|
||||||
//go:linkname syscall_loadlibrary syscall.loadlibrary
|
|
||||||
func syscall_loadlibrary(filename *uint16) (handle Handle, err Errno)
|
|
||||||
|
|
||||||
//go:linkname syscall_getprocaddress syscall.getprocaddress
|
|
||||||
func syscall_getprocaddress(handle Handle, procname *uint8) (proc uintptr, err Errno)
|
|
||||||
|
|
||||||
// DLLError describes reasons for DLL load failures.
|
// DLLError describes reasons for DLL load failures.
|
||||||
type DLLError struct {
|
type DLLError struct {
|
||||||
Err error
|
Err error
|
||||||
|
@ -32,7 +20,9 @@ type DLLError struct {
|
||||||
|
|
||||||
func (e *DLLError) Error() string { return e.Msg }
|
func (e *DLLError) Error() string { return e.Msg }
|
||||||
|
|
||||||
func (e *DLLError) Unwrap() error { return e.Err }
|
// 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.
|
// A DLL implements access to a single DLL.
|
||||||
type DLL struct {
|
type DLL struct {
|
||||||
|
@ -50,7 +40,7 @@ func LoadDLL(name string) (dll *DLL, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
h, e := syscall_loadlibrary(namep)
|
h, e := loadlibrary(namep)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return nil, &DLLError{
|
return nil, &DLLError{
|
||||||
Err: e,
|
Err: e,
|
||||||
|
@ -60,7 +50,7 @@ func LoadDLL(name string) (dll *DLL, err error) {
|
||||||
}
|
}
|
||||||
d := &DLL{
|
d := &DLL{
|
||||||
Name: name,
|
Name: name,
|
||||||
Handle: h,
|
Handle: Handle(h),
|
||||||
}
|
}
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
@ -81,7 +71,7 @@ func (d *DLL) FindProc(name string) (proc *Proc, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
a, e := syscall_getprocaddress(d.Handle, namep)
|
a, e := getprocaddress(uintptr(d.Handle), namep)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return nil, &DLLError{
|
return nil, &DLLError{
|
||||||
Err: e,
|
Err: e,
|
||||||
|
@ -106,35 +96,6 @@ func (d *DLL) MustFindProc(name string) *Proc {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindProcByOrdinal searches DLL d for procedure by ordinal and returns *Proc
|
|
||||||
// if found. It returns an error if search fails.
|
|
||||||
func (d *DLL) FindProcByOrdinal(ordinal uintptr) (proc *Proc, err error) {
|
|
||||||
a, e := GetProcAddressByOrdinal(d.Handle, ordinal)
|
|
||||||
name := "#" + itoa(int(ordinal))
|
|
||||||
if e != nil {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustFindProcByOrdinal is like FindProcByOrdinal but panics if search fails.
|
|
||||||
func (d *DLL) MustFindProcByOrdinal(ordinal uintptr) *Proc {
|
|
||||||
p, e := d.FindProcByOrdinal(ordinal)
|
|
||||||
if e != nil {
|
|
||||||
panic(e)
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release unloads DLL d from memory.
|
// Release unloads DLL d from memory.
|
||||||
func (d *DLL) Release() (err error) {
|
func (d *DLL) Release() (err error) {
|
||||||
return FreeLibrary(d.Handle)
|
return FreeLibrary(d.Handle)
|
||||||
|
@ -391,6 +352,7 @@ func loadLibraryEx(name string, system bool) (*DLL, error) {
|
||||||
var flags uintptr
|
var flags uintptr
|
||||||
if system {
|
if system {
|
||||||
if canDoSearchSystem32() {
|
if canDoSearchSystem32() {
|
||||||
|
const LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
|
||||||
flags = LOAD_LIBRARY_SEARCH_SYSTEM32
|
flags = LOAD_LIBRARY_SEARCH_SYSTEM32
|
||||||
} else if isBaseName(name) {
|
} else if isBaseName(name) {
|
||||||
// WindowsXP or unpatched Windows machine
|
// WindowsXP or unpatched Windows machine
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
// Copyright 2019 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.
|
|
||||||
|
|
||||||
//go:build !go1.12
|
|
||||||
|
|
||||||
// This file is here to allow bodyless functions with go:linkname for Go 1.11
|
|
||||||
// and earlier (see https://golang.org/issue/23311).
|
|
|
@ -8,6 +8,7 @@ package windows
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"unicode/utf16"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,14 +38,20 @@ func (token Token) Environ(inheritExisting bool) (env []string, err error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer DestroyEnvironmentBlock(block)
|
defer DestroyEnvironmentBlock(block)
|
||||||
blockp := unsafe.Pointer(block)
|
blockp := uintptr(unsafe.Pointer(block))
|
||||||
for {
|
for {
|
||||||
entry := UTF16PtrToString((*uint16)(blockp))
|
entry := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(blockp))[:]
|
||||||
|
for i, v := range entry {
|
||||||
|
if v == 0 {
|
||||||
|
entry = entry[:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
if len(entry) == 0 {
|
if len(entry) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
env = append(env, entry)
|
env = append(env, string(utf16.Decode(entry)))
|
||||||
blockp = unsafe.Add(blockp, 2*(len(entry)+1))
|
blockp += 2 * (uintptr(len(entry)) + 1)
|
||||||
}
|
}
|
||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build windows
|
// +build windows
|
||||||
|
|
||||||
package windows
|
package windows
|
||||||
|
|
||||||
|
|
|
@ -6,23 +6,18 @@
|
||||||
|
|
||||||
package windows
|
package windows
|
||||||
|
|
||||||
import (
|
|
||||||
errorspkg "errors"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// EscapeArg rewrites command line argument s as prescribed
|
// EscapeArg rewrites command line argument s as prescribed
|
||||||
// in http://msdn.microsoft.com/en-us/library/ms880421.
|
// in http://msdn.microsoft.com/en-us/library/ms880421.
|
||||||
// This function returns "" (2 double quotes) if s is empty.
|
// This function returns "" (2 double quotes) if s is empty.
|
||||||
// Alternatively, these transformations are done:
|
// Alternatively, these transformations are done:
|
||||||
// - every back slash (\) is doubled, but only if immediately
|
// - every back slash (\) is doubled, but only if immediately
|
||||||
// followed by double quote (");
|
// followed by double quote (");
|
||||||
// - every double quote (") is escaped by back slash (\);
|
// - every double quote (") is escaped by back slash (\);
|
||||||
// - finally, s is wrapped with double quotes (arg -> "arg"),
|
// - finally, s is wrapped with double quotes (arg -> "arg"),
|
||||||
// but only if there is space or tab inside s.
|
// but only if there is space or tab inside s.
|
||||||
func EscapeArg(s string) string {
|
func EscapeArg(s string) string {
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return `""`
|
return "\"\""
|
||||||
}
|
}
|
||||||
n := len(s)
|
n := len(s)
|
||||||
hasSpace := false
|
hasSpace := false
|
||||||
|
@ -35,7 +30,7 @@ func EscapeArg(s string) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if hasSpace {
|
if hasSpace {
|
||||||
n += 2 // Reserve space for quotes.
|
n += 2
|
||||||
}
|
}
|
||||||
if n == len(s) {
|
if n == len(s) {
|
||||||
return s
|
return s
|
||||||
|
@ -78,110 +73,6 @@ func EscapeArg(s string) string {
|
||||||
return string(qs[:j])
|
return string(qs[:j])
|
||||||
}
|
}
|
||||||
|
|
||||||
// ComposeCommandLine escapes and joins the given arguments suitable for use as a Windows command line,
|
|
||||||
// in CreateProcess's CommandLine argument, CreateService/ChangeServiceConfig's BinaryPathName argument,
|
|
||||||
// or any program that uses CommandLineToArgv.
|
|
||||||
func ComposeCommandLine(args []string) string {
|
|
||||||
if len(args) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Per https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw:
|
|
||||||
// “This function accepts command lines that contain a program name; the
|
|
||||||
// program name can be enclosed in quotation marks or not.”
|
|
||||||
//
|
|
||||||
// Unfortunately, it provides no means of escaping interior quotation marks
|
|
||||||
// within that program name, and we have no way to report them here.
|
|
||||||
prog := args[0]
|
|
||||||
mustQuote := len(prog) == 0
|
|
||||||
for i := 0; i < len(prog); i++ {
|
|
||||||
c := prog[i]
|
|
||||||
if c <= ' ' || (c == '"' && i == 0) {
|
|
||||||
// Force quotes for not only the ASCII space and tab as described in the
|
|
||||||
// MSDN article, but also ASCII control characters.
|
|
||||||
// The documentation for CommandLineToArgvW doesn't say what happens when
|
|
||||||
// the first argument is not a valid program name, but it empirically
|
|
||||||
// seems to drop unquoted control characters.
|
|
||||||
mustQuote = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var commandLine []byte
|
|
||||||
if mustQuote {
|
|
||||||
commandLine = make([]byte, 0, len(prog)+2)
|
|
||||||
commandLine = append(commandLine, '"')
|
|
||||||
for i := 0; i < len(prog); i++ {
|
|
||||||
c := prog[i]
|
|
||||||
if c == '"' {
|
|
||||||
// This quote would interfere with our surrounding quotes.
|
|
||||||
// We have no way to report an error, so just strip out
|
|
||||||
// the offending character instead.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
commandLine = append(commandLine, c)
|
|
||||||
}
|
|
||||||
commandLine = append(commandLine, '"')
|
|
||||||
} else {
|
|
||||||
if len(args) == 1 {
|
|
||||||
// args[0] is a valid command line representing itself.
|
|
||||||
// No need to allocate a new slice or string for it.
|
|
||||||
return prog
|
|
||||||
}
|
|
||||||
commandLine = []byte(prog)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, arg := range args[1:] {
|
|
||||||
commandLine = append(commandLine, ' ')
|
|
||||||
// TODO(bcmills): since we're already appending to a slice, it would be nice
|
|
||||||
// to avoid the intermediate allocations of EscapeArg.
|
|
||||||
// Perhaps we can factor out an appendEscapedArg function.
|
|
||||||
commandLine = append(commandLine, EscapeArg(arg)...)
|
|
||||||
}
|
|
||||||
return string(commandLine)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecomposeCommandLine breaks apart its argument command line into unescaped parts using CommandLineToArgv,
|
|
||||||
// as gathered from GetCommandLine, QUERY_SERVICE_CONFIG's BinaryPathName argument, or elsewhere that
|
|
||||||
// command lines are passed around.
|
|
||||||
// DecomposeCommandLine returns an error if commandLine contains NUL.
|
|
||||||
func DecomposeCommandLine(commandLine string) ([]string, error) {
|
|
||||||
if len(commandLine) == 0 {
|
|
||||||
return []string{}, nil
|
|
||||||
}
|
|
||||||
utf16CommandLine, err := UTF16FromString(commandLine)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errorspkg.New("string with NUL passed to DecomposeCommandLine")
|
|
||||||
}
|
|
||||||
var argc int32
|
|
||||||
argv, err := commandLineToArgv(&utf16CommandLine[0], &argc)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer LocalFree(Handle(unsafe.Pointer(argv)))
|
|
||||||
|
|
||||||
var args []string
|
|
||||||
for _, p := range unsafe.Slice(argv, argc) {
|
|
||||||
args = append(args, UTF16PtrToString(p))
|
|
||||||
}
|
|
||||||
return args, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CommandLineToArgv parses a Unicode command line string and sets
|
|
||||||
// argc to the number of parsed arguments.
|
|
||||||
//
|
|
||||||
// The returned memory should be freed using a single call to LocalFree.
|
|
||||||
//
|
|
||||||
// Note that although the return type of CommandLineToArgv indicates 8192
|
|
||||||
// entries of up to 8192 characters each, the actual count of parsed arguments
|
|
||||||
// may exceed 8192, and the documentation for CommandLineToArgvW does not mention
|
|
||||||
// any bound on the lengths of the individual argument strings.
|
|
||||||
// (See https://go.dev/issue/63236.)
|
|
||||||
func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) {
|
|
||||||
argp, err := commandLineToArgv(cmd, argc)
|
|
||||||
argv = (*[8192]*[8192]uint16)(unsafe.Pointer(argp))
|
|
||||||
return argv, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func CloseOnExec(fd Handle) {
|
func CloseOnExec(fd Handle) {
|
||||||
SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
|
SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
|
||||||
}
|
}
|
||||||
|
@ -204,45 +95,3 @@ func FullPath(name string) (path string, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProcThreadAttributeList allocates a new ProcThreadAttributeListContainer, with the requested maximum number of attributes.
|
|
||||||
func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeListContainer, error) {
|
|
||||||
var size uintptr
|
|
||||||
err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size)
|
|
||||||
if err != ERROR_INSUFFICIENT_BUFFER {
|
|
||||||
if err == nil {
|
|
||||||
return nil, errorspkg.New("unable to query buffer size from InitializeProcThreadAttributeList")
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
alloc, err := LocalAlloc(LMEM_FIXED, uint32(size))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// size is guaranteed to be ≥1 by InitializeProcThreadAttributeList.
|
|
||||||
al := &ProcThreadAttributeListContainer{data: (*ProcThreadAttributeList)(unsafe.Pointer(alloc))}
|
|
||||||
err = initializeProcThreadAttributeList(al.data, maxAttrCount, 0, &size)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return al, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update modifies the ProcThreadAttributeList using UpdateProcThreadAttribute.
|
|
||||||
func (al *ProcThreadAttributeListContainer) Update(attribute uintptr, value unsafe.Pointer, size uintptr) error {
|
|
||||||
al.pointers = append(al.pointers, value)
|
|
||||||
return updateProcThreadAttribute(al.data, 0, attribute, value, size, nil, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete frees ProcThreadAttributeList's resources.
|
|
||||||
func (al *ProcThreadAttributeListContainer) Delete() {
|
|
||||||
deleteProcThreadAttributeList(al.data)
|
|
||||||
LocalFree(Handle(unsafe.Pointer(al.data)))
|
|
||||||
al.data = nil
|
|
||||||
al.pointers = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns the actual ProcThreadAttributeList to be passed to StartupInfoEx.
|
|
||||||
func (al *ProcThreadAttributeListContainer) List() *ProcThreadAttributeList {
|
|
||||||
return al.data
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,33 +16,11 @@ const (
|
||||||
MEM_RESET_UNDO = 0x01000000
|
MEM_RESET_UNDO = 0x01000000
|
||||||
MEM_LARGE_PAGES = 0x20000000
|
MEM_LARGE_PAGES = 0x20000000
|
||||||
|
|
||||||
PAGE_NOACCESS = 0x00000001
|
PAGE_NOACCESS = 0x01
|
||||||
PAGE_READONLY = 0x00000002
|
PAGE_READONLY = 0x02
|
||||||
PAGE_READWRITE = 0x00000004
|
PAGE_READWRITE = 0x04
|
||||||
PAGE_WRITECOPY = 0x00000008
|
PAGE_WRITECOPY = 0x08
|
||||||
PAGE_EXECUTE = 0x00000010
|
PAGE_EXECUTE_READ = 0x20
|
||||||
PAGE_EXECUTE_READ = 0x00000020
|
PAGE_EXECUTE_READWRITE = 0x40
|
||||||
PAGE_EXECUTE_READWRITE = 0x00000040
|
PAGE_EXECUTE_WRITECOPY = 0x80
|
||||||
PAGE_EXECUTE_WRITECOPY = 0x00000080
|
|
||||||
PAGE_GUARD = 0x00000100
|
|
||||||
PAGE_NOCACHE = 0x00000200
|
|
||||||
PAGE_WRITECOMBINE = 0x00000400
|
|
||||||
PAGE_TARGETS_INVALID = 0x40000000
|
|
||||||
PAGE_TARGETS_NO_UPDATE = 0x40000000
|
|
||||||
|
|
||||||
QUOTA_LIMITS_HARDWS_MIN_DISABLE = 0x00000002
|
|
||||||
QUOTA_LIMITS_HARDWS_MIN_ENABLE = 0x00000001
|
|
||||||
QUOTA_LIMITS_HARDWS_MAX_DISABLE = 0x00000008
|
|
||||||
QUOTA_LIMITS_HARDWS_MAX_ENABLE = 0x00000004
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type MemoryBasicInformation struct {
|
|
||||||
BaseAddress uintptr
|
|
||||||
AllocationBase uintptr
|
|
||||||
AllocationProtect uint32
|
|
||||||
PartitionId uint16
|
|
||||||
RegionSize uintptr
|
|
||||||
State uint32
|
|
||||||
Protect uint32
|
|
||||||
Type uint32
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,8 +9,6 @@ shopt -s nullglob
|
||||||
|
|
||||||
winerror="$(printf '%s\n' "/mnt/c/Program Files (x86)/Windows Kits/"/*/Include/*/shared/winerror.h | sort -Vr | head -n 1)"
|
winerror="$(printf '%s\n' "/mnt/c/Program Files (x86)/Windows Kits/"/*/Include/*/shared/winerror.h | sort -Vr | head -n 1)"
|
||||||
[[ -n $winerror ]] || { echo "Unable to find winerror.h" >&2; exit 1; }
|
[[ -n $winerror ]] || { echo "Unable to find winerror.h" >&2; exit 1; }
|
||||||
ntstatus="$(printf '%s\n' "/mnt/c/Program Files (x86)/Windows Kits/"/*/Include/*/shared/ntstatus.h | sort -Vr | head -n 1)"
|
|
||||||
[[ -n $ntstatus ]] || { echo "Unable to find ntstatus.h" >&2; exit 1; }
|
|
||||||
|
|
||||||
declare -A errors
|
declare -A errors
|
||||||
|
|
||||||
|
@ -61,10 +59,5 @@ declare -A errors
|
||||||
echo "$key $vtype = $value"
|
echo "$key $vtype = $value"
|
||||||
done < "$winerror"
|
done < "$winerror"
|
||||||
|
|
||||||
while read -r line; do
|
|
||||||
[[ $line =~ ^#define\ (STATUS_[^\s]+)\ +\(\(NTSTATUS\)((0x)?[0-9a-fA-F]+)L?\) ]] || continue
|
|
||||||
echo "${BASH_REMATCH[1]} NTStatus = ${BASH_REMATCH[2]}"
|
|
||||||
done < "$ntstatus"
|
|
||||||
|
|
||||||
echo ")"
|
echo ")"
|
||||||
} | gofmt > "zerrors_windows.go"
|
} | gofmt > "zerrors_windows.go"
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build generate
|
// +build generate
|
||||||
|
|
||||||
package windows
|
package windows
|
||||||
|
|
||||||
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go setupapi_windows.go
|
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build windows && race
|
// +build windows,race
|
||||||
|
|
||||||
package windows
|
package windows
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build windows && !race
|
// +build windows,!race
|
||||||
|
|
||||||
package windows
|
package windows
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build windows
|
// +build windows
|
||||||
|
|
||||||
// Package registry provides access to the Windows registry.
|
// Package registry provides access to the Windows registry.
|
||||||
//
|
//
|
||||||
|
@ -19,11 +19,11 @@
|
||||||
// log.Fatal(err)
|
// log.Fatal(err)
|
||||||
// }
|
// }
|
||||||
// fmt.Printf("Windows system root is %q\n", s)
|
// fmt.Printf("Windows system root is %q\n", s)
|
||||||
|
//
|
||||||
package registry
|
package registry
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"runtime"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -113,13 +113,6 @@ func OpenRemoteKey(pcname string, k Key) (Key, error) {
|
||||||
// The parameter n controls the number of returned names,
|
// The parameter n controls the number of returned names,
|
||||||
// analogous to the way os.File.Readdirnames works.
|
// analogous to the way os.File.Readdirnames works.
|
||||||
func (k Key) ReadSubKeyNames(n int) ([]string, error) {
|
func (k Key) ReadSubKeyNames(n int) ([]string, error) {
|
||||||
// RegEnumKeyEx must be called repeatedly and to completion.
|
|
||||||
// During this time, this goroutine cannot migrate away from
|
|
||||||
// its current thread. See https://golang.org/issue/49320 and
|
|
||||||
// https://golang.org/issue/49466.
|
|
||||||
runtime.LockOSThread()
|
|
||||||
defer runtime.UnlockOSThread()
|
|
||||||
|
|
||||||
names := make([]string, 0)
|
names := make([]string, 0)
|
||||||
// Registry key size limit is 255 bytes and described there:
|
// Registry key size limit is 255 bytes and described there:
|
||||||
// https://msdn.microsoft.com/library/windows/desktop/ms724872.aspx
|
// https://msdn.microsoft.com/library/windows/desktop/ms724872.aspx
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build generate
|
// +build generate
|
||||||
|
|
||||||
package registry
|
package registry
|
||||||
|
|
||||||
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall.go
|
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall.go
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build windows
|
// +build windows
|
||||||
|
|
||||||
package registry
|
package registry
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build windows
|
// +build windows
|
||||||
|
|
||||||
package registry
|
package registry
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ func (k Key) GetStringValue(name string) (val string, valtype uint32, err error)
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return "", typ, nil
|
return "", typ, nil
|
||||||
}
|
}
|
||||||
u := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[: len(data)/2 : len(data)/2]
|
u := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[:]
|
||||||
return syscall.UTF16ToString(u), typ, nil
|
return syscall.UTF16ToString(u), typ, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +185,8 @@ func ExpandString(value string) (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if n <= uint32(len(r)) {
|
if n <= uint32(len(r)) {
|
||||||
return syscall.UTF16ToString(r[:n]), nil
|
u := (*[1 << 29]uint16)(unsafe.Pointer(&r[0]))[:]
|
||||||
|
return syscall.UTF16ToString(u), nil
|
||||||
}
|
}
|
||||||
r = make([]uint16, n)
|
r = make([]uint16, n)
|
||||||
}
|
}
|
||||||
|
@ -207,7 +208,7 @@ func (k Key) GetStringsValue(name string) (val []string, valtype uint32, err err
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return nil, typ, nil
|
return nil, typ, nil
|
||||||
}
|
}
|
||||||
p := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[: len(data)/2 : len(data)/2]
|
p := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[:len(data)/2]
|
||||||
if len(p) == 0 {
|
if len(p) == 0 {
|
||||||
return nil, typ, nil
|
return nil, typ, nil
|
||||||
}
|
}
|
||||||
|
@ -298,7 +299,7 @@ func (k Key) setStringValue(name string, valtype uint32, value string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[: len(v)*2 : len(v)*2]
|
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
|
||||||
return k.setValue(name, valtype, buf)
|
return k.setValue(name, valtype, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,7 +329,7 @@ func (k Key) SetStringsValue(name string, value []string) error {
|
||||||
ss += s + "\x00"
|
ss += s + "\x00"
|
||||||
}
|
}
|
||||||
v := utf16.Encode([]rune(ss + "\x00"))
|
v := utf16.Encode([]rune(ss + "\x00"))
|
||||||
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[: len(v)*2 : len(v)*2]
|
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
|
||||||
return k.setValue(name, MULTI_SZ, buf)
|
return k.setValue(name, MULTI_SZ, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ const (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||||
errERROR_EINVAL error = syscall.EINVAL
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// errnoErr returns common boxed Errno values, to prevent
|
// errnoErr returns common boxed Errno values, to prevent
|
||||||
|
@ -27,7 +26,7 @@ var (
|
||||||
func errnoErr(e syscall.Errno) error {
|
func errnoErr(e syscall.Errno) error {
|
||||||
switch e {
|
switch e {
|
||||||
case 0:
|
case 0:
|
||||||
return errERROR_EINVAL
|
return nil
|
||||||
case errnoERROR_IO_PENDING:
|
case errnoERROR_IO_PENDING:
|
||||||
return errERROR_IO_PENDING
|
return errERROR_IO_PENDING
|
||||||
}
|
}
|
||||||
|
@ -41,24 +40,16 @@ var (
|
||||||
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||||
|
|
||||||
procRegConnectRegistryW = modadvapi32.NewProc("RegConnectRegistryW")
|
|
||||||
procRegCreateKeyExW = modadvapi32.NewProc("RegCreateKeyExW")
|
procRegCreateKeyExW = modadvapi32.NewProc("RegCreateKeyExW")
|
||||||
procRegDeleteKeyW = modadvapi32.NewProc("RegDeleteKeyW")
|
procRegDeleteKeyW = modadvapi32.NewProc("RegDeleteKeyW")
|
||||||
procRegDeleteValueW = modadvapi32.NewProc("RegDeleteValueW")
|
|
||||||
procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
|
|
||||||
procRegLoadMUIStringW = modadvapi32.NewProc("RegLoadMUIStringW")
|
|
||||||
procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW")
|
procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW")
|
||||||
|
procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
|
||||||
|
procRegDeleteValueW = modadvapi32.NewProc("RegDeleteValueW")
|
||||||
|
procRegLoadMUIStringW = modadvapi32.NewProc("RegLoadMUIStringW")
|
||||||
|
procRegConnectRegistryW = modadvapi32.NewProc("RegConnectRegistryW")
|
||||||
procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW")
|
procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW")
|
||||||
)
|
)
|
||||||
|
|
||||||
func regConnectRegistry(machinename *uint16, key syscall.Handle, result *syscall.Handle) (regerrno error) {
|
|
||||||
r0, _, _ := syscall.Syscall(procRegConnectRegistryW.Addr(), 3, uintptr(unsafe.Pointer(machinename)), uintptr(key), uintptr(unsafe.Pointer(result)))
|
|
||||||
if r0 != 0 {
|
|
||||||
regerrno = syscall.Errno(r0)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) {
|
func regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) {
|
||||||
r0, _, _ := syscall.Syscall9(procRegCreateKeyExW.Addr(), 9, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(reserved), uintptr(unsafe.Pointer(class)), uintptr(options), uintptr(desired), uintptr(unsafe.Pointer(sa)), uintptr(unsafe.Pointer(result)), uintptr(unsafe.Pointer(disposition)))
|
r0, _, _ := syscall.Syscall9(procRegCreateKeyExW.Addr(), 9, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(reserved), uintptr(unsafe.Pointer(class)), uintptr(options), uintptr(desired), uintptr(unsafe.Pointer(sa)), uintptr(unsafe.Pointer(result)), uintptr(unsafe.Pointer(disposition)))
|
||||||
if r0 != 0 {
|
if r0 != 0 {
|
||||||
|
@ -75,8 +66,8 @@ func regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) {
|
func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) {
|
||||||
r0, _, _ := syscall.Syscall(procRegDeleteValueW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(name)), 0)
|
r0, _, _ := syscall.Syscall6(procRegSetValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(valueName)), uintptr(reserved), uintptr(vtype), uintptr(unsafe.Pointer(buf)), uintptr(bufsize))
|
||||||
if r0 != 0 {
|
if r0 != 0 {
|
||||||
regerrno = syscall.Errno(r0)
|
regerrno = syscall.Errno(r0)
|
||||||
}
|
}
|
||||||
|
@ -91,6 +82,14 @@ func regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint3
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall(procRegDeleteValueW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(name)), 0)
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) {
|
func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) {
|
||||||
r0, _, _ := syscall.Syscall9(procRegLoadMUIStringW.Addr(), 7, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(unsafe.Pointer(buflenCopied)), uintptr(flags), uintptr(unsafe.Pointer(dir)), 0, 0)
|
r0, _, _ := syscall.Syscall9(procRegLoadMUIStringW.Addr(), 7, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(unsafe.Pointer(buflenCopied)), uintptr(flags), uintptr(unsafe.Pointer(dir)), 0, 0)
|
||||||
if r0 != 0 {
|
if r0 != 0 {
|
||||||
|
@ -99,8 +98,8 @@ func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) {
|
func regConnectRegistry(machinename *uint16, key syscall.Handle, result *syscall.Handle) (regerrno error) {
|
||||||
r0, _, _ := syscall.Syscall6(procRegSetValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(valueName)), uintptr(reserved), uintptr(vtype), uintptr(unsafe.Pointer(buf)), uintptr(bufsize))
|
r0, _, _ := syscall.Syscall(procRegConnectRegistryW.Addr(), 3, uintptr(unsafe.Pointer(machinename)), uintptr(key), uintptr(unsafe.Pointer(result)))
|
||||||
if r0 != 0 {
|
if r0 != 0 {
|
||||||
regerrno = syscall.Errno(r0)
|
regerrno = syscall.Errno(r0)
|
||||||
}
|
}
|
||||||
|
@ -111,7 +110,11 @@ func expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32,
|
||||||
r0, _, e1 := syscall.Syscall(procExpandEnvironmentStringsW.Addr(), 3, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size))
|
r0, _, e1 := syscall.Syscall(procExpandEnvironmentStringsW.Addr(), 3, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size))
|
||||||
n = uint32(r0)
|
n = uint32(r0)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
err = errnoErr(e1)
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,14 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
STANDARD_RIGHTS_REQUIRED = 0xf0000
|
||||||
|
STANDARD_RIGHTS_READ = 0x20000
|
||||||
|
STANDARD_RIGHTS_WRITE = 0x20000
|
||||||
|
STANDARD_RIGHTS_EXECUTE = 0x20000
|
||||||
|
STANDARD_RIGHTS_ALL = 0x1F0000
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NameUnknown = 0
|
NameUnknown = 0
|
||||||
NameFullyQualifiedDN = 1
|
NameFullyQualifiedDN = 1
|
||||||
|
@ -227,15 +235,16 @@ func LookupSID(system, account string) (sid *SID, domain string, accType uint32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// String converts SID to a string format suitable for display, storage, or transmission.
|
// String converts SID to a string format
|
||||||
func (sid *SID) String() string {
|
// suitable for display, storage, or transmission.
|
||||||
|
func (sid *SID) String() (string, error) {
|
||||||
var s *uint16
|
var s *uint16
|
||||||
e := ConvertSidToStringSid(sid, &s)
|
e := ConvertSidToStringSid(sid, &s)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return ""
|
return "", e
|
||||||
}
|
}
|
||||||
defer LocalFree((Handle)(unsafe.Pointer(s)))
|
defer LocalFree((Handle)(unsafe.Pointer(s)))
|
||||||
return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:])
|
return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Len returns the length, in bytes, of a valid security identifier SID.
|
// Len returns the length, in bytes, of a valid security identifier SID.
|
||||||
|
@ -622,7 +631,6 @@ func (tml *Tokenmandatorylabel) Size() uint32 {
|
||||||
|
|
||||||
// Authorization Functions
|
// Authorization Functions
|
||||||
//sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
|
//sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
|
||||||
//sys isTokenRestricted(tokenHandle Token) (ret bool, err error) [!failretval] = advapi32.IsTokenRestricted
|
|
||||||
//sys OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
|
//sys OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
|
||||||
//sys OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken
|
//sys OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken
|
||||||
//sys ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
|
//sys ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
|
||||||
|
@ -636,8 +644,6 @@ func (tml *Tokenmandatorylabel) Size() uint32 {
|
||||||
//sys DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx
|
//sys DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx
|
||||||
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
|
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
|
||||||
//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
|
//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
|
||||||
//sys getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetWindowsDirectoryW
|
|
||||||
//sys getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemWindowsDirectoryW
|
|
||||||
|
|
||||||
// An access token contains the security information for a logon session.
|
// An access token contains the security information for a logon session.
|
||||||
// The system creates an access token when a user logs on, and every
|
// The system creates an access token when a user logs on, and every
|
||||||
|
@ -648,16 +654,21 @@ func (tml *Tokenmandatorylabel) Size() uint32 {
|
||||||
// system-related operations on the local computer.
|
// system-related operations on the local computer.
|
||||||
type Token Handle
|
type Token Handle
|
||||||
|
|
||||||
// OpenCurrentProcessToken opens an access token associated with current
|
// OpenCurrentProcessToken opens the access token
|
||||||
// process with TOKEN_QUERY access. It is a real token that needs to be closed.
|
// associated with current process. It is a real
|
||||||
//
|
// token that needs to be closed, unlike
|
||||||
// Deprecated: Explicitly call OpenProcessToken(CurrentProcess(), ...)
|
// GetCurrentProcessToken.
|
||||||
// with the desired access instead, or use GetCurrentProcessToken for a
|
|
||||||
// TOKEN_QUERY token.
|
|
||||||
func OpenCurrentProcessToken() (Token, error) {
|
func OpenCurrentProcessToken() (Token, error) {
|
||||||
var token Token
|
p, e := GetCurrentProcess()
|
||||||
err := OpenProcessToken(CurrentProcess(), TOKEN_QUERY, &token)
|
if e != nil {
|
||||||
return token, err
|
return 0, e
|
||||||
|
}
|
||||||
|
var t Token
|
||||||
|
e = OpenProcessToken(p, TOKEN_QUERY, &t)
|
||||||
|
if e != nil {
|
||||||
|
return 0, e
|
||||||
|
}
|
||||||
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentProcessToken returns the access token associated with
|
// GetCurrentProcessToken returns the access token associated with
|
||||||
|
@ -774,8 +785,8 @@ func (token Token) GetLinkedToken() (Token, error) {
|
||||||
return linkedToken, nil
|
return linkedToken, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSystemDirectory retrieves the path to current location of the system
|
// GetSystemDirectory retrieves path to current location of the system
|
||||||
// directory, which is typically, though not always, `C:\Windows\System32`.
|
// directory, which is typically, though not always, C:\Windows\System32.
|
||||||
func GetSystemDirectory() (string, error) {
|
func GetSystemDirectory() (string, error) {
|
||||||
n := uint32(MAX_PATH)
|
n := uint32(MAX_PATH)
|
||||||
for {
|
for {
|
||||||
|
@ -791,42 +802,6 @@ func GetSystemDirectory() (string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWindowsDirectory retrieves the path to current location of the Windows
|
|
||||||
// directory, which is typically, though not always, `C:\Windows`. This may
|
|
||||||
// be a private user directory in the case that the application is running
|
|
||||||
// under a terminal server.
|
|
||||||
func GetWindowsDirectory() (string, error) {
|
|
||||||
n := uint32(MAX_PATH)
|
|
||||||
for {
|
|
||||||
b := make([]uint16, n)
|
|
||||||
l, e := getWindowsDirectory(&b[0], n)
|
|
||||||
if e != nil {
|
|
||||||
return "", e
|
|
||||||
}
|
|
||||||
if l <= n {
|
|
||||||
return UTF16ToString(b[:l]), nil
|
|
||||||
}
|
|
||||||
n = l
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSystemWindowsDirectory retrieves the path to current location of the
|
|
||||||
// Windows directory, which is typically, though not always, `C:\Windows`.
|
|
||||||
func GetSystemWindowsDirectory() (string, error) {
|
|
||||||
n := uint32(MAX_PATH)
|
|
||||||
for {
|
|
||||||
b := make([]uint16, n)
|
|
||||||
l, e := getSystemWindowsDirectory(&b[0], n)
|
|
||||||
if e != nil {
|
|
||||||
return "", e
|
|
||||||
}
|
|
||||||
if l <= n {
|
|
||||||
return UTF16ToString(b[:l]), nil
|
|
||||||
}
|
|
||||||
n = l
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsMember reports whether the access token t is a member of the provided SID.
|
// IsMember reports whether the access token t is a member of the provided SID.
|
||||||
func (t Token) IsMember(sid *SID) (bool, error) {
|
func (t Token) IsMember(sid *SID) (bool, error) {
|
||||||
var b int32
|
var b int32
|
||||||
|
@ -836,16 +811,6 @@ func (t Token) IsMember(sid *SID) (bool, error) {
|
||||||
return b != 0, nil
|
return b != 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRestricted reports whether the access token t is a restricted token.
|
|
||||||
func (t Token) IsRestricted() (isRestricted bool, err error) {
|
|
||||||
isRestricted, err = isTokenRestricted(t)
|
|
||||||
if !isRestricted && err == syscall.EINVAL {
|
|
||||||
// If err is EINVAL, this returned ERROR_SUCCESS indicating a non-restricted token.
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
WTS_CONSOLE_CONNECT = 0x1
|
WTS_CONSOLE_CONNECT = 0x1
|
||||||
WTS_CONSOLE_DISCONNECT = 0x2
|
WTS_CONSOLE_DISCONNECT = 0x2
|
||||||
|
@ -887,549 +852,3 @@ type WTS_SESSION_INFO struct {
|
||||||
//sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken
|
//sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken
|
||||||
//sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW
|
//sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW
|
||||||
//sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory
|
//sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory
|
||||||
//sys WTSGetActiveConsoleSessionId() (sessionID uint32)
|
|
||||||
|
|
||||||
type ACL struct {
|
|
||||||
aclRevision byte
|
|
||||||
sbz1 byte
|
|
||||||
aclSize uint16
|
|
||||||
aceCount uint16
|
|
||||||
sbz2 uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
type SECURITY_DESCRIPTOR struct {
|
|
||||||
revision byte
|
|
||||||
sbz1 byte
|
|
||||||
control SECURITY_DESCRIPTOR_CONTROL
|
|
||||||
owner *SID
|
|
||||||
group *SID
|
|
||||||
sacl *ACL
|
|
||||||
dacl *ACL
|
|
||||||
}
|
|
||||||
|
|
||||||
type SECURITY_QUALITY_OF_SERVICE struct {
|
|
||||||
Length uint32
|
|
||||||
ImpersonationLevel uint32
|
|
||||||
ContextTrackingMode byte
|
|
||||||
EffectiveOnly byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constants for the ContextTrackingMode field of SECURITY_QUALITY_OF_SERVICE.
|
|
||||||
const (
|
|
||||||
SECURITY_STATIC_TRACKING = 0
|
|
||||||
SECURITY_DYNAMIC_TRACKING = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
type SecurityAttributes struct {
|
|
||||||
Length uint32
|
|
||||||
SecurityDescriptor *SECURITY_DESCRIPTOR
|
|
||||||
InheritHandle uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type SE_OBJECT_TYPE uint32
|
|
||||||
|
|
||||||
// Constants for type SE_OBJECT_TYPE
|
|
||||||
const (
|
|
||||||
SE_UNKNOWN_OBJECT_TYPE = 0
|
|
||||||
SE_FILE_OBJECT = 1
|
|
||||||
SE_SERVICE = 2
|
|
||||||
SE_PRINTER = 3
|
|
||||||
SE_REGISTRY_KEY = 4
|
|
||||||
SE_LMSHARE = 5
|
|
||||||
SE_KERNEL_OBJECT = 6
|
|
||||||
SE_WINDOW_OBJECT = 7
|
|
||||||
SE_DS_OBJECT = 8
|
|
||||||
SE_DS_OBJECT_ALL = 9
|
|
||||||
SE_PROVIDER_DEFINED_OBJECT = 10
|
|
||||||
SE_WMIGUID_OBJECT = 11
|
|
||||||
SE_REGISTRY_WOW64_32KEY = 12
|
|
||||||
SE_REGISTRY_WOW64_64KEY = 13
|
|
||||||
)
|
|
||||||
|
|
||||||
type SECURITY_INFORMATION uint32
|
|
||||||
|
|
||||||
// Constants for type SECURITY_INFORMATION
|
|
||||||
const (
|
|
||||||
OWNER_SECURITY_INFORMATION = 0x00000001
|
|
||||||
GROUP_SECURITY_INFORMATION = 0x00000002
|
|
||||||
DACL_SECURITY_INFORMATION = 0x00000004
|
|
||||||
SACL_SECURITY_INFORMATION = 0x00000008
|
|
||||||
LABEL_SECURITY_INFORMATION = 0x00000010
|
|
||||||
ATTRIBUTE_SECURITY_INFORMATION = 0x00000020
|
|
||||||
SCOPE_SECURITY_INFORMATION = 0x00000040
|
|
||||||
BACKUP_SECURITY_INFORMATION = 0x00010000
|
|
||||||
PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
|
|
||||||
PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000
|
|
||||||
UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000
|
|
||||||
UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000
|
|
||||||
)
|
|
||||||
|
|
||||||
type SECURITY_DESCRIPTOR_CONTROL uint16
|
|
||||||
|
|
||||||
// Constants for type SECURITY_DESCRIPTOR_CONTROL
|
|
||||||
const (
|
|
||||||
SE_OWNER_DEFAULTED = 0x0001
|
|
||||||
SE_GROUP_DEFAULTED = 0x0002
|
|
||||||
SE_DACL_PRESENT = 0x0004
|
|
||||||
SE_DACL_DEFAULTED = 0x0008
|
|
||||||
SE_SACL_PRESENT = 0x0010
|
|
||||||
SE_SACL_DEFAULTED = 0x0020
|
|
||||||
SE_DACL_AUTO_INHERIT_REQ = 0x0100
|
|
||||||
SE_SACL_AUTO_INHERIT_REQ = 0x0200
|
|
||||||
SE_DACL_AUTO_INHERITED = 0x0400
|
|
||||||
SE_SACL_AUTO_INHERITED = 0x0800
|
|
||||||
SE_DACL_PROTECTED = 0x1000
|
|
||||||
SE_SACL_PROTECTED = 0x2000
|
|
||||||
SE_RM_CONTROL_VALID = 0x4000
|
|
||||||
SE_SELF_RELATIVE = 0x8000
|
|
||||||
)
|
|
||||||
|
|
||||||
type ACCESS_MASK uint32
|
|
||||||
|
|
||||||
// Constants for type ACCESS_MASK
|
|
||||||
const (
|
|
||||||
DELETE = 0x00010000
|
|
||||||
READ_CONTROL = 0x00020000
|
|
||||||
WRITE_DAC = 0x00040000
|
|
||||||
WRITE_OWNER = 0x00080000
|
|
||||||
SYNCHRONIZE = 0x00100000
|
|
||||||
STANDARD_RIGHTS_REQUIRED = 0x000F0000
|
|
||||||
STANDARD_RIGHTS_READ = READ_CONTROL
|
|
||||||
STANDARD_RIGHTS_WRITE = READ_CONTROL
|
|
||||||
STANDARD_RIGHTS_EXECUTE = READ_CONTROL
|
|
||||||
STANDARD_RIGHTS_ALL = 0x001F0000
|
|
||||||
SPECIFIC_RIGHTS_ALL = 0x0000FFFF
|
|
||||||
ACCESS_SYSTEM_SECURITY = 0x01000000
|
|
||||||
MAXIMUM_ALLOWED = 0x02000000
|
|
||||||
GENERIC_READ = 0x80000000
|
|
||||||
GENERIC_WRITE = 0x40000000
|
|
||||||
GENERIC_EXECUTE = 0x20000000
|
|
||||||
GENERIC_ALL = 0x10000000
|
|
||||||
)
|
|
||||||
|
|
||||||
type ACCESS_MODE uint32
|
|
||||||
|
|
||||||
// Constants for type ACCESS_MODE
|
|
||||||
const (
|
|
||||||
NOT_USED_ACCESS = 0
|
|
||||||
GRANT_ACCESS = 1
|
|
||||||
SET_ACCESS = 2
|
|
||||||
DENY_ACCESS = 3
|
|
||||||
REVOKE_ACCESS = 4
|
|
||||||
SET_AUDIT_SUCCESS = 5
|
|
||||||
SET_AUDIT_FAILURE = 6
|
|
||||||
)
|
|
||||||
|
|
||||||
// Constants for AceFlags and Inheritance fields
|
|
||||||
const (
|
|
||||||
NO_INHERITANCE = 0x0
|
|
||||||
SUB_OBJECTS_ONLY_INHERIT = 0x1
|
|
||||||
SUB_CONTAINERS_ONLY_INHERIT = 0x2
|
|
||||||
SUB_CONTAINERS_AND_OBJECTS_INHERIT = 0x3
|
|
||||||
INHERIT_NO_PROPAGATE = 0x4
|
|
||||||
INHERIT_ONLY = 0x8
|
|
||||||
INHERITED_ACCESS_ENTRY = 0x10
|
|
||||||
INHERITED_PARENT = 0x10000000
|
|
||||||
INHERITED_GRANDPARENT = 0x20000000
|
|
||||||
OBJECT_INHERIT_ACE = 0x1
|
|
||||||
CONTAINER_INHERIT_ACE = 0x2
|
|
||||||
NO_PROPAGATE_INHERIT_ACE = 0x4
|
|
||||||
INHERIT_ONLY_ACE = 0x8
|
|
||||||
INHERITED_ACE = 0x10
|
|
||||||
VALID_INHERIT_FLAGS = 0x1F
|
|
||||||
)
|
|
||||||
|
|
||||||
type MULTIPLE_TRUSTEE_OPERATION uint32
|
|
||||||
|
|
||||||
// Constants for MULTIPLE_TRUSTEE_OPERATION
|
|
||||||
const (
|
|
||||||
NO_MULTIPLE_TRUSTEE = 0
|
|
||||||
TRUSTEE_IS_IMPERSONATE = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
type TRUSTEE_FORM uint32
|
|
||||||
|
|
||||||
// Constants for TRUSTEE_FORM
|
|
||||||
const (
|
|
||||||
TRUSTEE_IS_SID = 0
|
|
||||||
TRUSTEE_IS_NAME = 1
|
|
||||||
TRUSTEE_BAD_FORM = 2
|
|
||||||
TRUSTEE_IS_OBJECTS_AND_SID = 3
|
|
||||||
TRUSTEE_IS_OBJECTS_AND_NAME = 4
|
|
||||||
)
|
|
||||||
|
|
||||||
type TRUSTEE_TYPE uint32
|
|
||||||
|
|
||||||
// Constants for TRUSTEE_TYPE
|
|
||||||
const (
|
|
||||||
TRUSTEE_IS_UNKNOWN = 0
|
|
||||||
TRUSTEE_IS_USER = 1
|
|
||||||
TRUSTEE_IS_GROUP = 2
|
|
||||||
TRUSTEE_IS_DOMAIN = 3
|
|
||||||
TRUSTEE_IS_ALIAS = 4
|
|
||||||
TRUSTEE_IS_WELL_KNOWN_GROUP = 5
|
|
||||||
TRUSTEE_IS_DELETED = 6
|
|
||||||
TRUSTEE_IS_INVALID = 7
|
|
||||||
TRUSTEE_IS_COMPUTER = 8
|
|
||||||
)
|
|
||||||
|
|
||||||
// Constants for ObjectsPresent field
|
|
||||||
const (
|
|
||||||
ACE_OBJECT_TYPE_PRESENT = 0x1
|
|
||||||
ACE_INHERITED_OBJECT_TYPE_PRESENT = 0x2
|
|
||||||
)
|
|
||||||
|
|
||||||
type EXPLICIT_ACCESS struct {
|
|
||||||
AccessPermissions ACCESS_MASK
|
|
||||||
AccessMode ACCESS_MODE
|
|
||||||
Inheritance uint32
|
|
||||||
Trustee TRUSTEE
|
|
||||||
}
|
|
||||||
|
|
||||||
// This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions.
|
|
||||||
type TrusteeValue uintptr
|
|
||||||
|
|
||||||
func TrusteeValueFromString(str string) TrusteeValue {
|
|
||||||
return TrusteeValue(unsafe.Pointer(StringToUTF16Ptr(str)))
|
|
||||||
}
|
|
||||||
func TrusteeValueFromSID(sid *SID) TrusteeValue {
|
|
||||||
return TrusteeValue(unsafe.Pointer(sid))
|
|
||||||
}
|
|
||||||
func TrusteeValueFromObjectsAndSid(objectsAndSid *OBJECTS_AND_SID) TrusteeValue {
|
|
||||||
return TrusteeValue(unsafe.Pointer(objectsAndSid))
|
|
||||||
}
|
|
||||||
func TrusteeValueFromObjectsAndName(objectsAndName *OBJECTS_AND_NAME) TrusteeValue {
|
|
||||||
return TrusteeValue(unsafe.Pointer(objectsAndName))
|
|
||||||
}
|
|
||||||
|
|
||||||
type TRUSTEE struct {
|
|
||||||
MultipleTrustee *TRUSTEE
|
|
||||||
MultipleTrusteeOperation MULTIPLE_TRUSTEE_OPERATION
|
|
||||||
TrusteeForm TRUSTEE_FORM
|
|
||||||
TrusteeType TRUSTEE_TYPE
|
|
||||||
TrusteeValue TrusteeValue
|
|
||||||
}
|
|
||||||
|
|
||||||
type OBJECTS_AND_SID struct {
|
|
||||||
ObjectsPresent uint32
|
|
||||||
ObjectTypeGuid GUID
|
|
||||||
InheritedObjectTypeGuid GUID
|
|
||||||
Sid *SID
|
|
||||||
}
|
|
||||||
|
|
||||||
type OBJECTS_AND_NAME struct {
|
|
||||||
ObjectsPresent uint32
|
|
||||||
ObjectType SE_OBJECT_TYPE
|
|
||||||
ObjectTypeName *uint16
|
|
||||||
InheritedObjectTypeName *uint16
|
|
||||||
Name *uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
//sys getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetSecurityInfo
|
|
||||||
//sys SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetSecurityInfo
|
|
||||||
//sys getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetNamedSecurityInfoW
|
|
||||||
//sys SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetNamedSecurityInfoW
|
|
||||||
//sys SetKernelObjectSecurity(handle Handle, securityInformation SECURITY_INFORMATION, securityDescriptor *SECURITY_DESCRIPTOR) (err error) = advapi32.SetKernelObjectSecurity
|
|
||||||
|
|
||||||
//sys buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) = advapi32.BuildSecurityDescriptorW
|
|
||||||
//sys initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) = advapi32.InitializeSecurityDescriptor
|
|
||||||
|
|
||||||
//sys getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) = advapi32.GetSecurityDescriptorControl
|
|
||||||
//sys getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorDacl
|
|
||||||
//sys getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorSacl
|
|
||||||
//sys getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorOwner
|
|
||||||
//sys getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorGroup
|
|
||||||
//sys getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) = advapi32.GetSecurityDescriptorLength
|
|
||||||
//sys getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) [failretval!=0] = advapi32.GetSecurityDescriptorRMControl
|
|
||||||
//sys isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) = advapi32.IsValidSecurityDescriptor
|
|
||||||
|
|
||||||
//sys setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) = advapi32.SetSecurityDescriptorControl
|
|
||||||
//sys setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorDacl
|
|
||||||
//sys setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorSacl
|
|
||||||
//sys setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) = advapi32.SetSecurityDescriptorOwner
|
|
||||||
//sys setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) = advapi32.SetSecurityDescriptorGroup
|
|
||||||
//sys setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) = advapi32.SetSecurityDescriptorRMControl
|
|
||||||
|
|
||||||
//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
|
|
||||||
//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
|
|
||||||
|
|
||||||
//sys makeAbsoluteSD(selfRelativeSD *SECURITY_DESCRIPTOR, absoluteSD *SECURITY_DESCRIPTOR, absoluteSDSize *uint32, dacl *ACL, daclSize *uint32, sacl *ACL, saclSize *uint32, owner *SID, ownerSize *uint32, group *SID, groupSize *uint32) (err error) = advapi32.MakeAbsoluteSD
|
|
||||||
//sys makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD
|
|
||||||
|
|
||||||
//sys setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW
|
|
||||||
|
|
||||||
// Control returns the security descriptor control bits.
|
|
||||||
func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) {
|
|
||||||
err = getSecurityDescriptorControl(sd, &control, &revision)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetControl sets the security descriptor control bits.
|
|
||||||
func (sd *SECURITY_DESCRIPTOR) SetControl(controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) error {
|
|
||||||
return setSecurityDescriptorControl(sd, controlBitsOfInterest, controlBitsToSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RMControl returns the security descriptor resource manager control bits.
|
|
||||||
func (sd *SECURITY_DESCRIPTOR) RMControl() (control uint8, err error) {
|
|
||||||
err = getSecurityDescriptorRMControl(sd, &control)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetRMControl sets the security descriptor resource manager control bits.
|
|
||||||
func (sd *SECURITY_DESCRIPTOR) SetRMControl(rmControl uint8) {
|
|
||||||
setSecurityDescriptorRMControl(sd, &rmControl)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DACL returns the security descriptor DACL and whether it was defaulted. The dacl return value may be nil
|
|
||||||
// if a DACL exists but is an "empty DACL", meaning fully permissive. If the DACL does not exist, err returns
|
|
||||||
// ERROR_OBJECT_NOT_FOUND.
|
|
||||||
func (sd *SECURITY_DESCRIPTOR) DACL() (dacl *ACL, defaulted bool, err error) {
|
|
||||||
var present bool
|
|
||||||
err = getSecurityDescriptorDacl(sd, &present, &dacl, &defaulted)
|
|
||||||
if !present {
|
|
||||||
err = ERROR_OBJECT_NOT_FOUND
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetDACL sets the absolute security descriptor DACL.
|
|
||||||
func (absoluteSD *SECURITY_DESCRIPTOR) SetDACL(dacl *ACL, present, defaulted bool) error {
|
|
||||||
return setSecurityDescriptorDacl(absoluteSD, present, dacl, defaulted)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SACL returns the security descriptor SACL and whether it was defaulted. The sacl return value may be nil
|
|
||||||
// if a SACL exists but is an "empty SACL", meaning fully permissive. If the SACL does not exist, err returns
|
|
||||||
// ERROR_OBJECT_NOT_FOUND.
|
|
||||||
func (sd *SECURITY_DESCRIPTOR) SACL() (sacl *ACL, defaulted bool, err error) {
|
|
||||||
var present bool
|
|
||||||
err = getSecurityDescriptorSacl(sd, &present, &sacl, &defaulted)
|
|
||||||
if !present {
|
|
||||||
err = ERROR_OBJECT_NOT_FOUND
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetSACL sets the absolute security descriptor SACL.
|
|
||||||
func (absoluteSD *SECURITY_DESCRIPTOR) SetSACL(sacl *ACL, present, defaulted bool) error {
|
|
||||||
return setSecurityDescriptorSacl(absoluteSD, present, sacl, defaulted)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Owner returns the security descriptor owner and whether it was defaulted.
|
|
||||||
func (sd *SECURITY_DESCRIPTOR) Owner() (owner *SID, defaulted bool, err error) {
|
|
||||||
err = getSecurityDescriptorOwner(sd, &owner, &defaulted)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOwner sets the absolute security descriptor owner.
|
|
||||||
func (absoluteSD *SECURITY_DESCRIPTOR) SetOwner(owner *SID, defaulted bool) error {
|
|
||||||
return setSecurityDescriptorOwner(absoluteSD, owner, defaulted)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Group returns the security descriptor group and whether it was defaulted.
|
|
||||||
func (sd *SECURITY_DESCRIPTOR) Group() (group *SID, defaulted bool, err error) {
|
|
||||||
err = getSecurityDescriptorGroup(sd, &group, &defaulted)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetGroup sets the absolute security descriptor owner.
|
|
||||||
func (absoluteSD *SECURITY_DESCRIPTOR) SetGroup(group *SID, defaulted bool) error {
|
|
||||||
return setSecurityDescriptorGroup(absoluteSD, group, defaulted)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Length returns the length of the security descriptor.
|
|
||||||
func (sd *SECURITY_DESCRIPTOR) Length() uint32 {
|
|
||||||
return getSecurityDescriptorLength(sd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValid returns whether the security descriptor is valid.
|
|
||||||
func (sd *SECURITY_DESCRIPTOR) IsValid() bool {
|
|
||||||
return isValidSecurityDescriptor(sd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the SDDL form of the security descriptor, with a function signature that can be
|
|
||||||
// used with %v formatting directives.
|
|
||||||
func (sd *SECURITY_DESCRIPTOR) String() string {
|
|
||||||
var sddl *uint16
|
|
||||||
err := convertSecurityDescriptorToStringSecurityDescriptor(sd, 1, 0xff, &sddl, nil)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
defer LocalFree(Handle(unsafe.Pointer(sddl)))
|
|
||||||
return UTF16PtrToString(sddl)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToAbsolute converts a self-relative security descriptor into an absolute one.
|
|
||||||
func (selfRelativeSD *SECURITY_DESCRIPTOR) ToAbsolute() (absoluteSD *SECURITY_DESCRIPTOR, err error) {
|
|
||||||
control, _, err := selfRelativeSD.Control()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if control&SE_SELF_RELATIVE == 0 {
|
|
||||||
err = ERROR_INVALID_PARAMETER
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var absoluteSDSize, daclSize, saclSize, ownerSize, groupSize uint32
|
|
||||||
err = makeAbsoluteSD(selfRelativeSD, nil, &absoluteSDSize,
|
|
||||||
nil, &daclSize, nil, &saclSize, nil, &ownerSize, nil, &groupSize)
|
|
||||||
switch err {
|
|
||||||
case ERROR_INSUFFICIENT_BUFFER:
|
|
||||||
case nil:
|
|
||||||
// makeAbsoluteSD is expected to fail, but it succeeds.
|
|
||||||
return nil, ERROR_INTERNAL_ERROR
|
|
||||||
default:
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if absoluteSDSize > 0 {
|
|
||||||
absoluteSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, absoluteSDSize)[0]))
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
dacl *ACL
|
|
||||||
sacl *ACL
|
|
||||||
owner *SID
|
|
||||||
group *SID
|
|
||||||
)
|
|
||||||
if daclSize > 0 {
|
|
||||||
dacl = (*ACL)(unsafe.Pointer(&make([]byte, daclSize)[0]))
|
|
||||||
}
|
|
||||||
if saclSize > 0 {
|
|
||||||
sacl = (*ACL)(unsafe.Pointer(&make([]byte, saclSize)[0]))
|
|
||||||
}
|
|
||||||
if ownerSize > 0 {
|
|
||||||
owner = (*SID)(unsafe.Pointer(&make([]byte, ownerSize)[0]))
|
|
||||||
}
|
|
||||||
if groupSize > 0 {
|
|
||||||
group = (*SID)(unsafe.Pointer(&make([]byte, groupSize)[0]))
|
|
||||||
}
|
|
||||||
err = makeAbsoluteSD(selfRelativeSD, absoluteSD, &absoluteSDSize,
|
|
||||||
dacl, &daclSize, sacl, &saclSize, owner, &ownerSize, group, &groupSize)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToSelfRelative converts an absolute security descriptor into a self-relative one.
|
|
||||||
func (absoluteSD *SECURITY_DESCRIPTOR) ToSelfRelative() (selfRelativeSD *SECURITY_DESCRIPTOR, err error) {
|
|
||||||
control, _, err := absoluteSD.Control()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if control&SE_SELF_RELATIVE != 0 {
|
|
||||||
err = ERROR_INVALID_PARAMETER
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var selfRelativeSDSize uint32
|
|
||||||
err = makeSelfRelativeSD(absoluteSD, nil, &selfRelativeSDSize)
|
|
||||||
switch err {
|
|
||||||
case ERROR_INSUFFICIENT_BUFFER:
|
|
||||||
case nil:
|
|
||||||
// makeSelfRelativeSD is expected to fail, but it succeeds.
|
|
||||||
return nil, ERROR_INTERNAL_ERROR
|
|
||||||
default:
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if selfRelativeSDSize > 0 {
|
|
||||||
selfRelativeSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, selfRelativeSDSize)[0]))
|
|
||||||
}
|
|
||||||
err = makeSelfRelativeSD(absoluteSD, selfRelativeSD, &selfRelativeSDSize)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (selfRelativeSD *SECURITY_DESCRIPTOR) copySelfRelativeSecurityDescriptor() *SECURITY_DESCRIPTOR {
|
|
||||||
sdLen := int(selfRelativeSD.Length())
|
|
||||||
const min = int(unsafe.Sizeof(SECURITY_DESCRIPTOR{}))
|
|
||||||
if sdLen < min {
|
|
||||||
sdLen = min
|
|
||||||
}
|
|
||||||
|
|
||||||
src := unsafe.Slice((*byte)(unsafe.Pointer(selfRelativeSD)), sdLen)
|
|
||||||
// SECURITY_DESCRIPTOR has pointers in it, which means checkptr expects for it to
|
|
||||||
// be aligned properly. When we're copying a Windows-allocated struct to a
|
|
||||||
// Go-allocated one, make sure that the Go allocation is aligned to the
|
|
||||||
// pointer size.
|
|
||||||
const psize = int(unsafe.Sizeof(uintptr(0)))
|
|
||||||
alloc := make([]uintptr, (sdLen+psize-1)/psize)
|
|
||||||
dst := unsafe.Slice((*byte)(unsafe.Pointer(&alloc[0])), sdLen)
|
|
||||||
copy(dst, src)
|
|
||||||
return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&dst[0]))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SecurityDescriptorFromString converts an SDDL string describing a security descriptor into a
|
|
||||||
// self-relative security descriptor object allocated on the Go heap.
|
|
||||||
func SecurityDescriptorFromString(sddl string) (sd *SECURITY_DESCRIPTOR, err error) {
|
|
||||||
var winHeapSD *SECURITY_DESCRIPTOR
|
|
||||||
err = convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &winHeapSD, nil)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
|
|
||||||
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSecurityInfo queries the security information for a given handle and returns the self-relative security
|
|
||||||
// descriptor result on the Go heap.
|
|
||||||
func GetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
|
|
||||||
var winHeapSD *SECURITY_DESCRIPTOR
|
|
||||||
err = getSecurityInfo(handle, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
|
|
||||||
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNamedSecurityInfo queries the security information for a given named object and returns the self-relative security
|
|
||||||
// descriptor result on the Go heap.
|
|
||||||
func GetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
|
|
||||||
var winHeapSD *SECURITY_DESCRIPTOR
|
|
||||||
err = getNamedSecurityInfo(objectName, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
|
|
||||||
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildSecurityDescriptor makes a new security descriptor using the input trustees, explicit access lists, and
|
|
||||||
// prior security descriptor to be merged, any of which can be nil, returning the self-relative security descriptor
|
|
||||||
// result on the Go heap.
|
|
||||||
func BuildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, accessEntries []EXPLICIT_ACCESS, auditEntries []EXPLICIT_ACCESS, mergedSecurityDescriptor *SECURITY_DESCRIPTOR) (sd *SECURITY_DESCRIPTOR, err error) {
|
|
||||||
var winHeapSD *SECURITY_DESCRIPTOR
|
|
||||||
var winHeapSDSize uint32
|
|
||||||
var firstAccessEntry *EXPLICIT_ACCESS
|
|
||||||
if len(accessEntries) > 0 {
|
|
||||||
firstAccessEntry = &accessEntries[0]
|
|
||||||
}
|
|
||||||
var firstAuditEntry *EXPLICIT_ACCESS
|
|
||||||
if len(auditEntries) > 0 {
|
|
||||||
firstAuditEntry = &auditEntries[0]
|
|
||||||
}
|
|
||||||
err = buildSecurityDescriptor(owner, group, uint32(len(accessEntries)), firstAccessEntry, uint32(len(auditEntries)), firstAuditEntry, mergedSecurityDescriptor, &winHeapSDSize, &winHeapSD)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
|
|
||||||
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSecurityDescriptor creates and initializes a new absolute security descriptor.
|
|
||||||
func NewSecurityDescriptor() (absoluteSD *SECURITY_DESCRIPTOR, err error) {
|
|
||||||
absoluteSD = &SECURITY_DESCRIPTOR{}
|
|
||||||
err = initializeSecurityDescriptor(absoluteSD, 1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ACLFromEntries returns a new ACL on the Go heap containing a list of explicit entries as well as those of another ACL.
|
|
||||||
// Both explicitEntries and mergedACL are optional and can be nil.
|
|
||||||
func ACLFromEntries(explicitEntries []EXPLICIT_ACCESS, mergedACL *ACL) (acl *ACL, err error) {
|
|
||||||
var firstExplicitEntry *EXPLICIT_ACCESS
|
|
||||||
if len(explicitEntries) > 0 {
|
|
||||||
firstExplicitEntry = &explicitEntries[0]
|
|
||||||
}
|
|
||||||
var winHeapACL *ACL
|
|
||||||
err = setEntriesInAcl(uint32(len(explicitEntries)), firstExplicitEntry, mergedACL, &winHeapACL)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer LocalFree(Handle(unsafe.Pointer(winHeapACL)))
|
|
||||||
aclBytes := make([]byte, winHeapACL.aclSize)
|
|
||||||
copy(aclBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(winHeapACL))[:len(aclBytes):len(aclBytes)])
|
|
||||||
return (*ACL)(unsafe.Pointer(&aclBytes[0])), nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build windows
|
// +build windows
|
||||||
|
|
||||||
package windows
|
package windows
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@ const (
|
||||||
SC_MANAGER_ALL_ACCESS = 0xf003f
|
SC_MANAGER_ALL_ACCESS = 0xf003f
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenSCManagerW
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SERVICE_KERNEL_DRIVER = 1
|
SERVICE_KERNEL_DRIVER = 1
|
||||||
SERVICE_FILE_SYSTEM_DRIVER = 2
|
SERVICE_FILE_SYSTEM_DRIVER = 2
|
||||||
|
@ -63,7 +65,6 @@ const (
|
||||||
SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 32
|
SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 32
|
||||||
SERVICE_ACCEPT_POWEREVENT = 64
|
SERVICE_ACCEPT_POWEREVENT = 64
|
||||||
SERVICE_ACCEPT_SESSIONCHANGE = 128
|
SERVICE_ACCEPT_SESSIONCHANGE = 128
|
||||||
SERVICE_ACCEPT_PRESHUTDOWN = 256
|
|
||||||
|
|
||||||
SERVICE_CONTROL_STOP = 1
|
SERVICE_CONTROL_STOP = 1
|
||||||
SERVICE_CONTROL_PAUSE = 2
|
SERVICE_CONTROL_PAUSE = 2
|
||||||
|
@ -79,7 +80,6 @@ const (
|
||||||
SERVICE_CONTROL_HARDWAREPROFILECHANGE = 12
|
SERVICE_CONTROL_HARDWAREPROFILECHANGE = 12
|
||||||
SERVICE_CONTROL_POWEREVENT = 13
|
SERVICE_CONTROL_POWEREVENT = 13
|
||||||
SERVICE_CONTROL_SESSIONCHANGE = 14
|
SERVICE_CONTROL_SESSIONCHANGE = 14
|
||||||
SERVICE_CONTROL_PRESHUTDOWN = 15
|
|
||||||
|
|
||||||
SERVICE_ACTIVE = 1
|
SERVICE_ACTIVE = 1
|
||||||
SERVICE_INACTIVE = 2
|
SERVICE_INACTIVE = 2
|
||||||
|
@ -126,26 +126,8 @@ const (
|
||||||
SERVICE_NOTIFY_CREATED = 0x00000080
|
SERVICE_NOTIFY_CREATED = 0x00000080
|
||||||
SERVICE_NOTIFY_DELETED = 0x00000100
|
SERVICE_NOTIFY_DELETED = 0x00000100
|
||||||
SERVICE_NOTIFY_DELETE_PENDING = 0x00000200
|
SERVICE_NOTIFY_DELETE_PENDING = 0x00000200
|
||||||
|
|
||||||
SC_EVENT_DATABASE_CHANGE = 0
|
|
||||||
SC_EVENT_PROPERTY_CHANGE = 1
|
|
||||||
SC_EVENT_STATUS_CHANGE = 2
|
|
||||||
|
|
||||||
SERVICE_START_REASON_DEMAND = 0x00000001
|
|
||||||
SERVICE_START_REASON_AUTO = 0x00000002
|
|
||||||
SERVICE_START_REASON_TRIGGER = 0x00000004
|
|
||||||
SERVICE_START_REASON_RESTART_ON_FAILURE = 0x00000008
|
|
||||||
SERVICE_START_REASON_DELAYEDAUTO = 0x00000010
|
|
||||||
|
|
||||||
SERVICE_DYNAMIC_INFORMATION_LEVEL_START_REASON = 1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ENUM_SERVICE_STATUS struct {
|
|
||||||
ServiceName *uint16
|
|
||||||
DisplayName *uint16
|
|
||||||
ServiceStatus SERVICE_STATUS
|
|
||||||
}
|
|
||||||
|
|
||||||
type SERVICE_STATUS struct {
|
type SERVICE_STATUS struct {
|
||||||
ServiceType uint32
|
ServiceType uint32
|
||||||
CurrentState uint32
|
CurrentState uint32
|
||||||
|
@ -177,10 +159,6 @@ type SERVICE_DESCRIPTION struct {
|
||||||
Description *uint16
|
Description *uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
type SERVICE_DELAYED_AUTO_START_INFO struct {
|
|
||||||
IsDelayedAutoStartUp uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type SERVICE_STATUS_PROCESS struct {
|
type SERVICE_STATUS_PROCESS struct {
|
||||||
ServiceType uint32
|
ServiceType uint32
|
||||||
CurrentState uint32
|
CurrentState uint32
|
||||||
|
@ -217,10 +195,6 @@ type SERVICE_FAILURE_ACTIONS struct {
|
||||||
Actions *SC_ACTION
|
Actions *SC_ACTION
|
||||||
}
|
}
|
||||||
|
|
||||||
type SERVICE_FAILURE_ACTIONS_FLAG struct {
|
|
||||||
FailureActionsOnNonCrashFailures int32
|
|
||||||
}
|
|
||||||
|
|
||||||
type SC_ACTION struct {
|
type SC_ACTION struct {
|
||||||
Type uint32
|
Type uint32
|
||||||
Delay uint32
|
Delay uint32
|
||||||
|
@ -232,7 +206,6 @@ type QUERY_SERVICE_LOCK_STATUS struct {
|
||||||
LockDuration uint32
|
LockDuration uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenSCManagerW
|
|
||||||
//sys CloseServiceHandle(handle Handle) (err error) = advapi32.CloseServiceHandle
|
//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 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 OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenServiceW
|
||||||
|
@ -250,8 +223,3 @@ type QUERY_SERVICE_LOCK_STATUS struct {
|
||||||
//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 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
|
//sys QueryServiceStatusEx(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceStatusEx
|
||||||
//sys NotifyServiceStatusChange(service Handle, notifyMask uint32, notifier *SERVICE_NOTIFY) (ret error) = advapi32.NotifyServiceStatusChangeW
|
//sys NotifyServiceStatusChange(service Handle, notifyMask uint32, notifier *SERVICE_NOTIFY) (ret error) = advapi32.NotifyServiceStatusChangeW
|
||||||
//sys SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) = sechost.SubscribeServiceChangeNotifications?
|
|
||||||
//sys UnsubscribeServiceChangeNotifications(subscription uintptr) = sechost.UnsubscribeServiceChangeNotifications?
|
|
||||||
//sys RegisterServiceCtrlHandlerEx(serviceName *uint16, handlerProc uintptr, context uintptr) (handle Handle, err error) = advapi32.RegisterServiceCtrlHandlerExW
|
|
||||||
//sys QueryServiceDynamicInformation(service Handle, infoLevel uint32, dynamicInfo unsafe.Pointer) (err error) = advapi32.QueryServiceDynamicInformation?
|
|
||||||
//sys EnumDependentServices(service Handle, activityState uint32, services *ENUM_SERVICE_STATUS, buffSize uint32, bytesNeeded *uint32, servicesReturned *uint32) (err error) = advapi32.EnumDependentServicesW
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build windows
|
// +build windows
|
||||||
|
|
||||||
package windows
|
package windows
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build windows
|
// +build windows
|
||||||
|
|
||||||
// Package windows contains an interface to the low-level operating system
|
// Package windows contains an interface to the low-level operating system
|
||||||
// primitives. OS details vary depending on the underlying system, and
|
// primitives. OS details vary depending on the underlying system, and
|
||||||
|
@ -25,18 +25,17 @@
|
||||||
package windows // import "golang.org/x/sys/windows"
|
package windows // import "golang.org/x/sys/windows"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ByteSliceFromString returns a NUL-terminated slice of bytes
|
// ByteSliceFromString returns a NUL-terminated slice of bytes
|
||||||
// containing the text of s. If s contains a NUL byte at any
|
// containing the text of s. If s contains a NUL byte at any
|
||||||
// location, it returns (nil, syscall.EINVAL).
|
// location, it returns (nil, syscall.EINVAL).
|
||||||
func ByteSliceFromString(s string) ([]byte, error) {
|
func ByteSliceFromString(s string) ([]byte, error) {
|
||||||
if strings.IndexByte(s, 0) != -1 {
|
for i := 0; i < len(s); i++ {
|
||||||
return nil, syscall.EINVAL
|
if s[i] == 0 {
|
||||||
|
return nil, syscall.EINVAL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
a := make([]byte, len(s)+1)
|
a := make([]byte, len(s)+1)
|
||||||
copy(a, s)
|
copy(a, s)
|
||||||
|
@ -54,35 +53,6 @@ func BytePtrFromString(s string) (*byte, error) {
|
||||||
return &a[0], nil
|
return &a[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ByteSliceToString returns a string form of the text represented by the slice s, with a terminating NUL and any
|
|
||||||
// bytes after the NUL removed.
|
|
||||||
func ByteSliceToString(s []byte) string {
|
|
||||||
if i := bytes.IndexByte(s, 0); i != -1 {
|
|
||||||
s = s[:i]
|
|
||||||
}
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BytePtrToString takes a pointer to a sequence of text and returns the corresponding string.
|
|
||||||
// If the pointer is nil, it returns the empty string. It assumes that the text sequence is terminated
|
|
||||||
// at a zero byte; if the zero byte is not present, the program may crash.
|
|
||||||
func BytePtrToString(p *byte) string {
|
|
||||||
if p == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if *p == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find NUL terminator.
|
|
||||||
n := 0
|
|
||||||
for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ {
|
|
||||||
ptr = unsafe.Pointer(uintptr(ptr) + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(unsafe.Slice(p, n))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Single-word zero for use when we need a valid pointer to 0 bytes.
|
// Single-word zero for use when we need a valid pointer to 0 bytes.
|
||||||
// See mksyscall.pl.
|
// See mksyscall.pl.
|
||||||
var _zero uintptr
|
var _zero uintptr
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -20,16 +20,3 @@ type Servent struct {
|
||||||
Port uint16
|
Port uint16
|
||||||
Proto *byte
|
Proto *byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type JOBOBJECT_BASIC_LIMIT_INFORMATION struct {
|
|
||||||
PerProcessUserTimeLimit int64
|
|
||||||
PerJobUserTimeLimit int64
|
|
||||||
LimitFlags uint32
|
|
||||||
MinimumWorkingSetSize uintptr
|
|
||||||
MaximumWorkingSetSize uintptr
|
|
||||||
ActiveProcessLimit uint32
|
|
||||||
Affinity uintptr
|
|
||||||
PriorityClass uint32
|
|
||||||
SchedulingClass uint32
|
|
||||||
_ uint32 // pad to 8 byte boundary
|
|
||||||
}
|
|
||||||
|
|
|
@ -20,15 +20,3 @@ type Servent struct {
|
||||||
Proto *byte
|
Proto *byte
|
||||||
Port uint16
|
Port uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
type JOBOBJECT_BASIC_LIMIT_INFORMATION struct {
|
|
||||||
PerProcessUserTimeLimit int64
|
|
||||||
PerJobUserTimeLimit int64
|
|
||||||
LimitFlags uint32
|
|
||||||
MinimumWorkingSetSize uintptr
|
|
||||||
MaximumWorkingSetSize uintptr
|
|
||||||
ActiveProcessLimit uint32
|
|
||||||
Affinity uintptr
|
|
||||||
PriorityClass uint32
|
|
||||||
SchedulingClass uint32
|
|
||||||
}
|
|
||||||
|
|
|
@ -20,16 +20,3 @@ type Servent struct {
|
||||||
Port uint16
|
Port uint16
|
||||||
Proto *byte
|
Proto *byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type JOBOBJECT_BASIC_LIMIT_INFORMATION struct {
|
|
||||||
PerProcessUserTimeLimit int64
|
|
||||||
PerJobUserTimeLimit int64
|
|
||||||
LimitFlags uint32
|
|
||||||
MinimumWorkingSetSize uintptr
|
|
||||||
MaximumWorkingSetSize uintptr
|
|
||||||
ActiveProcessLimit uint32
|
|
||||||
Affinity uintptr
|
|
||||||
PriorityClass uint32
|
|
||||||
SchedulingClass uint32
|
|
||||||
_ uint32 // pad to 8 byte boundary
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
type JOBOBJECT_BASIC_LIMIT_INFORMATION struct {
|
|
||||||
PerProcessUserTimeLimit int64
|
|
||||||
PerJobUserTimeLimit int64
|
|
||||||
LimitFlags uint32
|
|
||||||
MinimumWorkingSetSize uintptr
|
|
||||||
MaximumWorkingSetSize uintptr
|
|
||||||
ActiveProcessLimit uint32
|
|
||||||
Affinity uintptr
|
|
||||||
PriorityClass uint32
|
|
||||||
SchedulingClass uint32
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,6 @@
|
||||||
# git.rootprojects.org/root/go-gitver v1.1.3
|
# git.rootprojects.org/root/go-gitver v1.1.3
|
||||||
## explicit; go 1.12
|
|
||||||
git.rootprojects.org/root/go-gitver
|
git.rootprojects.org/root/go-gitver
|
||||||
git.rootprojects.org/root/go-gitver/gitver
|
git.rootprojects.org/root/go-gitver/gitver
|
||||||
# golang.org/x/sys v0.14.0
|
# golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7
|
||||||
## explicit; go 1.18
|
|
||||||
golang.org/x/sys/windows
|
|
||||||
golang.org/x/sys/windows/registry
|
golang.org/x/sys/windows/registry
|
||||||
|
golang.org/x/sys/windows
|
||||||
|
|
Loading…
Reference in New Issue