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 }