1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
17 "internal/syscall/windows/registry"
20 func randKeyName(prefix
string) string {
21 const numbers
= "0123456789"
22 buf
:= make([]byte, 10)
24 for i
, b
:= range buf
{
25 buf
[i
] = numbers
[b%byte
(len(numbers
))]
27 return prefix
+ string(buf
)
30 func TestReadSubKeyNames(t
*testing
.T
) {
31 k
, err
:= registry
.OpenKey(registry
.CLASSES_ROOT
, "TypeLib", registry
.ENUMERATE_SUB_KEYS
)
37 names
, err
:= k
.ReadSubKeyNames(-1)
42 for _
, name
:= range names
{
43 // Every PC has "stdole 2.0 OLE Automation" library installed.
44 if name
== "{00020430-0000-0000-C000-000000000046}" {
49 t
.Fatal("could not find stdole 2.0 OLE Automation")
53 func TestCreateOpenDeleteKey(t
*testing
.T
) {
54 k
, err
:= registry
.OpenKey(registry
.CURRENT_USER
, "Software", registry
.QUERY_VALUE
)
60 testKName
:= randKeyName("TestCreateOpenDeleteKey_")
62 testK
, exist
, err
:= registry
.CreateKey(k
, testKName
, registry
.CREATE_SUB_KEY
)
69 t
.Fatalf("key %q already exists", testKName
)
72 testKAgain
, exist
, err
:= registry
.CreateKey(k
, testKName
, registry
.CREATE_SUB_KEY
)
76 defer testKAgain
.Close()
79 t
.Fatalf("key %q should already exist", testKName
)
82 testKOpened
, err
:= registry
.OpenKey(k
, testKName
, registry
.ENUMERATE_SUB_KEYS
)
86 defer testKOpened
.Close()
88 err
= registry
.DeleteKey(k
, testKName
)
93 testKOpenedAgain
, err
:= registry
.OpenKey(k
, testKName
, registry
.ENUMERATE_SUB_KEYS
)
95 defer testKOpenedAgain
.Close()
96 t
.Fatalf("key %q should already been deleted", testKName
)
98 if err
!= registry
.ErrNotExist
{
99 t
.Fatalf(`unexpected error ("not exist" expected): %v`, err
)
103 func equalStringSlice(a
, b
[]string) bool {
104 if len(a
) != len(b
) {
118 type ValueTest
struct {
125 var ValueTests
= []ValueTest
{
126 {Type
: registry
.SZ
, Name
: "String1", Value
: ""},
127 {Type
: registry
.SZ
, Name
: "String2", Value
: "\000", WillFail
: true},
128 {Type
: registry
.SZ
, Name
: "String3", Value
: "Hello World"},
129 {Type
: registry
.SZ
, Name
: "String4", Value
: "Hello World\000", WillFail
: true},
130 {Type
: registry
.EXPAND_SZ
, Name
: "ExpString1", Value
: ""},
131 {Type
: registry
.EXPAND_SZ
, Name
: "ExpString2", Value
: "\000", WillFail
: true},
132 {Type
: registry
.EXPAND_SZ
, Name
: "ExpString3", Value
: "Hello World"},
133 {Type
: registry
.EXPAND_SZ
, Name
: "ExpString4", Value
: "Hello\000World", WillFail
: true},
134 {Type
: registry
.EXPAND_SZ
, Name
: "ExpString5", Value
: "%PATH%"},
135 {Type
: registry
.EXPAND_SZ
, Name
: "ExpString6", Value
: "%NO_SUCH_VARIABLE%"},
136 {Type
: registry
.EXPAND_SZ
, Name
: "ExpString7", Value
: "%PATH%;."},
137 {Type
: registry
.BINARY
, Name
: "Binary1", Value
: []byte{}},
138 {Type
: registry
.BINARY
, Name
: "Binary2", Value
: []byte{1, 2, 3}},
139 {Type
: registry
.BINARY
, Name
: "Binary3", Value
: []byte{3, 2, 1, 0, 1, 2, 3}},
140 {Type
: registry
.DWORD
, Name
: "Dword1", Value
: uint64(0)},
141 {Type
: registry
.DWORD
, Name
: "Dword2", Value
: uint64(1)},
142 {Type
: registry
.DWORD
, Name
: "Dword3", Value
: uint64(0xff)},
143 {Type
: registry
.DWORD
, Name
: "Dword4", Value
: uint64(0xffff)},
144 {Type
: registry
.QWORD
, Name
: "Qword1", Value
: uint64(0)},
145 {Type
: registry
.QWORD
, Name
: "Qword2", Value
: uint64(1)},
146 {Type
: registry
.QWORD
, Name
: "Qword3", Value
: uint64(0xff)},
147 {Type
: registry
.QWORD
, Name
: "Qword4", Value
: uint64(0xffff)},
148 {Type
: registry
.QWORD
, Name
: "Qword5", Value
: uint64(0xffffff)},
149 {Type
: registry
.QWORD
, Name
: "Qword6", Value
: uint64(0xffffffff)},
150 {Type
: registry
.MULTI_SZ
, Name
: "MultiString1", Value
: []string{"a", "b", "c"}},
151 {Type
: registry
.MULTI_SZ
, Name
: "MultiString2", Value
: []string{"abc", "", "cba"}},
152 {Type
: registry
.MULTI_SZ
, Name
: "MultiString3", Value
: []string{""}},
153 {Type
: registry
.MULTI_SZ
, Name
: "MultiString4", Value
: []string{"abcdef"}},
154 {Type
: registry
.MULTI_SZ
, Name
: "MultiString5", Value
: []string{"\000"}, WillFail
: true},
155 {Type
: registry
.MULTI_SZ
, Name
: "MultiString6", Value
: []string{"a\000b"}, WillFail
: true},
156 {Type
: registry
.MULTI_SZ
, Name
: "MultiString7", Value
: []string{"ab", "\000", "cd"}, WillFail
: true},
157 {Type
: registry
.MULTI_SZ
, Name
: "MultiString8", Value
: []string{"\000", "cd"}, WillFail
: true},
158 {Type
: registry
.MULTI_SZ
, Name
: "MultiString9", Value
: []string{"ab", "\000"}, WillFail
: true},
161 func setValues(t
*testing
.T
, k registry
.Key
) {
162 for _
, test
:= range ValueTests
{
166 err
= k
.SetStringValue(test
.Name
, test
.Value
.(string))
167 case registry
.EXPAND_SZ
:
168 err
= k
.SetExpandStringValue(test
.Name
, test
.Value
.(string))
169 case registry
.MULTI_SZ
:
170 err
= k
.SetStringsValue(test
.Name
, test
.Value
.([]string))
171 case registry
.BINARY
:
172 err
= k
.SetBinaryValue(test
.Name
, test
.Value
.([]byte))
174 err
= k
.SetDWordValue(test
.Name
, uint32(test
.Value
.(uint64)))
176 err
= k
.SetQWordValue(test
.Name
, test
.Value
.(uint64))
178 t
.Fatalf("unsupported type %d for %s value", test
.Type
, test
.Name
)
182 t
.Fatalf("setting %s value %q should fail, but succeeded", test
.Name
, test
.Value
)
192 func enumerateValues(t
*testing
.T
, k registry
.Key
) {
193 names
, err
:= k
.ReadValueNames(-1)
198 haveNames
:= make(map[string]bool)
199 for _
, n
:= range names
{
202 for _
, test
:= range ValueTests
{
203 wantFound
:= !test
.WillFail
204 _
, haveFound
:= haveNames
[test
.Name
]
205 if wantFound
&& !haveFound
{
206 t
.Errorf("value %s is not found while enumerating", test
.Name
)
208 if haveFound
&& !wantFound
{
209 t
.Errorf("value %s is found while enumerating, but expected to fail", test
.Name
)
212 delete(haveNames
, test
.Name
)
215 for n
, v
:= range haveNames
{
216 t
.Errorf("value %s (%v) is found while enumerating, but has not been created", n
, v
)
220 func testErrNotExist(t
*testing
.T
, name
string, err error
) {
222 t
.Errorf("%s value should not exist", name
)
225 if err
!= registry
.ErrNotExist
{
226 t
.Errorf("reading %s value should return 'not exist' error, but got: %s", name
, err
)
231 func testErrUnexpectedType(t
*testing
.T
, test ValueTest
, gottype
uint32, err error
) {
233 t
.Errorf("GetXValue(%q) should not succeed", test
.Name
)
236 if err
!= registry
.ErrUnexpectedType
{
237 t
.Errorf("reading %s value should return 'unexpected key value type' error, but got: %s", test
.Name
, err
)
240 if gottype
!= test
.Type
{
241 t
.Errorf("want %s value type %v, got %v", test
.Name
, test
.Type
, gottype
)
246 func testGetStringValue(t
*testing
.T
, k registry
.Key
, test ValueTest
) {
247 got
, gottype
, err
:= k
.GetStringValue(test
.Name
)
249 t
.Errorf("GetStringValue(%s) failed: %v", test
.Name
, err
)
252 if got
!= test
.Value
{
253 t
.Errorf("want %s value %q, got %q", test
.Name
, test
.Value
, got
)
256 if gottype
!= test
.Type
{
257 t
.Errorf("want %s value type %v, got %v", test
.Name
, test
.Type
, gottype
)
260 if gottype
== registry
.EXPAND_SZ
{
261 _
, err
= registry
.ExpandString(got
)
263 t
.Errorf("ExpandString(%s) failed: %v", got
, err
)
269 func testGetIntegerValue(t
*testing
.T
, k registry
.Key
, test ValueTest
) {
270 got
, gottype
, err
:= k
.GetIntegerValue(test
.Name
)
272 t
.Errorf("GetIntegerValue(%s) failed: %v", test
.Name
, err
)
275 if got
!= test
.Value
.(uint64) {
276 t
.Errorf("want %s value %v, got %v", test
.Name
, test
.Value
, got
)
279 if gottype
!= test
.Type
{
280 t
.Errorf("want %s value type %v, got %v", test
.Name
, test
.Type
, gottype
)
285 func testGetBinaryValue(t
*testing
.T
, k registry
.Key
, test ValueTest
) {
286 got
, gottype
, err
:= k
.GetBinaryValue(test
.Name
)
288 t
.Errorf("GetBinaryValue(%s) failed: %v", test
.Name
, err
)
291 if !bytes
.Equal(got
, test
.Value
.([]byte)) {
292 t
.Errorf("want %s value %v, got %v", test
.Name
, test
.Value
, got
)
295 if gottype
!= test
.Type
{
296 t
.Errorf("want %s value type %v, got %v", test
.Name
, test
.Type
, gottype
)
301 func testGetStringsValue(t
*testing
.T
, k registry
.Key
, test ValueTest
) {
302 got
, gottype
, err
:= k
.GetStringsValue(test
.Name
)
304 t
.Errorf("GetStringsValue(%s) failed: %v", test
.Name
, err
)
307 if !equalStringSlice(got
, test
.Value
.([]string)) {
308 t
.Errorf("want %s value %#v, got %#v", test
.Name
, test
.Value
, got
)
311 if gottype
!= test
.Type
{
312 t
.Errorf("want %s value type %v, got %v", test
.Name
, test
.Type
, gottype
)
317 func testGetValue(t
*testing
.T
, k registry
.Key
, test ValueTest
, size
int) {
321 // read data with no buffer
322 gotsize
, gottype
, err
:= k
.GetValue(test
.Name
, nil)
324 t
.Errorf("GetValue(%s, [%d]byte) failed: %v", test
.Name
, size
, err
)
328 t
.Errorf("want %s value size of %d, got %v", test
.Name
, size
, gotsize
)
331 if gottype
!= test
.Type
{
332 t
.Errorf("want %s value type %v, got %v", test
.Name
, test
.Type
, gottype
)
335 // read data with short buffer
336 gotsize
, gottype
, err
= k
.GetValue(test
.Name
, make([]byte, size
-1))
338 t
.Errorf("GetValue(%s, [%d]byte) should fail, but succeeded", test
.Name
, size
-1)
341 if err
!= registry
.ErrShortBuffer
{
342 t
.Errorf("reading %s value should return 'short buffer' error, but got: %s", test
.Name
, err
)
346 t
.Errorf("want %s value size of %d, got %v", test
.Name
, size
, gotsize
)
349 if gottype
!= test
.Type
{
350 t
.Errorf("want %s value type %v, got %v", test
.Name
, test
.Type
, gottype
)
354 gotsize
, gottype
, err
= k
.GetValue(test
.Name
, make([]byte, size
))
356 t
.Errorf("GetValue(%s, [%d]byte) failed: %v", test
.Name
, size
, err
)
360 t
.Errorf("want %s value size of %d, got %v", test
.Name
, size
, gotsize
)
363 if gottype
!= test
.Type
{
364 t
.Errorf("want %s value type %v, got %v", test
.Name
, test
.Type
, gottype
)
367 // check GetValue returns ErrNotExist as required
368 _
, _
, err
= k
.GetValue(test
.Name
+"_not_there", make([]byte, size
))
370 t
.Errorf("GetValue(%q) should not succeed", test
.Name
)
373 if err
!= registry
.ErrNotExist
{
374 t
.Errorf("GetValue(%q) should return 'not exist' error, but got: %s", test
.Name
, err
)
379 func testValues(t
*testing
.T
, k registry
.Key
) {
380 for _
, test
:= range ValueTests
{
382 case registry
.SZ
, registry
.EXPAND_SZ
:
384 _
, _
, err
:= k
.GetStringValue(test
.Name
)
385 testErrNotExist(t
, test
.Name
, err
)
387 testGetStringValue(t
, k
, test
)
388 _
, gottype
, err
:= k
.GetIntegerValue(test
.Name
)
389 testErrUnexpectedType(t
, test
, gottype
, err
)
390 // Size of utf16 string in bytes is not perfect,
391 // but correct for current test values.
392 // Size also includes terminating 0.
393 testGetValue(t
, k
, test
, (len(test
.Value
.(string))+1)*2)
395 _
, _
, err
:= k
.GetStringValue(test
.Name
+ "_string_not_created")
396 testErrNotExist(t
, test
.Name
+"_string_not_created", err
)
397 case registry
.DWORD
, registry
.QWORD
:
398 testGetIntegerValue(t
, k
, test
)
399 _
, gottype
, err
:= k
.GetBinaryValue(test
.Name
)
400 testErrUnexpectedType(t
, test
, gottype
, err
)
401 _
, _
, err
= k
.GetIntegerValue(test
.Name
+ "_int_not_created")
402 testErrNotExist(t
, test
.Name
+"_int_not_created", err
)
404 if test
.Type
== registry
.DWORD
{
407 testGetValue(t
, k
, test
, size
)
408 case registry
.BINARY
:
409 testGetBinaryValue(t
, k
, test
)
410 _
, gottype
, err
:= k
.GetStringsValue(test
.Name
)
411 testErrUnexpectedType(t
, test
, gottype
, err
)
412 _
, _
, err
= k
.GetBinaryValue(test
.Name
+ "_byte_not_created")
413 testErrNotExist(t
, test
.Name
+"_byte_not_created", err
)
414 testGetValue(t
, k
, test
, len(test
.Value
.([]byte)))
415 case registry
.MULTI_SZ
:
417 _
, _
, err
:= k
.GetStringsValue(test
.Name
)
418 testErrNotExist(t
, test
.Name
, err
)
420 testGetStringsValue(t
, k
, test
)
421 _
, gottype
, err
:= k
.GetStringValue(test
.Name
)
422 testErrUnexpectedType(t
, test
, gottype
, err
)
424 for _
, s
:= range test
.Value
.([]string) {
425 size
+= len(s
) + 1 // nil terminated
427 size
+= 1 // extra nil at the end
428 size
*= 2 // count bytes, not uint16
429 testGetValue(t
, k
, test
, size
)
431 _
, _
, err
:= k
.GetStringsValue(test
.Name
+ "_strings_not_created")
432 testErrNotExist(t
, test
.Name
+"_strings_not_created", err
)
434 t
.Errorf("unsupported type %d for %s value", test
.Type
, test
.Name
)
440 func testStat(t
*testing
.T
, k registry
.Key
) {
441 subk
, _
, err
:= registry
.CreateKey(k
, "subkey", registry
.CREATE_SUB_KEY
)
448 defer registry
.DeleteKey(k
, "subkey")
455 if ki
.SubKeyCount
!= 1 {
456 t
.Error("key must have 1 subkey")
458 if ki
.MaxSubKeyLen
!= 6 {
459 t
.Error("key max subkey name length must be 6")
461 if ki
.ValueCount
!= 24 {
462 t
.Errorf("key must have 24 values, but is %d", ki
.ValueCount
)
464 if ki
.MaxValueNameLen
!= 12 {
465 t
.Errorf("key max value name length must be 10, but is %d", ki
.MaxValueNameLen
)
467 if ki
.MaxValueLen
!= 38 {
468 t
.Errorf("key max value length must be 38, but is %d", ki
.MaxValueLen
)
472 func deleteValues(t
*testing
.T
, k registry
.Key
) {
473 for _
, test
:= range ValueTests
{
477 err
:= k
.DeleteValue(test
.Name
)
483 names
, err
:= k
.ReadValueNames(-1)
489 t
.Errorf("some values remain after deletion: %v", names
)
493 func TestValues(t
*testing
.T
) {
494 softwareK
, err
:= registry
.OpenKey(registry
.CURRENT_USER
, "Software", registry
.QUERY_VALUE
)
498 defer softwareK
.Close()
500 testKName
:= randKeyName("TestValues_")
502 k
, exist
, err
:= registry
.CreateKey(softwareK
, testKName
, registry
.CREATE_SUB_KEY|registry
.QUERY_VALUE|registry
.SET_VALUE
)
509 t
.Fatalf("key %q already exists", testKName
)
512 defer registry
.DeleteKey(softwareK
, testKName
)
516 enumerateValues(t
, k
)
525 func walkKey(t
*testing
.T
, k registry
.Key
, kname
string) {
526 names
, err
:= k
.ReadValueNames(-1)
528 t
.Fatalf("reading value names of %s failed: %v", kname
, err
)
530 for _
, name
:= range names
{
531 _
, valtype
, err
:= k
.GetValue(name
, nil)
533 t
.Fatalf("reading value type of %s of %s failed: %v", name
, kname
, err
)
538 _
, _
, err
:= k
.GetStringValue(name
)
542 case registry
.EXPAND_SZ
:
543 s
, _
, err
:= k
.GetStringValue(name
)
547 _
, err
= registry
.ExpandString(s
)
551 case registry
.DWORD
, registry
.QWORD
:
552 _
, _
, err
:= k
.GetIntegerValue(name
)
556 case registry
.BINARY
:
557 _
, _
, err
:= k
.GetBinaryValue(name
)
561 case registry
.MULTI_SZ
:
562 _
, _
, err
:= k
.GetStringsValue(name
)
566 case registry
.FULL_RESOURCE_DESCRIPTOR
, registry
.RESOURCE_LIST
, registry
.RESOURCE_REQUIREMENTS_LIST
:
567 // TODO: not implemented
569 t
.Fatalf("value type %d of %s of %s failed: %v", valtype
, name
, kname
, err
)
573 names
, err
= k
.ReadSubKeyNames(-1)
575 t
.Fatalf("reading sub-keys of %s failed: %v", kname
, err
)
577 for _
, name
:= range names
{
579 subk
, err
:= registry
.OpenKey(k
, name
, registry
.ENUMERATE_SUB_KEYS|registry
.QUERY_VALUE
)
581 if err
== syscall
.ERROR_ACCESS_DENIED
{
582 // ignore error, if we are not allowed to access this key
585 t
.Fatalf("opening sub-keys %s of %s failed: %v", name
, kname
, err
)
589 walkKey(t
, subk
, kname
+`\`+name
)
594 func TestWalkFullRegistry(t
*testing
.T
) {
596 t
.Skip("skipping long running test in short mode")
598 walkKey(t
, registry
.CLASSES_ROOT
, "CLASSES_ROOT")
599 walkKey(t
, registry
.CURRENT_USER
, "CURRENT_USER")
600 walkKey(t
, registry
.LOCAL_MACHINE
, "LOCAL_MACHINE")
601 walkKey(t
, registry
.USERS
, "USERS")
602 walkKey(t
, registry
.CURRENT_CONFIG
, "CURRENT_CONFIG")
605 func TestExpandString(t
*testing
.T
) {
606 got
, err
:= registry
.ExpandString("%PATH%")
610 want
:= os
.Getenv("PATH")
612 t
.Errorf("want %q string expanded, got %q", want
, got
)
616 func TestInvalidValues(t
*testing
.T
) {
617 softwareK
, err
:= registry
.OpenKey(registry
.CURRENT_USER
, "Software", registry
.QUERY_VALUE
)
621 defer softwareK
.Close()
623 testKName
:= randKeyName("TestInvalidValues_")
625 k
, exist
, err
:= registry
.CreateKey(softwareK
, testKName
, registry
.CREATE_SUB_KEY|registry
.QUERY_VALUE|registry
.SET_VALUE
)
632 t
.Fatalf("key %q already exists", testKName
)
635 defer registry
.DeleteKey(softwareK
, testKName
)
637 var tests
= []struct {
642 {registry
.DWORD
, "Dword1", nil},
643 {registry
.DWORD
, "Dword2", []byte{1, 2, 3}},
644 {registry
.QWORD
, "Qword1", nil},
645 {registry
.QWORD
, "Qword2", []byte{1, 2, 3}},
646 {registry
.QWORD
, "Qword3", []byte{1, 2, 3, 4, 5, 6, 7}},
647 {registry
.MULTI_SZ
, "MultiString1", nil},
648 {registry
.MULTI_SZ
, "MultiString2", []byte{0}},
649 {registry
.MULTI_SZ
, "MultiString3", []byte{'a', 'b', 0}},
650 {registry
.MULTI_SZ
, "MultiString4", []byte{'a', 0, 0, 'b', 0}},
651 {registry
.MULTI_SZ
, "MultiString5", []byte{'a', 0, 0}},
654 for _
, test
:= range tests
{
655 err
:= k
.SetValue(test
.Name
, test
.Type
, test
.Data
)
657 t
.Fatalf("SetValue for %q failed: %v", test
.Name
, err
)
661 for _
, test
:= range tests
{
663 case registry
.DWORD
, registry
.QWORD
:
664 value
, valType
, err
:= k
.GetIntegerValue(test
.Name
)
666 t
.Errorf("GetIntegerValue(%q) succeeded. Returns type=%d value=%v", test
.Name
, valType
, value
)
668 case registry
.MULTI_SZ
:
669 value
, valType
, err
:= k
.GetStringsValue(test
.Name
)
672 t
.Errorf("GetStringsValue(%q) succeeded. Returns type=%d value=%v", test
.Name
, valType
, value
)
676 t
.Errorf("unsupported type %d for %s value", test
.Type
, test
.Name
)
681 func TestGetMUIStringValue(t
*testing
.T
) {
682 if err
:= registry
.LoadRegLoadMUIString(); err
!= nil {
683 t
.Skip("regLoadMUIString not supported; skipping")
685 if err
:= procGetDynamicTimeZoneInformation
.Find(); err
!= nil {
686 t
.Skipf("%s not supported; skipping", procGetDynamicTimeZoneInformation
.Name
)
688 var dtzi DynamicTimezoneinformation
689 if _
, err
:= GetDynamicTimeZoneInformation(&dtzi
); err
!= nil {
692 tzKeyName
:= syscall
.UTF16ToString(dtzi
.TimeZoneKeyName
[:])
693 timezoneK
, err
:= registry
.OpenKey(registry
.LOCAL_MACHINE
,
694 `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\`+tzKeyName
, registry
.READ
)
698 defer timezoneK
.Close()
700 type testType
struct {
704 var tests
= []testType
{
705 {"MUI_Std", syscall
.UTF16ToString(dtzi
.StandardName
[:])},
707 if dtzi
.DynamicDaylightTimeDisabled
== 0 {
708 tests
= append(tests
, testType
{"MUI_Dlt", syscall
.UTF16ToString(dtzi
.DaylightName
[:])})
711 for _
, test
:= range tests
{
712 got
, err
:= timezoneK
.GetMUIStringValue(test
.name
)
714 t
.Error("GetMUIStringValue:", err
)
717 if got
!= test
.want
{
718 t
.Errorf("GetMUIStringValue: %s: Got %q, want %q", test
.name
, got
, test
.want
)
723 type DynamicTimezoneinformation
struct {
725 StandardName
[32]uint16
726 StandardDate syscall
.Systemtime
728 DaylightName
[32]uint16
729 DaylightDate syscall
.Systemtime
731 TimeZoneKeyName
[128]uint16
732 DynamicDaylightTimeDisabled
uint8
736 kernel32DLL
= syscall
.NewLazyDLL("kernel32")
738 procGetDynamicTimeZoneInformation
= kernel32DLL
.NewProc("GetDynamicTimeZoneInformation")
741 func GetDynamicTimeZoneInformation(dtzi
*DynamicTimezoneinformation
) (rc
uint32, err error
) {
742 r0
, _
, e1
:= syscall
.Syscall(procGetDynamicTimeZoneInformation
.Addr(), 1, uintptr(unsafe
.Pointer(dtzi
)), 0, 0)
744 if rc
== 0xffffffff {