Compare commits
5 Commits
Author | SHA1 | Date |
---|---|---|
AJ ONeal | ce27e9d610 | |
AJ ONeal | 6f178a6de4 | |
AJ ONeal | 3bf23349a1 | |
AJ ONeal | ff57c6cc53 | |
AJ ONeal | c2ce9b4085 |
4
go.mod
4
go.mod
|
@ -1,8 +1,8 @@
|
|||
module git.rootprojects.org/root/pathman
|
||||
|
||||
go 1.12
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
git.rootprojects.org/root/go-gitver v1.1.3
|
||||
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7
|
||||
golang.org/x/sys v0.14.0
|
||||
)
|
||||
|
|
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/go.mod h1:Rj1v3TBhvdaSphFEqMynUYwAz/4f+wY/+syBTvRrmlI=
|
||||
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7 h1:LepdCS8Gf/MVejFIt8lsiexZATdoGVyp5bcyS+rYoUI=
|
||||
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
#!/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
|
|
@ -0,0 +1,39 @@
|
|||
#!/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
|
|
@ -0,0 +1,49 @@
|
|||
#!/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 = ""
|
|
@ -0,0 +1,52 @@
|
|||
#!/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
|
|
@ -1,3 +0,0 @@
|
|||
module git.rootprojects.org/root/go-gitver
|
||||
|
||||
go 1.12
|
|
@ -1,3 +0,0 @@
|
|||
# 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.
|
|
@ -1,3 +0,0 @@
|
|||
# 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,8 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
// +build go1.9
|
||||
//go:build windows && go1.9
|
||||
|
||||
package windows
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
// 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)
|
|
@ -1,13 +0,0 @@
|
|||
// 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)
|
|
@ -1,11 +0,0 @@
|
|||
// 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,6 +11,18 @@ import (
|
|||
"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.
|
||||
type DLLError struct {
|
||||
Err error
|
||||
|
@ -20,9 +32,7 @@ type DLLError struct {
|
|||
|
||||
func (e *DLLError) Error() string { return e.Msg }
|
||||
|
||||
// Implemented in runtime/syscall_windows.goc; we provide jumps to them in our assembly file.
|
||||
func loadlibrary(filename *uint16) (handle uintptr, err syscall.Errno)
|
||||
func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err syscall.Errno)
|
||||
func (e *DLLError) Unwrap() error { return e.Err }
|
||||
|
||||
// A DLL implements access to a single DLL.
|
||||
type DLL struct {
|
||||
|
@ -40,7 +50,7 @@ func LoadDLL(name string) (dll *DLL, err error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h, e := loadlibrary(namep)
|
||||
h, e := syscall_loadlibrary(namep)
|
||||
if e != 0 {
|
||||
return nil, &DLLError{
|
||||
Err: e,
|
||||
|
@ -50,7 +60,7 @@ func LoadDLL(name string) (dll *DLL, err error) {
|
|||
}
|
||||
d := &DLL{
|
||||
Name: name,
|
||||
Handle: Handle(h),
|
||||
Handle: h,
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
@ -71,7 +81,7 @@ func (d *DLL) FindProc(name string) (proc *Proc, err error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a, e := getprocaddress(uintptr(d.Handle), namep)
|
||||
a, e := syscall_getprocaddress(d.Handle, namep)
|
||||
if e != 0 {
|
||||
return nil, &DLLError{
|
||||
Err: e,
|
||||
|
@ -96,6 +106,35 @@ func (d *DLL) MustFindProc(name string) *Proc {
|
|||
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.
|
||||
func (d *DLL) Release() (err error) {
|
||||
return FreeLibrary(d.Handle)
|
||||
|
@ -352,7 +391,6 @@ func loadLibraryEx(name string, system bool) (*DLL, error) {
|
|||
var flags uintptr
|
||||
if system {
|
||||
if canDoSearchSystem32() {
|
||||
const LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
|
||||
flags = LOAD_LIBRARY_SEARCH_SYSTEM32
|
||||
} else if isBaseName(name) {
|
||||
// WindowsXP or unpatched Windows machine
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// 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,7 +8,6 @@ package windows
|
|||
|
||||
import (
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
@ -38,20 +37,14 @@ func (token Token) Environ(inheritExisting bool) (env []string, err error) {
|
|||
return nil, err
|
||||
}
|
||||
defer DestroyEnvironmentBlock(block)
|
||||
blockp := uintptr(unsafe.Pointer(block))
|
||||
blockp := unsafe.Pointer(block)
|
||||
for {
|
||||
entry := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(blockp))[:]
|
||||
for i, v := range entry {
|
||||
if v == 0 {
|
||||
entry = entry[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
entry := UTF16PtrToString((*uint16)(blockp))
|
||||
if len(entry) == 0 {
|
||||
break
|
||||
}
|
||||
env = append(env, string(utf16.Decode(entry)))
|
||||
blockp += 2 * (uintptr(len(entry)) + 1)
|
||||
env = append(env, entry)
|
||||
blockp = unsafe.Add(blockp, 2*(len(entry)+1))
|
||||
}
|
||||
return env, nil
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
//go:build windows
|
||||
|
||||
package windows
|
||||
|
||||
|
|
|
@ -6,18 +6,23 @@
|
|||
|
||||
package windows
|
||||
|
||||
import (
|
||||
errorspkg "errors"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// EscapeArg rewrites command line argument s as prescribed
|
||||
// in http://msdn.microsoft.com/en-us/library/ms880421.
|
||||
// This function returns "" (2 double quotes) if s is empty.
|
||||
// Alternatively, these transformations are done:
|
||||
// - every back slash (\) is doubled, but only if immediately
|
||||
// followed by double quote (");
|
||||
// - every double quote (") is escaped by back slash (\);
|
||||
// - finally, s is wrapped with double quotes (arg -> "arg"),
|
||||
// but only if there is space or tab inside s.
|
||||
// - every back slash (\) is doubled, but only if immediately
|
||||
// followed by double quote (");
|
||||
// - every double quote (") is escaped by back slash (\);
|
||||
// - finally, s is wrapped with double quotes (arg -> "arg"),
|
||||
// but only if there is space or tab inside s.
|
||||
func EscapeArg(s string) string {
|
||||
if len(s) == 0 {
|
||||
return "\"\""
|
||||
return `""`
|
||||
}
|
||||
n := len(s)
|
||||
hasSpace := false
|
||||
|
@ -30,7 +35,7 @@ func EscapeArg(s string) string {
|
|||
}
|
||||
}
|
||||
if hasSpace {
|
||||
n += 2
|
||||
n += 2 // Reserve space for quotes.
|
||||
}
|
||||
if n == len(s) {
|
||||
return s
|
||||
|
@ -73,6 +78,110 @@ func EscapeArg(s string) string {
|
|||
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) {
|
||||
SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
|
||||
}
|
||||
|
@ -95,3 +204,45 @@ 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,11 +16,33 @@ const (
|
|||
MEM_RESET_UNDO = 0x01000000
|
||||
MEM_LARGE_PAGES = 0x20000000
|
||||
|
||||
PAGE_NOACCESS = 0x01
|
||||
PAGE_READONLY = 0x02
|
||||
PAGE_READWRITE = 0x04
|
||||
PAGE_WRITECOPY = 0x08
|
||||
PAGE_EXECUTE_READ = 0x20
|
||||
PAGE_EXECUTE_READWRITE = 0x40
|
||||
PAGE_EXECUTE_WRITECOPY = 0x80
|
||||
PAGE_NOACCESS = 0x00000001
|
||||
PAGE_READONLY = 0x00000002
|
||||
PAGE_READWRITE = 0x00000004
|
||||
PAGE_WRITECOPY = 0x00000008
|
||||
PAGE_EXECUTE = 0x00000010
|
||||
PAGE_EXECUTE_READ = 0x00000020
|
||||
PAGE_EXECUTE_READWRITE = 0x00000040
|
||||
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,6 +9,8 @@ shopt -s nullglob
|
|||
|
||||
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; }
|
||||
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
|
||||
|
||||
|
@ -59,5 +61,10 @@ declare -A errors
|
|||
echo "$key $vtype = $value"
|
||||
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 ")"
|
||||
} | gofmt > "zerrors_windows.go"
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build generate
|
||||
//go:build generate
|
||||
|
||||
package windows
|
||||
|
||||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go
|
||||
//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
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows,race
|
||||
//go:build windows && race
|
||||
|
||||
package windows
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows,!race
|
||||
//go:build windows && !race
|
||||
|
||||
package windows
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
//go:build windows
|
||||
|
||||
// Package registry provides access to the Windows registry.
|
||||
//
|
||||
|
@ -19,11 +19,11 @@
|
|||
// log.Fatal(err)
|
||||
// }
|
||||
// fmt.Printf("Windows system root is %q\n", s)
|
||||
//
|
||||
package registry
|
||||
|
||||
import (
|
||||
"io"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
@ -113,6 +113,13 @@ func OpenRemoteKey(pcname string, k Key) (Key, error) {
|
|||
// The parameter n controls the number of returned names,
|
||||
// analogous to the way os.File.Readdirnames works.
|
||||
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)
|
||||
// Registry key size limit is 255 bytes and described there:
|
||||
// https://msdn.microsoft.com/library/windows/desktop/ms724872.aspx
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build generate
|
||||
//go:build generate
|
||||
|
||||
package registry
|
||||
|
||||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall.go
|
||||
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall.go
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
//go:build windows
|
||||
|
||||
package registry
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
//go:build windows
|
||||
|
||||
package registry
|
||||
|
||||
|
@ -108,7 +108,7 @@ func (k Key) GetStringValue(name string) (val string, valtype uint32, err error)
|
|||
if len(data) == 0 {
|
||||
return "", typ, nil
|
||||
}
|
||||
u := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[:]
|
||||
u := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[: len(data)/2 : len(data)/2]
|
||||
return syscall.UTF16ToString(u), typ, nil
|
||||
}
|
||||
|
||||
|
@ -185,8 +185,7 @@ func ExpandString(value string) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
if n <= uint32(len(r)) {
|
||||
u := (*[1 << 29]uint16)(unsafe.Pointer(&r[0]))[:]
|
||||
return syscall.UTF16ToString(u), nil
|
||||
return syscall.UTF16ToString(r[:n]), nil
|
||||
}
|
||||
r = make([]uint16, n)
|
||||
}
|
||||
|
@ -208,7 +207,7 @@ func (k Key) GetStringsValue(name string) (val []string, valtype uint32, err err
|
|||
if len(data) == 0 {
|
||||
return nil, typ, nil
|
||||
}
|
||||
p := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[:len(data)/2]
|
||||
p := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[: len(data)/2 : len(data)/2]
|
||||
if len(p) == 0 {
|
||||
return nil, typ, nil
|
||||
}
|
||||
|
@ -299,7 +298,7 @@ func (k Key) setStringValue(name string, valtype uint32, value string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
|
||||
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[: len(v)*2 : len(v)*2]
|
||||
return k.setValue(name, valtype, buf)
|
||||
}
|
||||
|
||||
|
@ -329,7 +328,7 @@ func (k Key) SetStringsValue(name string, value []string) error {
|
|||
ss += s + "\x00"
|
||||
}
|
||||
v := utf16.Encode([]rune(ss + "\x00"))
|
||||
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
|
||||
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[: len(v)*2 : len(v)*2]
|
||||
return k.setValue(name, MULTI_SZ, buf)
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ const (
|
|||
|
||||
var (
|
||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||
errERROR_EINVAL error = syscall.EINVAL
|
||||
)
|
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent
|
||||
|
@ -26,7 +27,7 @@ var (
|
|||
func errnoErr(e syscall.Errno) error {
|
||||
switch e {
|
||||
case 0:
|
||||
return nil
|
||||
return errERROR_EINVAL
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
|
@ -40,16 +41,24 @@ var (
|
|||
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
|
||||
procRegConnectRegistryW = modadvapi32.NewProc("RegConnectRegistryW")
|
||||
procRegCreateKeyExW = modadvapi32.NewProc("RegCreateKeyExW")
|
||||
procRegDeleteKeyW = modadvapi32.NewProc("RegDeleteKeyW")
|
||||
procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW")
|
||||
procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
|
||||
procRegDeleteValueW = modadvapi32.NewProc("RegDeleteValueW")
|
||||
procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
|
||||
procRegLoadMUIStringW = modadvapi32.NewProc("RegLoadMUIStringW")
|
||||
procRegConnectRegistryW = modadvapi32.NewProc("RegConnectRegistryW")
|
||||
procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW")
|
||||
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) {
|
||||
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 {
|
||||
|
@ -66,8 +75,8 @@ func regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) {
|
|||
return
|
||||
}
|
||||
|
||||
func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) {
|
||||
r0, _, _ := syscall.Syscall6(procRegSetValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(valueName)), uintptr(reserved), uintptr(vtype), uintptr(unsafe.Pointer(buf)), uintptr(bufsize))
|
||||
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)
|
||||
}
|
||||
|
@ -82,14 +91,6 @@ func regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint3
|
|||
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) {
|
||||
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 {
|
||||
|
@ -98,8 +99,8 @@ func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint
|
|||
return
|
||||
}
|
||||
|
||||
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)))
|
||||
func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) {
|
||||
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 {
|
||||
regerrno = syscall.Errno(r0)
|
||||
}
|
||||
|
@ -110,11 +111,7 @@ 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))
|
||||
n = uint32(r0)
|
||||
if n == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -9,14 +9,6 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
STANDARD_RIGHTS_REQUIRED = 0xf0000
|
||||
STANDARD_RIGHTS_READ = 0x20000
|
||||
STANDARD_RIGHTS_WRITE = 0x20000
|
||||
STANDARD_RIGHTS_EXECUTE = 0x20000
|
||||
STANDARD_RIGHTS_ALL = 0x1F0000
|
||||
)
|
||||
|
||||
const (
|
||||
NameUnknown = 0
|
||||
NameFullyQualifiedDN = 1
|
||||
|
@ -235,16 +227,15 @@ func LookupSID(system, account string) (sid *SID, domain string, accType uint32,
|
|||
}
|
||||
}
|
||||
|
||||
// String converts SID to a string format
|
||||
// suitable for display, storage, or transmission.
|
||||
func (sid *SID) String() (string, error) {
|
||||
// String converts SID to a string format suitable for display, storage, or transmission.
|
||||
func (sid *SID) String() string {
|
||||
var s *uint16
|
||||
e := ConvertSidToStringSid(sid, &s)
|
||||
if e != nil {
|
||||
return "", e
|
||||
return ""
|
||||
}
|
||||
defer LocalFree((Handle)(unsafe.Pointer(s)))
|
||||
return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
|
||||
return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:])
|
||||
}
|
||||
|
||||
// Len returns the length, in bytes, of a valid security identifier SID.
|
||||
|
@ -631,6 +622,7 @@ func (tml *Tokenmandatorylabel) Size() uint32 {
|
|||
|
||||
// Authorization Functions
|
||||
//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 OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken
|
||||
//sys ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
|
||||
|
@ -644,6 +636,8 @@ func (tml *Tokenmandatorylabel) Size() uint32 {
|
|||
//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 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.
|
||||
// The system creates an access token when a user logs on, and every
|
||||
|
@ -654,21 +648,16 @@ func (tml *Tokenmandatorylabel) Size() uint32 {
|
|||
// system-related operations on the local computer.
|
||||
type Token Handle
|
||||
|
||||
// OpenCurrentProcessToken opens the access token
|
||||
// associated with current process. It is a real
|
||||
// token that needs to be closed, unlike
|
||||
// GetCurrentProcessToken.
|
||||
// OpenCurrentProcessToken opens an access token associated with current
|
||||
// process with TOKEN_QUERY access. It is a real token that needs to be closed.
|
||||
//
|
||||
// Deprecated: Explicitly call OpenProcessToken(CurrentProcess(), ...)
|
||||
// with the desired access instead, or use GetCurrentProcessToken for a
|
||||
// TOKEN_QUERY token.
|
||||
func OpenCurrentProcessToken() (Token, error) {
|
||||
p, e := GetCurrentProcess()
|
||||
if e != nil {
|
||||
return 0, e
|
||||
}
|
||||
var t Token
|
||||
e = OpenProcessToken(p, TOKEN_QUERY, &t)
|
||||
if e != nil {
|
||||
return 0, e
|
||||
}
|
||||
return t, nil
|
||||
var token Token
|
||||
err := OpenProcessToken(CurrentProcess(), TOKEN_QUERY, &token)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// GetCurrentProcessToken returns the access token associated with
|
||||
|
@ -785,8 +774,8 @@ func (token Token) GetLinkedToken() (Token, error) {
|
|||
return linkedToken, nil
|
||||
}
|
||||
|
||||
// GetSystemDirectory retrieves path to current location of the system
|
||||
// directory, which is typically, though not always, C:\Windows\System32.
|
||||
// GetSystemDirectory retrieves the path to current location of the system
|
||||
// directory, which is typically, though not always, `C:\Windows\System32`.
|
||||
func GetSystemDirectory() (string, error) {
|
||||
n := uint32(MAX_PATH)
|
||||
for {
|
||||
|
@ -802,6 +791,42 @@ 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.
|
||||
func (t Token) IsMember(sid *SID) (bool, error) {
|
||||
var b int32
|
||||
|
@ -811,6 +836,16 @@ func (t Token) IsMember(sid *SID) (bool, error) {
|
|||
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 (
|
||||
WTS_CONSOLE_CONNECT = 0x1
|
||||
WTS_CONSOLE_DISCONNECT = 0x2
|
||||
|
@ -852,3 +887,549 @@ type WTS_SESSION_INFO struct {
|
|||
//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 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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
//go:build windows
|
||||
|
||||
package windows
|
||||
|
||||
|
@ -16,8 +16,6 @@ const (
|
|||
SC_MANAGER_ALL_ACCESS = 0xf003f
|
||||
)
|
||||
|
||||
//sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenSCManagerW
|
||||
|
||||
const (
|
||||
SERVICE_KERNEL_DRIVER = 1
|
||||
SERVICE_FILE_SYSTEM_DRIVER = 2
|
||||
|
@ -65,6 +63,7 @@ const (
|
|||
SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 32
|
||||
SERVICE_ACCEPT_POWEREVENT = 64
|
||||
SERVICE_ACCEPT_SESSIONCHANGE = 128
|
||||
SERVICE_ACCEPT_PRESHUTDOWN = 256
|
||||
|
||||
SERVICE_CONTROL_STOP = 1
|
||||
SERVICE_CONTROL_PAUSE = 2
|
||||
|
@ -80,6 +79,7 @@ const (
|
|||
SERVICE_CONTROL_HARDWAREPROFILECHANGE = 12
|
||||
SERVICE_CONTROL_POWEREVENT = 13
|
||||
SERVICE_CONTROL_SESSIONCHANGE = 14
|
||||
SERVICE_CONTROL_PRESHUTDOWN = 15
|
||||
|
||||
SERVICE_ACTIVE = 1
|
||||
SERVICE_INACTIVE = 2
|
||||
|
@ -126,8 +126,26 @@ const (
|
|||
SERVICE_NOTIFY_CREATED = 0x00000080
|
||||
SERVICE_NOTIFY_DELETED = 0x00000100
|
||||
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 {
|
||||
ServiceType uint32
|
||||
CurrentState uint32
|
||||
|
@ -159,6 +177,10 @@ type SERVICE_DESCRIPTION struct {
|
|||
Description *uint16
|
||||
}
|
||||
|
||||
type SERVICE_DELAYED_AUTO_START_INFO struct {
|
||||
IsDelayedAutoStartUp uint32
|
||||
}
|
||||
|
||||
type SERVICE_STATUS_PROCESS struct {
|
||||
ServiceType uint32
|
||||
CurrentState uint32
|
||||
|
@ -195,6 +217,10 @@ type SERVICE_FAILURE_ACTIONS struct {
|
|||
Actions *SC_ACTION
|
||||
}
|
||||
|
||||
type SERVICE_FAILURE_ACTIONS_FLAG struct {
|
||||
FailureActionsOnNonCrashFailures int32
|
||||
}
|
||||
|
||||
type SC_ACTION struct {
|
||||
Type uint32
|
||||
Delay uint32
|
||||
|
@ -206,6 +232,7 @@ type QUERY_SERVICE_LOCK_STATUS struct {
|
|||
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 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
|
||||
|
@ -223,3 +250,8 @@ 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 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 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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
//go:build windows
|
||||
|
||||
package windows
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
//go:build windows
|
||||
|
||||
// Package windows contains an interface to the low-level operating system
|
||||
// primitives. OS details vary depending on the underlying system, and
|
||||
|
@ -25,17 +25,18 @@
|
|||
package windows // import "golang.org/x/sys/windows"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// ByteSliceFromString returns a NUL-terminated slice of bytes
|
||||
// containing the text of s. If s contains a NUL byte at any
|
||||
// location, it returns (nil, syscall.EINVAL).
|
||||
func ByteSliceFromString(s string) ([]byte, error) {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == 0 {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
if strings.IndexByte(s, 0) != -1 {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
a := make([]byte, len(s)+1)
|
||||
copy(a, s)
|
||||
|
@ -53,6 +54,35 @@ func BytePtrFromString(s string) (*byte, error) {
|
|||
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.
|
||||
// See mksyscall.pl.
|
||||
var _zero uintptr
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -20,3 +20,16 @@ type Servent struct {
|
|||
Port uint16
|
||||
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,3 +20,15 @@ type Servent struct {
|
|||
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
|
||||
}
|
||||
|
|
|
@ -20,3 +20,16 @@ type Servent struct {
|
|||
Port uint16
|
||||
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
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// 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,6 +1,8 @@
|
|||
# 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/gitver
|
||||
# golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7
|
||||
golang.org/x/sys/windows/registry
|
||||
# golang.org/x/sys v0.14.0
|
||||
## explicit; go 1.18
|
||||
golang.org/x/sys/windows
|
||||
golang.org/x/sys/windows/registry
|
||||
|
|
Loading…
Reference in New Issue