mirror of
https://github.com/rwinkhart/sys.git
synced 2026-09-01 22:57:29 -04:00
windows/registry: copy latest changes from internal/syscall/registry
This CL includes changes from: https://golang.org/cl/13929 https://golang.org/cl/13854 Part of fixing https://golang.org/issue/12015 Change-Id: I62e00e165d97d2349c89a783aed7fcbe9e0abd34 Reviewed-on: https://go-review.googlesource.com/14016 Run-TryBot: Alex Brainman <alex.brainman@gmail.com> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
committed by
Alex Brainman
parent
0879c8a4d6
commit
98fc11432b
@@ -13,6 +13,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"golang.org/x/sys/windows/registry"
|
"golang.org/x/sys/windows/registry"
|
||||||
)
|
)
|
||||||
@@ -680,3 +681,74 @@ func TestInvalidValues(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
var tests = []struct {
|
||||||
|
key registry.Key
|
||||||
|
name string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{timezoneK, "MUI_Std", syscall.UTF16ToString(dtzi.StandardName[:])},
|
||||||
|
{timezoneK, "MUI_Dlt", syscall.UTF16ToString(dtzi.DaylightName[:])},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
got, err := test.key.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
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,10 +19,15 @@ const (
|
|||||||
_ERROR_NO_MORE_ITEMS syscall.Errno = 259
|
_ERROR_NO_MORE_ITEMS syscall.Errno = 259
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func LoadRegLoadMUIString() error {
|
||||||
|
return procRegLoadMUIStringW.Find()
|
||||||
|
}
|
||||||
|
|
||||||
//sys regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) = advapi32.RegCreateKeyExW
|
//sys regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) = advapi32.RegCreateKeyExW
|
||||||
//sys regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) = advapi32.RegDeleteKeyW
|
//sys regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) = advapi32.RegDeleteKeyW
|
||||||
//sys regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) = advapi32.RegSetValueExW
|
//sys regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) = advapi32.RegSetValueExW
|
||||||
//sys regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegEnumValueW
|
//sys regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegEnumValueW
|
||||||
//sys regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) = advapi32.RegDeleteValueW
|
//sys regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) = advapi32.RegDeleteValueW
|
||||||
|
//sys regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) = advapi32.RegLoadMUIStringW
|
||||||
|
|
||||||
//sys expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) = kernel32.ExpandEnvironmentStringsW
|
//sys expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) = kernel32.ExpandEnvironmentStringsW
|
||||||
|
|||||||
@@ -112,6 +112,61 @@ func (k Key) GetStringValue(name string) (val string, valtype uint32, err error)
|
|||||||
return syscall.UTF16ToString(u), typ, nil
|
return syscall.UTF16ToString(u), typ, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMUIStringValue retrieves the localized string value for
|
||||||
|
// the specified value name associated with an open key k.
|
||||||
|
// If the value name doesn't exist or the localized string value
|
||||||
|
// can't be resolved, GetMUIStringValue returns ErrNotExist.
|
||||||
|
// GetMUIStringValue panics if the system doesn't support
|
||||||
|
// regLoadMUIString; use LoadRegLoadMUIString to check if
|
||||||
|
// regLoadMUIString is supported before calling this function.
|
||||||
|
func (k Key) GetMUIStringValue(name string) (string, error) {
|
||||||
|
pname, err := syscall.UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]uint16, 1024)
|
||||||
|
var buflen uint32
|
||||||
|
var pdir *uint16
|
||||||
|
|
||||||
|
err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
|
||||||
|
if err == syscall.ERROR_FILE_NOT_FOUND { // Try fallback path
|
||||||
|
|
||||||
|
// Try to resolve the string value using the system directory as
|
||||||
|
// a DLL search path; this assumes the string value is of the form
|
||||||
|
// @[path]\dllname,-strID but with no path given, e.g. @tzres.dll,-320.
|
||||||
|
|
||||||
|
// This approach works with tzres.dll but may have to be revised
|
||||||
|
// in the future to allow callers to provide custom search paths.
|
||||||
|
|
||||||
|
var s string
|
||||||
|
s, err = ExpandString("%SystemRoot%\\system32\\")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
pdir, err = syscall.UTF16PtrFromString(s)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
|
||||||
|
}
|
||||||
|
|
||||||
|
for err == syscall.ERROR_MORE_DATA { // Grow buffer if needed
|
||||||
|
if buflen <= uint32(len(buf)) {
|
||||||
|
break // Buffer not growing, assume race; break
|
||||||
|
}
|
||||||
|
buf = make([]uint16, buflen)
|
||||||
|
err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return syscall.UTF16ToString(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
// ExpandString expands environment-variable strings and replaces
|
// ExpandString expands environment-variable strings and replaces
|
||||||
// them with the values defined for the current user.
|
// them with the values defined for the current user.
|
||||||
// Use ExpandString to expand EXPAND_SZ strings.
|
// Use ExpandString to expand EXPAND_SZ strings.
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ var (
|
|||||||
procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW")
|
procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW")
|
||||||
procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
|
procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
|
||||||
procRegDeleteValueW = modadvapi32.NewProc("RegDeleteValueW")
|
procRegDeleteValueW = modadvapi32.NewProc("RegDeleteValueW")
|
||||||
|
procRegLoadMUIStringW = modadvapi32.NewProc("RegLoadMUIStringW")
|
||||||
procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW")
|
procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW")
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -59,6 +60,14 @@ func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) {
|
|||||||
return
|
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 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) {
|
func expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) {
|
||||||
r0, _, e1 := syscall.Syscall(procExpandEnvironmentStringsW.Addr(), 3, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size))
|
r0, _, e1 := syscall.Syscall(procExpandEnvironmentStringsW.Addr(), 3, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size))
|
||||||
n = uint32(r0)
|
n = uint32(r0)
|
||||||
|
|||||||
Reference in New Issue
Block a user