1 /** DGui project file. 2 3 Copyright: Trogu Antonio Davide 2011-2013 4 5 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 7 Authors: Trogu Antonio Davide 8 */ 9 module dguihub.registry; 10 11 pragma(lib, "advapi32.lib"); 12 13 private import std.utf : toUTFz, toUTF8; 14 15 private import std..string : format; 16 17 private import std.conv; 18 import dguihub.core.winapi; 19 import dguihub.core.interfaces.idisposable; 20 import dguihub.core.exception; 21 import dguihub.core.handle; 22 23 enum RegistryValueType : uint { 24 binary = REG_BINARY, 25 dword = REG_DWORD, 26 qword = REG_QWORD, 27 string_ = REG_SZ, 28 } 29 30 interface IRegistryValue { 31 public void write(RegistryKey owner, string name); 32 public RegistryValueType valueType(); 33 } 34 35 abstract class RegistryValue(T) : IRegistryValue { 36 private T _value; 37 38 public this(T val) { 39 this._value = val; 40 } 41 42 @property public abstract RegistryValueType valueType(); 43 } 44 45 final class RegistryValueBinary : RegistryValue!(ubyte[]) { 46 public this(ubyte[] b) { 47 super(b); 48 } 49 50 @property public override RegistryValueType valueType() { 51 return RegistryValueType.binary; 52 } 53 54 public override string toString() { 55 string s; 56 57 foreach (ubyte b; this._value) { 58 s ~= format("%02X", b); 59 } 60 61 return s; 62 } 63 64 public void write(RegistryKey owner, string name) { 65 ulong res = RegSetValueExW(owner.handle, toUTFz!(wchar*)(name), 0, 66 REG_BINARY, cast(ubyte*)this._value.ptr, this._value.length); 67 68 if (res != ERROR_SUCCESS) { 69 throwException!(RegistryException)("RegSetValueEx failed, Key '%s'", name); 70 } 71 } 72 } 73 74 final class RegistryValueString : RegistryValue!(string) { 75 public this(string s) { 76 super(s); 77 } 78 79 @property public override RegistryValueType valueType() { 80 return RegistryValueType.string_; 81 } 82 83 public override string toString() { 84 return this._value.idup; 85 } 86 87 public void write(RegistryKey owner, string name) { 88 ulong res = RegSetValueExW(owner.handle, toUTFz!(wchar*)(name), 0, 89 REG_SZ, cast(ubyte*)this._value.ptr, this._value.length); 90 91 if (res != ERROR_SUCCESS) { 92 throwException!(RegistryException)("RegSetValueEx failed, Key '%s'", name); 93 } 94 } 95 } 96 97 final class RegistryValueDword : RegistryValue!(uint) { 98 public this(uint i) { 99 super(i); 100 } 101 102 @property public override RegistryValueType valueType() { 103 return RegistryValueType.dword; 104 } 105 106 public override string toString() { 107 return to!(string)(this._value); 108 } 109 110 public void write(RegistryKey owner, string name) { 111 ulong res = RegSetValueExW(owner.handle, toUTFz!(wchar*)(name), 0, 112 REG_DWORD, cast(ubyte*)&this._value, uint.sizeof); 113 114 if (res != ERROR_SUCCESS) { 115 throwException!(RegistryException)("RegSetValueEx failed, Key '%s'", name); 116 } 117 } 118 } 119 120 final class RegistryValueQword : RegistryValue!(ulong) { 121 public this(ulong l) { 122 super(l); 123 } 124 125 @property public override RegistryValueType valueType() { 126 return RegistryValueType.qword; 127 } 128 129 public override string toString() { 130 return to!(string)(this._value); 131 } 132 133 public void write(RegistryKey owner, string name) { 134 ulong res = RegSetValueExW(owner.handle, toUTFz!(wchar*)(name), 0, 135 REG_QWORD, cast(ubyte*)&this._value, ulong.sizeof); 136 137 if (res != ERROR_SUCCESS) { 138 throwException!(RegistryException)("RegSetValueEx failed, Key '%s'", name); 139 } 140 } 141 } 142 143 final class RegistryKey : Handle!(HKEY), IDisposable { 144 private bool _owned; 145 146 package this(HKEY hKey, bool owned = true) { 147 this._handle = hKey; 148 this._owned = owned; 149 } 150 151 public ~this() { 152 this.dispose(); 153 } 154 155 public void dispose() { 156 if (this._owned) { 157 RegCloseKey(this._handle); 158 this._handle = null; 159 } 160 } 161 162 private void doDeleteSubKey(HKEY hKey, string name) { 163 const uint MAX_KEY_LENGTH = 0xFF; 164 const uint MAX_VALUE_NAME = 0x3FFF; 165 166 HKEY hDelKey; 167 uint valuesCount, subKeysCount; 168 wchar[] keyName = new wchar[MAX_KEY_LENGTH]; 169 wchar[] valName = new wchar[MAX_VALUE_NAME]; 170 171 if (RegOpenKeyExW(hKey, toUTFz!(wchar*)(name), 0, KEY_ALL_ACCESS, 172 &hDelKey) != ERROR_SUCCESS) { 173 throwException!(RegistryException)("Cannot open Key '%s'", to!(string)(name.ptr)); 174 } 175 176 if (RegQueryInfoKeyW(hDelKey, null, null, null, &subKeysCount, null, 177 null, &valuesCount, null, null, null, null) != ERROR_SUCCESS) { 178 throwException!(RegistryException)("Cannot query Key '%s'", to!(string)(name.ptr)); 179 } 180 181 for (int i = 0; i < subKeysCount; i++) { 182 uint size = MAX_KEY_LENGTH; 183 184 RegEnumKeyExW(hDelKey, 0, keyName.ptr, &size, null, null, null, null); 185 } 186 this.doDeleteSubKey(hDelKey, toUTF8(keyName)); 187 188 for (int i = 0; i < valuesCount; i++) { 189 uint size = MAX_VALUE_NAME; 190 191 if (RegEnumValueW(hDelKey, 0, valName.ptr, &size, null, null, null, null) != ERROR_SUCCESS) { 192 throwException!(RegistryException)("Cannot enumerate values from key '%s'", name); 193 } 194 195 if (RegDeleteValueW(hDelKey, valName.ptr) != ERROR_SUCCESS) { 196 throwException!(RegistryException)("Cannot delete Value '%s'", toUTF8(valName)); 197 } 198 } 199 200 RegCloseKey(hDelKey); 201 202 if (RegDeleteKeyW(hKey, toUTFz!(wchar*)(name)) != ERROR_SUCCESS) { 203 throwException!(RegistryException)("Cannot delete Key '%s'", to!(string)(name.ptr)); 204 } 205 } 206 207 public RegistryKey createSubKey(string name) { 208 HKEY hKey; 209 uint disp; 210 211 int res = RegCreateKeyExW(this._handle, toUTFz!(wchar*)(name), 0, null, 212 0, KEY_ALL_ACCESS, null, &hKey, &disp); 213 214 switch (res) { 215 case ERROR_SUCCESS: 216 return new RegistryKey(hKey); 217 218 default: 219 throwException!(RegistryException)("Cannot create Key '%s'", name); 220 } 221 222 return null; 223 } 224 225 public void deleteSubKey(string name) { 226 this.doDeleteSubKey(this._handle, name); 227 } 228 229 public RegistryKey getSubKey(string name) { 230 HKEY hKey; 231 232 int res = RegOpenKeyExW(this._handle, toUTFz!(wchar*)(name), 0, KEY_ALL_ACCESS, &hKey); 233 234 switch (res) { 235 case ERROR_SUCCESS: 236 return new RegistryKey(hKey); 237 238 default: 239 throwException!(RegistryException)("Cannot retrieve Key '%s'", name); 240 } 241 242 return null; 243 } 244 245 public void setValue(string name, IRegistryValue val) { 246 val.write(this, name); 247 } 248 249 public IRegistryValue getValue(string name) { 250 uint len; 251 uint type; 252 IRegistryValue ival = null; 253 254 int res = RegQueryValueExW(this._handle, toUTFz!(wchar*)(name), null, &type, null, &len); 255 256 if (res != ERROR_SUCCESS) { 257 return null; 258 } 259 260 switch (type) { 261 case REG_BINARY: 262 ubyte[] val = new ubyte[len]; 263 RegQueryValueExW(this._handle, toUTFz!(wchar*)(name), null, &type, val.ptr, &len); 264 ival = new RegistryValueBinary(val); 265 break; 266 267 case REG_DWORD: 268 uint val; 269 RegQueryValueExW(this._handle, toUTFz!(wchar*)(name), null, &type, 270 cast(ubyte*)&val, &len); 271 ival = new RegistryValueDword(val); 272 break; 273 274 case REG_QWORD: 275 ulong val; 276 RegQueryValueExW(this._handle, toUTFz!(wchar*)(name), null, &type, 277 cast(ubyte*)&val, &len); 278 ival = new RegistryValueQword(val); 279 break; 280 281 case REG_SZ: 282 wchar[] val = new wchar[len]; 283 RegQueryValueExW(this._handle, toUTFz!(wchar*)(name), null, &type, 284 cast(ubyte*)val.ptr, &len); 285 ival = new RegistryValueString(toUTF8(val)); 286 break; 287 288 default: 289 throwException!(RegistryException)("Unsupported Format"); 290 } 291 292 return ival; 293 } 294 } 295 296 final class Registry { 297 private static RegistryKey _classesRoot; 298 private static RegistryKey _currentConfig; 299 private static RegistryKey _currentUser; 300 private static RegistryKey _dynData; 301 private static RegistryKey _localMachine; 302 private static RegistryKey _performanceData; 303 private static RegistryKey _users; 304 305 private this() { 306 307 } 308 309 @property public static RegistryKey classesRoot() { 310 if (!_classesRoot) { 311 _classesRoot = new RegistryKey(HKEY_CLASSES_ROOT, false); 312 } 313 314 return _classesRoot; 315 } 316 317 @property public static RegistryKey currentConfig() { 318 if (!_currentConfig) { 319 _currentConfig = new RegistryKey(HKEY_CURRENT_CONFIG, false); 320 } 321 322 return _currentConfig; 323 } 324 325 @property public static RegistryKey currentUser() { 326 if (!_currentUser) { 327 _currentUser = new RegistryKey(HKEY_CURRENT_USER, false); 328 } 329 330 return _currentUser; 331 } 332 333 @property public static RegistryKey dynData() { 334 if (!_dynData) { 335 _dynData = new RegistryKey(HKEY_DYN_DATA, false); 336 } 337 338 return _dynData; 339 } 340 341 @property public static RegistryKey localMachine() { 342 if (!_localMachine) { 343 _localMachine = new RegistryKey(HKEY_LOCAL_MACHINE, false); 344 } 345 346 return _localMachine; 347 } 348 349 @property public static RegistryKey performanceData() { 350 if (!_performanceData) { 351 _performanceData = new RegistryKey(HKEY_PERFORMANCE_DATA, false); 352 } 353 354 return _performanceData; 355 } 356 357 @property public static RegistryKey users() { 358 if (!_users) { 359 _users = new RegistryKey(HKEY_USERS, false); 360 } 361 362 return _users; 363 } 364 }