github.com/FISCO-BCOS/crypto@v0.0.0-20200202032121-bd8ab0b5d4f1/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 // +build windows 6 7 package registry_test 8 9 import ( 10 "bytes" 11 "crypto/rand" 12 "os" 13 "syscall" 14 "testing" 15 "unsafe" 16 17 "internal/syscall/windows/registry" 18 ) 19 20 func randKeyName(prefix string) string { 21 const numbers = "0123456789" 22 buf := make([]byte, 10) 23 rand.Read(buf) 24 for i, b := range buf { 25 buf[i] = numbers[b%byte(len(numbers))] 26 } 27 return prefix + string(buf) 28 } 29 30 func TestReadSubKeyNames(t *testing.T) { 31 k, err := registry.OpenKey(registry.CLASSES_ROOT, "TypeLib", registry.ENUMERATE_SUB_KEYS) 32 if err != nil { 33 t.Fatal(err) 34 } 35 defer k.Close() 36 37 names, err := k.ReadSubKeyNames(-1) 38 if err != nil { 39 t.Fatal(err) 40 } 41 var foundStdOle bool 42 for _, name := range names { 43 // Every PC has "stdole 2.0 OLE Automation" library installed. 44 if name == "{00020430-0000-0000-C000-000000000046}" { 45 foundStdOle = true 46 } 47 } 48 if !foundStdOle { 49 t.Fatal("could not find stdole 2.0 OLE Automation") 50 } 51 } 52 53 func TestCreateOpenDeleteKey(t *testing.T) { 54 k, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE) 55 if err != nil { 56 t.Fatal(err) 57 } 58 defer k.Close() 59 60 testKName := randKeyName("TestCreateOpenDeleteKey_") 61 62 testK, exist, err := registry.CreateKey(k, testKName, registry.CREATE_SUB_KEY) 63 if err != nil { 64 t.Fatal(err) 65 } 66 defer testK.Close() 67 68 if exist { 69 t.Fatalf("key %q already exists", testKName) 70 } 71 72 testKAgain, exist, err := registry.CreateKey(k, testKName, registry.CREATE_SUB_KEY) 73 if err != nil { 74 t.Fatal(err) 75 } 76 defer testKAgain.Close() 77 78 if !exist { 79 t.Fatalf("key %q should already exist", testKName) 80 } 81 82 testKOpened, err := registry.OpenKey(k, testKName, registry.ENUMERATE_SUB_KEYS) 83 if err != nil { 84 t.Fatal(err) 85 } 86 defer testKOpened.Close() 87 88 err = registry.DeleteKey(k, testKName) 89 if err != nil { 90 t.Fatal(err) 91 } 92 93 testKOpenedAgain, err := registry.OpenKey(k, testKName, registry.ENUMERATE_SUB_KEYS) 94 if err == nil { 95 defer testKOpenedAgain.Close() 96 t.Fatalf("key %q should already been deleted", testKName) 97 } 98 if err != registry.ErrNotExist { 99 t.Fatalf(`unexpected error ("not exist" expected): %v`, err) 100 } 101 } 102 103 func equalStringSlice(a, b []string) bool { 104 if len(a) != len(b) { 105 return false 106 } 107 if a == nil { 108 return true 109 } 110 for i := range a { 111 if a[i] != b[i] { 112 return false 113 } 114 } 115 return true 116 } 117 118 type ValueTest struct { 119 Type uint32 120 Name string 121 Value interface{} 122 WillFail bool 123 } 124 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}, 159 } 160 161 func setValues(t *testing.T, k registry.Key) { 162 for _, test := range ValueTests { 163 var err error 164 switch test.Type { 165 case registry.SZ: 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)) 173 case registry.DWORD: 174 err = k.SetDWordValue(test.Name, uint32(test.Value.(uint64))) 175 case registry.QWORD: 176 err = k.SetQWordValue(test.Name, test.Value.(uint64)) 177 default: 178 t.Fatalf("unsupported type %d for %s value", test.Type, test.Name) 179 } 180 if test.WillFail { 181 if err == nil { 182 t.Fatalf("setting %s value %q should fail, but succeeded", test.Name, test.Value) 183 } 184 } else { 185 if err != nil { 186 t.Fatal(err) 187 } 188 } 189 } 190 } 191 192 func enumerateValues(t *testing.T, k registry.Key) { 193 names, err := k.ReadValueNames(-1) 194 if err != nil { 195 t.Error(err) 196 return 197 } 198 haveNames := make(map[string]bool) 199 for _, n := range names { 200 haveNames[n] = false 201 } 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) 207 } 208 if haveFound && !wantFound { 209 t.Errorf("value %s is found while enumerating, but expected to fail", test.Name) 210 } 211 if haveFound { 212 delete(haveNames, test.Name) 213 } 214 } 215 for n, v := range haveNames { 216 t.Errorf("value %s (%v) is found while enumerating, but has not been created", n, v) 217 } 218 } 219 220 func testErrNotExist(t *testing.T, name string, err error) { 221 if err == nil { 222 t.Errorf("%s value should not exist", name) 223 return 224 } 225 if err != registry.ErrNotExist { 226 t.Errorf("reading %s value should return 'not exist' error, but got: %s", name, err) 227 return 228 } 229 } 230 231 func testErrUnexpectedType(t *testing.T, test ValueTest, gottype uint32, err error) { 232 if err == nil { 233 t.Errorf("GetXValue(%q) should not succeed", test.Name) 234 return 235 } 236 if err != registry.ErrUnexpectedType { 237 t.Errorf("reading %s value should return 'unexpected key value type' error, but got: %s", test.Name, err) 238 return 239 } 240 if gottype != test.Type { 241 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 242 return 243 } 244 } 245 246 func testGetStringValue(t *testing.T, k registry.Key, test ValueTest) { 247 got, gottype, err := k.GetStringValue(test.Name) 248 if err != nil { 249 t.Errorf("GetStringValue(%s) failed: %v", test.Name, err) 250 return 251 } 252 if got != test.Value { 253 t.Errorf("want %s value %q, got %q", test.Name, test.Value, got) 254 return 255 } 256 if gottype != test.Type { 257 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 258 return 259 } 260 if gottype == registry.EXPAND_SZ { 261 _, err = registry.ExpandString(got) 262 if err != nil { 263 t.Errorf("ExpandString(%s) failed: %v", got, err) 264 return 265 } 266 } 267 } 268 269 func testGetIntegerValue(t *testing.T, k registry.Key, test ValueTest) { 270 got, gottype, err := k.GetIntegerValue(test.Name) 271 if err != nil { 272 t.Errorf("GetIntegerValue(%s) failed: %v", test.Name, err) 273 return 274 } 275 if got != test.Value.(uint64) { 276 t.Errorf("want %s value %v, got %v", test.Name, test.Value, got) 277 return 278 } 279 if gottype != test.Type { 280 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 281 return 282 } 283 } 284 285 func testGetBinaryValue(t *testing.T, k registry.Key, test ValueTest) { 286 got, gottype, err := k.GetBinaryValue(test.Name) 287 if err != nil { 288 t.Errorf("GetBinaryValue(%s) failed: %v", test.Name, err) 289 return 290 } 291 if !bytes.Equal(got, test.Value.([]byte)) { 292 t.Errorf("want %s value %v, got %v", test.Name, test.Value, got) 293 return 294 } 295 if gottype != test.Type { 296 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 297 return 298 } 299 } 300 301 func testGetStringsValue(t *testing.T, k registry.Key, test ValueTest) { 302 got, gottype, err := k.GetStringsValue(test.Name) 303 if err != nil { 304 t.Errorf("GetStringsValue(%s) failed: %v", test.Name, err) 305 return 306 } 307 if !equalStringSlice(got, test.Value.([]string)) { 308 t.Errorf("want %s value %#v, got %#v", test.Name, test.Value, got) 309 return 310 } 311 if gottype != test.Type { 312 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 313 return 314 } 315 } 316 317 func testGetValue(t *testing.T, k registry.Key, test ValueTest, size int) { 318 if size <= 0 { 319 return 320 } 321 // read data with no buffer 322 gotsize, gottype, err := k.GetValue(test.Name, nil) 323 if err != nil { 324 t.Errorf("GetValue(%s, [%d]byte) failed: %v", test.Name, size, err) 325 return 326 } 327 if gotsize != size { 328 t.Errorf("want %s value size of %d, got %v", test.Name, size, gotsize) 329 return 330 } 331 if gottype != test.Type { 332 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 333 return 334 } 335 // read data with short buffer 336 gotsize, gottype, err = k.GetValue(test.Name, make([]byte, size-1)) 337 if err == nil { 338 t.Errorf("GetValue(%s, [%d]byte) should fail, but succeeded", test.Name, size-1) 339 return 340 } 341 if err != registry.ErrShortBuffer { 342 t.Errorf("reading %s value should return 'short buffer' error, but got: %s", test.Name, err) 343 return 344 } 345 if gotsize != size { 346 t.Errorf("want %s value size of %d, got %v", test.Name, size, gotsize) 347 return 348 } 349 if gottype != test.Type { 350 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 351 return 352 } 353 // read full data 354 gotsize, gottype, err = k.GetValue(test.Name, make([]byte, size)) 355 if err != nil { 356 t.Errorf("GetValue(%s, [%d]byte) failed: %v", test.Name, size, err) 357 return 358 } 359 if gotsize != size { 360 t.Errorf("want %s value size of %d, got %v", test.Name, size, gotsize) 361 return 362 } 363 if gottype != test.Type { 364 t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype) 365 return 366 } 367 // check GetValue returns ErrNotExist as required 368 _, _, err = k.GetValue(test.Name+"_not_there", make([]byte, size)) 369 if err == nil { 370 t.Errorf("GetValue(%q) should not succeed", test.Name) 371 return 372 } 373 if err != registry.ErrNotExist { 374 t.Errorf("GetValue(%q) should return 'not exist' error, but got: %s", test.Name, err) 375 return 376 } 377 } 378 379 func testValues(t *testing.T, k registry.Key) { 380 for _, test := range ValueTests { 381 switch test.Type { 382 case registry.SZ, registry.EXPAND_SZ: 383 if test.WillFail { 384 _, _, err := k.GetStringValue(test.Name) 385 testErrNotExist(t, test.Name, err) 386 } else { 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) 394 } 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) 403 size := 8 404 if test.Type == registry.DWORD { 405 size = 4 406 } 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: 416 if test.WillFail { 417 _, _, err := k.GetStringsValue(test.Name) 418 testErrNotExist(t, test.Name, err) 419 } else { 420 testGetStringsValue(t, k, test) 421 _, gottype, err := k.GetStringValue(test.Name) 422 testErrUnexpectedType(t, test, gottype, err) 423 size := 0 424 for _, s := range test.Value.([]string) { 425 size += len(s) + 1 // nil terminated 426 } 427 size += 1 // extra nil at the end 428 size *= 2 // count bytes, not uint16 429 testGetValue(t, k, test, size) 430 } 431 _, _, err := k.GetStringsValue(test.Name + "_strings_not_created") 432 testErrNotExist(t, test.Name+"_strings_not_created", err) 433 default: 434 t.Errorf("unsupported type %d for %s value", test.Type, test.Name) 435 continue 436 } 437 } 438 } 439 440 func testStat(t *testing.T, k registry.Key) { 441 subk, _, err := registry.CreateKey(k, "subkey", registry.CREATE_SUB_KEY) 442 if err != nil { 443 t.Error(err) 444 return 445 } 446 defer subk.Close() 447 448 defer registry.DeleteKey(k, "subkey") 449 450 ki, err := k.Stat() 451 if err != nil { 452 t.Error(err) 453 return 454 } 455 if ki.SubKeyCount != 1 { 456 t.Error("key must have 1 subkey") 457 } 458 if ki.MaxSubKeyLen != 6 { 459 t.Error("key max subkey name length must be 6") 460 } 461 if ki.ValueCount != 24 { 462 t.Errorf("key must have 24 values, but is %d", ki.ValueCount) 463 } 464 if ki.MaxValueNameLen != 12 { 465 t.Errorf("key max value name length must be 10, but is %d", ki.MaxValueNameLen) 466 } 467 if ki.MaxValueLen != 38 { 468 t.Errorf("key max value length must be 38, but is %d", ki.MaxValueLen) 469 } 470 } 471 472 func deleteValues(t *testing.T, k registry.Key) { 473 for _, test := range ValueTests { 474 if test.WillFail { 475 continue 476 } 477 err := k.DeleteValue(test.Name) 478 if err != nil { 479 t.Error(err) 480 continue 481 } 482 } 483 names, err := k.ReadValueNames(-1) 484 if err != nil { 485 t.Error(err) 486 return 487 } 488 if len(names) != 0 { 489 t.Errorf("some values remain after deletion: %v", names) 490 } 491 } 492 493 func TestValues(t *testing.T) { 494 softwareK, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE) 495 if err != nil { 496 t.Fatal(err) 497 } 498 defer softwareK.Close() 499 500 testKName := randKeyName("TestValues_") 501 502 k, exist, err := registry.CreateKey(softwareK, testKName, registry.CREATE_SUB_KEY|registry.QUERY_VALUE|registry.SET_VALUE) 503 if err != nil { 504 t.Fatal(err) 505 } 506 defer k.Close() 507 508 if exist { 509 t.Fatalf("key %q already exists", testKName) 510 } 511 512 defer registry.DeleteKey(softwareK, testKName) 513 514 setValues(t, k) 515 516 enumerateValues(t, k) 517 518 testValues(t, k) 519 520 testStat(t, k) 521 522 deleteValues(t, k) 523 } 524 525 func walkKey(t *testing.T, k registry.Key, kname string) { 526 names, err := k.ReadValueNames(-1) 527 if err != nil { 528 t.Fatalf("reading value names of %s failed: %v", kname, err) 529 } 530 for _, name := range names { 531 _, valtype, err := k.GetValue(name, nil) 532 if err != nil { 533 t.Fatalf("reading value type of %s of %s failed: %v", name, kname, err) 534 } 535 switch valtype { 536 case registry.NONE: 537 case registry.SZ: 538 _, _, err := k.GetStringValue(name) 539 if err != nil { 540 t.Error(err) 541 } 542 case registry.EXPAND_SZ: 543 s, _, err := k.GetStringValue(name) 544 if err != nil { 545 t.Error(err) 546 } 547 _, err = registry.ExpandString(s) 548 if err != nil { 549 t.Error(err) 550 } 551 case registry.DWORD, registry.QWORD: 552 _, _, err := k.GetIntegerValue(name) 553 if err != nil { 554 t.Error(err) 555 } 556 case registry.BINARY: 557 _, _, err := k.GetBinaryValue(name) 558 if err != nil { 559 t.Error(err) 560 } 561 case registry.MULTI_SZ: 562 _, _, err := k.GetStringsValue(name) 563 if err != nil { 564 t.Error(err) 565 } 566 case registry.FULL_RESOURCE_DESCRIPTOR, registry.RESOURCE_LIST, registry.RESOURCE_REQUIREMENTS_LIST: 567 // TODO: not implemented 568 default: 569 t.Fatalf("value type %d of %s of %s failed: %v", valtype, name, kname, err) 570 } 571 } 572 573 names, err = k.ReadSubKeyNames(-1) 574 if err != nil { 575 t.Fatalf("reading sub-keys of %s failed: %v", kname, err) 576 } 577 for _, name := range names { 578 func() { 579 subk, err := registry.OpenKey(k, name, registry.ENUMERATE_SUB_KEYS|registry.QUERY_VALUE) 580 if err != nil { 581 if err == syscall.ERROR_ACCESS_DENIED { 582 // ignore error, if we are not allowed to access this key 583 return 584 } 585 t.Fatalf("opening sub-keys %s of %s failed: %v", name, kname, err) 586 } 587 defer subk.Close() 588 589 walkKey(t, subk, kname+`\`+name) 590 }() 591 } 592 } 593 594 func TestWalkFullRegistry(t *testing.T) { 595 if testing.Short() { 596 t.Skip("skipping long running test in short mode") 597 } 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") 603 } 604 605 func TestExpandString(t *testing.T) { 606 got, err := registry.ExpandString("%PATH%") 607 if err != nil { 608 t.Fatal(err) 609 } 610 want := os.Getenv("PATH") 611 if got != want { 612 t.Errorf("want %q string expanded, got %q", want, got) 613 } 614 } 615 616 func TestInvalidValues(t *testing.T) { 617 softwareK, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE) 618 if err != nil { 619 t.Fatal(err) 620 } 621 defer softwareK.Close() 622 623 testKName := randKeyName("TestInvalidValues_") 624 625 k, exist, err := registry.CreateKey(softwareK, testKName, registry.CREATE_SUB_KEY|registry.QUERY_VALUE|registry.SET_VALUE) 626 if err != nil { 627 t.Fatal(err) 628 } 629 defer k.Close() 630 631 if exist { 632 t.Fatalf("key %q already exists", testKName) 633 } 634 635 defer registry.DeleteKey(softwareK, testKName) 636 637 var tests = []struct { 638 Type uint32 639 Name string 640 Data []byte 641 }{ 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}}, 652 } 653 654 for _, test := range tests { 655 err := k.SetValue(test.Name, test.Type, test.Data) 656 if err != nil { 657 t.Fatalf("SetValue for %q failed: %v", test.Name, err) 658 } 659 } 660 661 for _, test := range tests { 662 switch test.Type { 663 case registry.DWORD, registry.QWORD: 664 value, valType, err := k.GetIntegerValue(test.Name) 665 if err == nil { 666 t.Errorf("GetIntegerValue(%q) succeeded. Returns type=%d value=%v", test.Name, valType, value) 667 } 668 case registry.MULTI_SZ: 669 value, valType, err := k.GetStringsValue(test.Name) 670 if err == nil { 671 if len(value) != 0 { 672 t.Errorf("GetStringsValue(%q) succeeded. Returns type=%d value=%v", test.Name, valType, value) 673 } 674 } 675 default: 676 t.Errorf("unsupported type %d for %s value", test.Type, test.Name) 677 } 678 } 679 } 680 681 func TestGetMUIStringValue(t *testing.T) { 682 if err := registry.LoadRegLoadMUIString(); err != nil { 683 t.Skip("regLoadMUIString not supported; skipping") 684 } 685 if err := procGetDynamicTimeZoneInformation.Find(); err != nil { 686 t.Skipf("%s not supported; skipping", procGetDynamicTimeZoneInformation.Name) 687 } 688 var dtzi DynamicTimezoneinformation 689 if _, err := GetDynamicTimeZoneInformation(&dtzi); err != nil { 690 t.Fatal(err) 691 } 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) 695 if err != nil { 696 t.Fatal(err) 697 } 698 defer timezoneK.Close() 699 700 type testType struct { 701 name string 702 want string 703 } 704 var tests = []testType{ 705 {"MUI_Std", syscall.UTF16ToString(dtzi.StandardName[:])}, 706 } 707 if dtzi.DynamicDaylightTimeDisabled == 0 { 708 tests = append(tests, testType{"MUI_Dlt", syscall.UTF16ToString(dtzi.DaylightName[:])}) 709 } 710 711 for _, test := range tests { 712 got, err := timezoneK.GetMUIStringValue(test.name) 713 if err != nil { 714 t.Error("GetMUIStringValue:", err) 715 } 716 717 if got != test.want { 718 t.Errorf("GetMUIStringValue: %s: Got %q, want %q", test.name, got, test.want) 719 } 720 } 721 } 722 723 type DynamicTimezoneinformation struct { 724 Bias int32 725 StandardName [32]uint16 726 StandardDate syscall.Systemtime 727 StandardBias int32 728 DaylightName [32]uint16 729 DaylightDate syscall.Systemtime 730 DaylightBias int32 731 TimeZoneKeyName [128]uint16 732 DynamicDaylightTimeDisabled uint8 733 } 734 735 var ( 736 kernel32DLL = syscall.NewLazyDLL("kernel32") 737 738 procGetDynamicTimeZoneInformation = kernel32DLL.NewProc("GetDynamicTimeZoneInformation") 739 ) 740 741 func GetDynamicTimeZoneInformation(dtzi *DynamicTimezoneinformation) (rc uint32, err error) { 742 r0, _, e1 := syscall.Syscall(procGetDynamicTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(dtzi)), 0, 0) 743 rc = uint32(r0) 744 if rc == 0xffffffff { 745 if e1 != 0 { 746 err = error(e1) 747 } else { 748 err = syscall.EINVAL 749 } 750 } 751 return 752 }