OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / sys / windows / registry / registry_test.go
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         "golang.org/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|registry.QUERY_VALUE)
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 }