1 /******************************************************************************
2 *
3 * Copyright (C) 2004-2008, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * Author: Alexey Krivonogov ( gentee )
11 *
12 ******************************************************************************/
13
14 /*-----------------------------------------------------------------------------
15 * Id: registry L "Registry"
16 *
17 * Summary: Working with the Registry. This library allows you to work with
18 the Windows Registry. For using this library, it is required to
19 specify the file registry.g (from
20 lib\registry subfolder) with include command. #srcg[
21 |include : $"...\gentee\lib\registry\registry.g"]
22 *
23 * List: *#lng/funcs#,regdelkey,regdelvalue,reggetmultistr,reggetnum,
24 regkeys,regsetmultistr,regsetnum,regvaltype,regvalues,regverify,
25 *#lng/methods#,buf_regget,buf_regset,str_regget,str_regset
26 *
27 -----------------------------------------------------------------------------*/
28
29 define <export>
30 {
31 /*-----------------------------------------------------------------------------
32 * Id: regroot D
33 *
34 * Summary: Registry roots
35 *
36 -----------------------------------------------------------------------------*/
37 HKEY_CLASSES_ROOT = 0x80000000 // Classes Root.
38 HKEY_CURRENT_USER = 0x80000001 // Current user's settings.
39 HKEY_LOCAL_MACHINE = 0x80000002 // Local machine settings.
40 HKEY_USERS = 0x80000003 // All users' settings
41
42 //-----------------------------------------------------------------------------
43 REG_OPTION_NON_VOLATILE = 0x00000000
44
45 REG_CREATED_NEW_KEY = 0x00000001
46 REG_OPENED_EXISTING_KEY = 0x00000002
47 /*-----------------------------------------------------------------------------
48 * Id: regtype D
49 *
50 * Summary: Registry types
51 *
52 -----------------------------------------------------------------------------*/
53 REG_NONE = 0 // Unknown.
54 REG_SZ = 1 // String.
55 REG_EXPAND_SZ = 2 // Expanded string. String with environment variables.
56 REG_BINARY = 3 // Binary data.
57 REG_DWORD = 4 // Number.
58 REG_MULTI_SZ = 7 // String sequence.
59
60 //-----------------------------------------------------------------------------
61 KEY_READ = 0x20019
62 KEY_WRITE = 0x20006
63
64 /*-----------------------------------------------------------------------------
65 * Id: regsetret D
66 *
67 * Summary: Result of buf.regset
68 *
69 -----------------------------------------------------------------------------
70 #define 0 // No data has been written.
71 #define 1 // The value of the key was created during the writing process.
72 #define 2 // Data is written into the existing value.
73
74 //-----------------------------------------------------------------------------
75 -----------------------------------------------------------------------------*/
76 REGSET_FALSE = 0
77 REGSET_CREATED = 1
78 REGSET_OPENED = 2
79
80 ERROR_NO_MORE_ITEMS = 259
81 }
82
83 import "advapi32.dll"
84 {
85 int RegCloseKey( uint )
86 int RegCreateKeyExA( uint, uint, uint, uint, uint, uint, uint, uint,
87 uint ) -> RegCreateKeyEx
88 int RegDeleteKeyA( uint, uint ) -> RegDeleteKey
89 int RegDeleteValueA( uint, uint ) -> RegDeleteValue
90 int RegEnumKeyExA( uint, uint, uint, uint, uint, uint, uint,
91 filetime ) -> RegEnumKeyEx
92 int RegEnumValueA( uint, uint, uint, uint, uint, uint, uint,
93 uint ) -> RegEnumValue
94 int RegOpenKeyExA( uint, uint, uint, uint, uint ) -> RegOpenKeyEx
95 int RegQueryValueExA( uint, uint, uint, uint,
96 uint, uint ) -> RegQueryValueEx
97 int RegSetValueExA( uint, uint, uint, uint, uint, uint ) -> RegSetValueEx
98 }
99
100 /*-----------------------------------------------------------------------------
101 * Id: regvaltype F
102 *
103 * Summary: Get the type of a registry key value.
104 *
105 * Params: root - A root key. $$[regroot]
106 subkey - A name of the registry key.
107 valname - The name of the key value the type of which is being /
108 determined.
109 *
110 * Return: 0 is returned if the type is not determined or there is no such
111 value. Besides, the following values are possible: $$[regtype]
112 *
113 -----------------------------------------------------------------------------*/
114
115 func uint regvaltype( uint root, str subkey, str valname )
116 {
117 uint hkey
118 uint result
119
120 if !RegOpenKeyEx( root, subkey.ptr(), 0, $KEY_READ, &hkey )
121 {
122 if RegQueryValueEx( hkey, valname.ptr(), 0, &result, 0, 0 ) : result = 0
123 RegCloseKey( hkey )
124 }
125 return result
126 }
127
128 /*-----------------------------------------------------------------------------
129 * Id: buf_regget F2
130 *
131 * Summary: Getting a value. This method writes the value of a registry key
132 into a #a(buffer) object.
133 *
134 * Params: root - A root key. $$[regroot]
135 subkey - A name of the registry key.
136 valname - A name of the specified key value.
137 regtype - The pointer to uint the type of this value will be /
138 written to. It can be 0.
139 *
140 * Return: #lng/retobj#
141 *
142 -----------------------------------------------------------------------------*/
143
144 method buf buf.regget( uint root, str subkey, str valname, uint regtype )
145 {
146 uint size
147 uint hkey
148
149 this.clear()
150 if !RegOpenKeyEx( root, subkey.ptr(), 0, $KEY_READ, &hkey )
151 {
152 if !RegQueryValueEx( hkey, valname.ptr(), 0, regtype, 0, &size )
153 {
154 this.expand( size )
155 if !RegQueryValueEx( hkey, valname.ptr(), 0, 0, this.ptr(), &size )
156 {
157 this.use = size
158 }
159 }
160 elif regtype : regtype->uint = 0
161 RegCloseKey( hkey )
162 }
163 return this
164 }
165
166 /*-----------------------------------------------------------------------------
167 * Id: str_regget F2
168 *
169 * Summary: Getting a value. This method writes the value of a registry key
170 into a #a(string) object.
171 *
172 * Params: root - A root key. $$[regroot]
173 subkey - A name of the registry key.
174 valname - A name of the specified key value.
175 *
176 * Return: #lng/retobj#
177 *
178 -----------------------------------------------------------------------------*/
179
180 method str str.regget( uint root, str subkey, str valname )
181 {
182 uint size itype
183
184 this->buf.regget( root, subkey, valname, &itype )
185
186 if itype == $REG_SZ || itype == $REG_EXPAND_SZ || itype == $REG_MULTI_SZ
187 {
188 this.setlenptr()
189 }
190 elif itype == $REG_DWORD
191 {
192 size = this.ptr()->uint
193 this = str( size )
194 }
195 else : this->buf += byte( 0 )
196
197 return this
198 }
199
200 /*-----------------------------------------------------------------------------
201 * Id: str_regget_1 FA
202 *
203 * Summary: This method writes the value of a registry key
204 into a #a(string) object.
205 *
206 * Params: root - A root key. $$[regroot]
207 subkey - A name of the registry key.
208 valname - A name of the specified key value.
209 defval - The default string in case there is no value.
210 *
211 * Return: #lng/retobj#
212 *
213 -----------------------------------------------------------------------------*/
214
215 method str str.regget( uint root, str subkey, str valname, str defval )
216 {
217 uint size itype
218
219 if !regvaltype( root, subkey, valname )
220 {
221 this = defval
222 }
223 else : this.regget( root, subkey, valname )
224
225 return this
226 }
227
228 /*-----------------------------------------------------------------------------
229 * Id: reggetnum F
230 *
231 * Summary: Get the numerical value of a registry key.
232 *
233 * Params: root - A root key. $$[regroot]
234 subkey - A name of the registry key.
235 valname - A name of the specified key value.
236 *
237 * Return: A numerical value is returned.
238 *
239 -----------------------------------------------------------------------------*/
240
241 func uint reggetnum( uint root, str subkey, str valname )
242 {
243 uint size itype
244 buf data
245
246 data.regget( root, subkey, valname, &itype )
247
248 if itype == $REG_SZ || itype == $REG_EXPAND_SZ || itype == $REG_MULTI_SZ
249 {
250 return data->str.uint()
251 }
252 elif itype == $REG_DWORD
253 {
254 return data.ptr()->uint
255 }
256
257 return 0
258 }
259
260 /*-----------------------------------------------------------------------------
261 * Id: reggetnum_1 F8
262 *
263 * Summary: Get the numerical value of a registry key.
264 *
265 * Params: root - A root key. $$[regroot]
266 subkey - A name of the registry key.
267 valname - A name of the specified key value.
268 defval - The default number in case there is no value.
269 *
270 * Return: A numerical value is returned.
271 *
272 -----------------------------------------------------------------------------*/
273
274 func uint reggetnum( uint root, str subkey, str valname, uint defval )
275 {
276 if !regvaltype( root, subkey, valname ) : return defval
277 return reggetnum( root, subkey, valname )
278 }
279
280 /*-----------------------------------------------------------------------------
281 * Id: regverify F
282 *
283 * Summary: Creating missing keys. Check if there is a certain key in the
284 registry and create it if it is not there.
285 *
286 * Params: root - A root key. $$[regroot]
287 subkey - The name of the registry key being checked.
288 ret - The array of strings all the created keys will be written to./
289 It can be 0.
290 *
291 * Return: #lng/retf#
292 *
293 -----------------------------------------------------------------------------*/
294
295 func uint regverify( uint root, str subkey, arrstr ret )
296 {
297 arrstr keys
298 str key
299 uint i hkey dwi
300
301 subkey.fdelslash()
302 subkey.split( keys, '\', 0 )
303 if ret : ret.clear()
304
305 fornum i, *keys
306 {
307 key.faddname( keys[ i ] )
308
309 if !RegCreateKeyEx( root, key.ptr(), 0, 0,
310 $REG_OPTION_NON_VOLATILE, $KEY_WRITE, 0, &hkey, &dwi )
311 {
312 if dwi == $REG_CREATED_NEW_KEY && ret
313 {
314 ret += key
315 }
316 RegCloseKey( hkey )
317 }
318 else : return 0
319 }
320 return 1
321 }
322
323 /*-----------------------------------------------------------------------------
324 * Id: buf_regset F2
325 *
326 * Summary: Writing a value. Write the data of an buf object as registry
327 key value. If there is no key, it will be created.
328 *
329 * Params: root - A root key. $$[regroot]
330 subkey - A name of the registry key.
331 valname - The name of the value being written.
332 regtype - Value type. $$[regtype]
333 ret - The array of strings all the created keys will be written to. /
334 It can be 0.
335 *
336 * Return: $$[regsetret]
337 *
338 -----------------------------------------------------------------------------*/
339
340 method uint buf.regset( uint root, str subkey, str valname, uint regtype,
341 arrstr ret )
342 {
343 uint result size exist
344 uint hkey dwi
345
346 subkey.fdelslash()
347 if regvaltype( root, subkey, valname ) : exist = 1
348 else : regverify( root, subkey, ret )
349
350 if !RegCreateKeyEx( root, subkey.ptr(), 0, 0, $REG_OPTION_NON_VOLATILE,
351 $KEY_WRITE | $KEY_READ, 0, &hkey, &dwi )
352 {
353 size = ?( regtype == $REG_DWORD, 4, *this )
354
355 if !RegSetValueEx( hkey, valname.ptr(), 0, regtype, this.ptr(),
356 size ) : result = 1 + exist
357 RegCloseKey( hkey )
358 }
359
360 return result
361 }
362
363 /*-----------------------------------------------------------------------------
364 * Id: str_regset F2
365 *
366 * Summary: Write a string as a registry key value. If there is no key,
367 it will be created.
368 *
369 * Params: root - A root key. $$[regroot]
370 subkey - A name of the registry key.
371 valname - The name of the value being written.
372 ret - The array of strings all the created keys will be written to. /
373 It can be 0.
374 *
375 * Return: $$[regsetret]
376 *
377 -----------------------------------------------------------------------------*/
378
379 method uint str.regset( uint root, str subkey, str valname, arrstr ret )
380 {
381 return this->buf.regset( root, subkey, valname, $REG_SZ, ret )
382 }
383
384 /*-----------------------------------------------------------------------------
385 * Id: str_regset_1 FA
386 *
387 * Summary: Write a string as a registry key value. If there is no key,
388 it will be created.
389 *
390 * Params: root - A root key. $$[regroot]
391 subkey - A name of the registry key.
392 valname - The name of the value being written.
393 *
394 * Return: $$[regsetret].
395 *
396 -----------------------------------------------------------------------------*/
397
398 method uint str.regset( uint root, str subkey, str valname )
399 {
400 return this->buf.regset( root, subkey, valname, $REG_SZ, 0->arrstr )
401 }
402
403 /*-----------------------------------------------------------------------------
404 * Id: regsetnum F
405 *
406 * Summary: Write a number as a registry key value. If there is no key, it
407 will be created.
408 *
409 * Params: root - A root key. $$[regroot]
410 subkey - A name of the registry key.
411 valname - The name of the value being written.
412 value - The number being written.
413 ret - The array of strings all the created keys will be written to. /
414 It can be 0.
415 *
416 * Return: $$[regsetret]
417 *
418 -----------------------------------------------------------------------------*/
419
420 func uint regsetnum( uint root, str subkey, str valname, uint value,
421 arrstr ret )
422 {
423 buf bnum
424
425 bnum += value
426 return bnum.regset( root, subkey, valname, $REG_DWORD, ret )
427 }
428
429 /*-----------------------------------------------------------------------------
430 * Id: regsetmultistr F
431 *
432 * Summary: Writing a string sequence. Write an array of strings as a value of
433 a registry key of the $REG_MULTISZ type. If there is no key,
434 it will be created.
435 *
436 * Params: root - A root key. $$[regroot]
437 subkey - A name of the registry key.
438 valname - The name of the value being written.
439 val - The arrays of strings being written.
440 ret - The array of strings all the created keys will be written to. /
441 It can be 0.
442 *
443 * Return: $$[regsetret]
444 *
445 -----------------------------------------------------------------------------*/
446
447 func uint regsetmultistr( uint root, str subkey, str valname, arrstr val,
448 arrstr ret )
449 {
450 buf bmulti
451
452 //bmulti.setmultistr( val )
453 val.setmultistr( bmulti )
454 return bmulti.regset( root, subkey, valname, $REG_MULTI_SZ, ret )
455 }
456
457 /*-----------------------------------------------------------------------------
458 * Id: reggetmultistr F
459 *
460 * Summary: Getting a string sequence. Get the value of a registry key of
461 the $REG_MULTISZ type into a string array.
462 *
463 * Params: root - A root key. $$[regroot]
464 subkey - A name of the registry key.
465 valname - A name of the specified key value.
466 val - The array strings are written to.
467 *
468 * Return: #lng/retpar( val )
469 *
470 -----------------------------------------------------------------------------*/
471
472 func arrstr reggetmultistr( uint root, str subkey, str valname, arrstr val )
473 {
474 buf bmulti
475 uint regtype
476
477 val.clear()
478 bmulti.regget( root, subkey, valname, ®type )
479
480 if regtype == $REG_MULTI_SZ || regtype == $REG_SZ ||
481 regtype == $REG_EXPAND_SZ
482 {
483 bmulti.getmultistr( val )
484 }
485
486 return val
487 }
488
489 func uint regenum( uint root, str subkey, arrstr ret, uint enumtype )
490 {
491 uint hkey index size
492 filetime ft
493 str stemp
494
495 subfunc int enum
496 {
497 if enumtype
498 {
499 return RegEnumValue( hkey, index++, stemp.ptr(), &size, 0, 0,
500 0, 0 )
501 }
502 return RegEnumKeyEx( hkey, index++, stemp.ptr(), &size, 0, 0,
503 0, ft )
504 }
505
506 ret.clear()
507 if RegOpenKeyEx( root, subkey.ptr(), 0, $KEY_READ, &hkey )
508 {
509 return 0
510 }
511 size = 512
512 stemp.reserve( size )
513
514 while enum() != $ERROR_NO_MORE_ITEMS
515 {
516 stemp.setlenptr()
517 ret += stemp
518 size = 512
519 }
520 RegCloseKey( hkey )
521 return 1
522 }
523
524 /*-----------------------------------------------------------------------------
525 * Id: regkeys F
526 *
527 * Summary: Getting the list of keys.
528 *
529 * Params: root - A root key. $$[regroot]
530 subkey - A name of the registry key.
531 ret - The array the names of the keys will be written to.
532 *
533 * Return: #lng/retf#
534 *
535 -----------------------------------------------------------------------------*/
536
537 func uint regkeys( uint root, str subkey, arrstr ret )
538 {
539 return regenum( root, subkey, ret, 0 )
540 }
541
542 /*-----------------------------------------------------------------------------
543 * Id: regvalues F
544 *
545 * Summary: Getting the list of values in a key.
546 *
547 * Params: root - A root key. $$[regroot]
548 subkey - A name of the registry key.
549 ret - The array the names of values in the keys will be written to.
550 *
551 * Return: #lng/retf#
552 *
553 -----------------------------------------------------------------------------*/
554
555 func uint regvalues( uint root, str subkey, arrstr ret )
556 {
557 return regenum( root, subkey, ret, 1 )
558 }
559
560 /*-----------------------------------------------------------------------------
561 * Id: regdelkey F
562 *
563 * Summary: Deleting a registry key.
564 *
565 * Params: root - A root key. $$[regroot]
566 subkey - The name of the registry key being deleted.
567 *
568 * Return: #lng/retf#
569 *
570 -----------------------------------------------------------------------------*/
571
572 func uint regdelkey( uint root, str subkey )
573 {
574 arrstr keys
575 uint i
576 str stemp
577
578 if !regkeys( root, subkey, keys )
579 {
580 return 0
581 }
582 fornum i, *keys
583 {
584 stemp = subkey
585 if !regdelkey( root, stemp.faddname( keys[ i ] )) : return 0
586 }
587 return !RegDeleteKey( root, subkey.ptr())
588 }
589
590 /*-----------------------------------------------------------------------------
591 ** Id: regdelvalue F
592 *
593 * Summary: Deleting the value of a key.
594 *
595 * Params: root - A root key. $$[regroot]
596 subkey - A name of the registry key.
597 value - The name of the value being deleted.
598 *
599 * Return: #lng/retf#
600 *
601 -----------------------------------------------------------------------------*/
602
603 func uint regdelvalue( uint root, str subkey, str value )
604 {
605 uint hkey
606 uint result
607
608 if !RegOpenKeyEx( root, subkey.ptr(), 0, $KEY_WRITE, &hkey )
609 {
610 result = !RegDeleteValue( hkey, value.ptr())
611 RegCloseKey( hkey )
612 }
613 return result
614 }
615