registry_test.go 21 KB

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