TUN-813: Clean up cloudflared dependencies

This commit is contained in:
Areg Harutyunyan
2018-07-24 18:04:33 -05:00
parent d06fc520c7
commit 0468866626
3310 changed files with 993 additions and 1223303 deletions

View File

@@ -1,11 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package registry
func (k Key) SetValue(name string, valtype uint32, data []byte) error {
return k.setValue(name, valtype, data)
}

View File

@@ -1,756 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package registry_test
import (
"bytes"
"crypto/rand"
"os"
"syscall"
"testing"
"time"
"unsafe"
"golang.org/x/sys/windows/registry"
)
func randKeyName(prefix string) string {
const numbers = "0123456789"
buf := make([]byte, 10)
rand.Read(buf)
for i, b := range buf {
buf[i] = numbers[b%byte(len(numbers))]
}
return prefix + string(buf)
}
func TestReadSubKeyNames(t *testing.T) {
k, err := registry.OpenKey(registry.CLASSES_ROOT, "TypeLib", registry.ENUMERATE_SUB_KEYS)
if err != nil {
t.Fatal(err)
}
defer k.Close()
names, err := k.ReadSubKeyNames(-1)
if err != nil {
t.Fatal(err)
}
var foundStdOle bool
for _, name := range names {
// Every PC has "stdole 2.0 OLE Automation" library installed.
if name == "{00020430-0000-0000-C000-000000000046}" {
foundStdOle = true
}
}
if !foundStdOle {
t.Fatal("could not find stdole 2.0 OLE Automation")
}
}
func TestCreateOpenDeleteKey(t *testing.T) {
k, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE)
if err != nil {
t.Fatal(err)
}
defer k.Close()
testKName := randKeyName("TestCreateOpenDeleteKey_")
testK, exist, err := registry.CreateKey(k, testKName, registry.CREATE_SUB_KEY)
if err != nil {
t.Fatal(err)
}
defer testK.Close()
if exist {
t.Fatalf("key %q already exists", testKName)
}
testKAgain, exist, err := registry.CreateKey(k, testKName, registry.CREATE_SUB_KEY)
if err != nil {
t.Fatal(err)
}
defer testKAgain.Close()
if !exist {
t.Fatalf("key %q should already exist", testKName)
}
testKOpened, err := registry.OpenKey(k, testKName, registry.ENUMERATE_SUB_KEYS)
if err != nil {
t.Fatal(err)
}
defer testKOpened.Close()
err = registry.DeleteKey(k, testKName)
if err != nil {
t.Fatal(err)
}
testKOpenedAgain, err := registry.OpenKey(k, testKName, registry.ENUMERATE_SUB_KEYS)
if err == nil {
defer testKOpenedAgain.Close()
t.Fatalf("key %q should already been deleted", testKName)
}
if err != registry.ErrNotExist {
t.Fatalf(`unexpected error ("not exist" expected): %v`, err)
}
}
func equalStringSlice(a, b []string) bool {
if len(a) != len(b) {
return false
}
if a == nil {
return true
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
type ValueTest struct {
Type uint32
Name string
Value interface{}
WillFail bool
}
var ValueTests = []ValueTest{
{Type: registry.SZ, Name: "String1", Value: ""},
{Type: registry.SZ, Name: "String2", Value: "\000", WillFail: true},
{Type: registry.SZ, Name: "String3", Value: "Hello World"},
{Type: registry.SZ, Name: "String4", Value: "Hello World\000", WillFail: true},
{Type: registry.EXPAND_SZ, Name: "ExpString1", Value: ""},
{Type: registry.EXPAND_SZ, Name: "ExpString2", Value: "\000", WillFail: true},
{Type: registry.EXPAND_SZ, Name: "ExpString3", Value: "Hello World"},
{Type: registry.EXPAND_SZ, Name: "ExpString4", Value: "Hello\000World", WillFail: true},
{Type: registry.EXPAND_SZ, Name: "ExpString5", Value: "%PATH%"},
{Type: registry.EXPAND_SZ, Name: "ExpString6", Value: "%NO_SUCH_VARIABLE%"},
{Type: registry.EXPAND_SZ, Name: "ExpString7", Value: "%PATH%;."},
{Type: registry.BINARY, Name: "Binary1", Value: []byte{}},
{Type: registry.BINARY, Name: "Binary2", Value: []byte{1, 2, 3}},
{Type: registry.BINARY, Name: "Binary3", Value: []byte{3, 2, 1, 0, 1, 2, 3}},
{Type: registry.DWORD, Name: "Dword1", Value: uint64(0)},
{Type: registry.DWORD, Name: "Dword2", Value: uint64(1)},
{Type: registry.DWORD, Name: "Dword3", Value: uint64(0xff)},
{Type: registry.DWORD, Name: "Dword4", Value: uint64(0xffff)},
{Type: registry.QWORD, Name: "Qword1", Value: uint64(0)},
{Type: registry.QWORD, Name: "Qword2", Value: uint64(1)},
{Type: registry.QWORD, Name: "Qword3", Value: uint64(0xff)},
{Type: registry.QWORD, Name: "Qword4", Value: uint64(0xffff)},
{Type: registry.QWORD, Name: "Qword5", Value: uint64(0xffffff)},
{Type: registry.QWORD, Name: "Qword6", Value: uint64(0xffffffff)},
{Type: registry.MULTI_SZ, Name: "MultiString1", Value: []string{"a", "b", "c"}},
{Type: registry.MULTI_SZ, Name: "MultiString2", Value: []string{"abc", "", "cba"}},
{Type: registry.MULTI_SZ, Name: "MultiString3", Value: []string{""}},
{Type: registry.MULTI_SZ, Name: "MultiString4", Value: []string{"abcdef"}},
{Type: registry.MULTI_SZ, Name: "MultiString5", Value: []string{"\000"}, WillFail: true},
{Type: registry.MULTI_SZ, Name: "MultiString6", Value: []string{"a\000b"}, WillFail: true},
{Type: registry.MULTI_SZ, Name: "MultiString7", Value: []string{"ab", "\000", "cd"}, WillFail: true},
{Type: registry.MULTI_SZ, Name: "MultiString8", Value: []string{"\000", "cd"}, WillFail: true},
{Type: registry.MULTI_SZ, Name: "MultiString9", Value: []string{"ab", "\000"}, WillFail: true},
}
func setValues(t *testing.T, k registry.Key) {
for _, test := range ValueTests {
var err error
switch test.Type {
case registry.SZ:
err = k.SetStringValue(test.Name, test.Value.(string))
case registry.EXPAND_SZ:
err = k.SetExpandStringValue(test.Name, test.Value.(string))
case registry.MULTI_SZ:
err = k.SetStringsValue(test.Name, test.Value.([]string))
case registry.BINARY:
err = k.SetBinaryValue(test.Name, test.Value.([]byte))
case registry.DWORD:
err = k.SetDWordValue(test.Name, uint32(test.Value.(uint64)))
case registry.QWORD:
err = k.SetQWordValue(test.Name, test.Value.(uint64))
default:
t.Fatalf("unsupported type %d for %s value", test.Type, test.Name)
}
if test.WillFail {
if err == nil {
t.Fatalf("setting %s value %q should fail, but succeeded", test.Name, test.Value)
}
} else {
if err != nil {
t.Fatal(err)
}
}
}
}
func enumerateValues(t *testing.T, k registry.Key) {
names, err := k.ReadValueNames(-1)
if err != nil {
t.Error(err)
return
}
haveNames := make(map[string]bool)
for _, n := range names {
haveNames[n] = false
}
for _, test := range ValueTests {
wantFound := !test.WillFail
_, haveFound := haveNames[test.Name]
if wantFound && !haveFound {
t.Errorf("value %s is not found while enumerating", test.Name)
}
if haveFound && !wantFound {
t.Errorf("value %s is found while enumerating, but expected to fail", test.Name)
}
if haveFound {
delete(haveNames, test.Name)
}
}
for n, v := range haveNames {
t.Errorf("value %s (%v) is found while enumerating, but has not been cretaed", n, v)
}
}
func testErrNotExist(t *testing.T, name string, err error) {
if err == nil {
t.Errorf("%s value should not exist", name)
return
}
if err != registry.ErrNotExist {
t.Errorf("reading %s value should return 'not exist' error, but got: %s", name, err)
return
}
}
func testErrUnexpectedType(t *testing.T, test ValueTest, gottype uint32, err error) {
if err == nil {
t.Errorf("GetXValue(%q) should not succeed", test.Name)
return
}
if err != registry.ErrUnexpectedType {
t.Errorf("reading %s value should return 'unexpected key value type' error, but got: %s", test.Name, err)
return
}
if gottype != test.Type {
t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
return
}
}
func testGetStringValue(t *testing.T, k registry.Key, test ValueTest) {
got, gottype, err := k.GetStringValue(test.Name)
if err != nil {
t.Errorf("GetStringValue(%s) failed: %v", test.Name, err)
return
}
if got != test.Value {
t.Errorf("want %s value %q, got %q", test.Name, test.Value, got)
return
}
if gottype != test.Type {
t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
return
}
if gottype == registry.EXPAND_SZ {
_, err = registry.ExpandString(got)
if err != nil {
t.Errorf("ExpandString(%s) failed: %v", got, err)
return
}
}
}
func testGetIntegerValue(t *testing.T, k registry.Key, test ValueTest) {
got, gottype, err := k.GetIntegerValue(test.Name)
if err != nil {
t.Errorf("GetIntegerValue(%s) failed: %v", test.Name, err)
return
}
if got != test.Value.(uint64) {
t.Errorf("want %s value %v, got %v", test.Name, test.Value, got)
return
}
if gottype != test.Type {
t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
return
}
}
func testGetBinaryValue(t *testing.T, k registry.Key, test ValueTest) {
got, gottype, err := k.GetBinaryValue(test.Name)
if err != nil {
t.Errorf("GetBinaryValue(%s) failed: %v", test.Name, err)
return
}
if !bytes.Equal(got, test.Value.([]byte)) {
t.Errorf("want %s value %v, got %v", test.Name, test.Value, got)
return
}
if gottype != test.Type {
t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
return
}
}
func testGetStringsValue(t *testing.T, k registry.Key, test ValueTest) {
got, gottype, err := k.GetStringsValue(test.Name)
if err != nil {
t.Errorf("GetStringsValue(%s) failed: %v", test.Name, err)
return
}
if !equalStringSlice(got, test.Value.([]string)) {
t.Errorf("want %s value %#v, got %#v", test.Name, test.Value, got)
return
}
if gottype != test.Type {
t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
return
}
}
func testGetValue(t *testing.T, k registry.Key, test ValueTest, size int) {
if size <= 0 {
return
}
// read data with no buffer
gotsize, gottype, err := k.GetValue(test.Name, nil)
if err != nil {
t.Errorf("GetValue(%s, [%d]byte) failed: %v", test.Name, size, err)
return
}
if gotsize != size {
t.Errorf("want %s value size of %d, got %v", test.Name, size, gotsize)
return
}
if gottype != test.Type {
t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
return
}
// read data with short buffer
gotsize, gottype, err = k.GetValue(test.Name, make([]byte, size-1))
if err == nil {
t.Errorf("GetValue(%s, [%d]byte) should fail, but succeeded", test.Name, size-1)
return
}
if err != registry.ErrShortBuffer {
t.Errorf("reading %s value should return 'short buffer' error, but got: %s", test.Name, err)
return
}
if gotsize != size {
t.Errorf("want %s value size of %d, got %v", test.Name, size, gotsize)
return
}
if gottype != test.Type {
t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
return
}
// read full data
gotsize, gottype, err = k.GetValue(test.Name, make([]byte, size))
if err != nil {
t.Errorf("GetValue(%s, [%d]byte) failed: %v", test.Name, size, err)
return
}
if gotsize != size {
t.Errorf("want %s value size of %d, got %v", test.Name, size, gotsize)
return
}
if gottype != test.Type {
t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
return
}
// check GetValue returns ErrNotExist as required
_, _, err = k.GetValue(test.Name+"_not_there", make([]byte, size))
if err == nil {
t.Errorf("GetValue(%q) should not succeed", test.Name)
return
}
if err != registry.ErrNotExist {
t.Errorf("GetValue(%q) should return 'not exist' error, but got: %s", test.Name, err)
return
}
}
func testValues(t *testing.T, k registry.Key) {
for _, test := range ValueTests {
switch test.Type {
case registry.SZ, registry.EXPAND_SZ:
if test.WillFail {
_, _, err := k.GetStringValue(test.Name)
testErrNotExist(t, test.Name, err)
} else {
testGetStringValue(t, k, test)
_, gottype, err := k.GetIntegerValue(test.Name)
testErrUnexpectedType(t, test, gottype, err)
// Size of utf16 string in bytes is not perfect,
// but correct for current test values.
// Size also includes terminating 0.
testGetValue(t, k, test, (len(test.Value.(string))+1)*2)
}
_, _, err := k.GetStringValue(test.Name + "_string_not_created")
testErrNotExist(t, test.Name+"_string_not_created", err)
case registry.DWORD, registry.QWORD:
testGetIntegerValue(t, k, test)
_, gottype, err := k.GetBinaryValue(test.Name)
testErrUnexpectedType(t, test, gottype, err)
_, _, err = k.GetIntegerValue(test.Name + "_int_not_created")
testErrNotExist(t, test.Name+"_int_not_created", err)
size := 8
if test.Type == registry.DWORD {
size = 4
}
testGetValue(t, k, test, size)
case registry.BINARY:
testGetBinaryValue(t, k, test)
_, gottype, err := k.GetStringsValue(test.Name)
testErrUnexpectedType(t, test, gottype, err)
_, _, err = k.GetBinaryValue(test.Name + "_byte_not_created")
testErrNotExist(t, test.Name+"_byte_not_created", err)
testGetValue(t, k, test, len(test.Value.([]byte)))
case registry.MULTI_SZ:
if test.WillFail {
_, _, err := k.GetStringsValue(test.Name)
testErrNotExist(t, test.Name, err)
} else {
testGetStringsValue(t, k, test)
_, gottype, err := k.GetStringValue(test.Name)
testErrUnexpectedType(t, test, gottype, err)
size := 0
for _, s := range test.Value.([]string) {
size += len(s) + 1 // nil terminated
}
size += 1 // extra nil at the end
size *= 2 // count bytes, not uint16
testGetValue(t, k, test, size)
}
_, _, err := k.GetStringsValue(test.Name + "_strings_not_created")
testErrNotExist(t, test.Name+"_strings_not_created", err)
default:
t.Errorf("unsupported type %d for %s value", test.Type, test.Name)
continue
}
}
}
func testStat(t *testing.T, k registry.Key) {
subk, _, err := registry.CreateKey(k, "subkey", registry.CREATE_SUB_KEY)
if err != nil {
t.Error(err)
return
}
defer subk.Close()
defer registry.DeleteKey(k, "subkey")
ki, err := k.Stat()
if err != nil {
t.Error(err)
return
}
if ki.SubKeyCount != 1 {
t.Error("key must have 1 subkey")
}
if ki.MaxSubKeyLen != 6 {
t.Error("key max subkey name length must be 6")
}
if ki.ValueCount != 24 {
t.Errorf("key must have 24 values, but is %d", ki.ValueCount)
}
if ki.MaxValueNameLen != 12 {
t.Errorf("key max value name length must be 10, but is %d", ki.MaxValueNameLen)
}
if ki.MaxValueLen != 38 {
t.Errorf("key max value length must be 38, but is %d", ki.MaxValueLen)
}
if mt, ct := ki.ModTime(), time.Now(); ct.Sub(mt) > 100*time.Millisecond {
t.Errorf("key mod time is not close to current time: mtime=%v current=%v delta=%v", mt, ct, ct.Sub(mt))
}
}
func deleteValues(t *testing.T, k registry.Key) {
for _, test := range ValueTests {
if test.WillFail {
continue
}
err := k.DeleteValue(test.Name)
if err != nil {
t.Error(err)
continue
}
}
names, err := k.ReadValueNames(-1)
if err != nil {
t.Error(err)
return
}
if len(names) != 0 {
t.Errorf("some values remain after deletion: %v", names)
}
}
func TestValues(t *testing.T) {
softwareK, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE)
if err != nil {
t.Fatal(err)
}
defer softwareK.Close()
testKName := randKeyName("TestValues_")
k, exist, err := registry.CreateKey(softwareK, testKName, registry.CREATE_SUB_KEY|registry.QUERY_VALUE|registry.SET_VALUE)
if err != nil {
t.Fatal(err)
}
defer k.Close()
if exist {
t.Fatalf("key %q already exists", testKName)
}
defer registry.DeleteKey(softwareK, testKName)
setValues(t, k)
enumerateValues(t, k)
testValues(t, k)
testStat(t, k)
deleteValues(t, k)
}
func walkKey(t *testing.T, k registry.Key, kname string) {
names, err := k.ReadValueNames(-1)
if err != nil {
t.Fatalf("reading value names of %s failed: %v", kname, err)
}
for _, name := range names {
_, valtype, err := k.GetValue(name, nil)
if err != nil {
t.Fatalf("reading value type of %s of %s failed: %v", name, kname, err)
}
switch valtype {
case registry.NONE:
case registry.SZ:
_, _, err := k.GetStringValue(name)
if err != nil {
t.Error(err)
}
case registry.EXPAND_SZ:
s, _, err := k.GetStringValue(name)
if err != nil {
t.Error(err)
}
_, err = registry.ExpandString(s)
if err != nil {
t.Error(err)
}
case registry.DWORD, registry.QWORD:
_, _, err := k.GetIntegerValue(name)
if err != nil {
t.Error(err)
}
case registry.BINARY:
_, _, err := k.GetBinaryValue(name)
if err != nil {
t.Error(err)
}
case registry.MULTI_SZ:
_, _, err := k.GetStringsValue(name)
if err != nil {
t.Error(err)
}
case registry.FULL_RESOURCE_DESCRIPTOR, registry.RESOURCE_LIST, registry.RESOURCE_REQUIREMENTS_LIST:
// TODO: not implemented
default:
t.Fatalf("value type %d of %s of %s failed: %v", valtype, name, kname, err)
}
}
names, err = k.ReadSubKeyNames(-1)
if err != nil {
t.Fatalf("reading sub-keys of %s failed: %v", kname, err)
}
for _, name := range names {
func() {
subk, err := registry.OpenKey(k, name, registry.ENUMERATE_SUB_KEYS|registry.QUERY_VALUE)
if err != nil {
if err == syscall.ERROR_ACCESS_DENIED {
// ignore error, if we are not allowed to access this key
return
}
t.Fatalf("opening sub-keys %s of %s failed: %v", name, kname, err)
}
defer subk.Close()
walkKey(t, subk, kname+`\`+name)
}()
}
}
func TestWalkFullRegistry(t *testing.T) {
if testing.Short() {
t.Skip("skipping long running test in short mode")
}
walkKey(t, registry.CLASSES_ROOT, "CLASSES_ROOT")
walkKey(t, registry.CURRENT_USER, "CURRENT_USER")
walkKey(t, registry.LOCAL_MACHINE, "LOCAL_MACHINE")
walkKey(t, registry.USERS, "USERS")
walkKey(t, registry.CURRENT_CONFIG, "CURRENT_CONFIG")
}
func TestExpandString(t *testing.T) {
got, err := registry.ExpandString("%PATH%")
if err != nil {
t.Fatal(err)
}
want := os.Getenv("PATH")
if got != want {
t.Errorf("want %q string expanded, got %q", want, got)
}
}
func TestInvalidValues(t *testing.T) {
softwareK, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE)
if err != nil {
t.Fatal(err)
}
defer softwareK.Close()
testKName := randKeyName("TestInvalidValues_")
k, exist, err := registry.CreateKey(softwareK, testKName, registry.CREATE_SUB_KEY|registry.QUERY_VALUE|registry.SET_VALUE)
if err != nil {
t.Fatal(err)
}
defer k.Close()
if exist {
t.Fatalf("key %q already exists", testKName)
}
defer registry.DeleteKey(softwareK, testKName)
var tests = []struct {
Type uint32
Name string
Data []byte
}{
{registry.DWORD, "Dword1", nil},
{registry.DWORD, "Dword2", []byte{1, 2, 3}},
{registry.QWORD, "Qword1", nil},
{registry.QWORD, "Qword2", []byte{1, 2, 3}},
{registry.QWORD, "Qword3", []byte{1, 2, 3, 4, 5, 6, 7}},
{registry.MULTI_SZ, "MultiString1", nil},
{registry.MULTI_SZ, "MultiString2", []byte{0}},
{registry.MULTI_SZ, "MultiString3", []byte{'a', 'b', 0}},
{registry.MULTI_SZ, "MultiString4", []byte{'a', 0, 0, 'b', 0}},
{registry.MULTI_SZ, "MultiString5", []byte{'a', 0, 0}},
}
for _, test := range tests {
err := k.SetValue(test.Name, test.Type, test.Data)
if err != nil {
t.Fatalf("SetValue for %q failed: %v", test.Name, err)
}
}
for _, test := range tests {
switch test.Type {
case registry.DWORD, registry.QWORD:
value, valType, err := k.GetIntegerValue(test.Name)
if err == nil {
t.Errorf("GetIntegerValue(%q) succeeded. Returns type=%d value=%v", test.Name, valType, value)
}
case registry.MULTI_SZ:
value, valType, err := k.GetStringsValue(test.Name)
if err == nil {
if len(value) != 0 {
t.Errorf("GetStringsValue(%q) succeeded. Returns type=%d value=%v", test.Name, valType, value)
}
}
default:
t.Errorf("unsupported type %d for %s value", test.Type, test.Name)
}
}
}
func TestGetMUIStringValue(t *testing.T) {
if err := registry.LoadRegLoadMUIString(); err != nil {
t.Skip("regLoadMUIString not supported; skipping")
}
if err := procGetDynamicTimeZoneInformation.Find(); err != nil {
t.Skipf("%s not supported; skipping", procGetDynamicTimeZoneInformation.Name)
}
var dtzi DynamicTimezoneinformation
if _, err := GetDynamicTimeZoneInformation(&dtzi); err != nil {
t.Fatal(err)
}
tzKeyName := syscall.UTF16ToString(dtzi.TimeZoneKeyName[:])
timezoneK, err := registry.OpenKey(registry.LOCAL_MACHINE,
`SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\`+tzKeyName, registry.READ)
if err != nil {
t.Fatal(err)
}
defer timezoneK.Close()
type testType struct {
name string
want string
}
var tests = []testType{
{"MUI_Std", syscall.UTF16ToString(dtzi.StandardName[:])},
}
if dtzi.DynamicDaylightTimeDisabled == 0 {
tests = append(tests, testType{"MUI_Dlt", syscall.UTF16ToString(dtzi.DaylightName[:])})
}
for _, test := range tests {
got, err := timezoneK.GetMUIStringValue(test.name)
if err != nil {
t.Error("GetMUIStringValue:", err)
}
if got != test.want {
t.Errorf("GetMUIStringValue: %s: Got %q, want %q", test.name, got, test.want)
}
}
}
type DynamicTimezoneinformation struct {
Bias int32
StandardName [32]uint16
StandardDate syscall.Systemtime
StandardBias int32
DaylightName [32]uint16
DaylightDate syscall.Systemtime
DaylightBias int32
TimeZoneKeyName [128]uint16
DynamicDaylightTimeDisabled uint8
}
var (
kernel32DLL = syscall.NewLazyDLL("kernel32")
procGetDynamicTimeZoneInformation = kernel32DLL.NewProc("GetDynamicTimeZoneInformation")
)
func GetDynamicTimeZoneInformation(dtzi *DynamicTimezoneinformation) (rc uint32, err error) {
r0, _, e1 := syscall.Syscall(procGetDynamicTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(dtzi)), 0, 0)
rc = uint32(r0)
if rc == 0xffffffff {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}

View File

@@ -1,56 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package debug
import (
"os"
"strconv"
)
// Log interface allows different log implementations to be used.
type Log interface {
Close() error
Info(eid uint32, msg string) error
Warning(eid uint32, msg string) error
Error(eid uint32, msg string) error
}
// ConsoleLog provides access to the console.
type ConsoleLog struct {
Name string
}
// New creates new ConsoleLog.
func New(source string) *ConsoleLog {
return &ConsoleLog{Name: source}
}
// Close closes console log l.
func (l *ConsoleLog) Close() error {
return nil
}
func (l *ConsoleLog) report(kind string, eid uint32, msg string) error {
s := l.Name + "." + kind + "(" + strconv.Itoa(int(eid)) + "): " + msg + "\n"
_, err := os.Stdout.Write([]byte(s))
return err
}
// Info writes an information event msg with event id eid to the console l.
func (l *ConsoleLog) Info(eid uint32, msg string) error {
return l.report("info", eid, msg)
}
// Warning writes an warning event msg with event id eid to the console l.
func (l *ConsoleLog) Warning(eid uint32, msg string) error {
return l.report("warn", eid, msg)
}
// Error writes an error event msg with event id eid to the console l.
func (l *ConsoleLog) Error(eid uint32, msg string) error {
return l.report("error", eid, msg)
}

View File

@@ -1,45 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
// Package debug provides facilities to execute svc.Handler on console.
//
package debug
import (
"os"
"os/signal"
"syscall"
"golang.org/x/sys/windows/svc"
)
// Run executes service name by calling appropriate handler function.
// The process is running on console, unlike real service. Use Ctrl+C to
// send "Stop" command to your service.
func Run(name string, handler svc.Handler) error {
cmds := make(chan svc.ChangeRequest)
changes := make(chan svc.Status)
sig := make(chan os.Signal)
signal.Notify(sig)
go func() {
status := svc.Status{State: svc.Stopped}
for {
select {
case <-sig:
cmds <- svc.ChangeRequest{Cmd: svc.Stop, CurrentStatus: status}
case status = <-changes:
}
}
}()
_, errno := handler.Execute([]string{name}, cmds, changes)
if errno != 0 {
return syscall.Errno(errno)
}
return nil
}

View File

@@ -1,51 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package eventlog_test
import (
"testing"
"golang.org/x/sys/windows/svc/eventlog"
)
func TestLog(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode - it modifies system logs")
}
const name = "mylog"
const supports = eventlog.Error | eventlog.Warning | eventlog.Info
err := eventlog.InstallAsEventCreate(name, supports)
if err != nil {
t.Fatalf("Install failed: %s", err)
}
defer func() {
err = eventlog.Remove(name)
if err != nil {
t.Fatalf("Remove failed: %s", err)
}
}()
l, err := eventlog.Open(name)
if err != nil {
t.Fatalf("Open failed: %s", err)
}
defer l.Close()
err = l.Info(1, "info")
if err != nil {
t.Fatalf("Info failed: %s", err)
}
err = l.Warning(2, "warning")
if err != nil {
t.Fatalf("Warning failed: %s", err)
}
err = l.Error(3, "error")
if err != nil {
t.Fatalf("Error failed: %s", err)
}
}

View File

@@ -1,22 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package main
import (
"syscall"
)
// BUG(brainman): MessageBeep Windows api is broken on Windows 7,
// so this example does not beep when runs as service on Windows 7.
var (
beepFunc = syscall.MustLoadDLL("user32.dll").MustFindProc("MessageBeep")
)
func beep() {
beepFunc.Call(0xffffffff)
}

View File

@@ -1,92 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package main
import (
"fmt"
"os"
"path/filepath"
"golang.org/x/sys/windows/svc/eventlog"
"golang.org/x/sys/windows/svc/mgr"
)
func exePath() (string, error) {
prog := os.Args[0]
p, err := filepath.Abs(prog)
if err != nil {
return "", err
}
fi, err := os.Stat(p)
if err == nil {
if !fi.Mode().IsDir() {
return p, nil
}
err = fmt.Errorf("%s is directory", p)
}
if filepath.Ext(p) == "" {
p += ".exe"
fi, err := os.Stat(p)
if err == nil {
if !fi.Mode().IsDir() {
return p, nil
}
err = fmt.Errorf("%s is directory", p)
}
}
return "", err
}
func installService(name, desc string) error {
exepath, err := exePath()
if err != nil {
return err
}
m, err := mgr.Connect()
if err != nil {
return err
}
defer m.Disconnect()
s, err := m.OpenService(name)
if err == nil {
s.Close()
return fmt.Errorf("service %s already exists", name)
}
s, err = m.CreateService(name, exepath, mgr.Config{DisplayName: desc}, "is", "auto-started")
if err != nil {
return err
}
defer s.Close()
err = eventlog.InstallAsEventCreate(name, eventlog.Error|eventlog.Warning|eventlog.Info)
if err != nil {
s.Delete()
return fmt.Errorf("SetupEventLogSource() failed: %s", err)
}
return nil
}
func removeService(name string) error {
m, err := mgr.Connect()
if err != nil {
return err
}
defer m.Disconnect()
s, err := m.OpenService(name)
if err != nil {
return fmt.Errorf("service %s is not installed", name)
}
defer s.Close()
err = s.Delete()
if err != nil {
return err
}
err = eventlog.Remove(name)
if err != nil {
return fmt.Errorf("RemoveEventLogSource() failed: %s", err)
}
return nil
}

View File

@@ -1,76 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
// Example service program that beeps.
//
// The program demonstrates how to create Windows service and
// install / remove it on a computer. It also shows how to
// stop / start / pause / continue any service, and how to
// write to event log. It also shows how to use debug
// facilities available in debug package.
//
package main
import (
"fmt"
"log"
"os"
"strings"
"golang.org/x/sys/windows/svc"
)
func usage(errmsg string) {
fmt.Fprintf(os.Stderr,
"%s\n\n"+
"usage: %s <command>\n"+
" where <command> is one of\n"+
" install, remove, debug, start, stop, pause or continue.\n",
errmsg, os.Args[0])
os.Exit(2)
}
func main() {
const svcName = "myservice"
isIntSess, err := svc.IsAnInteractiveSession()
if err != nil {
log.Fatalf("failed to determine if we are running in an interactive session: %v", err)
}
if !isIntSess {
runService(svcName, false)
return
}
if len(os.Args) < 2 {
usage("no command specified")
}
cmd := strings.ToLower(os.Args[1])
switch cmd {
case "debug":
runService(svcName, true)
return
case "install":
err = installService(svcName, "my service")
case "remove":
err = removeService(svcName)
case "start":
err = startService(svcName)
case "stop":
err = controlService(svcName, svc.Stop, svc.Stopped)
case "pause":
err = controlService(svcName, svc.Pause, svc.Paused)
case "continue":
err = controlService(svcName, svc.Continue, svc.Running)
default:
usage(fmt.Sprintf("invalid command %s", cmd))
}
if err != nil {
log.Fatalf("failed to %s %s: %v", cmd, svcName, err)
}
return
}

View File

@@ -1,62 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package main
import (
"fmt"
"time"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/mgr"
)
func startService(name string) error {
m, err := mgr.Connect()
if err != nil {
return err
}
defer m.Disconnect()
s, err := m.OpenService(name)
if err != nil {
return fmt.Errorf("could not access service: %v", err)
}
defer s.Close()
err = s.Start("is", "manual-started")
if err != nil {
return fmt.Errorf("could not start service: %v", err)
}
return nil
}
func controlService(name string, c svc.Cmd, to svc.State) error {
m, err := mgr.Connect()
if err != nil {
return err
}
defer m.Disconnect()
s, err := m.OpenService(name)
if err != nil {
return fmt.Errorf("could not access service: %v", err)
}
defer s.Close()
status, err := s.Control(c)
if err != nil {
return fmt.Errorf("could not send control=%d: %v", c, err)
}
timeout := time.Now().Add(10 * time.Second)
for status.State != to {
if timeout.Before(time.Now()) {
return fmt.Errorf("timeout waiting for service to go to state=%d", to)
}
time.Sleep(300 * time.Millisecond)
status, err = s.Query()
if err != nil {
return fmt.Errorf("could not retrieve service status: %v", err)
}
}
return nil
}

View File

@@ -1,84 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package main
import (
"fmt"
"strings"
"time"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/debug"
"golang.org/x/sys/windows/svc/eventlog"
)
var elog debug.Log
type myservice struct{}
func (m *myservice) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown | svc.AcceptPauseAndContinue
changes <- svc.Status{State: svc.StartPending}
fasttick := time.Tick(500 * time.Millisecond)
slowtick := time.Tick(2 * time.Second)
tick := fasttick
changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
elog.Info(1, strings.Join(args, "-"))
loop:
for {
select {
case <-tick:
beep()
elog.Info(1, "beep")
case c := <-r:
switch c.Cmd {
case svc.Interrogate:
changes <- c.CurrentStatus
// Testing deadlock from https://code.google.com/p/winsvc/issues/detail?id=4
time.Sleep(100 * time.Millisecond)
changes <- c.CurrentStatus
case svc.Stop, svc.Shutdown:
break loop
case svc.Pause:
changes <- svc.Status{State: svc.Paused, Accepts: cmdsAccepted}
tick = slowtick
case svc.Continue:
changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
tick = fasttick
default:
elog.Error(1, fmt.Sprintf("unexpected control request #%d", c))
}
}
}
changes <- svc.Status{State: svc.StopPending}
return
}
func runService(name string, isDebug bool) {
var err error
if isDebug {
elog = debug.New(name)
} else {
elog, err = eventlog.Open(name)
if err != nil {
return
}
}
defer elog.Close()
elog.Info(1, fmt.Sprintf("starting %s service", name))
run := svc.Run
if isDebug {
run = debug.Run
}
err = run(name, &myservice{})
if err != nil {
elog.Error(1, fmt.Sprintf("%s service failed: %v", name, err))
return
}
elog.Info(1, fmt.Sprintf("%s service stopped", name))
}

View File

@@ -1,250 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package mgr_test
import (
"os"
"path/filepath"
"sort"
"strings"
"syscall"
"testing"
"time"
"golang.org/x/sys/windows/svc/mgr"
)
func TestOpenLanManServer(t *testing.T) {
m, err := mgr.Connect()
if err != nil {
if errno, ok := err.(syscall.Errno); ok && errno == syscall.ERROR_ACCESS_DENIED {
t.Skip("Skipping test: we don't have rights to manage services.")
}
t.Fatalf("SCM connection failed: %s", err)
}
defer m.Disconnect()
s, err := m.OpenService("LanmanServer")
if err != nil {
t.Fatalf("OpenService(lanmanserver) failed: %s", err)
}
defer s.Close()
_, err = s.Config()
if err != nil {
t.Fatalf("Config failed: %s", err)
}
}
func install(t *testing.T, m *mgr.Mgr, name, exepath string, c mgr.Config) {
// Sometimes it takes a while for the service to get
// removed after previous test run.
for i := 0; ; i++ {
s, err := m.OpenService(name)
if err != nil {
break
}
s.Close()
if i > 10 {
t.Fatalf("service %s already exists", name)
}
time.Sleep(300 * time.Millisecond)
}
s, err := m.CreateService(name, exepath, c)
if err != nil {
t.Fatalf("CreateService(%s) failed: %v", name, err)
}
defer s.Close()
}
func depString(d []string) string {
if len(d) == 0 {
return ""
}
for i := range d {
d[i] = strings.ToLower(d[i])
}
ss := sort.StringSlice(d)
ss.Sort()
return strings.Join([]string(ss), " ")
}
func testConfig(t *testing.T, s *mgr.Service, should mgr.Config) mgr.Config {
is, err := s.Config()
if err != nil {
t.Fatalf("Config failed: %s", err)
}
if should.DisplayName != is.DisplayName {
t.Fatalf("config mismatch: DisplayName is %q, but should have %q", is.DisplayName, should.DisplayName)
}
if should.StartType != is.StartType {
t.Fatalf("config mismatch: StartType is %v, but should have %v", is.StartType, should.StartType)
}
if should.Description != is.Description {
t.Fatalf("config mismatch: Description is %q, but should have %q", is.Description, should.Description)
}
if depString(should.Dependencies) != depString(is.Dependencies) {
t.Fatalf("config mismatch: Dependencies is %v, but should have %v", is.Dependencies, should.Dependencies)
}
return is
}
func testRecoveryActions(t *testing.T, s *mgr.Service, should []mgr.RecoveryAction) {
is, err := s.RecoveryActions()
if err != nil {
t.Fatalf("RecoveryActions failed: %s", err)
}
if len(should) != len(is) {
t.Errorf("recovery action mismatch: contains %v actions, but should have %v", len(is), len(should))
}
for i, _ := range is {
if should[i].Type != is[i].Type {
t.Errorf("recovery action mismatch: Type is %v, but should have %v", is[i].Type, should[i].Type)
}
if should[i].Delay != is[i].Delay {
t.Errorf("recovery action mismatch: Delay is %v, but should have %v", is[i].Delay, should[i].Delay)
}
}
}
func testResetPeriod(t *testing.T, s *mgr.Service, should uint32) {
is, err := s.ResetPeriod()
if err != nil {
t.Fatalf("ResetPeriod failed: %s", err)
}
if should != is {
t.Errorf("reset period mismatch: reset period is %v, but should have %v", is, should)
}
}
func testSetRecoveryActions(t *testing.T, s *mgr.Service) {
r := []mgr.RecoveryAction{
mgr.RecoveryAction{
Type: mgr.NoAction,
Delay: 60000 * time.Millisecond,
},
mgr.RecoveryAction{
Type: mgr.ServiceRestart,
Delay: 4 * time.Minute,
},
mgr.RecoveryAction{
Type: mgr.ServiceRestart,
Delay: time.Minute,
},
mgr.RecoveryAction{
Type: mgr.RunCommand,
Delay: 4000 * time.Millisecond,
},
}
// 4 recovery actions with reset period
err := s.SetRecoveryActions(r, uint32(10000))
if err != nil {
t.Fatalf("SetRecoveryActions failed: %v", err)
}
testRecoveryActions(t, s, r)
testResetPeriod(t, s, uint32(10000))
// Infinite reset period
err = s.SetRecoveryActions(r, syscall.INFINITE)
if err != nil {
t.Fatalf("SetRecoveryActions failed: %v", err)
}
testRecoveryActions(t, s, r)
testResetPeriod(t, s, syscall.INFINITE)
// nil recovery actions
err = s.SetRecoveryActions(nil, 0)
if err.Error() != "recoveryActions cannot be nil" {
t.Fatalf("SetRecoveryActions failed with unexpected error message of %q", err)
}
// Delete all recovery actions and reset period
err = s.ResetRecoveryActions()
if err != nil {
t.Fatalf("ResetRecoveryActions failed: %v", err)
}
testRecoveryActions(t, s, nil)
testResetPeriod(t, s, 0)
}
func remove(t *testing.T, s *mgr.Service) {
err := s.Delete()
if err != nil {
t.Fatalf("Delete failed: %s", err)
}
}
func TestMyService(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode - it modifies system services")
}
const name = "myservice"
m, err := mgr.Connect()
if err != nil {
if errno, ok := err.(syscall.Errno); ok && errno == syscall.ERROR_ACCESS_DENIED {
t.Skip("Skipping test: we don't have rights to manage services.")
}
t.Fatalf("SCM connection failed: %s", err)
}
defer m.Disconnect()
c := mgr.Config{
StartType: mgr.StartDisabled,
DisplayName: "my service",
Description: "my service is just a test",
Dependencies: []string{"LanmanServer", "W32Time"},
}
exename := os.Args[0]
exepath, err := filepath.Abs(exename)
if err != nil {
t.Fatalf("filepath.Abs(%s) failed: %s", exename, err)
}
install(t, m, name, exepath, c)
s, err := m.OpenService(name)
if err != nil {
t.Fatalf("service %s is not installed", name)
}
defer s.Close()
c.BinaryPathName = exepath
c = testConfig(t, s, c)
c.StartType = mgr.StartManual
err = s.UpdateConfig(c)
if err != nil {
t.Fatalf("UpdateConfig failed: %v", err)
}
testConfig(t, s, c)
svcnames, err := m.ListServices()
if err != nil {
t.Fatalf("ListServices failed: %v", err)
}
var myserviceIsInstalled bool
for _, sn := range svcnames {
if sn == name {
myserviceIsInstalled = true
break
}
}
if !myserviceIsInstalled {
t.Errorf("ListServices failed to find %q service", name)
}
testSetRecoveryActions(t, s)
remove(t, s)
}

View File

@@ -1,135 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package svc_test
import (
"fmt"
"io/ioutil"
"math/rand"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"time"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/mgr"
)
func getState(t *testing.T, s *mgr.Service) svc.State {
status, err := s.Query()
if err != nil {
t.Fatalf("Query(%s) failed: %s", s.Name, err)
}
return status.State
}
func testState(t *testing.T, s *mgr.Service, want svc.State) {
have := getState(t, s)
if have != want {
t.Fatalf("%s state is=%d want=%d", s.Name, have, want)
}
}
func waitState(t *testing.T, s *mgr.Service, want svc.State) {
for i := 0; ; i++ {
have := getState(t, s)
if have == want {
return
}
if i > 10 {
t.Fatalf("%s state is=%d, waiting timeout", s.Name, have)
}
time.Sleep(300 * time.Millisecond)
}
}
func TestExample(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode - it modifies system services")
}
const name = "myservice"
m, err := mgr.Connect()
if err != nil {
t.Fatalf("SCM connection failed: %s", err)
}
defer m.Disconnect()
dir, err := ioutil.TempDir("", "svc")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
defer os.RemoveAll(dir)
exepath := filepath.Join(dir, "a.exe")
o, err := exec.Command("go", "build", "-o", exepath, "golang.org/x/sys/windows/svc/example").CombinedOutput()
if err != nil {
t.Fatalf("failed to build service program: %v\n%v", err, string(o))
}
s, err := m.OpenService(name)
if err == nil {
err = s.Delete()
if err != nil {
s.Close()
t.Fatalf("Delete failed: %s", err)
}
s.Close()
}
s, err = m.CreateService(name, exepath, mgr.Config{DisplayName: "my service"}, "is", "auto-started")
if err != nil {
t.Fatalf("CreateService(%s) failed: %v", name, err)
}
defer s.Close()
args := []string{"is", "manual-started", fmt.Sprintf("%d", rand.Int())}
testState(t, s, svc.Stopped)
err = s.Start(args...)
if err != nil {
t.Fatalf("Start(%s) failed: %s", s.Name, err)
}
waitState(t, s, svc.Running)
time.Sleep(1 * time.Second)
// testing deadlock from issues 4.
_, err = s.Control(svc.Interrogate)
if err != nil {
t.Fatalf("Control(%s) failed: %s", s.Name, err)
}
_, err = s.Control(svc.Interrogate)
if err != nil {
t.Fatalf("Control(%s) failed: %s", s.Name, err)
}
time.Sleep(1 * time.Second)
_, err = s.Control(svc.Stop)
if err != nil {
t.Fatalf("Control(%s) failed: %s", s.Name, err)
}
waitState(t, s, svc.Stopped)
err = s.Delete()
if err != nil {
t.Fatalf("Delete failed: %s", err)
}
cmd := `Get-Eventlog -LogName Application -Newest 100` +
` | Where Source -eq "myservice"` +
` | Select -first 10` +
` | Format-table -HideTableHeaders -property ReplacementStrings`
out, err := exec.Command("powershell", "-Command", cmd).CombinedOutput()
if err != nil {
t.Fatalf("powershell failed: %v\n%v", err, string(out))
}
if want := strings.Join(append([]string{name}, args...), "-"); !strings.Contains(string(out), want) {
t.Errorf("%q string does not contain %q", string(out), want)
}
}

View File

@@ -1,53 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package windows_test
import (
"syscall"
"testing"
"golang.org/x/sys/windows"
)
func testSetGetenv(t *testing.T, key, value string) {
err := windows.Setenv(key, value)
if err != nil {
t.Fatalf("Setenv failed to set %q: %v", value, err)
}
newvalue, found := windows.Getenv(key)
if !found {
t.Fatalf("Getenv failed to find %v variable (want value %q)", key, value)
}
if newvalue != value {
t.Fatalf("Getenv(%v) = %q; want %q", key, newvalue, value)
}
}
func TestEnv(t *testing.T) {
testSetGetenv(t, "TESTENV", "AVALUE")
// make sure TESTENV gets set to "", not deleted
testSetGetenv(t, "TESTENV", "")
}
func TestGetProcAddressByOrdinal(t *testing.T) {
// Attempt calling shlwapi.dll:IsOS, resolving it by ordinal, as
// suggested in
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb773795.aspx
h, err := windows.LoadLibrary("shlwapi.dll")
if err != nil {
t.Fatalf("Failed to load shlwapi.dll: %s", err)
}
procIsOS, err := windows.GetProcAddressByOrdinal(h, 437)
if err != nil {
t.Fatalf("Could not find shlwapi.dll:IsOS by ordinal: %s", err)
}
const OS_NT = 1
r, _, _ := syscall.Syscall(procIsOS, 1, OS_NT, 0, 0)
if r == 0 {
t.Error("shlwapi.dll:IsOS(OS_NT) returned 0, expected non-zero value")
}
}

View File

@@ -1,113 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package windows_test
import (
"io/ioutil"
"os"
"path/filepath"
"syscall"
"testing"
"unsafe"
"golang.org/x/sys/windows"
)
func TestWin32finddata(t *testing.T) {
dir, err := ioutil.TempDir("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
defer os.RemoveAll(dir)
path := filepath.Join(dir, "long_name.and_extension")
f, err := os.Create(path)
if err != nil {
t.Fatalf("failed to create %v: %v", path, err)
}
f.Close()
type X struct {
fd windows.Win32finddata
got byte
pad [10]byte // to protect ourselves
}
var want byte = 2 // it is unlikely to have this character in the filename
x := X{got: want}
pathp, _ := windows.UTF16PtrFromString(path)
h, err := windows.FindFirstFile(pathp, &(x.fd))
if err != nil {
t.Fatalf("FindFirstFile failed: %v", err)
}
err = windows.FindClose(h)
if err != nil {
t.Fatalf("FindClose failed: %v", err)
}
if x.got != want {
t.Fatalf("memory corruption: want=%d got=%d", want, x.got)
}
}
func TestFormatMessage(t *testing.T) {
dll := windows.MustLoadDLL("pdh.dll")
pdhOpenQuery := func(datasrc *uint16, userdata uint32, query *windows.Handle) (errno uintptr) {
r0, _, _ := syscall.Syscall(dll.MustFindProc("PdhOpenQueryW").Addr(), 3, uintptr(unsafe.Pointer(datasrc)), uintptr(userdata), uintptr(unsafe.Pointer(query)))
return r0
}
pdhCloseQuery := func(query windows.Handle) (errno uintptr) {
r0, _, _ := syscall.Syscall(dll.MustFindProc("PdhCloseQuery").Addr(), 1, uintptr(query), 0, 0)
return r0
}
var q windows.Handle
name, err := windows.UTF16PtrFromString("no_such_source")
if err != nil {
t.Fatal(err)
}
errno := pdhOpenQuery(name, 0, &q)
if errno == 0 {
pdhCloseQuery(q)
t.Fatal("PdhOpenQuery succeeded, but expected to fail.")
}
const flags uint32 = syscall.FORMAT_MESSAGE_FROM_HMODULE | syscall.FORMAT_MESSAGE_ARGUMENT_ARRAY | syscall.FORMAT_MESSAGE_IGNORE_INSERTS
buf := make([]uint16, 300)
_, err = windows.FormatMessage(flags, uintptr(dll.Handle), uint32(errno), 0, buf, nil)
if err != nil {
t.Fatalf("FormatMessage for handle=%x and errno=%x failed: %v", dll.Handle, errno, err)
}
}
func abort(funcname string, err error) {
panic(funcname + " failed: " + err.Error())
}
func ExampleLoadLibrary() {
h, err := windows.LoadLibrary("kernel32.dll")
if err != nil {
abort("LoadLibrary", err)
}
defer windows.FreeLibrary(h)
proc, err := windows.GetProcAddress(h, "GetVersion")
if err != nil {
abort("GetProcAddress", err)
}
r, _, _ := syscall.Syscall(uintptr(proc), 0, 0, 0, 0)
major := byte(r)
minor := uint8(r >> 8)
build := uint16(r >> 16)
print("windows version ", major, ".", minor, " (Build ", build, ")\n")
}
func TestTOKEN_ALL_ACCESS(t *testing.T) {
if windows.TOKEN_ALL_ACCESS != 0xF01FF {
t.Errorf("TOKEN_ALL_ACCESS = %x, want 0xF01FF", windows.TOKEN_ALL_ACCESS)
}
}