summary refs log tree commit diff stats
path: root/lib/windows/registry.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/windows/registry.nim')
-rw-r--r--lib/windows/registry.nim77
1 files changed, 77 insertions, 0 deletions
diff --git a/lib/windows/registry.nim b/lib/windows/registry.nim
new file mode 100644
index 000000000..06f84c881
--- /dev/null
+++ b/lib/windows/registry.nim
@@ -0,0 +1,77 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2016 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module is experimental and its interface may change.
+
+import winlean, os
+
+type
+  HKEY* = uint
+
+const
+  HKEY_LOCAL_MACHINE* = HKEY(0x80000002u)
+  HKEY_CURRENT_USER* = HKEY(2147483649)
+
+  RRF_RT_ANY = 0x0000ffff
+  KEY_WOW64_64KEY = 0x0100
+  KEY_WOW64_32KEY = 0x0200
+  KEY_READ = 0x00020019
+  REG_SZ = 1
+
+proc regOpenKeyEx(hKey: HKEY, lpSubKey: WideCString, ulOptions: int32,
+                  samDesired: int32,
+                  phkResult: var HKEY): int32 {.
+  importc: "RegOpenKeyExW", dynlib: "Advapi32.dll", stdcall.}
+
+proc regCloseKey(hkey: HKEY): int32 {.
+  importc: "RegCloseKey", dynlib: "Advapi32.dll", stdcall.}
+
+proc regGetValue(key: HKEY, lpSubKey, lpValue: WideCString;
+                 dwFlags: int32 = RRF_RT_ANY, pdwType: ptr int32,
+                 pvData: pointer,
+                 pcbData: ptr int32): int32 {.
+  importc: "RegGetValueW", dynlib: "Advapi32.dll", stdcall.}
+
+template call(f) =
+  let err = f
+  if err != 0:
+    raiseOSError(err.OSErrorCode, astToStr(f))
+
+proc getUnicodeValue*(path, key: string; handle: HKEY): string =
+  let hh = newWideCString path
+  let kk = newWideCString key
+  var bufsize: int32
+  # try a couple of different flag settings:
+  var flags: int32 = RRF_RT_ANY
+  let err = regGetValue(handle, hh, kk, flags, nil, nil, addr bufsize)
+  if err != 0:
+    var newHandle: HKEY
+    call regOpenKeyEx(handle, hh, 0, KEY_READ or KEY_WOW64_64KEY, newHandle)
+    call regGetValue(newHandle, nil, kk, flags, nil, nil, addr bufsize)
+    var res = newWideCString("", bufsize)
+    call regGetValue(newHandle, nil, kk, flags, nil, cast[pointer](res),
+                   addr bufsize)
+    result = res $ bufsize
+    call regCloseKey(newHandle)
+  else:
+    var res = newWideCString("", bufsize)
+    call regGetValue(handle, hh, kk, flags, nil, cast[pointer](res),
+                   addr bufsize)
+    result = res $ bufsize
+
+proc regSetValue(key: HKEY, lpSubKey, lpValueName: WideCString,
+                 dwType: int32; lpData: WideCString; cbData: int32): int32 {.
+  importc: "RegSetKeyValueW", dynlib: "Advapi32.dll", stdcall.}
+
+proc setUnicodeValue*(path, key, val: string; handle: HKey) =
+  let hh = newWideCString path
+  let kk = newWideCString key
+  let vv = newWideCString val
+  call regSetValue(handle, hh, kk, REG_SZ, vv, (vv.len.int32+1)*2)
+