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