gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/internal/syscall/windows/registry/registry_test.go (about) 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. 4 5 //go:build windows 6 // +build windows 7 8 package registry_test 9 10 import ( 11 "bytes" 12 "crypto/rand" 13 "os" 14 "syscall" 15 "testing" 16 "unsafe" 17 18 "gitee.com/ks-custle/core-gm/internal/syscall/windows/registry" 19 ) 20 21 func randKeyName(prefix string) string { 22 const numbers = "0123456789" 23 buf := make([]byte, 10) 24 rand.Read(buf) 25 for i, b := range buf { 26 buf[i] = numbers[b%byte(len(numbers))] 27 } 28 return prefix + string(buf) 29 } 30 31 func TestReadSubKeyNames(t *testing.T) { 32 k, err := registry.OpenKey(registry.CLASSES_ROOT, "TypeLib", registry.ENUMERATE_SUB_KEYS) 33 if err != nil { 34 t.Fatal(err) 35 } 36 defer k.Close() 37 38 names, err := k.ReadSubKeyNames() 39 if err != nil { 40 t.Fatal(err) 41 } 42 var foundStdOle bool 43 for _, name := range names { 44 // Every PC has "stdole 2.0 OLE Automation" library installed. 45 if name == "{00020430-0000-0000-C000-000000000046}" { 46 foundStdOle = true 47 } 48 } 49 if !foundStdOle { 50 t.Fatal("could not find stdole 2.0 OLE Automation") 51 } 52 } 53 54 func TestCreateOpenDeleteKey(t *testing.T) { 55 k, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE) 56 if err != nil { 57 t.Fatal(err) 58 } 59 defer k.Close() 60 61 testKName := randKeyName("TestCreateOpenDeleteKey_") 62 63 testK, exist, err := registry.CreateKey(k, testKName, registry.CREATE_SUB_KEY) 64 if err != nil { 65 t.Fatal(err) 66 } 67 defer testK.Close() 68 69 if exist { 70 t.Fatalf("key %q already exists", testKName) 71 } 72 73 testKAgain, exist, err := registry.CreateKey(k, testKName, registry.CREATE_SUB_KEY) 74 if err != nil { 75 t.Fatal(err) 76 } 77 defer testKAgain.Close() 78 79 if !exist { 80 t.Fatalf("key %q should already exist", testKName) 81 } 82 83 testKOpened, err := registry.OpenKey(k, testKName, registry.ENUMERATE_SUB_KEYS) 84 if err != nil { 85 t.Fatal(err) 86 } 87 defer testKOpened.Close() 88 89 err = registry.DeleteKey(k, testKName) 90 if err != nil { 91 t.Fatal(err) 92 } 93 94 testKOpenedAgain, err := registry.OpenKey(k, testKName, registry.ENUMERATE_SUB_KEYS) 95 if err == nil { 96 defer testKOpenedAgain.Close() 97 t.Fatalf("key %q should already been deleted", testKName) 98 } 99 if err != registry.ErrNotExist { 100 t.Fatalf(`unexpected error ("not exist" expected): %v`, err) 101 } 102 } 103 104 func equalStringSlice(a, b []string) bool { 105 if len(a) != len(b) { 106 return false 107 } 108 if a == nil { 109 return true 110 } 111 for i := range a { 112 if a[i] != b[i] { 113 return false 114 } 115 } 116 return true 117 } 118 119 type ValueTest struct { 120 Type uint32 121 Name string 122 Value interface{} 123 WillFail bool 124 } 125 126 var ValueTests = []ValueTest{ 127 {Type: registry.SZ, Name: "String1", Value: ""}, 128 {Type: registry.SZ, Name: "String2", Value: "\000", WillFail: true}, 129 {Type: registry.SZ, Name: "String3", Value: "Hello World"}, 130 {Type: registry.SZ, Name: "String4", Value: "Hello World\000", WillFail: true}, 131 {Type: registry.EXPAND_SZ, Name: "ExpString1", Value: ""}, 132 {Type: registry.EXPAND_SZ, Name: "ExpString2", Value: "\000", WillFail: true}, 133 {Type: registry.EXPAND_SZ, Name: "ExpString3", Value: "Hello World"}, 134 {Type: registry.EXPAND_SZ, Name: "ExpString4", Value: "Hello\000World", WillFail: true}, 135 {Type: registry.EXPAND_SZ, Name: "ExpString5", Value: "%PATH%"}, 136 {Type: registry.EXPAND_SZ, Name: "ExpString6", Value: "%NO_SUCH_VARIABLE%"}, 137 {Type: registry.EXPAND_SZ, Name: "ExpString7", Value: "%PATH%;."}, 138 {Type: registry.BINARY, Name: "Binary1", Value: []byte{}}, 139 {Type: registry.BINARY, Name: "Binary2", Value: []byte{1, 2, 3}}, 140 {Type: registry.BINARY, Name: "Binary3", Value: []byte{3, 2, 1, 0, 1, 2, 3}}, 141 {Type: registry.DWORD, Name: "Dword1", Value: uint64(0)}, 142 {Type: registry.DWORD, Name: "Dword2", Value: uint64(1)}, 143 {Type: registry.DWORD, Name: "Dword3", Value: uint64(0xff)}, 144 {Type: registry.DWORD, Name: "Dword4", Value: uint64(0xffff)}, 145 {Type: registry.QWORD, Name: "Qword1", Value: uint64(0)}, 146 {Type: registry.QWORD, Name: "Qword2", Value: uint64(1)}, 147 {Type: registry.QWORD, Name: "Qword3", Value: uint64(0xff)}, 148 {Type: registry.QWORD, Name: "Qword4", Value: uint64(0xffff)}, 149 {Type: registry.QWORD, Name: "Qword5", Value: uint64(0xffffff)}, 150 {Type: registry.QWORD, Name: "Qword6", Value: uint64(0xffffffff)}, 151 {Type: registry.MULTI_SZ, Name: "MultiString1", Value: []string{"a", "b", "c"}}, 152 {Type: registry.MULTI_SZ, Name: "MultiString2", Value: []string{"abc", "", "cba"}}, 153 {Type: registry.MULTI_SZ, Name: "MultiString3", Value: []string{""}}, 154 {Type: registry.MULTI_SZ, Name: "MultiString4", Value: []string{"abcdef"}}, 155 {Type: registry.MULTI_SZ, Name: "MultiString5", Value: []string{"\000"}, WillFail: true}, 156 {Type: registry.MULTI_SZ, Name: "MultiString6", Value: []string{"a\000b"}, WillFail: true}, 157 {Type: registry.MULTI_SZ, Name: "MultiString7", Value: []string{"ab", "\000", "cd"}, WillFail: true}, 158 {Type: registry.MULTI_SZ, Name: "MultiString8", Value: []string{"\000", "cd"}, WillFail: true}, 159 {Type: registry.MULTI_SZ, Name: "MultiString9", Value: []string{"ab", "\000"}, WillFail: true}, 160 } 161 162 func setValues(t *testing.T, k registry.Key) { 163 for _, test := range ValueTests { 164 var err error 165 switch test.Type { 166 case registry.SZ: 167 err = k.SetStringValue(test.Name, test.Value.(string)) 168 case registry.EXPAND_SZ: 169 err = k.SetExpandStringValue(test.Name, test.Value.(string)) 170 case registry.MULTI_SZ: 171 err = k.SetStringsValue(test.Name, test.Value.([]string)) 172 case registry.BINARY: 173 err = k.SetBinaryValue(test.Name, test.Value.([]byte)) 174 case registry.DWORD: 175 err = k.SetDWordValue(test.Name, uint32(test.Value.(uint64))) 176 case registry.QWORD: 177 err = k.SetQWordValue(test.Name, test.Value.(uint64)) 178 default: 179 t.Fatalf("unsupported type %d for %s value", test.Type, test.Name) 180 } 181 if test.WillFail { 182 if err == nil { 183 t.Fatalf("setting %s value %q should fail, but succeeded", test.Name, test.Value) 184 } 185 } else { 186 if err != nil { 187 t.Fatal(err) 188 } 189 } 190 } 191 } 192 193 func enumerateValues(t *testing.T, k registry.Key) { 194 names, err := k.ReadValueNames() 195 if err != nil { 196 t.Error(err) 197 return 198 } 199 haveNames := make(map[string]bool) 200 for _, n := range names { 201 haveNames[n] = false 202 } 203 for _, test := range ValueTests { 204 wantFound := !test.WillFail 205 _, haveFound := haveNames[test.Name] 206 if wantFound && !haveFound { 207 t.Errorf("value %s is not found while enumerating", test.Name) 208 } 209 if haveFound && !wantFound { 210 t.Errorf("value %s is found while enumerating, but expected to fail", test.Name) 211 } 212 if haveFound { 213 delete(haveNames, test.Name) 214 } 215 } 216 for n, v := range haveNames { 217 t.Errorf("value %s (%v) is found while enumerating, but has not been created", n, v) 218 } 219 } 220 221 func testErrNotExist(t *testing.T, name string, err error) { 222 if err == nil { 223 t.Errorf("%s value should not exist", name) 224 return 225 } 226 if err != registry.ErrNotExist { 227 t.Errorf("reading %s value should return 'not exist' error, but got: %s", name, err) 228 return 229 } 230 } 231 232 func testErrUnexpectedType(t *testing.T, test ValueTest, gottype uint32, err error) { 233 if err == nil { 234 t.Errorf("GetXValue(%q) should not succeed", test.Name) 235 return 236 } 237 if err != registry.ErrUnexpectedType { 238 t.Errorf("reading %s value should return 'unexpected key value type' error, but got: %s", test.Name, err) 239 return 240 } 241 if gottype != test.Type { 242 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 243 return 244 } 245 } 246 247 func testGetStringValue(t *testing.T, k registry.Key, test ValueTest) { 248 got, gottype, err := k.GetStringValue(test.Name) 249 if err != nil { 250 t.Errorf("GetStringValue(%s) failed: %v", test.Name, err) 251 return 252 } 253 if got != test.Value { 254 t.Errorf("want %s value %q, got %q", test.Name, test.Value, got) 255 return 256 } 257 if gottype != test.Type { 258 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 259 return 260 } 261 if gottype == registry.EXPAND_SZ { 262 _, err = registry.ExpandString(got) 263 if err != nil { 264 t.Errorf("ExpandString(%s) failed: %v", got, err) 265 return 266 } 267 } 268 } 269 270 func testGetIntegerValue(t *testing.T, k registry.Key, test ValueTest) { 271 got, gottype, err := k.GetIntegerValue(test.Name) 272 if err != nil { 273 t.Errorf("GetIntegerValue(%s) failed: %v", test.Name, err) 274 return 275 } 276 if got != test.Value.(uint64) { 277 t.Errorf("want %s value %v, got %v", test.Name, test.Value, got) 278 return 279 } 280 if gottype != test.Type { 281 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 282 return 283 } 284 } 285 286 func testGetBinaryValue(t *testing.T, k registry.Key, test ValueTest) { 287 got, gottype, err := k.GetBinaryValue(test.Name) 288 if err != nil { 289 t.Errorf("GetBinaryValue(%s) failed: %v", test.Name, err) 290 return 291 } 292 if !bytes.Equal(got, test.Value.([]byte)) { 293 t.Errorf("want %s value %v, got %v", test.Name, test.Value, got) 294 return 295 } 296 if gottype != test.Type { 297 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 298 return 299 } 300 } 301 302 func testGetStringsValue(t *testing.T, k registry.Key, test ValueTest) { 303 got, gottype, err := k.GetStringsValue(test.Name) 304 if err != nil { 305 t.Errorf("GetStringsValue(%s) failed: %v", test.Name, err) 306 return 307 } 308 if !equalStringSlice(got, test.Value.([]string)) { 309 t.Errorf("want %s value %#v, got %#v", test.Name, test.Value, got) 310 return 311 } 312 if gottype != test.Type { 313 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 314 return 315 } 316 } 317 318 func testGetValue(t *testing.T, k registry.Key, test ValueTest, size int) { 319 if size <= 0 { 320 return 321 } 322 // read data with no buffer 323 gotsize, gottype, err := k.GetValue(test.Name, nil) 324 if err != nil { 325 t.Errorf("GetValue(%s, [%d]byte) failed: %v", test.Name, size, err) 326 return 327 } 328 if gotsize != size { 329 t.Errorf("want %s value size of %d, got %v", test.Name, size, gotsize) 330 return 331 } 332 if gottype != test.Type { 333 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 334 return 335 } 336 // read data with short buffer 337 gotsize, gottype, err = k.GetValue(test.Name, make([]byte, size-1)) 338 if err == nil { 339 t.Errorf("GetValue(%s, [%d]byte) should fail, but succeeded", test.Name, size-1) 340 return 341 } 342 if err != registry.ErrShortBuffer { 343 t.Errorf("reading %s value should return 'short buffer' error, but got: %s", test.Name, err) 344 return 345 } 346 if gotsize != size { 347 t.Errorf("want %s value size of %d, got %v", test.Name, size, gotsize) 348 return 349 } 350 if gottype != test.Type { 351 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 352 return 353 } 354 // read full data 355 gotsize, gottype, err = k.GetValue(test.Name, make([]byte, size)) 356 if err != nil { 357 t.Errorf("GetValue(%s, [%d]byte) failed: %v", test.Name, size, err) 358 return 359 } 360 if gotsize != size { 361 t.Errorf("want %s value size of %d, got %v", test.Name, size, gotsize) 362 return 363 } 364 if gottype != test.Type { 365 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 366 return 367 } 368 // check GetValue returns ErrNotExist as required 369 _, _, err = k.GetValue(test.Name+"_not_there", make([]byte, size)) 370 if err == nil { 371 t.Errorf("GetValue(%q) should not succeed", test.Name) 372 return 373 } 374 if err != registry.ErrNotExist { 375 t.Errorf("GetValue(%q) should return 'not exist' error, but got: %s", test.Name, err) 376 return 377 } 378 } 379 380 func testValues(t *testing.T, k registry.Key) { 381 for _, test := range ValueTests { 382 switch test.Type { 383 case registry.SZ, registry.EXPAND_SZ: 384 if test.WillFail { 385 _, _, err := k.GetStringValue(test.Name) 386 testErrNotExist(t, test.Name, err) 387 } else { 388 testGetStringValue(t, k, test) 389 _, gottype, err := k.GetIntegerValue(test.Name) 390 testErrUnexpectedType(t, test, gottype, err) 391 // Size of utf16 string in bytes is not perfect, 392 // but correct for current test values. 393 // Size also includes terminating 0. 394 testGetValue(t, k, test, (len(test.Value.(string))+1)*2) 395 } 396 _, _, err := k.GetStringValue(test.Name + "_string_not_created") 397 testErrNotExist(t, test.Name+"_string_not_created", err) 398 case registry.DWORD, registry.QWORD: 399 testGetIntegerValue(t, k, test) 400 _, gottype, err := k.GetBinaryValue(test.Name) 401 testErrUnexpectedType(t, test, gottype, err) 402 _, _, err = k.GetIntegerValue(test.Name + "_int_not_created") 403 testErrNotExist(t, test.Name+"_int_not_created", err) 404 size := 8 405 if test.Type == registry.DWORD { 406 size = 4 407 } 408 testGetValue(t, k, test, size) 409 case registry.BINARY: 410 testGetBinaryValue(t, k, test) 411 _, gottype, err := k.GetStringsValue(test.Name) 412 testErrUnexpectedType(t, test, gottype, err) 413 _, _, err = k.GetBinaryValue(test.Name + "_byte_not_created") 414 testErrNotExist(t, test.Name+"_byte_not_created", err) 415 testGetValue(t, k, test, len(test.Value.([]byte))) 416 case registry.MULTI_SZ: 417 if test.WillFail { 418 _, _, err := k.GetStringsValue(test.Name) 419 testErrNotExist(t, test.Name, err) 420 } else { 421 testGetStringsValue(t, k, test) 422 _, gottype, err := k.GetStringValue(test.Name) 423 testErrUnexpectedType(t, test, gottype, err) 424 size := 0 425 for _, s := range test.Value.([]string) { 426 size += len(s) + 1 // nil terminated 427 } 428 size += 1 // extra nil at the end 429 size *= 2 // count bytes, not uint16 430 testGetValue(t, k, test, size) 431 } 432 _, _, err := k.GetStringsValue(test.Name + "_strings_not_created") 433 testErrNotExist(t, test.Name+"_strings_not_created", err) 434 default: 435 t.Errorf("unsupported type %d for %s value", test.Type, test.Name) 436 continue 437 } 438 } 439 } 440 441 func testStat(t *testing.T, k registry.Key) { 442 subk, _, err := registry.CreateKey(k, "subkey", registry.CREATE_SUB_KEY) 443 if err != nil { 444 t.Error(err) 445 return 446 } 447 defer subk.Close() 448 449 defer registry.DeleteKey(k, "subkey") 450 451 ki, err := k.Stat() 452 if err != nil { 453 t.Error(err) 454 return 455 } 456 if ki.SubKeyCount != 1 { 457 t.Error("key must have 1 subkey") 458 } 459 if ki.MaxSubKeyLen != 6 { 460 t.Error("key max subkey name length must be 6") 461 } 462 if ki.ValueCount != 24 { 463 t.Errorf("key must have 24 values, but is %d", ki.ValueCount) 464 } 465 if ki.MaxValueNameLen != 12 { 466 t.Errorf("key max value name length must be 10, but is %d", ki.MaxValueNameLen) 467 } 468 if ki.MaxValueLen != 38 { 469 t.Errorf("key max value length must be 38, but is %d", ki.MaxValueLen) 470 } 471 } 472 473 func deleteValues(t *testing.T, k registry.Key) { 474 for _, test := range ValueTests { 475 if test.WillFail { 476 continue 477 } 478 err := k.DeleteValue(test.Name) 479 if err != nil { 480 t.Error(err) 481 continue 482 } 483 } 484 names, err := k.ReadValueNames() 485 if err != nil { 486 t.Error(err) 487 return 488 } 489 if len(names) != 0 { 490 t.Errorf("some values remain after deletion: %v", names) 491 } 492 } 493 494 func TestValues(t *testing.T) { 495 softwareK, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE) 496 if err != nil { 497 t.Fatal(err) 498 } 499 defer softwareK.Close() 500 501 testKName := randKeyName("TestValues_") 502 503 k, exist, err := registry.CreateKey(softwareK, testKName, registry.CREATE_SUB_KEY|registry.QUERY_VALUE|registry.SET_VALUE) 504 if err != nil { 505 t.Fatal(err) 506 } 507 defer k.Close() 508 509 if exist { 510 t.Fatalf("key %q already exists", testKName) 511 } 512 513 defer registry.DeleteKey(softwareK, testKName) 514 515 setValues(t, k) 516 517 enumerateValues(t, k) 518 519 testValues(t, k) 520 521 testStat(t, k) 522 523 deleteValues(t, k) 524 } 525 526 func TestExpandString(t *testing.T) { 527 got, err := registry.ExpandString("%PATH%") 528 if err != nil { 529 t.Fatal(err) 530 } 531 want := os.Getenv("PATH") 532 if got != want { 533 t.Errorf("want %q string expanded, got %q", want, got) 534 } 535 } 536 537 func TestInvalidValues(t *testing.T) { 538 softwareK, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE) 539 if err != nil { 540 t.Fatal(err) 541 } 542 defer softwareK.Close() 543 544 testKName := randKeyName("TestInvalidValues_") 545 546 k, exist, err := registry.CreateKey(softwareK, testKName, registry.CREATE_SUB_KEY|registry.QUERY_VALUE|registry.SET_VALUE) 547 if err != nil { 548 t.Fatal(err) 549 } 550 defer k.Close() 551 552 if exist { 553 t.Fatalf("key %q already exists", testKName) 554 } 555 556 defer registry.DeleteKey(softwareK, testKName) 557 558 var tests = []struct { 559 Type uint32 560 Name string 561 Data []byte 562 }{ 563 {registry.DWORD, "Dword1", nil}, 564 {registry.DWORD, "Dword2", []byte{1, 2, 3}}, 565 {registry.QWORD, "Qword1", nil}, 566 {registry.QWORD, "Qword2", []byte{1, 2, 3}}, 567 {registry.QWORD, "Qword3", []byte{1, 2, 3, 4, 5, 6, 7}}, 568 {registry.MULTI_SZ, "MultiString1", nil}, 569 {registry.MULTI_SZ, "MultiString2", []byte{0}}, 570 {registry.MULTI_SZ, "MultiString3", []byte{'a', 'b', 0}}, 571 {registry.MULTI_SZ, "MultiString4", []byte{'a', 0, 0, 'b', 0}}, 572 {registry.MULTI_SZ, "MultiString5", []byte{'a', 0, 0}}, 573 } 574 575 for _, test := range tests { 576 err := k.SetValue(test.Name, test.Type, test.Data) 577 if err != nil { 578 t.Fatalf("SetValue for %q failed: %v", test.Name, err) 579 } 580 } 581 582 for _, test := range tests { 583 switch test.Type { 584 case registry.DWORD, registry.QWORD: 585 value, valType, err := k.GetIntegerValue(test.Name) 586 if err == nil { 587 t.Errorf("GetIntegerValue(%q) succeeded. Returns type=%d value=%v", test.Name, valType, value) 588 } 589 case registry.MULTI_SZ: 590 value, valType, err := k.GetStringsValue(test.Name) 591 if err == nil { 592 if len(value) != 0 { 593 t.Errorf("GetStringsValue(%q) succeeded. Returns type=%d value=%v", test.Name, valType, value) 594 } 595 } 596 default: 597 t.Errorf("unsupported type %d for %s value", test.Type, test.Name) 598 } 599 } 600 } 601 602 func TestGetMUIStringValue(t *testing.T) { 603 if err := registry.LoadRegLoadMUIString(); err != nil { 604 t.Skip("regLoadMUIString not supported; skipping") 605 } 606 if err := procGetDynamicTimeZoneInformation.Find(); err != nil { 607 t.Skipf("%s not supported; skipping", procGetDynamicTimeZoneInformation.Name) 608 } 609 var dtzi DynamicTimezoneinformation 610 if _, err := GetDynamicTimeZoneInformation(&dtzi); err != nil { 611 t.Fatal(err) 612 } 613 tzKeyName := syscall.UTF16ToString(dtzi.TimeZoneKeyName[:]) 614 timezoneK, err := registry.OpenKey(registry.LOCAL_MACHINE, 615 `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\`+tzKeyName, registry.READ) 616 if err != nil { 617 t.Fatal(err) 618 } 619 defer timezoneK.Close() 620 621 type testType struct { 622 name string 623 want string 624 } 625 var tests = []testType{ 626 {"MUI_Std", syscall.UTF16ToString(dtzi.StandardName[:])}, 627 } 628 if dtzi.DynamicDaylightTimeDisabled == 0 { 629 tests = append(tests, testType{"MUI_Dlt", syscall.UTF16ToString(dtzi.DaylightName[:])}) 630 } 631 632 for _, test := range tests { 633 got, err := timezoneK.GetMUIStringValue(test.name) 634 if err != nil { 635 t.Error("GetMUIStringValue:", err) 636 } 637 638 if got != test.want { 639 t.Errorf("GetMUIStringValue: %s: Got %q, want %q", test.name, got, test.want) 640 } 641 } 642 } 643 644 type DynamicTimezoneinformation struct { 645 Bias int32 646 StandardName [32]uint16 647 StandardDate syscall.Systemtime 648 StandardBias int32 649 DaylightName [32]uint16 650 DaylightDate syscall.Systemtime 651 DaylightBias int32 652 TimeZoneKeyName [128]uint16 653 DynamicDaylightTimeDisabled uint8 654 } 655 656 var ( 657 kernel32DLL = syscall.NewLazyDLL("kernel32") 658 659 procGetDynamicTimeZoneInformation = kernel32DLL.NewProc("GetDynamicTimeZoneInformation") 660 ) 661 662 func GetDynamicTimeZoneInformation(dtzi *DynamicTimezoneinformation) (rc uint32, err error) { 663 r0, _, e1 := syscall.Syscall(procGetDynamicTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(dtzi)), 0, 0) 664 rc = uint32(r0) 665 if rc == 0xffffffff { 666 if e1 != 0 { 667 err = error(e1) 668 } else { 669 err = syscall.EINVAL 670 } 671 } 672 return 673 }