github.com/Andyfoo/golang/x/sys@v0.0.0-20190901054642-57c1bf301704/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 "time" 16 "unsafe" 17 18 "github.com/Andyfoo/golang/x/sys/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(-1) 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(-1) 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 cretaed", 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 if mt, ct := ki.ModTime(), time.Now(); ct.Sub(mt) > 100*time.Millisecond { 472 t.Errorf("key mod time is not close to current time: mtime=%v current=%v delta=%v", mt, ct, ct.Sub(mt)) 473 } 474 } 475 476 func deleteValues(t *testing.T, k registry.Key) { 477 for _, test := range ValueTests { 478 if test.WillFail { 479 continue 480 } 481 err := k.DeleteValue(test.Name) 482 if err != nil { 483 t.Error(err) 484 continue 485 } 486 } 487 names, err := k.ReadValueNames(-1) 488 if err != nil { 489 t.Error(err) 490 return 491 } 492 if len(names) != 0 { 493 t.Errorf("some values remain after deletion: %v", names) 494 } 495 } 496 497 func TestValues(t *testing.T) { 498 softwareK, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE) 499 if err != nil { 500 t.Fatal(err) 501 } 502 defer softwareK.Close() 503 504 testKName := randKeyName("TestValues_") 505 506 k, exist, err := registry.CreateKey(softwareK, testKName, registry.CREATE_SUB_KEY|registry.QUERY_VALUE|registry.SET_VALUE) 507 if err != nil { 508 t.Fatal(err) 509 } 510 defer k.Close() 511 512 if exist { 513 t.Fatalf("key %q already exists", testKName) 514 } 515 516 defer registry.DeleteKey(softwareK, testKName) 517 518 setValues(t, k) 519 520 enumerateValues(t, k) 521 522 testValues(t, k) 523 524 testStat(t, k) 525 526 deleteValues(t, k) 527 } 528 529 func walkKey(t *testing.T, k registry.Key, kname string) { 530 names, err := k.ReadValueNames(-1) 531 if err != nil { 532 t.Fatalf("reading value names of %s failed: %v", kname, err) 533 } 534 for _, name := range names { 535 _, valtype, err := k.GetValue(name, nil) 536 if err != nil { 537 t.Fatalf("reading value type of %s of %s failed: %v", name, kname, err) 538 } 539 switch valtype { 540 case registry.NONE: 541 case registry.SZ: 542 _, _, err := k.GetStringValue(name) 543 if err != nil { 544 t.Error(err) 545 } 546 case registry.EXPAND_SZ: 547 s, _, err := k.GetStringValue(name) 548 if err != nil { 549 t.Error(err) 550 } 551 _, err = registry.ExpandString(s) 552 if err != nil { 553 t.Error(err) 554 } 555 case registry.DWORD, registry.QWORD: 556 _, _, err := k.GetIntegerValue(name) 557 if err != nil { 558 t.Error(err) 559 } 560 case registry.BINARY: 561 _, _, err := k.GetBinaryValue(name) 562 if err != nil { 563 t.Error(err) 564 } 565 case registry.MULTI_SZ: 566 _, _, err := k.GetStringsValue(name) 567 if err != nil { 568 t.Error(err) 569 } 570 case registry.FULL_RESOURCE_DESCRIPTOR, registry.RESOURCE_LIST, registry.RESOURCE_REQUIREMENTS_LIST: 571 // TODO: not implemented 572 default: 573 t.Fatalf("value type %d of %s of %s failed: %v", valtype, name, kname, err) 574 } 575 } 576 577 names, err = k.ReadSubKeyNames(-1) 578 if err != nil { 579 t.Fatalf("reading sub-keys of %s failed: %v", kname, err) 580 } 581 for _, name := range names { 582 func() { 583 subk, err := registry.OpenKey(k, name, registry.ENUMERATE_SUB_KEYS|registry.QUERY_VALUE) 584 if err != nil { 585 if err == syscall.ERROR_ACCESS_DENIED { 586 // ignore error, if we are not allowed to access this key 587 return 588 } 589 t.Fatalf("opening sub-keys %s of %s failed: %v", name, kname, err) 590 } 591 defer subk.Close() 592 593 walkKey(t, subk, kname+`\`+name) 594 }() 595 } 596 } 597 598 func TestWalkFullRegistry(t *testing.T) { 599 if testing.Short() { 600 t.Skip("skipping long running test in short mode") 601 } 602 walkKey(t, registry.CLASSES_ROOT, "CLASSES_ROOT") 603 walkKey(t, registry.CURRENT_USER, "CURRENT_USER") 604 walkKey(t, registry.LOCAL_MACHINE, "LOCAL_MACHINE") 605 walkKey(t, registry.USERS, "USERS") 606 walkKey(t, registry.CURRENT_CONFIG, "CURRENT_CONFIG") 607 } 608 609 func TestExpandString(t *testing.T) { 610 got, err := registry.ExpandString("%PATH%") 611 if err != nil { 612 t.Fatal(err) 613 } 614 want := os.Getenv("PATH") 615 if got != want { 616 t.Errorf("want %q string expanded, got %q", want, got) 617 } 618 } 619 620 func TestInvalidValues(t *testing.T) { 621 softwareK, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE) 622 if err != nil { 623 t.Fatal(err) 624 } 625 defer softwareK.Close() 626 627 testKName := randKeyName("TestInvalidValues_") 628 629 k, exist, err := registry.CreateKey(softwareK, testKName, registry.CREATE_SUB_KEY|registry.QUERY_VALUE|registry.SET_VALUE) 630 if err != nil { 631 t.Fatal(err) 632 } 633 defer k.Close() 634 635 if exist { 636 t.Fatalf("key %q already exists", testKName) 637 } 638 639 defer registry.DeleteKey(softwareK, testKName) 640 641 var tests = []struct { 642 Type uint32 643 Name string 644 Data []byte 645 }{ 646 {registry.DWORD, "Dword1", nil}, 647 {registry.DWORD, "Dword2", []byte{1, 2, 3}}, 648 {registry.QWORD, "Qword1", nil}, 649 {registry.QWORD, "Qword2", []byte{1, 2, 3}}, 650 {registry.QWORD, "Qword3", []byte{1, 2, 3, 4, 5, 6, 7}}, 651 {registry.MULTI_SZ, "MultiString1", nil}, 652 {registry.MULTI_SZ, "MultiString2", []byte{0}}, 653 {registry.MULTI_SZ, "MultiString3", []byte{'a', 'b', 0}}, 654 {registry.MULTI_SZ, "MultiString4", []byte{'a', 0, 0, 'b', 0}}, 655 {registry.MULTI_SZ, "MultiString5", []byte{'a', 0, 0}}, 656 } 657 658 for _, test := range tests { 659 err := k.SetValue(test.Name, test.Type, test.Data) 660 if err != nil { 661 t.Fatalf("SetValue for %q failed: %v", test.Name, err) 662 } 663 } 664 665 for _, test := range tests { 666 switch test.Type { 667 case registry.DWORD, registry.QWORD: 668 value, valType, err := k.GetIntegerValue(test.Name) 669 if err == nil { 670 t.Errorf("GetIntegerValue(%q) succeeded. Returns type=%d value=%v", test.Name, valType, value) 671 } 672 case registry.MULTI_SZ: 673 value, valType, err := k.GetStringsValue(test.Name) 674 if err == nil { 675 if len(value) != 0 { 676 t.Errorf("GetStringsValue(%q) succeeded. Returns type=%d value=%v", test.Name, valType, value) 677 } 678 } 679 default: 680 t.Errorf("unsupported type %d for %s value", test.Type, test.Name) 681 } 682 } 683 } 684 685 func TestGetMUIStringValue(t *testing.T) { 686 if err := registry.LoadRegLoadMUIString(); err != nil { 687 t.Skip("regLoadMUIString not supported; skipping") 688 } 689 if err := procGetDynamicTimeZoneInformation.Find(); err != nil { 690 t.Skipf("%s not supported; skipping", procGetDynamicTimeZoneInformation.Name) 691 } 692 var dtzi DynamicTimezoneinformation 693 if _, err := GetDynamicTimeZoneInformation(&dtzi); err != nil { 694 t.Fatal(err) 695 } 696 tzKeyName := syscall.UTF16ToString(dtzi.TimeZoneKeyName[:]) 697 timezoneK, err := registry.OpenKey(registry.LOCAL_MACHINE, 698 `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\`+tzKeyName, registry.READ) 699 if err != nil { 700 t.Fatal(err) 701 } 702 defer timezoneK.Close() 703 704 type testType struct { 705 name string 706 want string 707 } 708 var tests = []testType{ 709 {"MUI_Std", syscall.UTF16ToString(dtzi.StandardName[:])}, 710 } 711 if dtzi.DynamicDaylightTimeDisabled == 0 { 712 tests = append(tests, testType{"MUI_Dlt", syscall.UTF16ToString(dtzi.DaylightName[:])}) 713 } 714 715 for _, test := range tests { 716 got, err := timezoneK.GetMUIStringValue(test.name) 717 if err != nil { 718 t.Error("GetMUIStringValue:", err) 719 } 720 721 if got != test.want { 722 t.Errorf("GetMUIStringValue: %s: Got %q, want %q", test.name, got, test.want) 723 } 724 } 725 } 726 727 type DynamicTimezoneinformation struct { 728 Bias int32 729 StandardName [32]uint16 730 StandardDate syscall.Systemtime 731 StandardBias int32 732 DaylightName [32]uint16 733 DaylightDate syscall.Systemtime 734 DaylightBias int32 735 TimeZoneKeyName [128]uint16 736 DynamicDaylightTimeDisabled uint8 737 } 738 739 var ( 740 kernel32DLL = syscall.NewLazyDLL("kernel32") 741 742 procGetDynamicTimeZoneInformation = kernel32DLL.NewProc("GetDynamicTimeZoneInformation") 743 ) 744 745 func GetDynamicTimeZoneInformation(dtzi *DynamicTimezoneinformation) (rc uint32, err error) { 746 r0, _, e1 := syscall.Syscall(procGetDynamicTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(dtzi)), 0, 0) 747 rc = uint32(r0) 748 if rc == 0xffffffff { 749 if e1 != 0 { 750 err = error(e1) 751 } else { 752 err = syscall.EINVAL 753 } 754 } 755 return 756 }